nuxt-i18n-micro 2.1.0 → 2.3.0
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/client/200.html +2 -2
- package/dist/client/404.html +2 -2
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/1f0be1c2-48e6-40e6-8faf-6f8e0f051970.json +1 -0
- package/dist/client/index.html +2 -2
- package/dist/module.json +1 -1
- package/dist/module.mjs +136 -26
- package/dist/runtime/components/i18n-t.vue +11 -11
- package/dist/runtime/components/locale-redirect.vue +1 -1
- package/dist/runtime/plugins/01.plugin.js +3 -1
- package/dist/runtime/plugins/06.redirect.js +46 -10
- package/package.json +2 -2
- package/dist/client/_nuxt/builds/meta/df79903a-9996-4527-8269-e47de875a594.json +0 -1
package/dist/client/200.html
CHANGED
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
<link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/CBxwnKtU.js">
|
|
9
9
|
<link rel="prefetch" as="style" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/error-500.BqKd8Zt-.css">
|
|
10
10
|
<link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/BYEpoBUk.js">
|
|
11
|
-
<script type="module" src="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/XZXfxmri.js" crossorigin></script></head><body><div id="__nuxt"></div><div id="teleports"></div><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},
|
|
12
|
-
<script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__NUXT_DEVTOOLS_I18N_BASE__/",buildId:"
|
|
11
|
+
<script type="module" src="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/XZXfxmri.js" crossorigin></script></head><body><div id="__nuxt"></div><div id="teleports"></div><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1762281061506,false]</script>
|
|
12
|
+
<script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__NUXT_DEVTOOLS_I18N_BASE__/",buildId:"1f0be1c2-48e6-40e6-8faf-6f8e0f051970",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
|
package/dist/client/404.html
CHANGED
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
<link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/CBxwnKtU.js">
|
|
9
9
|
<link rel="prefetch" as="style" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/error-500.BqKd8Zt-.css">
|
|
10
10
|
<link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/BYEpoBUk.js">
|
|
11
|
-
<script type="module" src="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/XZXfxmri.js" crossorigin></script></head><body><div id="__nuxt"></div><div id="teleports"></div><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},
|
|
12
|
-
<script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__NUXT_DEVTOOLS_I18N_BASE__/",buildId:"
|
|
11
|
+
<script type="module" src="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/XZXfxmri.js" crossorigin></script></head><body><div id="__nuxt"></div><div id="teleports"></div><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1762281061507,false]</script>
|
|
12
|
+
<script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__NUXT_DEVTOOLS_I18N_BASE__/",buildId:"1f0be1c2-48e6-40e6-8faf-6f8e0f051970",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"id":"
|
|
1
|
+
{"id":"1f0be1c2-48e6-40e6-8faf-6f8e0f051970","timestamp":1762281055061}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"id":"1f0be1c2-48e6-40e6-8faf-6f8e0f051970","timestamp":1762281055061,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":[]}
|
package/dist/client/index.html
CHANGED
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
<link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/CBxwnKtU.js">
|
|
9
9
|
<link rel="prefetch" as="style" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/error-500.BqKd8Zt-.css">
|
|
10
10
|
<link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/BYEpoBUk.js">
|
|
11
|
-
<script type="module" src="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/XZXfxmri.js" crossorigin></script></head><body><div id="__nuxt"></div><div id="teleports"></div><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},
|
|
12
|
-
<script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__NUXT_DEVTOOLS_I18N_BASE__/",buildId:"
|
|
11
|
+
<script type="module" src="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/XZXfxmri.js" crossorigin></script></head><body><div id="__nuxt"></div><div id="teleports"></div><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1762281061507,false]</script>
|
|
12
|
+
<script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__NUXT_DEVTOOLS_I18N_BASE__/",buildId:"1f0be1c2-48e6-40e6-8faf-6f8e0f051970",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -199,6 +199,19 @@ function extractDefineI18nRouteData(content, _filePath) {
|
|
|
199
199
|
return null;
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
|
+
function normalizeRouteKey(key) {
|
|
203
|
+
return key.split("/").map((segment) => {
|
|
204
|
+
if (segment.startsWith("[...") && segment.endsWith("]")) {
|
|
205
|
+
const paramName = segment.substring(4, segment.length - 1);
|
|
206
|
+
return `:${paramName}(.*)*`;
|
|
207
|
+
}
|
|
208
|
+
if (segment.startsWith("[") && segment.endsWith("]")) {
|
|
209
|
+
const paramName = segment.substring(1, segment.length - 1);
|
|
210
|
+
return `:${paramName}`;
|
|
211
|
+
}
|
|
212
|
+
return segment;
|
|
213
|
+
}).join("/");
|
|
214
|
+
}
|
|
202
215
|
const normalizePath = (routePath) => {
|
|
203
216
|
if (!routePath) {
|
|
204
217
|
return "";
|
|
@@ -249,7 +262,22 @@ class PageManager {
|
|
|
249
262
|
this.noPrefixRedirect = noPrefixRedirect;
|
|
250
263
|
this.excludePatterns = excludePatterns;
|
|
251
264
|
this.activeLocaleCodes = this.computeActiveLocaleCodes();
|
|
252
|
-
|
|
265
|
+
const normalizedGlobalRoutes = {};
|
|
266
|
+
for (const key in globalLocaleRoutes) {
|
|
267
|
+
const newKey = normalizeRouteKey(key);
|
|
268
|
+
const localePaths = globalLocaleRoutes[key];
|
|
269
|
+
if (typeof localePaths === "object") {
|
|
270
|
+
const normalizedLocalePaths = {};
|
|
271
|
+
for (const locale in localePaths) {
|
|
272
|
+
const customPath = localePaths[locale];
|
|
273
|
+
normalizedLocalePaths[locale] = normalizeRouteKey(customPath);
|
|
274
|
+
}
|
|
275
|
+
normalizedGlobalRoutes[newKey] = normalizedLocalePaths;
|
|
276
|
+
} else {
|
|
277
|
+
normalizedGlobalRoutes[newKey] = localePaths;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
this.globalLocaleRoutes = normalizedGlobalRoutes;
|
|
253
281
|
this.filesLocaleRoutes = filesLocaleRoutes || {};
|
|
254
282
|
this.routeLocales = routeLocales || {};
|
|
255
283
|
}
|
|
@@ -279,22 +307,76 @@ class PageManager {
|
|
|
279
307
|
extendPages(pages, customRegex, isCloudflarePages) {
|
|
280
308
|
this.localizedPaths = this.extractLocalizedPaths(pages);
|
|
281
309
|
const additionalRoutes = [];
|
|
310
|
+
const originalPagePaths = /* @__PURE__ */ new Map();
|
|
282
311
|
for (const page of [...pages]) {
|
|
312
|
+
if (isPageRedirectOnly(page)) {
|
|
313
|
+
continue;
|
|
314
|
+
}
|
|
283
315
|
if (page.path && isInternalPath(page.path, this.excludePatterns)) {
|
|
284
316
|
continue;
|
|
285
317
|
}
|
|
286
|
-
|
|
287
|
-
|
|
318
|
+
const originalPath = page.path ?? "";
|
|
319
|
+
originalPagePaths.set(page, originalPath);
|
|
320
|
+
const pageName = buildRouteNameFromRoute(page.name, page.path);
|
|
321
|
+
const normalizedOriginalPath = normalizeRouteKey(originalPath);
|
|
322
|
+
const customPaths = this.localizedPaths[originalPath] || this.localizedPaths[pageName];
|
|
323
|
+
const isLocalizationDisabled = this.globalLocaleRoutes[pageName] === false || this.globalLocaleRoutes[normalizedOriginalPath] === false;
|
|
324
|
+
if (isLocalizationDisabled) {
|
|
325
|
+
continue;
|
|
288
326
|
}
|
|
289
|
-
const
|
|
290
|
-
|
|
327
|
+
const allowedLocales = this.getAllowedLocalesForPage(originalPath, pageName);
|
|
328
|
+
const originalChildren = cloneArray(page.children ?? []);
|
|
329
|
+
if (isNoPrefixStrategy(this.strategy)) {
|
|
330
|
+
if (customPaths) {
|
|
331
|
+
this.locales.forEach((locale) => {
|
|
332
|
+
const customPath = customPaths[locale.code];
|
|
333
|
+
if (customPath && allowedLocales.includes(locale.code)) {
|
|
334
|
+
const newRoute = this.createLocalizedRoute(page, [locale.code], originalChildren, true, customPath, customRegex, false, locale.code, originalPath);
|
|
335
|
+
if (newRoute) {
|
|
336
|
+
additionalRoutes.push(newRoute);
|
|
337
|
+
if (this.noPrefixRedirect && locale.code === this.defaultLocale.code) {
|
|
338
|
+
page.redirect = normalizePath(customPath);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
this.handleAliasRoutes(page, additionalRoutes, customRegex, allowedLocales);
|
|
291
345
|
continue;
|
|
292
346
|
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
this.
|
|
347
|
+
const defaultLocaleCode = this.defaultLocale.code;
|
|
348
|
+
if (allowedLocales.includes(defaultLocaleCode)) {
|
|
349
|
+
const customPath = customPaths?.[defaultLocaleCode];
|
|
350
|
+
if (isPrefixExceptDefaultStrategy(this.strategy)) {
|
|
351
|
+
if (customPath) {
|
|
352
|
+
page.path = normalizePath(customPath);
|
|
353
|
+
}
|
|
354
|
+
page.children = this.createLocalizedChildren(originalChildren, originalPath, [defaultLocaleCode], false, false, false, customPath ? { [defaultLocaleCode]: customPath } : {});
|
|
355
|
+
}
|
|
297
356
|
}
|
|
357
|
+
const localesToGenerate = this.locales.filter((l) => {
|
|
358
|
+
if (!allowedLocales.includes(l.code)) return false;
|
|
359
|
+
if (isPrefixExceptDefaultStrategy(this.strategy) && l.code === defaultLocaleCode) return false;
|
|
360
|
+
return true;
|
|
361
|
+
});
|
|
362
|
+
if (localesToGenerate.length > 0) {
|
|
363
|
+
if (customPaths) {
|
|
364
|
+
localesToGenerate.forEach((locale) => {
|
|
365
|
+
if (customPaths[locale.code]) {
|
|
366
|
+
const newRoute = this.createLocalizedRoute(page, [locale.code], originalChildren, true, customPaths[locale.code], customRegex, false, locale.code, originalPath);
|
|
367
|
+
if (newRoute) additionalRoutes.push(newRoute);
|
|
368
|
+
} else {
|
|
369
|
+
const newRoute = this.createLocalizedRoute(page, [locale.code], originalChildren, false, "", customRegex, false, locale.code, originalPath);
|
|
370
|
+
if (newRoute) additionalRoutes.push(newRoute);
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
} else {
|
|
374
|
+
const localeCodes = localesToGenerate.map((l) => l.code);
|
|
375
|
+
const newRoute = this.createLocalizedRoute(page, localeCodes, originalChildren, false, "", customRegex, false, true, originalPath);
|
|
376
|
+
if (newRoute) additionalRoutes.push(newRoute);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
this.handleAliasRoutes(page, additionalRoutes, customRegex, allowedLocales);
|
|
298
380
|
}
|
|
299
381
|
if (isPrefixStrategy(this.strategy) && !isCloudflarePages) {
|
|
300
382
|
for (let i = pages.length - 1; i >= 0; i--) {
|
|
@@ -316,7 +398,8 @@ class PageManager {
|
|
|
316
398
|
pages.forEach((page) => {
|
|
317
399
|
const pageName = buildRouteNameFromRoute(page.name, page.path);
|
|
318
400
|
const normalizedFullPath = normalizePath(path.posix.join(parentPath, page.path));
|
|
319
|
-
const
|
|
401
|
+
const normalizedKey = normalizeRouteKey(normalizedFullPath);
|
|
402
|
+
const globalLocalePath = this.globalLocaleRoutes[normalizedKey] || this.globalLocaleRoutes[pageName];
|
|
320
403
|
if (!globalLocalePath) {
|
|
321
404
|
const filesLocalePath = this.filesLocaleRoutes[pageName];
|
|
322
405
|
if (filesLocalePath && typeof filesLocalePath === "object") {
|
|
@@ -564,16 +647,17 @@ class PageManager {
|
|
|
564
647
|
}
|
|
565
648
|
return baseName;
|
|
566
649
|
}
|
|
567
|
-
createLocalizedRoute(page, localeCodes, originalChildren, isCustom, customPath = "", customRegex, force = false, parentLocale = false) {
|
|
650
|
+
createLocalizedRoute(page, localeCodes, originalChildren, isCustom, customPath = "", customRegex, force = false, parentLocale = false, originalPagePath) {
|
|
568
651
|
const routePath = this.buildRoutePath(localeCodes, page.path, encodeURI(customPath), isCustom, customRegex, force);
|
|
569
|
-
if (!routePath || routePath
|
|
652
|
+
if (!routePath || routePath === page.path) return null;
|
|
570
653
|
if (localeCodes.length === 0) return null;
|
|
571
654
|
const firstLocale = localeCodes[0];
|
|
572
655
|
if (!firstLocale) return null;
|
|
573
|
-
const
|
|
656
|
+
const parentPathForChildren = originalPagePath ?? page.path ?? "";
|
|
657
|
+
const routeName = buildRouteName(buildRouteNameFromRoute(page.name ?? "", parentPathForChildren), firstLocale, isCustom);
|
|
574
658
|
return {
|
|
575
659
|
...page,
|
|
576
|
-
children: this.createLocalizedChildren(originalChildren,
|
|
660
|
+
children: this.createLocalizedChildren(originalChildren, parentPathForChildren, localeCodes, true, false, parentLocale, { [firstLocale]: customPath }),
|
|
577
661
|
path: routePath,
|
|
578
662
|
name: routeName,
|
|
579
663
|
alias: [],
|
|
@@ -787,6 +871,9 @@ const module = defineNuxtModule({
|
|
|
787
871
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
788
872
|
// @ts-ignore
|
|
789
873
|
routeDisableMeta,
|
|
874
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
875
|
+
// @ts-ignore
|
|
876
|
+
globalLocaleRoutes: mergedGlobalLocaleRoutes,
|
|
790
877
|
experimental: {
|
|
791
878
|
i18nPreviousPageFallback: options.experimental?.i18nPreviousPageFallback ?? false,
|
|
792
879
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
@@ -947,16 +1034,33 @@ ${accepts}
|
|
|
947
1034
|
localeManager.ensureTranslationFilesExist(pagesNames, options.translationDir, nuxt.options.rootDir);
|
|
948
1035
|
}
|
|
949
1036
|
pageManager.extendPages(pages, options.customRegexMatcher, isCloudflarePages);
|
|
950
|
-
if (
|
|
951
|
-
const
|
|
952
|
-
|
|
953
|
-
name
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
globalLocaleRoutes: options.globalLocaleRoutes
|
|
1037
|
+
if (!isCloudflarePages) {
|
|
1038
|
+
const strategy = options.strategy;
|
|
1039
|
+
if (isPrefixStrategy(strategy)) {
|
|
1040
|
+
const rootPageIndex = pages.findIndex((page) => page.name === "index" && page.path === "/");
|
|
1041
|
+
if (rootPageIndex > -1) {
|
|
1042
|
+
pages.splice(rootPageIndex, 1);
|
|
957
1043
|
}
|
|
958
|
-
|
|
959
|
-
|
|
1044
|
+
const fallbackRoute = {
|
|
1045
|
+
path: "/:pathMatch(.*)*",
|
|
1046
|
+
name: "custom-fallback-route",
|
|
1047
|
+
file: resolver.resolve("./runtime/components/locale-redirect.vue")
|
|
1048
|
+
};
|
|
1049
|
+
pages.push(fallbackRoute);
|
|
1050
|
+
logger.info("Strategy 'prefix': Added fallback route to redirect all non-prefixed paths.");
|
|
1051
|
+
}
|
|
1052
|
+
const needsFallback = isPrefixStrategy(options.strategy) || isPrefixExceptDefaultStrategy(options.strategy);
|
|
1053
|
+
if (needsFallback) {
|
|
1054
|
+
const fallbackRoute = {
|
|
1055
|
+
path: "/:pathMatch(.*)*",
|
|
1056
|
+
name: "custom-fallback-route",
|
|
1057
|
+
file: resolver.resolve("./runtime/components/locale-redirect.vue"),
|
|
1058
|
+
meta: {
|
|
1059
|
+
globalLocaleRoutes: options.globalLocaleRoutes
|
|
1060
|
+
}
|
|
1061
|
+
};
|
|
1062
|
+
pages.push(fallbackRoute);
|
|
1063
|
+
}
|
|
960
1064
|
}
|
|
961
1065
|
if (!isNoPrefixStrategy(options.strategy)) {
|
|
962
1066
|
if (isCloudflarePages) {
|
|
@@ -993,7 +1097,9 @@ ${accepts}
|
|
|
993
1097
|
}
|
|
994
1098
|
}
|
|
995
1099
|
if (page.children && page.children.length) {
|
|
996
|
-
page.children.forEach((childPage) =>
|
|
1100
|
+
page.children.forEach((childPage) => {
|
|
1101
|
+
processPageWithChildren(childPage, fullPath);
|
|
1102
|
+
});
|
|
997
1103
|
}
|
|
998
1104
|
};
|
|
999
1105
|
pages.forEach((page) => {
|
|
@@ -1104,7 +1210,9 @@ ${accepts}
|
|
|
1104
1210
|
routesToRemove.push(route);
|
|
1105
1211
|
}
|
|
1106
1212
|
});
|
|
1107
|
-
routesToRemove.forEach((route) =>
|
|
1213
|
+
routesToRemove.forEach((route) => {
|
|
1214
|
+
routesSet.delete(route);
|
|
1215
|
+
});
|
|
1108
1216
|
const additionalRoutes = /* @__PURE__ */ new Set();
|
|
1109
1217
|
const routeRules = nuxt.options.routeRules || {};
|
|
1110
1218
|
routesSet.forEach((route) => {
|
|
@@ -1131,7 +1239,9 @@ ${accepts}
|
|
|
1131
1239
|
});
|
|
1132
1240
|
}
|
|
1133
1241
|
});
|
|
1134
|
-
additionalRoutes.forEach((route) =>
|
|
1242
|
+
additionalRoutes.forEach((route) => {
|
|
1243
|
+
routesSet.add(route);
|
|
1244
|
+
});
|
|
1135
1245
|
});
|
|
1136
1246
|
if (nuxt.options.dev) {
|
|
1137
1247
|
setupDevToolsUI(options, resolver.resolve);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import { h, defineComponent } from "vue";
|
|
2
|
+
import { h as hyperscript, defineComponent } from "vue";
|
|
3
3
|
import { useNuxtApp, useRoute } from "#imports";
|
|
4
4
|
export default defineComponent({
|
|
5
5
|
name: "I18nT",
|
|
@@ -53,18 +53,18 @@ export default defineComponent({
|
|
|
53
53
|
const $t = $_t(route);
|
|
54
54
|
if (props.number !== void 0) {
|
|
55
55
|
const numberValue = Number(props.number);
|
|
56
|
-
return
|
|
56
|
+
return hyperscript(props.tag, { ...attrs, innerHTML: $t(props.keypath, { number: $tn(numberValue) }) });
|
|
57
57
|
}
|
|
58
58
|
if (props.date !== void 0) {
|
|
59
|
-
return
|
|
59
|
+
return hyperscript(props.tag, { ...attrs, innerHTML: $t(props.keypath, { date: $td(props.date) }) });
|
|
60
60
|
}
|
|
61
61
|
if (props.relativeDate !== void 0) {
|
|
62
|
-
return
|
|
62
|
+
return hyperscript(props.tag, { ...attrs, innerHTML: $t(props.keypath, { relativeDate: $tdr(props.relativeDate) }) });
|
|
63
63
|
}
|
|
64
64
|
if (props.plural !== void 0) {
|
|
65
65
|
const count = Number.parseInt(props.plural.toString());
|
|
66
66
|
if (props.customPluralRule) {
|
|
67
|
-
return
|
|
67
|
+
return hyperscript(props.tag, { ...attrs, innerHTML: props.customPluralRule(
|
|
68
68
|
props.keypath,
|
|
69
69
|
count,
|
|
70
70
|
props.params,
|
|
@@ -72,7 +72,7 @@ export default defineComponent({
|
|
|
72
72
|
$t
|
|
73
73
|
) });
|
|
74
74
|
} else {
|
|
75
|
-
return
|
|
75
|
+
return hyperscript(props.tag, { ...attrs, innerHTML: $tc(props.keypath, { count, ...props.params }) });
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
const translation = ($t(props.keypath, { ...props.params, ...options }) ?? "").toString();
|
|
@@ -80,10 +80,10 @@ export default defineComponent({
|
|
|
80
80
|
return props.defaultValue ?? null;
|
|
81
81
|
}
|
|
82
82
|
if (props.html) {
|
|
83
|
-
return
|
|
83
|
+
return hyperscript(props.tag, { ...attrs, innerHTML: translation });
|
|
84
84
|
}
|
|
85
85
|
if (slots.default) {
|
|
86
|
-
return
|
|
86
|
+
return hyperscript(
|
|
87
87
|
props.tag,
|
|
88
88
|
attrs,
|
|
89
89
|
slots.default({ translation })
|
|
@@ -98,7 +98,7 @@ export default defineComponent({
|
|
|
98
98
|
if (index > lastIndex) {
|
|
99
99
|
children.push(translation.slice(lastIndex, index));
|
|
100
100
|
}
|
|
101
|
-
children.push(
|
|
101
|
+
children.push(hyperscript(slotFn));
|
|
102
102
|
lastIndex = index + placeholder.length;
|
|
103
103
|
}
|
|
104
104
|
}
|
|
@@ -106,13 +106,13 @@ export default defineComponent({
|
|
|
106
106
|
children.push(translation.slice(lastIndex));
|
|
107
107
|
}
|
|
108
108
|
if (slots.default) {
|
|
109
|
-
return
|
|
109
|
+
return hyperscript(
|
|
110
110
|
props.tag,
|
|
111
111
|
attrs,
|
|
112
112
|
slots.default({ children })
|
|
113
113
|
);
|
|
114
114
|
}
|
|
115
|
-
return
|
|
115
|
+
return hyperscript(props.tag, attrs, children);
|
|
116
116
|
};
|
|
117
117
|
}
|
|
118
118
|
});
|
|
@@ -52,7 +52,7 @@ if (globalLocaleRoutes && globalLocaleRoutes[currentPageName]) {
|
|
|
52
52
|
} else if (locales.includes(firstSegment) && globalLocaleRoutes && globalLocaleRoutes[currentLocalePageName]) {
|
|
53
53
|
const localizedRoutes = globalLocaleRoutes[currentLocalePageName];
|
|
54
54
|
if (localizedRoutes && localizedRoutes[firstSegment]) {
|
|
55
|
-
const localizedPath = `/${firstSegment}
|
|
55
|
+
const localizedPath = `/${firstSegment}/${localizedRoutes[firstSegment]}`;
|
|
56
56
|
if (route.fullPath !== localizedPath) {
|
|
57
57
|
handleRedirect(localizedPath);
|
|
58
58
|
}
|
|
@@ -46,7 +46,6 @@ export default defineNuxtPlugin(async (nuxtApp) => {
|
|
|
46
46
|
const enablePreviousPageFallback = i18nConfig.experimental?.i18nPreviousPageFallback ?? false;
|
|
47
47
|
nuxtApp.hook("page:finish", () => {
|
|
48
48
|
if (import.meta.client) {
|
|
49
|
-
i18nRouteParams.value = null;
|
|
50
49
|
previousPageInfo.value = null;
|
|
51
50
|
}
|
|
52
51
|
});
|
|
@@ -83,6 +82,9 @@ export default defineNuxtPlugin(async (nuxtApp) => {
|
|
|
83
82
|
}
|
|
84
83
|
}
|
|
85
84
|
router.beforeEach(async (to, from, next) => {
|
|
85
|
+
if (to.name !== from.name) {
|
|
86
|
+
i18nRouteParams.value = {};
|
|
87
|
+
}
|
|
86
88
|
if (to.path === from.path && !isNoPrefixStrategy(i18nConfig.strategy)) {
|
|
87
89
|
if (next) next();
|
|
88
90
|
return;
|
|
@@ -1,30 +1,64 @@
|
|
|
1
1
|
import { isNoPrefixStrategy, isPrefixStrategy } from "nuxt-i18n-micro-core";
|
|
2
2
|
import { defineNuxtPlugin, useRuntimeConfig, useRoute, useRouter, navigateTo, createError } from "#imports";
|
|
3
3
|
import { findAllowedLocalesForRoute } from "../utils/route-utils.js";
|
|
4
|
+
import { joinURL, withQuery } from "ufo";
|
|
5
|
+
function resolvePathWithParams(path, params) {
|
|
6
|
+
let resolvedPath = path;
|
|
7
|
+
for (const key in params) {
|
|
8
|
+
const value = params[key];
|
|
9
|
+
if (value) {
|
|
10
|
+
const stringValue = String(value);
|
|
11
|
+
resolvedPath = resolvedPath.replace(`:${key}()`, stringValue).replace(`:${key}`, stringValue);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return resolvedPath;
|
|
15
|
+
}
|
|
4
16
|
export default defineNuxtPlugin(async (nuxtApp) => {
|
|
5
17
|
const config = useRuntimeConfig();
|
|
6
18
|
const i18nConfig = config.public.i18nConfig;
|
|
7
|
-
const { routeLocales } = useRuntimeConfig().public.i18nConfig;
|
|
19
|
+
const { routeLocales, globalLocaleRoutes } = useRuntimeConfig().public.i18nConfig;
|
|
8
20
|
const route = useRoute();
|
|
9
21
|
const router = useRouter();
|
|
22
|
+
const checkGlobalLocaleRoutes = (to) => {
|
|
23
|
+
if (!globalLocaleRoutes || typeof globalLocaleRoutes !== "object" || Object.keys(globalLocaleRoutes).length === 0) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
const locales = i18nConfig.locales?.map((l) => l.code) || [];
|
|
27
|
+
const defaultLocale = i18nConfig.defaultLocale || "en";
|
|
28
|
+
const pathSegments = to.path.split("/").filter(Boolean);
|
|
29
|
+
const firstSegment = pathSegments[0];
|
|
30
|
+
const pathWithoutLocale = locales.includes(firstSegment) ? "/" + pathSegments.slice(1).join("/") : to.path;
|
|
31
|
+
const routeName = (typeof to.name === "string" ? to.name : "").replace("localized-", "").replace(new RegExp(`-(${locales.join("|")})$`), "");
|
|
32
|
+
const routeRules = globalLocaleRoutes[pathWithoutLocale] || globalLocaleRoutes[routeName];
|
|
33
|
+
if (routeRules && typeof routeRules === "object") {
|
|
34
|
+
const localeToUse = locales.includes(firstSegment) ? firstSegment : defaultLocale;
|
|
35
|
+
const customPathSegment = routeRules[localeToUse];
|
|
36
|
+
if (customPathSegment) {
|
|
37
|
+
const resolvedCustomPath = resolvePathWithParams(customPathSegment, to.params);
|
|
38
|
+
const localizedPath = locales.includes(firstSegment) ? joinURL(`/${firstSegment}`, resolvedCustomPath) : resolvedCustomPath;
|
|
39
|
+
if (decodeURI(to.path) !== decodeURI(localizedPath)) {
|
|
40
|
+
const finalUrl = withQuery(localizedPath, to.query);
|
|
41
|
+
navigateTo(finalUrl, { redirectCode: 301, external: true });
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
} else if (locales.includes(firstSegment)) {
|
|
45
|
+
throw createError({ statusCode: 404, statusMessage: "Page Not Found" });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
49
|
+
};
|
|
10
50
|
const checkRouteLocales = (to) => {
|
|
11
51
|
const allowedLocales = findAllowedLocalesForRoute(to, routeLocales);
|
|
12
|
-
if (!allowedLocales || allowedLocales.length === 0)
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
52
|
+
if (!allowedLocales || allowedLocales.length === 0) return;
|
|
15
53
|
const pathSegments = to.path.split("/").filter(Boolean);
|
|
16
54
|
const firstSegment = pathSegments[0];
|
|
17
55
|
const allLocales = i18nConfig.locales?.map((l) => l.code) || [];
|
|
18
56
|
if (firstSegment && allLocales.includes(firstSegment) && !allowedLocales.includes(firstSegment)) {
|
|
19
|
-
|
|
20
|
-
throw createError({
|
|
21
|
-
statusCode: 404,
|
|
22
|
-
statusMessage: "Page Not Found"
|
|
23
|
-
});
|
|
57
|
+
throw createError({ statusCode: 404, statusMessage: "Page Not Found" });
|
|
24
58
|
}
|
|
25
59
|
};
|
|
26
60
|
const handleRedirect = async (to) => {
|
|
27
|
-
const currentLocale = nuxtApp.$getLocale()
|
|
61
|
+
const currentLocale = nuxtApp.$getLocale(to);
|
|
28
62
|
const name = to.name?.toString();
|
|
29
63
|
let defaultRouteName = name?.toString().replace("localized-", "").replace(new RegExp(`-${currentLocale}$`), "");
|
|
30
64
|
if (!to.params.locale) {
|
|
@@ -45,12 +79,14 @@ export default defineNuxtPlugin(async (nuxtApp) => {
|
|
|
45
79
|
}
|
|
46
80
|
};
|
|
47
81
|
if (import.meta.server) {
|
|
82
|
+
if (checkGlobalLocaleRoutes(route)) return;
|
|
48
83
|
checkRouteLocales(route);
|
|
49
84
|
if (isPrefixStrategy(i18nConfig.strategy) || isNoPrefixStrategy(i18nConfig.strategy)) {
|
|
50
85
|
await handleRedirect(route);
|
|
51
86
|
}
|
|
52
87
|
}
|
|
53
88
|
router.beforeEach(async (to, from, next) => {
|
|
89
|
+
if (checkGlobalLocaleRoutes(to)) return;
|
|
54
90
|
if (from.path !== to.path) {
|
|
55
91
|
checkRouteLocales(to);
|
|
56
92
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-i18n-micro",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "Nuxt I18n Micro is a lightweight, high-performance internationalization module for Nuxt, designed to handle multi-language support with minimal overhead, fast build times, and efficient runtime performance.",
|
|
5
5
|
"repository": "s00d/nuxt-i18n-micro",
|
|
6
6
|
"license": "MIT",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"globby": "^14.1.0",
|
|
62
62
|
"sirv": "^2.0.4",
|
|
63
63
|
"ufo": "^1.5.4",
|
|
64
|
-
"nuxt-i18n-micro-core": "1.0.
|
|
64
|
+
"nuxt-i18n-micro-core": "1.0.23",
|
|
65
65
|
"nuxt-i18n-micro-test-utils": "1.0.7",
|
|
66
66
|
"nuxt-i18n-micro-types": "1.0.12"
|
|
67
67
|
},
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"id":"df79903a-9996-4527-8269-e47de875a594","timestamp":1761933265840,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":[]}
|