@bleedingdev/modern-js-plugin-i18n 3.5.0-ultramodern.100 → 3.5.0-ultramodern.101
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"modern",
|
|
18
18
|
"modern.js"
|
|
19
19
|
],
|
|
20
|
-
"version": "3.5.0-ultramodern.
|
|
20
|
+
"version": "3.5.0-ultramodern.101",
|
|
21
21
|
"engines": {
|
|
22
22
|
"node": ">=20"
|
|
23
23
|
},
|
|
@@ -91,12 +91,12 @@
|
|
|
91
91
|
}
|
|
92
92
|
},
|
|
93
93
|
"dependencies": {
|
|
94
|
-
"@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.5.0-ultramodern.
|
|
95
|
-
"@modern-js/runtime-utils": "npm:@bleedingdev/modern-js-runtime-utils@3.5.0-ultramodern.
|
|
96
|
-
"@modern-js/server-core": "npm:@bleedingdev/modern-js-server-core@3.5.0-ultramodern.
|
|
97
|
-
"@modern-js/server-runtime": "npm:@bleedingdev/modern-js-server-runtime@3.5.0-ultramodern.
|
|
98
|
-
"@modern-js/types": "npm:@bleedingdev/modern-js-types@3.5.0-ultramodern.
|
|
99
|
-
"@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.5.0-ultramodern.
|
|
94
|
+
"@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.5.0-ultramodern.101",
|
|
95
|
+
"@modern-js/runtime-utils": "npm:@bleedingdev/modern-js-runtime-utils@3.5.0-ultramodern.101",
|
|
96
|
+
"@modern-js/server-core": "npm:@bleedingdev/modern-js-server-core@3.5.0-ultramodern.101",
|
|
97
|
+
"@modern-js/server-runtime": "npm:@bleedingdev/modern-js-server-runtime@3.5.0-ultramodern.101",
|
|
98
|
+
"@modern-js/types": "npm:@bleedingdev/modern-js-types@3.5.0-ultramodern.101",
|
|
99
|
+
"@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.5.0-ultramodern.101",
|
|
100
100
|
"@swc/helpers": "^0.5.23",
|
|
101
101
|
"i18next-browser-languagedetector": "^8.2.1",
|
|
102
102
|
"i18next-chained-backend": "^5.0.5",
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
"i18next-http-middleware": "^3.9.7"
|
|
106
106
|
},
|
|
107
107
|
"peerDependencies": {
|
|
108
|
-
"@modern-js/runtime": "3.5.0-ultramodern.
|
|
108
|
+
"@modern-js/runtime": "3.5.0-ultramodern.101",
|
|
109
109
|
"i18next": ">=26.3.1",
|
|
110
110
|
"react": "^19.2.7",
|
|
111
111
|
"react-dom": "^19.2.7",
|
|
@@ -120,11 +120,12 @@
|
|
|
120
120
|
}
|
|
121
121
|
},
|
|
122
122
|
"devDependencies": {
|
|
123
|
-
"@modern-js/app-tools": "npm:@bleedingdev/modern-js-app-tools@3.5.0-ultramodern.
|
|
124
|
-
"@modern-js/runtime": "npm:@bleedingdev/modern-js-runtime@3.5.0-ultramodern.
|
|
123
|
+
"@modern-js/app-tools": "npm:@bleedingdev/modern-js-app-tools@3.5.0-ultramodern.101",
|
|
124
|
+
"@modern-js/runtime": "npm:@bleedingdev/modern-js-runtime@3.5.0-ultramodern.101",
|
|
125
125
|
"@rslib/core": "0.23.2",
|
|
126
126
|
"@types/node": "^26.1.1",
|
|
127
127
|
"@typescript/native-preview": "7.0.0-dev.20260707.2",
|
|
128
|
+
"esbuild": "^0.28.1",
|
|
128
129
|
"i18next": "26.3.6",
|
|
129
130
|
"react": "^19.2.7",
|
|
130
131
|
"react-dom": "^19.2.7",
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
2
|
-
import path from 'node:path';
|
|
3
1
|
import type { NestedRouteForCli } from '@modern-js/types';
|
|
4
2
|
import { describe, expect, test } from '@rstest/core';
|
|
5
3
|
import { i18nPlugin as i18nCliPlugin } from '../src/cli';
|
|
@@ -19,12 +17,6 @@ import {
|
|
|
19
17
|
validateLocalisedUrls,
|
|
20
18
|
} from '../src/shared/localisedUrls';
|
|
21
19
|
|
|
22
|
-
const localisedRoutesGoldenPath = path.join(
|
|
23
|
-
__dirname,
|
|
24
|
-
'fixtures',
|
|
25
|
-
'localised-routes.golden.json',
|
|
26
|
-
);
|
|
27
|
-
|
|
28
20
|
const createRoute = (
|
|
29
21
|
path: string,
|
|
30
22
|
children?: NestedRouteForCli[],
|
|
@@ -45,9 +37,6 @@ const createRequestContext = (pathname: string) =>
|
|
|
45
37
|
},
|
|
46
38
|
}) as any;
|
|
47
39
|
|
|
48
|
-
const serializeRoutesForGolden = (routes: unknown): string =>
|
|
49
|
-
`${JSON.stringify(routes, null, 2)}\n`;
|
|
50
|
-
|
|
51
40
|
describe('resolveLocalisedUrlsConfig', () => {
|
|
52
41
|
test('is opt-in: only a non-empty map enables the feature', () => {
|
|
53
42
|
const map = { '/about': { en: '/about', cs: '/o-nas' } };
|
|
@@ -119,7 +108,7 @@ describe('cli modifyFileSystemRoutes', () => {
|
|
|
119
108
|
return modifyRoutes!;
|
|
120
109
|
};
|
|
121
110
|
|
|
122
|
-
const
|
|
111
|
+
const generateLocalisedRoutes = () => {
|
|
123
112
|
const modifyRoutes = setupModifyRoutes({
|
|
124
113
|
localePathRedirect: true,
|
|
125
114
|
languages: ['en', 'cs', 'de'],
|
|
@@ -164,23 +153,53 @@ describe('cli modifyFileSystemRoutes', () => {
|
|
|
164
153
|
routes,
|
|
165
154
|
});
|
|
166
155
|
|
|
167
|
-
return
|
|
156
|
+
return result.routes;
|
|
168
157
|
};
|
|
169
158
|
|
|
170
|
-
test('
|
|
171
|
-
const localisedRoutes =
|
|
172
|
-
|
|
159
|
+
test('creates deterministic localized aliases with canonical route identity', () => {
|
|
160
|
+
const localisedRoutes = generateLocalisedRoutes();
|
|
161
|
+
expect(generateLocalisedRoutes()).toEqual(localisedRoutes);
|
|
173
162
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
163
|
+
const [localeLayout] = localisedRoutes;
|
|
164
|
+
expect(localeLayout.children?.map(route => route.path)).toEqual([
|
|
165
|
+
'about',
|
|
166
|
+
'o-nas',
|
|
167
|
+
'ueber-uns',
|
|
168
|
+
'products',
|
|
169
|
+
'produkty',
|
|
170
|
+
'produkte',
|
|
171
|
+
'docs',
|
|
172
|
+
'dokumenty',
|
|
173
|
+
'dokumente',
|
|
174
|
+
]);
|
|
175
|
+
expect(localeLayout.children?.slice(0, 3)).toMatchObject([
|
|
176
|
+
{
|
|
177
|
+
_component: 'about.tsx',
|
|
178
|
+
modernCanonicalPath: '/about',
|
|
179
|
+
path: 'about',
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
_component: 'about.tsx',
|
|
183
|
+
modernCanonicalPath: '/about',
|
|
184
|
+
path: 'o-nas',
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
_component: 'about.tsx',
|
|
188
|
+
modernCanonicalPath: '/about',
|
|
189
|
+
path: 'ueber-uns',
|
|
190
|
+
},
|
|
191
|
+
]);
|
|
192
|
+
for (const productRoute of localeLayout.children?.slice(3, 6) ?? []) {
|
|
193
|
+
expect(productRoute).toMatchObject({
|
|
194
|
+
_component: 'products.tsx',
|
|
195
|
+
modernCanonicalPath: '/products',
|
|
196
|
+
});
|
|
197
|
+
expect(productRoute.children?.[0]).toMatchObject({
|
|
198
|
+
_component: ':slug.tsx',
|
|
199
|
+
modernCanonicalPath: '/products/:slug',
|
|
200
|
+
path: ':slug',
|
|
201
|
+
});
|
|
179
202
|
}
|
|
180
|
-
|
|
181
|
-
await expect(readFile(localisedRoutesGoldenPath, 'utf8')).resolves.toBe(
|
|
182
|
-
localisedRoutes,
|
|
183
|
-
);
|
|
184
203
|
});
|
|
185
204
|
|
|
186
205
|
test('upstream-style configs without a map keep routes untouched', () => {
|
|
@@ -1,48 +1,170 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { mkdtemp, rm } from 'node:fs/promises';
|
|
2
|
+
import { tmpdir } from 'node:os';
|
|
3
|
+
import { basename, resolve } from 'node:path';
|
|
4
|
+
import { pathToFileURL } from 'node:url';
|
|
4
5
|
import { describe, expect, test } from '@rstest/core';
|
|
6
|
+
import { build } from 'esbuild';
|
|
7
|
+
import i18next from 'i18next';
|
|
8
|
+
import { createElement } from 'react';
|
|
9
|
+
import { renderToStaticMarkup } from 'react-dom/server';
|
|
10
|
+
import { i18nPlugin as noReactI18nextPlugin } from '../src/runtime/no-react-i18next';
|
|
5
11
|
|
|
6
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
12
|
const runtimeRoot = resolve(__dirname, '../src/runtime');
|
|
8
13
|
|
|
9
|
-
const readRuntimeSource = (file: string) =>
|
|
10
|
-
readFileSync(resolve(runtimeRoot, file), 'utf8').replace(/\r\n/gu, '\n');
|
|
11
|
-
|
|
12
14
|
describe('react-i18next runtime boundary', () => {
|
|
13
|
-
test('
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
test('bundles the disabled runtime entry when react-i18next is unavailable', async () => {
|
|
16
|
+
await expect(
|
|
17
|
+
build({
|
|
18
|
+
bundle: true,
|
|
19
|
+
entryPoints: [resolve(runtimeRoot, 'no-react-i18next.tsx')],
|
|
20
|
+
format: 'esm',
|
|
21
|
+
packages: 'external',
|
|
22
|
+
platform: 'node',
|
|
23
|
+
plugins: [
|
|
24
|
+
{
|
|
25
|
+
name: 'reject-react-i18next',
|
|
26
|
+
setup(buildApi) {
|
|
27
|
+
buildApi.onResolve({ filter: /^react-i18next$/ }, () => {
|
|
28
|
+
throw new Error(
|
|
29
|
+
'disabled runtime entry reached optional react-i18next',
|
|
30
|
+
);
|
|
31
|
+
});
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
write: false,
|
|
36
|
+
}),
|
|
37
|
+
).resolves.toBeDefined();
|
|
20
38
|
});
|
|
21
39
|
|
|
22
|
-
test('
|
|
23
|
-
|
|
24
|
-
|
|
40
|
+
test('bundles the default runtime entry with the react-i18next adapter', async () => {
|
|
41
|
+
let adapterResolutions = 0;
|
|
42
|
+
await build({
|
|
43
|
+
bundle: true,
|
|
44
|
+
entryPoints: [resolve(runtimeRoot, 'index.tsx')],
|
|
45
|
+
format: 'esm',
|
|
46
|
+
packages: 'external',
|
|
47
|
+
platform: 'node',
|
|
48
|
+
plugins: [
|
|
49
|
+
{
|
|
50
|
+
name: 'observe-react-i18next',
|
|
51
|
+
setup(buildApi) {
|
|
52
|
+
buildApi.onResolve({ filter: /^react-i18next$/ }, args => {
|
|
53
|
+
adapterResolutions += 1;
|
|
54
|
+
return { external: true, path: args.path };
|
|
55
|
+
});
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
write: false,
|
|
60
|
+
});
|
|
25
61
|
|
|
26
|
-
expect(
|
|
27
|
-
expect(core).not.toContain("from './i18n/utils'");
|
|
28
|
-
expect(pluginSetup).not.toContain("from './i18n/backend/middleware'");
|
|
29
|
-
expect(pluginSetup).not.toContain("from './i18n/utils'");
|
|
30
|
-
expect(pluginSetup).toContain("import('./i18n/backend/middleware')");
|
|
31
|
-
expect(pluginSetup).toContain("import('./i18n/utils')");
|
|
62
|
+
expect(adapterResolutions).toBeGreaterThan(0);
|
|
32
63
|
});
|
|
33
64
|
|
|
34
|
-
test('keeps
|
|
35
|
-
const
|
|
65
|
+
test('keeps expensive lifecycle helpers behind asynchronous bundle edges', async () => {
|
|
66
|
+
const result = await build({
|
|
67
|
+
bundle: true,
|
|
68
|
+
entryPoints: [resolve(runtimeRoot, 'pluginSetup.ts')],
|
|
69
|
+
format: 'esm',
|
|
70
|
+
metafile: true,
|
|
71
|
+
outdir: 'out',
|
|
72
|
+
packages: 'external',
|
|
73
|
+
platform: 'node',
|
|
74
|
+
splitting: true,
|
|
75
|
+
write: false,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const entryOutput = Object.values(result.metafile.outputs).find(output =>
|
|
79
|
+
output.entryPoint?.endsWith('/pluginSetup.ts'),
|
|
80
|
+
);
|
|
81
|
+
if (!entryOutput) {
|
|
82
|
+
throw new Error('pluginSetup entry output was not generated');
|
|
83
|
+
}
|
|
84
|
+
const dynamicOutputNames = entryOutput.imports
|
|
85
|
+
.filter(moduleImport => moduleImport.kind === 'dynamic-import')
|
|
86
|
+
.map(moduleImport => basename(moduleImport.path));
|
|
87
|
+
const dynamicOutputs = Object.entries(result.metafile.outputs)
|
|
88
|
+
.filter(([outputPath]) =>
|
|
89
|
+
dynamicOutputNames.includes(basename(outputPath)),
|
|
90
|
+
)
|
|
91
|
+
.map(([, output]) => output);
|
|
92
|
+
const dynamicEntries = dynamicOutputs.map(output =>
|
|
93
|
+
basename(output.entryPoint ?? ''),
|
|
94
|
+
);
|
|
36
95
|
|
|
37
|
-
expect(
|
|
38
|
-
|
|
96
|
+
expect(dynamicEntries).toEqual(
|
|
97
|
+
expect.arrayContaining(['middleware.ts', 'utils.ts']),
|
|
39
98
|
);
|
|
40
|
-
expect(context).toContain('globalStore[modernI18nContextKey] ??=');
|
|
41
99
|
});
|
|
42
100
|
|
|
43
|
-
test('
|
|
44
|
-
|
|
101
|
+
test('registers plugin lifecycle hooks synchronously', () => {
|
|
102
|
+
let beforeRender: unknown;
|
|
103
|
+
let rootWrapper: unknown;
|
|
104
|
+
const plugin = noReactI18nextPlugin({ reactI18next: false });
|
|
105
|
+
const setupResult = plugin.setup?.({
|
|
106
|
+
getRuntimeConfig: () => ({}),
|
|
107
|
+
onBeforeRender: hook => {
|
|
108
|
+
beforeRender = hook;
|
|
109
|
+
},
|
|
110
|
+
wrapRoot: wrapper => {
|
|
111
|
+
rootWrapper = wrapper;
|
|
112
|
+
},
|
|
113
|
+
} as any);
|
|
114
|
+
|
|
115
|
+
expect(setupResult).toBeUndefined();
|
|
116
|
+
expect(typeof beforeRender).toBe('function');
|
|
117
|
+
expect(typeof rootWrapper).toBe('function');
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test('shares Modern i18n context across independently bundled runtime copies', async () => {
|
|
121
|
+
const tempDir = await mkdtemp(
|
|
122
|
+
resolve(__dirname, '.modern-i18n-runtime-boundary-'),
|
|
123
|
+
);
|
|
124
|
+
try {
|
|
125
|
+
const contextEntry = resolve(runtimeRoot, 'context.tsx');
|
|
126
|
+
const copies = await Promise.all(
|
|
127
|
+
['copy-a.mjs', 'copy-b.mjs'].map(async filename => {
|
|
128
|
+
const outfile = resolve(tempDir, filename);
|
|
129
|
+
await build({
|
|
130
|
+
bundle: true,
|
|
131
|
+
entryPoints: [contextEntry],
|
|
132
|
+
format: 'esm',
|
|
133
|
+
jsx: 'automatic',
|
|
134
|
+
outfile,
|
|
135
|
+
packages: 'external',
|
|
136
|
+
platform: 'node',
|
|
137
|
+
});
|
|
138
|
+
return import(pathToFileURL(outfile).href);
|
|
139
|
+
}),
|
|
140
|
+
);
|
|
141
|
+
const [copyA, copyB] = copies;
|
|
142
|
+
const instance = i18next.createInstance();
|
|
143
|
+
await instance.init({
|
|
144
|
+
initImmediate: false,
|
|
145
|
+
lng: 'cs',
|
|
146
|
+
resources: { cs: { translation: { language: 'Jazyk' } } },
|
|
147
|
+
});
|
|
148
|
+
const Consumer = () =>
|
|
149
|
+
createElement('span', null, copyB.useModernI18n().language);
|
|
150
|
+
|
|
151
|
+
const html = renderToStaticMarkup(
|
|
152
|
+
createElement(
|
|
153
|
+
copyA.ModernI18nProvider,
|
|
154
|
+
{
|
|
155
|
+
value: {
|
|
156
|
+
i18nInstance: instance,
|
|
157
|
+
language: 'cs',
|
|
158
|
+
languages: ['en', 'cs'],
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
createElement(Consumer),
|
|
162
|
+
),
|
|
163
|
+
);
|
|
45
164
|
|
|
46
|
-
|
|
165
|
+
expect(html).toBe('<span>cs</span>');
|
|
166
|
+
} finally {
|
|
167
|
+
await rm(tempDir, { force: true, recursive: true });
|
|
168
|
+
}
|
|
47
169
|
});
|
|
48
170
|
});
|
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
[
|
|
2
|
-
{
|
|
3
|
-
"id": ":lang",
|
|
4
|
-
"path": ":lang",
|
|
5
|
-
"type": "nested",
|
|
6
|
-
"origin": "file-system",
|
|
7
|
-
"routeType": "layout",
|
|
8
|
-
"_component": ":lang.tsx",
|
|
9
|
-
"children": [
|
|
10
|
-
{
|
|
11
|
-
"id": "about",
|
|
12
|
-
"path": "about",
|
|
13
|
-
"type": "nested",
|
|
14
|
-
"origin": "file-system",
|
|
15
|
-
"routeType": "page",
|
|
16
|
-
"_component": "about.tsx",
|
|
17
|
-
"modernCanonicalPath": "/about"
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
"id": "about__localised_o-nas",
|
|
21
|
-
"path": "o-nas",
|
|
22
|
-
"type": "nested",
|
|
23
|
-
"origin": "file-system",
|
|
24
|
-
"routeType": "page",
|
|
25
|
-
"_component": "about.tsx",
|
|
26
|
-
"modernCanonicalPath": "/about"
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
"id": "about__localised_ueber-uns",
|
|
30
|
-
"path": "ueber-uns",
|
|
31
|
-
"type": "nested",
|
|
32
|
-
"origin": "file-system",
|
|
33
|
-
"routeType": "page",
|
|
34
|
-
"_component": "about.tsx",
|
|
35
|
-
"modernCanonicalPath": "/about"
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
"id": "products",
|
|
39
|
-
"path": "products",
|
|
40
|
-
"type": "nested",
|
|
41
|
-
"origin": "file-system",
|
|
42
|
-
"routeType": "layout",
|
|
43
|
-
"_component": "products.tsx",
|
|
44
|
-
"children": [
|
|
45
|
-
{
|
|
46
|
-
"id": ":slug",
|
|
47
|
-
"path": ":slug",
|
|
48
|
-
"type": "nested",
|
|
49
|
-
"origin": "file-system",
|
|
50
|
-
"routeType": "page",
|
|
51
|
-
"_component": ":slug.tsx",
|
|
52
|
-
"modernCanonicalPath": "/products/:slug"
|
|
53
|
-
}
|
|
54
|
-
],
|
|
55
|
-
"modernCanonicalPath": "/products"
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
"id": "products__localised_produkty",
|
|
59
|
-
"path": "produkty",
|
|
60
|
-
"type": "nested",
|
|
61
|
-
"origin": "file-system",
|
|
62
|
-
"routeType": "layout",
|
|
63
|
-
"_component": "products.tsx",
|
|
64
|
-
"children": [
|
|
65
|
-
{
|
|
66
|
-
"id": ":slug__localised_produkty",
|
|
67
|
-
"path": ":slug",
|
|
68
|
-
"type": "nested",
|
|
69
|
-
"origin": "file-system",
|
|
70
|
-
"routeType": "page",
|
|
71
|
-
"_component": ":slug.tsx",
|
|
72
|
-
"modernCanonicalPath": "/products/:slug"
|
|
73
|
-
}
|
|
74
|
-
],
|
|
75
|
-
"modernCanonicalPath": "/products"
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
"id": "products__localised_produkte",
|
|
79
|
-
"path": "produkte",
|
|
80
|
-
"type": "nested",
|
|
81
|
-
"origin": "file-system",
|
|
82
|
-
"routeType": "layout",
|
|
83
|
-
"_component": "products.tsx",
|
|
84
|
-
"children": [
|
|
85
|
-
{
|
|
86
|
-
"id": ":slug__localised_produkte",
|
|
87
|
-
"path": ":slug",
|
|
88
|
-
"type": "nested",
|
|
89
|
-
"origin": "file-system",
|
|
90
|
-
"routeType": "page",
|
|
91
|
-
"_component": ":slug.tsx",
|
|
92
|
-
"modernCanonicalPath": "/products/:slug"
|
|
93
|
-
}
|
|
94
|
-
],
|
|
95
|
-
"modernCanonicalPath": "/products"
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
"id": "docs",
|
|
99
|
-
"path": "docs",
|
|
100
|
-
"type": "nested",
|
|
101
|
-
"origin": "file-system",
|
|
102
|
-
"routeType": "layout",
|
|
103
|
-
"_component": "docs.tsx",
|
|
104
|
-
"children": [
|
|
105
|
-
{
|
|
106
|
-
"id": "*",
|
|
107
|
-
"path": "*",
|
|
108
|
-
"type": "nested",
|
|
109
|
-
"origin": "file-system",
|
|
110
|
-
"routeType": "page",
|
|
111
|
-
"_component": "*.tsx"
|
|
112
|
-
}
|
|
113
|
-
],
|
|
114
|
-
"modernCanonicalPath": "/docs"
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
"id": "docs__localised_dokumenty",
|
|
118
|
-
"path": "dokumenty",
|
|
119
|
-
"type": "nested",
|
|
120
|
-
"origin": "file-system",
|
|
121
|
-
"routeType": "layout",
|
|
122
|
-
"_component": "docs.tsx",
|
|
123
|
-
"children": [
|
|
124
|
-
{
|
|
125
|
-
"id": "*__localised_dokumenty",
|
|
126
|
-
"path": "*",
|
|
127
|
-
"type": "nested",
|
|
128
|
-
"origin": "file-system",
|
|
129
|
-
"routeType": "page",
|
|
130
|
-
"_component": "*.tsx"
|
|
131
|
-
}
|
|
132
|
-
],
|
|
133
|
-
"modernCanonicalPath": "/docs"
|
|
134
|
-
},
|
|
135
|
-
{
|
|
136
|
-
"id": "docs__localised_dokumente",
|
|
137
|
-
"path": "dokumente",
|
|
138
|
-
"type": "nested",
|
|
139
|
-
"origin": "file-system",
|
|
140
|
-
"routeType": "layout",
|
|
141
|
-
"_component": "docs.tsx",
|
|
142
|
-
"children": [
|
|
143
|
-
{
|
|
144
|
-
"id": "*__localised_dokumente",
|
|
145
|
-
"path": "*",
|
|
146
|
-
"type": "nested",
|
|
147
|
-
"origin": "file-system",
|
|
148
|
-
"routeType": "page",
|
|
149
|
-
"_component": "*.tsx"
|
|
150
|
-
}
|
|
151
|
-
],
|
|
152
|
-
"modernCanonicalPath": "/docs"
|
|
153
|
-
}
|
|
154
|
-
]
|
|
155
|
-
}
|
|
156
|
-
]
|