@bleedingdev/modern-js-plugin-i18n 3.5.0-ultramodern.9 → 3.5.0-ultramodern.91
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/dist/cjs/cli/index.js +2 -1
- package/dist/cjs/cli/locales.js +15 -15
- package/dist/cjs/runtime/Link.js +8 -89
- package/dist/cjs/runtime/context.js +78 -91
- package/dist/cjs/runtime/contextHelpers.js +143 -0
- package/dist/cjs/runtime/core.js +32 -132
- package/dist/cjs/runtime/hooks.js +54 -21
- package/dist/cjs/runtime/i18n/backend/defaults.node.js +7 -7
- package/dist/cjs/runtime/i18n/detection/cache.js +150 -0
- package/dist/cjs/runtime/i18n/detection/detector.js +100 -0
- package/dist/cjs/runtime/i18n/detection/index.js +8 -263
- package/dist/cjs/runtime/i18n/detection/initOptions.js +69 -0
- package/dist/cjs/runtime/i18n/detection/language.js +62 -0
- package/dist/cjs/runtime/i18n/detection/path.js +49 -0
- package/dist/cjs/runtime/i18n/detection/priority.js +66 -0
- package/dist/cjs/runtime/i18n/detection/ssr.js +70 -0
- package/dist/cjs/runtime/i18n/detection/types.js +18 -0
- package/dist/cjs/runtime/i18n/instance.js +34 -10
- package/dist/cjs/runtime/linkHelpers.js +148 -0
- package/dist/cjs/runtime/pluginSetup.js +102 -0
- package/dist/cjs/runtime/providerComposition.js +115 -0
- package/dist/cjs/runtime/reactI18next.js +43 -0
- package/dist/cjs/runtime/routerAdapter.js +16 -8
- package/dist/cjs/runtime/utils.js +1 -9
- package/dist/cjs/server/apiPrefix.js +72 -0
- package/dist/cjs/server/detectorOptions.js +97 -0
- package/dist/cjs/server/index.js +17 -144
- package/dist/cjs/server/redirectPolicy.js +96 -0
- package/dist/cjs/shared/detection.js +2 -104
- package/dist/cjs/shared/localisedUrls/config.js +49 -0
- package/dist/cjs/shared/localisedUrls/index.js +91 -0
- package/dist/cjs/shared/localisedUrls/normalise.js +87 -0
- package/dist/cjs/shared/localisedUrls/pathname.js +68 -0
- package/dist/cjs/shared/localisedUrls/patterns.js +130 -0
- package/dist/cjs/shared/localisedUrls/redirect.js +103 -0
- package/dist/cjs/shared/localisedUrls/resolve.js +88 -0
- package/dist/cjs/shared/localisedUrls/routes.js +130 -0
- package/dist/cjs/shared/localisedUrls/types.js +18 -0
- package/dist/cjs/shared/localisedUrls.js +28 -294
- package/dist/cjs/shared/utils.js +2 -8
- package/dist/esm/cli/index.mjs +2 -1
- package/dist/esm/cli/locales.mjs +13 -13
- package/dist/esm/runtime/Link.mjs +1 -82
- package/dist/esm/runtime/context.mjs +76 -92
- package/dist/esm/runtime/contextHelpers.mjs +87 -0
- package/dist/esm/runtime/core.mjs +30 -133
- package/dist/esm/runtime/hooks.mjs +56 -23
- package/dist/esm/runtime/i18n/backend/defaults.node.mjs +5 -5
- package/dist/esm/runtime/i18n/detection/cache.mjs +103 -0
- package/dist/esm/runtime/i18n/detection/detector.mjs +62 -0
- package/dist/esm/runtime/i18n/detection/index.mjs +4 -260
- package/dist/esm/runtime/i18n/detection/initOptions.mjs +28 -0
- package/dist/esm/runtime/i18n/detection/language.mjs +21 -0
- package/dist/esm/runtime/i18n/detection/path.mjs +11 -0
- package/dist/esm/runtime/i18n/detection/priority.mjs +28 -0
- package/dist/esm/runtime/i18n/detection/ssr.mjs +26 -0
- package/dist/esm/runtime/i18n/detection/types.mjs +0 -0
- package/dist/esm/runtime/i18n/instance.mjs +35 -8
- package/dist/esm/runtime/linkHelpers.mjs +98 -0
- package/dist/esm/runtime/pluginSetup.mjs +64 -0
- package/dist/esm/runtime/providerComposition.mjs +77 -0
- package/dist/esm/runtime/reactI18next.mjs +5 -0
- package/dist/esm/runtime/routerAdapter.mjs +16 -8
- package/dist/esm/runtime/utils.mjs +2 -10
- package/dist/esm/server/apiPrefix.mjs +31 -0
- package/dist/esm/server/detectorOptions.mjs +59 -0
- package/dist/esm/server/index.mjs +8 -135
- package/dist/esm/server/redirectPolicy.mjs +46 -0
- package/dist/esm/shared/detection.mjs +1 -71
- package/dist/esm/shared/localisedUrls/config.mjs +11 -0
- package/dist/esm/shared/localisedUrls/index.mjs +7 -0
- package/dist/esm/shared/localisedUrls/normalise.mjs +37 -0
- package/dist/esm/shared/localisedUrls/pathname.mjs +24 -0
- package/dist/esm/shared/localisedUrls/patterns.mjs +86 -0
- package/dist/esm/shared/localisedUrls/redirect.mjs +56 -0
- package/dist/esm/shared/localisedUrls/resolve.mjs +47 -0
- package/dist/esm/shared/localisedUrls/routes.mjs +89 -0
- package/dist/esm/shared/localisedUrls/types.mjs +0 -0
- package/dist/esm/shared/localisedUrls.mjs +1 -283
- package/dist/esm/shared/utils.mjs +1 -1
- package/dist/esm-node/cli/index.mjs +2 -1
- package/dist/esm-node/cli/locales.mjs +13 -13
- package/dist/esm-node/runtime/Link.mjs +1 -82
- package/dist/esm-node/runtime/context.mjs +76 -92
- package/dist/esm-node/runtime/contextHelpers.mjs +88 -0
- package/dist/esm-node/runtime/core.mjs +30 -133
- package/dist/esm-node/runtime/hooks.mjs +56 -23
- package/dist/esm-node/runtime/i18n/backend/defaults.node.mjs +5 -5
- package/dist/esm-node/runtime/i18n/detection/cache.mjs +104 -0
- package/dist/esm-node/runtime/i18n/detection/detector.mjs +63 -0
- package/dist/esm-node/runtime/i18n/detection/index.mjs +4 -260
- package/dist/esm-node/runtime/i18n/detection/initOptions.mjs +29 -0
- package/dist/esm-node/runtime/i18n/detection/language.mjs +22 -0
- package/dist/esm-node/runtime/i18n/detection/path.mjs +12 -0
- package/dist/esm-node/runtime/i18n/detection/priority.mjs +29 -0
- package/dist/esm-node/runtime/i18n/detection/ssr.mjs +27 -0
- package/dist/esm-node/runtime/i18n/detection/types.mjs +1 -0
- package/dist/esm-node/runtime/i18n/instance.mjs +35 -8
- package/dist/esm-node/runtime/linkHelpers.mjs +99 -0
- package/dist/esm-node/runtime/pluginSetup.mjs +65 -0
- package/dist/esm-node/runtime/providerComposition.mjs +78 -0
- package/dist/esm-node/runtime/reactI18next.mjs +6 -0
- package/dist/esm-node/runtime/routerAdapter.mjs +16 -8
- package/dist/esm-node/runtime/utils.mjs +2 -10
- package/dist/esm-node/server/apiPrefix.mjs +32 -0
- package/dist/esm-node/server/detectorOptions.mjs +60 -0
- package/dist/esm-node/server/index.mjs +8 -135
- package/dist/esm-node/server/redirectPolicy.mjs +47 -0
- package/dist/esm-node/shared/detection.mjs +1 -71
- package/dist/esm-node/shared/localisedUrls/config.mjs +12 -0
- package/dist/esm-node/shared/localisedUrls/index.mjs +8 -0
- package/dist/esm-node/shared/localisedUrls/normalise.mjs +38 -0
- package/dist/esm-node/shared/localisedUrls/pathname.mjs +25 -0
- package/dist/esm-node/shared/localisedUrls/patterns.mjs +87 -0
- package/dist/esm-node/shared/localisedUrls/redirect.mjs +57 -0
- package/dist/esm-node/shared/localisedUrls/resolve.mjs +48 -0
- package/dist/esm-node/shared/localisedUrls/routes.mjs +90 -0
- package/dist/esm-node/shared/localisedUrls/types.mjs +1 -0
- package/dist/esm-node/shared/localisedUrls.mjs +1 -283
- package/dist/esm-node/shared/utils.mjs +1 -1
- package/dist/types/cli/locales.d.ts +1 -1
- package/dist/types/runtime/Link.d.ts +3 -7
- package/dist/types/runtime/context.d.ts +21 -5
- package/dist/types/runtime/contextHelpers.d.ts +29 -0
- package/dist/types/runtime/core.d.ts +4 -8
- package/dist/types/runtime/hooks.d.ts +3 -7
- package/dist/types/runtime/i18n/backend/middleware.common.d.ts +2 -1
- package/dist/types/runtime/i18n/detection/cache.d.ts +14 -0
- package/dist/types/runtime/i18n/detection/detector.d.ts +8 -0
- package/dist/types/runtime/i18n/detection/index.d.ts +5 -50
- package/dist/types/runtime/i18n/detection/initOptions.d.ts +10 -0
- package/dist/types/runtime/i18n/detection/language.d.ts +11 -0
- package/dist/types/runtime/i18n/detection/middleware.d.ts +4 -4
- package/dist/types/runtime/i18n/detection/middleware.node.d.ts +4 -4
- package/dist/types/runtime/i18n/detection/path.d.ts +5 -0
- package/dist/types/runtime/i18n/detection/priority.d.ts +10 -0
- package/dist/types/runtime/i18n/detection/ssr.d.ts +9 -0
- package/dist/types/runtime/i18n/detection/types.d.ts +32 -0
- package/dist/types/runtime/i18n/instance.d.ts +31 -27
- package/dist/types/runtime/i18n/react-i18next.d.ts +1 -6
- package/dist/types/runtime/i18n/utils.d.ts +14 -5
- package/dist/types/runtime/linkHelpers.d.ts +17 -0
- package/dist/types/runtime/pluginSetup.d.ts +32 -0
- package/dist/types/runtime/providerComposition.d.ts +16 -0
- package/dist/types/runtime/reactI18next.d.ts +7 -0
- package/dist/types/runtime/routerAdapter.d.ts +7 -6
- package/dist/types/runtime/utils.d.ts +7 -2
- package/dist/types/server/apiPrefix.d.ts +7 -0
- package/dist/types/server/detectorOptions.d.ts +21 -0
- package/dist/types/server/index.d.ts +1 -6
- package/dist/types/server/redirectPolicy.d.ts +22 -0
- package/dist/types/shared/detection.d.ts +1 -11
- package/dist/types/shared/localisedUrls/config.d.ts +9 -0
- package/dist/types/shared/localisedUrls/index.d.ts +9 -0
- package/dist/types/shared/localisedUrls/normalise.d.ts +10 -0
- package/dist/types/shared/localisedUrls/pathname.d.ts +4 -0
- package/dist/types/shared/localisedUrls/patterns.d.ts +5 -0
- package/dist/types/shared/localisedUrls/redirect.d.ts +11 -0
- package/dist/types/shared/localisedUrls/resolve.d.ts +7 -0
- package/dist/types/shared/localisedUrls/routes.d.ts +3 -0
- package/dist/types/shared/localisedUrls/types.d.ts +14 -0
- package/dist/types/shared/localisedUrls.d.ts +2 -36
- package/dist/types/shared/utils.d.ts +0 -2
- package/package.json +17 -20
- package/rstest.config.mts +8 -1
- package/src/cli/index.ts +5 -4
- package/src/cli/locales.ts +3 -3
- package/src/runtime/Link.tsx +11 -138
- package/src/runtime/context.tsx +170 -207
- package/src/runtime/contextHelpers.ts +242 -0
- package/src/runtime/core.tsx +48 -275
- package/src/runtime/hooks.ts +86 -24
- package/src/runtime/i18n/backend/defaults.node.ts +2 -2
- package/src/runtime/i18n/backend/middleware.common.ts +5 -4
- package/src/runtime/i18n/detection/cache.ts +189 -0
- package/src/runtime/i18n/detection/detector.ts +166 -0
- package/src/runtime/i18n/detection/index.ts +10 -641
- package/src/runtime/i18n/detection/initOptions.ts +74 -0
- package/src/runtime/i18n/detection/language.ts +64 -0
- package/src/runtime/i18n/detection/middleware.node.ts +26 -7
- package/src/runtime/i18n/detection/middleware.ts +15 -7
- package/src/runtime/i18n/detection/path.ts +41 -0
- package/src/runtime/i18n/detection/priority.ts +82 -0
- package/src/runtime/i18n/detection/ssr.ts +47 -0
- package/src/runtime/i18n/detection/types.ts +41 -0
- package/src/runtime/i18n/instance.ts +98 -34
- package/src/runtime/i18n/react-i18next.ts +1 -6
- package/src/runtime/i18n/utils.ts +18 -9
- package/src/runtime/linkHelpers.ts +174 -0
- package/src/runtime/pluginSetup.ts +189 -0
- package/src/runtime/providerComposition.tsx +148 -0
- package/src/runtime/reactI18next.ts +20 -0
- package/src/runtime/routerAdapter.tsx +36 -15
- package/src/runtime/utils.ts +13 -35
- package/src/server/apiPrefix.ts +67 -0
- package/src/server/detectorOptions.ts +105 -0
- package/src/server/index.ts +14 -319
- package/src/server/redirectPolicy.ts +127 -0
- package/src/shared/detection.ts +1 -1
- package/src/shared/localisedUrls/config.ts +18 -0
- package/src/shared/localisedUrls/index.ts +24 -0
- package/src/shared/localisedUrls/normalise.ts +67 -0
- package/src/shared/localisedUrls/pathname.ts +60 -0
- package/src/shared/localisedUrls/patterns.ts +160 -0
- package/src/shared/localisedUrls/redirect.ts +93 -0
- package/src/shared/localisedUrls/resolve.ts +135 -0
- package/src/shared/localisedUrls/routes.ts +234 -0
- package/src/shared/localisedUrls/types.ts +18 -0
- package/src/shared/localisedUrls.ts +26 -623
- package/src/shared/utils.ts +2 -2
- package/tests/federatedI18nBoundary.client.test.tsx +112 -0
- package/tests/federatedI18nBoundary.test.tsx +120 -0
- package/tests/fixtures/localised-routes.golden.json +156 -0
- package/tests/link.test.tsx +111 -0
- package/tests/localisedUrlRewriteMatrix.fork.test.ts +147 -0
- package/tests/localisedUrls.test.ts +148 -2
- package/tests/reactI18nextRuntimeBoundary.test.ts +6 -3
- package/tests/redirectPolicy.test.ts +45 -0
- package/tests/routerAdapter.test.tsx +603 -0
- package/tests/type-fixture/fixture-globals.d.ts +11 -0
- package/tests/type-fixture/tsconfig.json +1 -0
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
1
3
|
import type { NestedRouteForCli } from '@modern-js/types';
|
|
2
4
|
import { describe, expect, test } from '@rstest/core';
|
|
3
5
|
import { i18nPlugin as i18nCliPlugin } from '../src/cli';
|
|
@@ -17,6 +19,12 @@ import {
|
|
|
17
19
|
validateLocalisedUrls,
|
|
18
20
|
} from '../src/shared/localisedUrls';
|
|
19
21
|
|
|
22
|
+
const localisedRoutesGoldenPath = path.join(
|
|
23
|
+
__dirname,
|
|
24
|
+
'fixtures',
|
|
25
|
+
'localised-routes.golden.json',
|
|
26
|
+
);
|
|
27
|
+
|
|
20
28
|
const createRoute = (
|
|
21
29
|
path: string,
|
|
22
30
|
children?: NestedRouteForCli[],
|
|
@@ -37,6 +45,9 @@ const createRequestContext = (pathname: string) =>
|
|
|
37
45
|
},
|
|
38
46
|
}) as any;
|
|
39
47
|
|
|
48
|
+
const serializeRoutesForGolden = (routes: unknown): string =>
|
|
49
|
+
`${JSON.stringify(routes, null, 2)}\n`;
|
|
50
|
+
|
|
40
51
|
describe('resolveLocalisedUrlsConfig', () => {
|
|
41
52
|
test('is opt-in: only a non-empty map enables the feature', () => {
|
|
42
53
|
const map = { '/about': { en: '/about', cs: '/o-nas' } };
|
|
@@ -108,6 +119,70 @@ describe('cli modifyFileSystemRoutes', () => {
|
|
|
108
119
|
return modifyRoutes!;
|
|
109
120
|
};
|
|
110
121
|
|
|
122
|
+
const generateLocalisedRoutesGolden = (): string => {
|
|
123
|
+
const modifyRoutes = setupModifyRoutes({
|
|
124
|
+
localePathRedirect: true,
|
|
125
|
+
languages: ['en', 'cs', 'de'],
|
|
126
|
+
localisedUrls: {
|
|
127
|
+
'/about': {
|
|
128
|
+
en: '/about',
|
|
129
|
+
cs: '/o-nas',
|
|
130
|
+
de: '/ueber-uns',
|
|
131
|
+
},
|
|
132
|
+
'/products': {
|
|
133
|
+
en: '/products',
|
|
134
|
+
cs: '/produkty',
|
|
135
|
+
de: '/produkte',
|
|
136
|
+
},
|
|
137
|
+
'/products/:slug': {
|
|
138
|
+
en: '/products/:slug',
|
|
139
|
+
cs: '/produkty/:slug',
|
|
140
|
+
de: '/produkte/:slug',
|
|
141
|
+
},
|
|
142
|
+
'/docs': {
|
|
143
|
+
en: '/docs',
|
|
144
|
+
cs: '/dokumenty',
|
|
145
|
+
de: '/dokumente',
|
|
146
|
+
},
|
|
147
|
+
'/docs/*': {
|
|
148
|
+
en: '/docs/*',
|
|
149
|
+
cs: '/dokumenty/*',
|
|
150
|
+
de: '/dokumente/*',
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
const routes = [
|
|
155
|
+
createRoute(':lang', [
|
|
156
|
+
createRoute('about'),
|
|
157
|
+
createRoute('products', [createRoute(':slug')]),
|
|
158
|
+
createRoute('docs', [createRoute('*')]),
|
|
159
|
+
]),
|
|
160
|
+
];
|
|
161
|
+
|
|
162
|
+
const result = modifyRoutes({
|
|
163
|
+
entrypoint: { entryName: 'main' },
|
|
164
|
+
routes,
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
return serializeRoutesForGolden(result.routes);
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
test('matches checked-in localised routes golden output', async () => {
|
|
171
|
+
const localisedRoutes = generateLocalisedRoutesGolden();
|
|
172
|
+
const repeatedLocalisedRoutes = generateLocalisedRoutesGolden();
|
|
173
|
+
|
|
174
|
+
expect(repeatedLocalisedRoutes).toBe(localisedRoutes);
|
|
175
|
+
|
|
176
|
+
if (process.env.UPDATE_I18N_LOCALISED_ROUTES_GOLDEN === '1') {
|
|
177
|
+
await mkdir(path.dirname(localisedRoutesGoldenPath), { recursive: true });
|
|
178
|
+
await writeFile(localisedRoutesGoldenPath, localisedRoutes);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
await expect(readFile(localisedRoutesGoldenPath, 'utf8')).resolves.toBe(
|
|
182
|
+
localisedRoutes,
|
|
183
|
+
);
|
|
184
|
+
});
|
|
185
|
+
|
|
111
186
|
test('upstream-style configs without a map keep routes untouched', () => {
|
|
112
187
|
const modifyRoutes = setupModifyRoutes({
|
|
113
188
|
localePathRedirect: true,
|
|
@@ -141,6 +216,25 @@ describe('cli modifyFileSystemRoutes', () => {
|
|
|
141
216
|
});
|
|
142
217
|
|
|
143
218
|
describe('localisedUrls', () => {
|
|
219
|
+
test('leaves framework-internal Module Federation routes unlocalised', () => {
|
|
220
|
+
const internalRoute = createRoute('_mf', [
|
|
221
|
+
createRoute('fragment', [createRoute('product-card')]),
|
|
222
|
+
]);
|
|
223
|
+
const publicRoute = createRoute(':lang', [createRoute('products')]);
|
|
224
|
+
const routes = [internalRoute, publicRoute];
|
|
225
|
+
|
|
226
|
+
expect(() =>
|
|
227
|
+
validateLocalisedUrls(routes, ['en', 'cs'], {
|
|
228
|
+
'/products': { en: '/products', cs: '/produkty' },
|
|
229
|
+
}),
|
|
230
|
+
).not.toThrow();
|
|
231
|
+
expect(
|
|
232
|
+
applyLocalisedUrlsToRoutes(routes, ['en', 'cs'], {
|
|
233
|
+
'/products': { en: '/products', cs: '/produkty' },
|
|
234
|
+
})[0],
|
|
235
|
+
).toEqual(internalRoute);
|
|
236
|
+
});
|
|
237
|
+
|
|
144
238
|
test('requires every localisable route path to define every language', () => {
|
|
145
239
|
const routes = [createRoute(':lang', [createRoute('terms-of-service')])];
|
|
146
240
|
|
|
@@ -272,6 +366,31 @@ describe('localisedUrls', () => {
|
|
|
272
366
|
).toBe('/products/cervena-bota');
|
|
273
367
|
});
|
|
274
368
|
|
|
369
|
+
test('encodes wildcard params while preserving path separators', () => {
|
|
370
|
+
const localisedUrls = {
|
|
371
|
+
'/docs/*': {
|
|
372
|
+
en: '/docs/*',
|
|
373
|
+
cs: '/dokumenty/*',
|
|
374
|
+
},
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
expect(
|
|
378
|
+
resolveLocalisedPath(
|
|
379
|
+
'/docs/a%20b/c%23d',
|
|
380
|
+
'cs',
|
|
381
|
+
['en', 'cs'],
|
|
382
|
+
localisedUrls,
|
|
383
|
+
),
|
|
384
|
+
).toBe('/dokumenty/a%20b/c%23d');
|
|
385
|
+
expect(
|
|
386
|
+
resolveCanonicalLocalisedPath(
|
|
387
|
+
'/dokumenty/a%20b/c%23d',
|
|
388
|
+
['en', 'cs'],
|
|
389
|
+
localisedUrls,
|
|
390
|
+
),
|
|
391
|
+
).toBe('/docs/a%20b/c%23d');
|
|
392
|
+
});
|
|
393
|
+
|
|
275
394
|
test('resolves static patterns before param patterns', () => {
|
|
276
395
|
const localisedUrls = {
|
|
277
396
|
'/products/:slug': {
|
|
@@ -321,6 +440,31 @@ describe('localisedUrls', () => {
|
|
|
321
440
|
).toBe('/products/cervena-bota');
|
|
322
441
|
});
|
|
323
442
|
|
|
443
|
+
test('strips case-insensitive locale prefixes before relocalising full pathnames', () => {
|
|
444
|
+
const localisedUrls = {
|
|
445
|
+
'/products/:slug': {
|
|
446
|
+
en: '/products/:slug',
|
|
447
|
+
cs: '/produkty/:slug',
|
|
448
|
+
},
|
|
449
|
+
};
|
|
450
|
+
|
|
451
|
+
expect(
|
|
452
|
+
localiseTargetPathname(
|
|
453
|
+
'/CS/produkty/cervena-bota',
|
|
454
|
+
'en',
|
|
455
|
+
['en', 'cs'],
|
|
456
|
+
localisedUrls,
|
|
457
|
+
),
|
|
458
|
+
).toBe('/en/products/cervena-bota');
|
|
459
|
+
expect(
|
|
460
|
+
canonicalTargetPathname(
|
|
461
|
+
'/CS/produkty/cervena-bota',
|
|
462
|
+
['en', 'cs'],
|
|
463
|
+
localisedUrls,
|
|
464
|
+
),
|
|
465
|
+
).toBe('/products/cervena-bota');
|
|
466
|
+
});
|
|
467
|
+
|
|
324
468
|
test('resolves nested optional route params with translated ancestors', () => {
|
|
325
469
|
const localisedUrls = {
|
|
326
470
|
'/checkout': {
|
|
@@ -509,7 +653,6 @@ describe('i18n server API prefix skips', () => {
|
|
|
509
653
|
header: () => ({ host: 'localhost' }),
|
|
510
654
|
},
|
|
511
655
|
get: () => null,
|
|
512
|
-
redirect: (url: string) => ({ redirectedTo: url }),
|
|
513
656
|
}) as any;
|
|
514
657
|
|
|
515
658
|
// Sanity: well-formed non-canonical slugs still redirect.
|
|
@@ -517,7 +660,10 @@ describe('i18n server API prefix skips', () => {
|
|
|
517
660
|
createContext('/cs/products/bota'),
|
|
518
661
|
async () => {},
|
|
519
662
|
);
|
|
520
|
-
expect(redirected).
|
|
663
|
+
expect(redirected.status).toBe(302);
|
|
664
|
+
expect(redirected.headers.get('location')).toBe('/cs/produkty/bota');
|
|
665
|
+
expect(redirected.headers.get('cache-control')).toBe('private, no-store');
|
|
666
|
+
expect(redirected.headers.get('vary')).toBe('Accept-Language, Cookie');
|
|
521
667
|
|
|
522
668
|
// Malformed encoding must fall through to next() instead of throwing.
|
|
523
669
|
let nextCalls = 0;
|
|
@@ -7,7 +7,7 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
7
7
|
const runtimeRoot = resolve(__dirname, '../src/runtime');
|
|
8
8
|
|
|
9
9
|
const readRuntimeSource = (file: string) =>
|
|
10
|
-
readFileSync(resolve(runtimeRoot, file), 'utf8');
|
|
10
|
+
readFileSync(resolve(runtimeRoot, file), 'utf8').replace(/\r\n/gu, '\n');
|
|
11
11
|
|
|
12
12
|
describe('react-i18next runtime boundary', () => {
|
|
13
13
|
test('keeps the disabled runtime entry free of the optional adapter edge', () => {
|
|
@@ -21,11 +21,14 @@ describe('react-i18next runtime boundary', () => {
|
|
|
21
21
|
|
|
22
22
|
test('keeps the runtime plugin factory entry synchronous for federation', () => {
|
|
23
23
|
const core = readRuntimeSource('core.tsx');
|
|
24
|
+
const pluginSetup = readRuntimeSource('pluginSetup.ts');
|
|
24
25
|
|
|
25
26
|
expect(core).not.toContain("from './i18n/backend/middleware'");
|
|
26
27
|
expect(core).not.toContain("from './i18n/utils'");
|
|
27
|
-
expect(
|
|
28
|
-
expect(
|
|
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')");
|
|
29
32
|
});
|
|
30
33
|
|
|
31
34
|
test('keeps the Modern i18n context stable across federated runtime copies', () => {
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { describe, expect, test } from '@rstest/core';
|
|
2
|
+
import { shouldIgnoreRedirect as shouldIgnoreRuntimeRedirect } from '../src/runtime/utils';
|
|
3
|
+
import {
|
|
4
|
+
isStaticResourceRequest,
|
|
5
|
+
shouldIgnoreRedirect as shouldIgnoreServerRedirect,
|
|
6
|
+
} from '../src/server/redirectPolicy';
|
|
7
|
+
|
|
8
|
+
const languages = ['en', 'cs'];
|
|
9
|
+
|
|
10
|
+
const defaultSkippedPaths = [
|
|
11
|
+
'/backend-mf-manifest.json',
|
|
12
|
+
'/backendRemoteEntry.cjs',
|
|
13
|
+
'/mf-manifest.json',
|
|
14
|
+
'/mf-stats.json',
|
|
15
|
+
'/remoteEntry.js',
|
|
16
|
+
'/static/app.js',
|
|
17
|
+
'/upload/avatar.png',
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
describe('locale redirect default skip policy', () => {
|
|
21
|
+
test('skips ADR-0002 Module Federation and static endpoints on the server', () => {
|
|
22
|
+
for (const pathname of defaultSkippedPaths) {
|
|
23
|
+
expect(isStaticResourceRequest(pathname, [], languages)).toBe(true);
|
|
24
|
+
expect(shouldIgnoreServerRedirect(pathname, '/', undefined)).toBe(true);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('skips language-prefixed static and upload endpoints', () => {
|
|
29
|
+
expect(isStaticResourceRequest('/cs/static/app.js', [], languages)).toBe(
|
|
30
|
+
true,
|
|
31
|
+
);
|
|
32
|
+
expect(
|
|
33
|
+
isStaticResourceRequest('/en/upload/avatar.png', [], languages),
|
|
34
|
+
).toBe(true);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test('uses the same default skip policy in runtime redirects', () => {
|
|
38
|
+
for (const pathname of defaultSkippedPaths) {
|
|
39
|
+
expect(shouldIgnoreRuntimeRedirect(pathname, languages)).toBe(true);
|
|
40
|
+
expect(shouldIgnoreRuntimeRedirect(`/cs${pathname}`, languages)).toBe(
|
|
41
|
+
true,
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
});
|