nuxt-i18n-micro 1.61.0 → 1.63.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 +8 -8
- package/dist/client/404.html +8 -8
- package/dist/client/_nuxt/{EwNUkbJF.js → AXE8DZQI.js} +1 -1
- package/dist/client/_nuxt/{DuZjM2Ym.js → D9gx-VEt.js} +1 -1
- package/dist/client/_nuxt/{C9njAg9E.js → Ddb0iCRU.js} +55 -55
- package/dist/client/_nuxt/{BIRJeTBr.js → Deg2o1hP.js} +1 -1
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/c4f80d33-396e-44b9-86d2-e62d781c506f.json +1 -0
- package/dist/client/_nuxt/error-404.vh32VtAd.css +1 -0
- package/dist/client/_nuxt/error-500.EgQ3RNLZ.css +1 -0
- package/dist/client/index.html +8 -8
- package/dist/module.json +1 -1
- package/dist/module.mjs +152 -52
- package/dist/runtime/composables/useLocaleHead.js +7 -2
- package/dist/runtime/plugins/01.plugin.d.ts +3 -3
- package/dist/runtime/plugins/01.plugin.js +130 -108
- package/dist/runtime/server/routes/get.js +17 -0
- package/dist/runtime/translation-server-middleware.js +4 -5
- package/package.json +11 -10
- package/dist/client/_nuxt/builds/meta/019df560-5b4f-4d25-8ca1-a8cad935e3d2.json +0 -1
- package/dist/client/_nuxt/error-404.C8aNxDEl.css +0 -1
- package/dist/client/_nuxt/error-500.C2JGrgZX.css +0 -1
- package/dist/runtime/server/middleware/i18n-loader.js +0 -61
- /package/dist/runtime/server/{middleware/i18n-loader.d.ts → routes/get.d.ts} +0 -0
|
@@ -1,12 +1,21 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useTranslationHelper, interpolate } from "nuxt-i18n-micro-core";
|
|
2
2
|
import { isNoPrefixStrategy, withPrefixStrategy } from "../helpers.js";
|
|
3
3
|
import { defineNuxtPlugin, useRuntimeConfig } from "#app";
|
|
4
|
-
import {
|
|
4
|
+
import { useRouter, useCookie, useState, navigateTo } from "#imports";
|
|
5
5
|
import { plural } from "#build/i18n.plural.mjs";
|
|
6
6
|
const i18nHelper = useTranslationHelper();
|
|
7
7
|
const isDev = process.env.NODE_ENV !== "production";
|
|
8
|
-
function
|
|
9
|
-
|
|
8
|
+
function getCurrentLocale(route, i18nConfig, hashLocale, noPrefixStrategy) {
|
|
9
|
+
if (i18nConfig.hashMode && hashLocale) {
|
|
10
|
+
return hashLocale;
|
|
11
|
+
}
|
|
12
|
+
if (isNoPrefixStrategy(i18nConfig.strategy) && noPrefixStrategy) {
|
|
13
|
+
return noPrefixStrategy;
|
|
14
|
+
}
|
|
15
|
+
return (route.params?.locale ?? i18nConfig.defaultLocale).toString();
|
|
16
|
+
}
|
|
17
|
+
function getCurrentName(route, i18nConfig, hashLocale, noPrefixStrategy) {
|
|
18
|
+
const currentLocaleCode = getCurrentLocale(route, i18nConfig, hashLocale, noPrefixStrategy);
|
|
10
19
|
const checkLocale = i18nConfig.locales?.find((l) => l.code === currentLocaleCode);
|
|
11
20
|
if (!checkLocale) {
|
|
12
21
|
return null;
|
|
@@ -35,10 +44,6 @@ function switchLocaleRoute(fromLocale, toLocale, route, router, i18nConfig, i18n
|
|
|
35
44
|
if (router.hasRoute(`localized-${routeName}-${toLocale}`)) {
|
|
36
45
|
const newParams2 = { ...route.params, ...i18nRouteParams?.[toLocale] };
|
|
37
46
|
newParams2.locale = toLocale;
|
|
38
|
-
if (i18nConfig.hashMode) {
|
|
39
|
-
const userLocaleCookie = useCookie("hash-locale");
|
|
40
|
-
userLocaleCookie.value = toLocale;
|
|
41
|
-
}
|
|
42
47
|
const newRoute2 = {
|
|
43
48
|
name: `localized-${routeName}-${toLocale}`,
|
|
44
49
|
params: newParams2
|
|
@@ -61,10 +66,6 @@ function switchLocaleRoute(fromLocale, toLocale, route, router, i18nConfig, i18n
|
|
|
61
66
|
newParams.locale = toLocale;
|
|
62
67
|
}
|
|
63
68
|
}
|
|
64
|
-
if (i18nConfig.hashMode) {
|
|
65
|
-
const userLocaleCookie = useCookie("hash-locale");
|
|
66
|
-
userLocaleCookie.value = toLocale;
|
|
67
|
-
}
|
|
68
69
|
const newRoute = {
|
|
69
70
|
name: newRouteName,
|
|
70
71
|
params: newParams
|
|
@@ -80,11 +81,6 @@ function switchLocale(fromLocale, toLocale, route, router, i18nConfig, i18nRoute
|
|
|
80
81
|
console.warn(`Locale ${toLocale} is not available`);
|
|
81
82
|
return Promise.reject(`Locale ${toLocale} is not available`);
|
|
82
83
|
}
|
|
83
|
-
if (isNoPrefixStrategy(i18nConfig.strategy)) {
|
|
84
|
-
const userLocaleCookie = useCookie("no-prefix-locale");
|
|
85
|
-
userLocaleCookie.value = toLocale;
|
|
86
|
-
}
|
|
87
|
-
i18nHelper.setLocale(toLocale);
|
|
88
84
|
const switchedRoute = switchLocaleRoute(
|
|
89
85
|
fromLocale,
|
|
90
86
|
toLocale,
|
|
@@ -101,7 +97,7 @@ function switchLocale(fromLocale, toLocale, route, router, i18nConfig, i18nRoute
|
|
|
101
97
|
}
|
|
102
98
|
return router.push(switchedRoute);
|
|
103
99
|
}
|
|
104
|
-
function getLocalizedRoute(to, router, i18nConfig, locale) {
|
|
100
|
+
function getLocalizedRoute(to, router, route, i18nConfig, locale, hashLocale, noPrefixStrategy) {
|
|
105
101
|
const resolveParams = (to2) => {
|
|
106
102
|
const params = typeof to2 === "object" && "params" in to2 && typeof to2.params === "object" ? { ...to2.params } : {};
|
|
107
103
|
if (typeof to2 === "string") {
|
|
@@ -135,7 +131,7 @@ function getLocalizedRoute(to, router, i18nConfig, locale) {
|
|
|
135
131
|
});
|
|
136
132
|
}
|
|
137
133
|
}
|
|
138
|
-
const currentLocale = locale ||
|
|
134
|
+
const currentLocale = locale || getCurrentLocale(route, i18nConfig, hashLocale, noPrefixStrategy);
|
|
139
135
|
const selectRoute = router.resolve(to);
|
|
140
136
|
const routeName = getRouteName(selectRoute, currentLocale).replace(new RegExp(`-${i18nConfig.defaultLocale}$`), "");
|
|
141
137
|
if (!routeName || routeName === "") {
|
|
@@ -220,21 +216,21 @@ export default defineNuxtPlugin(async (nuxtApp) => {
|
|
|
220
216
|
const i18nConfig = config.public.i18nConfig;
|
|
221
217
|
const apiBaseUrl = i18nConfig.apiBaseUrl ?? "_locales";
|
|
222
218
|
const runtimeConfig = useRuntimeConfig();
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
if (currentNoPrefixDefault) {
|
|
230
|
-
i18nHelper.setLocale(currentNoPrefixDefault);
|
|
219
|
+
let hashLocaleDefault = null;
|
|
220
|
+
let noPrefixDefault = null;
|
|
221
|
+
if (i18nConfig.hashMode) {
|
|
222
|
+
hashLocaleDefault = await nuxtApp.runWithContext(() => {
|
|
223
|
+
return useCookie("hash-locale").value;
|
|
224
|
+
});
|
|
231
225
|
}
|
|
232
|
-
if (
|
|
233
|
-
|
|
226
|
+
if (isNoPrefixStrategy(i18nConfig.strategy)) {
|
|
227
|
+
noPrefixDefault = await nuxtApp.runWithContext(() => {
|
|
228
|
+
return useCookie("no-prefix-locale").value;
|
|
229
|
+
});
|
|
234
230
|
}
|
|
235
|
-
const loadTranslationsIfNeeded = async (routeName, path) => {
|
|
231
|
+
const loadTranslationsIfNeeded = async (locale, routeName, path) => {
|
|
236
232
|
try {
|
|
237
|
-
if (!i18nHelper.hasPageTranslation(routeName)) {
|
|
233
|
+
if (!i18nHelper.hasPageTranslation(locale, routeName)) {
|
|
238
234
|
let fRouteName = routeName;
|
|
239
235
|
if (i18nConfig.routesLocaleLinks && i18nConfig.routesLocaleLinks[fRouteName]) {
|
|
240
236
|
fRouteName = i18nConfig.routesLocaleLinks[fRouteName];
|
|
@@ -243,51 +239,54 @@ export default defineNuxtPlugin(async (nuxtApp) => {
|
|
|
243
239
|
console.warn(`[nuxt-i18n-next] The page name is missing in the path: ${path}. Please ensure that definePageMeta({ name: 'pageName' }) is set.`);
|
|
244
240
|
return;
|
|
245
241
|
}
|
|
246
|
-
const
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
-
|
|
242
|
+
const url = `/${apiBaseUrl}/${fRouteName}/${locale}/data.json`.replace(/\/{2,}/g, "/");
|
|
243
|
+
const data = await $fetch(url, {
|
|
244
|
+
baseURL: runtimeConfig.app.baseURL,
|
|
245
|
+
params: {
|
|
246
|
+
v: i18nConfig.dateBuild
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
await i18nHelper.loadPageTranslations(locale, routeName, data ?? {});
|
|
250
250
|
}
|
|
251
251
|
} catch (_error) {
|
|
252
252
|
}
|
|
253
253
|
};
|
|
254
254
|
async function loadGlobalTranslations(to) {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
if (
|
|
258
|
-
await nuxtApp.runWithContext(() => {
|
|
259
|
-
|
|
260
|
-
i18nHelper.setLocale(locale);
|
|
261
|
-
return true;
|
|
255
|
+
let hashLocale = null;
|
|
256
|
+
let noPrefixLocale = null;
|
|
257
|
+
if (i18nConfig.hashMode) {
|
|
258
|
+
hashLocale = await nuxtApp.runWithContext(() => {
|
|
259
|
+
return useCookie("hash-locale").value;
|
|
262
260
|
});
|
|
263
261
|
}
|
|
264
|
-
if (i18nConfig.
|
|
265
|
-
await nuxtApp.runWithContext(() => {
|
|
266
|
-
|
|
267
|
-
i18nHelper.setLocale(locale);
|
|
268
|
-
return true;
|
|
262
|
+
if (isNoPrefixStrategy(i18nConfig.strategy)) {
|
|
263
|
+
noPrefixLocale = await nuxtApp.runWithContext(() => {
|
|
264
|
+
return useCookie("no-prefix-locale").value;
|
|
269
265
|
});
|
|
270
266
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
const url = `/${apiBaseUrl}/general/${locale}/data.json
|
|
267
|
+
const locale = getCurrentLocale(to, i18nConfig, hashLocale, noPrefixLocale);
|
|
268
|
+
if (!i18nHelper.hasGeneralTranslation(locale)) {
|
|
269
|
+
const url = `/${apiBaseUrl}/general/${locale}/data.json`.replace(/\/{2,}/g, "/");
|
|
274
270
|
const data = await $fetch(url, {
|
|
275
|
-
baseURL: runtimeConfig.app.baseURL
|
|
271
|
+
baseURL: runtimeConfig.app.baseURL,
|
|
272
|
+
params: {
|
|
273
|
+
v: i18nConfig.dateBuild
|
|
274
|
+
}
|
|
276
275
|
});
|
|
277
|
-
await i18nHelper.loadTranslations(data ?? {});
|
|
276
|
+
await i18nHelper.loadTranslations(locale, data ?? {});
|
|
278
277
|
}
|
|
279
278
|
if (!i18nConfig.disablePageLocales) {
|
|
280
|
-
const routeName = getRouteName(to,
|
|
281
|
-
await loadTranslationsIfNeeded(routeName, to.fullPath);
|
|
279
|
+
const routeName = getRouteName(to, locale);
|
|
280
|
+
await loadTranslationsIfNeeded(locale, routeName, to.fullPath);
|
|
282
281
|
}
|
|
283
282
|
await nuxtApp.callHook("i18n:register", (translations, selectedLocale) => {
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
}, i18nHelper.getLocale());
|
|
283
|
+
const routeName = getRouteName(to, locale);
|
|
284
|
+
i18nHelper.mergeTranslation(selectedLocale ?? locale, routeName, translations, true);
|
|
285
|
+
}, locale);
|
|
288
286
|
}
|
|
287
|
+
const router = useRouter();
|
|
289
288
|
router.beforeEach(async (to, from, next) => {
|
|
290
|
-
if (to.
|
|
289
|
+
if (to.path !== from.path || isNoPrefixStrategy(i18nConfig.strategy)) {
|
|
291
290
|
await loadGlobalTranslations(to);
|
|
292
291
|
}
|
|
293
292
|
if (next) {
|
|
@@ -297,10 +296,10 @@ export default defineNuxtPlugin(async (nuxtApp) => {
|
|
|
297
296
|
await loadGlobalTranslations(router.currentRoute.value);
|
|
298
297
|
const getTranslation = (key, params, defaultValue) => {
|
|
299
298
|
if (!key) return "";
|
|
300
|
-
const
|
|
301
|
-
const
|
|
302
|
-
const routeName = getRouteName(
|
|
303
|
-
let value = i18nHelper.getTranslation(routeName, key);
|
|
299
|
+
const route = router.currentRoute.value;
|
|
300
|
+
const locale = getCurrentLocale(route, i18nConfig, hashLocaleDefault, noPrefixDefault);
|
|
301
|
+
const routeName = getRouteName(route, locale);
|
|
302
|
+
let value = i18nHelper.getTranslation(locale, routeName, key);
|
|
304
303
|
if (!value) {
|
|
305
304
|
if (isDev && import.meta.client) {
|
|
306
305
|
console.warn(`Not found '${key}' key in '${locale}' locale messages.`);
|
|
@@ -316,13 +315,14 @@ export default defineNuxtPlugin(async (nuxtApp) => {
|
|
|
316
315
|
const provideData = {
|
|
317
316
|
i18n: void 0,
|
|
318
317
|
__micro: true,
|
|
319
|
-
getLocale: () =>
|
|
320
|
-
getLocaleName: () => getCurrentName(i18nConfig),
|
|
318
|
+
getLocale: () => getCurrentLocale(router.currentRoute.value, i18nConfig, hashLocaleDefault, noPrefixDefault),
|
|
319
|
+
getLocaleName: () => getCurrentName(router.currentRoute.value, i18nConfig, hashLocaleDefault, noPrefixDefault),
|
|
321
320
|
defaultLocale: () => i18nConfig.defaultLocale,
|
|
322
321
|
getLocales: () => i18nConfig.locales || [],
|
|
323
|
-
getRouteName: (
|
|
324
|
-
const
|
|
325
|
-
|
|
322
|
+
getRouteName: (route, locale) => {
|
|
323
|
+
const selectedLocale = locale ?? getCurrentLocale(router.currentRoute.value, i18nConfig, hashLocaleDefault, noPrefixDefault);
|
|
324
|
+
const selectedRoute = route ?? router.currentRoute.value;
|
|
325
|
+
return getRouteName(selectedRoute, selectedLocale);
|
|
326
326
|
},
|
|
327
327
|
t: getTranslation,
|
|
328
328
|
ts: (key, params, defaultValue) => {
|
|
@@ -330,41 +330,49 @@ export default defineNuxtPlugin(async (nuxtApp) => {
|
|
|
330
330
|
return value?.toString() ?? defaultValue ?? key;
|
|
331
331
|
},
|
|
332
332
|
tc: (key, params, defaultValue) => {
|
|
333
|
-
const
|
|
333
|
+
const route = router.currentRoute.value;
|
|
334
|
+
const currentLocale = getCurrentLocale(route, i18nConfig, hashLocaleDefault, noPrefixDefault);
|
|
334
335
|
const { count, ..._params } = typeof params === "number" ? { count: params } : params;
|
|
335
|
-
return plural(key, Number.parseInt(count.toString()), _params,
|
|
336
|
+
return plural(key, Number.parseInt(count.toString()), _params, currentLocale, getTranslation) ?? defaultValue ?? key;
|
|
336
337
|
},
|
|
337
338
|
tn: (value, options) => {
|
|
338
|
-
const
|
|
339
|
+
const route = router.currentRoute.value;
|
|
340
|
+
const locale = getCurrentLocale(route, i18nConfig, hashLocaleDefault, noPrefixDefault);
|
|
339
341
|
return formatNumber(value, locale, options);
|
|
340
342
|
},
|
|
341
343
|
td: (value, options) => {
|
|
342
|
-
const
|
|
344
|
+
const route = router.currentRoute.value;
|
|
345
|
+
const locale = getCurrentLocale(route, i18nConfig, hashLocaleDefault, noPrefixDefault);
|
|
343
346
|
return formatDate(value, locale, options);
|
|
344
347
|
},
|
|
345
348
|
tdr(value, options) {
|
|
346
|
-
const
|
|
349
|
+
const route = router.currentRoute.value;
|
|
350
|
+
const locale = getCurrentLocale(route, i18nConfig, hashLocaleDefault, noPrefixDefault);
|
|
347
351
|
return formatRelativeTime(value, locale, options);
|
|
348
352
|
},
|
|
349
353
|
has: (key) => {
|
|
350
354
|
return !!getTranslation(key);
|
|
351
355
|
},
|
|
352
356
|
mergeTranslations: (newTranslations) => {
|
|
353
|
-
const
|
|
354
|
-
const locale = (
|
|
355
|
-
const routeName = getRouteName(
|
|
356
|
-
i18nHelper.mergeTranslation(routeName, newTranslations);
|
|
357
|
+
const route = router.currentRoute.value;
|
|
358
|
+
const locale = getCurrentLocale(route, i18nConfig, hashLocaleDefault, noPrefixDefault);
|
|
359
|
+
const routeName = getRouteName(route, locale);
|
|
360
|
+
i18nHelper.mergeTranslation(locale, routeName, newTranslations);
|
|
357
361
|
},
|
|
358
362
|
mergeGlobalTranslations: (newTranslations) => {
|
|
359
|
-
|
|
363
|
+
const route = router.currentRoute.value;
|
|
364
|
+
const locale = getCurrentLocale(route, i18nConfig, hashLocaleDefault, noPrefixDefault);
|
|
365
|
+
i18nHelper.mergeGlobalTranslation(locale, newTranslations, true);
|
|
360
366
|
},
|
|
361
367
|
switchLocaleRoute: (toLocale) => {
|
|
362
|
-
const
|
|
363
|
-
|
|
368
|
+
const route = router.currentRoute.value;
|
|
369
|
+
const fromLocale = getCurrentLocale(route, i18nConfig, hashLocaleDefault, noPrefixDefault);
|
|
370
|
+
return switchLocaleRoute(fromLocale, toLocale, route, router, i18nConfig, i18nRouteParams.value);
|
|
364
371
|
},
|
|
365
372
|
switchLocalePath: (toLocale) => {
|
|
366
|
-
const
|
|
367
|
-
const
|
|
373
|
+
const route = router.currentRoute.value;
|
|
374
|
+
const fromLocale = getCurrentLocale(route, i18nConfig, hashLocaleDefault, noPrefixDefault);
|
|
375
|
+
const localeRoute = switchLocaleRoute(fromLocale, toLocale, route, router, i18nConfig, i18nRouteParams.value);
|
|
368
376
|
if (typeof localeRoute === "string") {
|
|
369
377
|
return localeRoute;
|
|
370
378
|
}
|
|
@@ -374,46 +382,60 @@ export default defineNuxtPlugin(async (nuxtApp) => {
|
|
|
374
382
|
return "";
|
|
375
383
|
},
|
|
376
384
|
switchLocale: (toLocale) => {
|
|
377
|
-
const
|
|
378
|
-
|
|
385
|
+
const route = router.currentRoute.value;
|
|
386
|
+
const fromLocale = getCurrentLocale(route, i18nConfig, hashLocaleDefault, noPrefixDefault);
|
|
387
|
+
if (i18nConfig.hashMode) {
|
|
388
|
+
hashLocaleDefault = toLocale;
|
|
389
|
+
useCookie("hash-locale").value = toLocale;
|
|
390
|
+
}
|
|
391
|
+
if (isNoPrefixStrategy(i18nConfig.strategy)) {
|
|
392
|
+
noPrefixDefault = toLocale;
|
|
393
|
+
useCookie("no-prefix-locale").value = toLocale;
|
|
394
|
+
}
|
|
395
|
+
switchLocale(fromLocale, toLocale, route, router, i18nConfig, i18nRouteParams.value);
|
|
379
396
|
},
|
|
380
|
-
switchRoute: (
|
|
397
|
+
switchRoute: (route, toLocale) => {
|
|
381
398
|
const currentRoute = router.currentRoute.value;
|
|
382
|
-
const fromLocale = (currentRoute
|
|
383
|
-
const
|
|
384
|
-
if (typeof
|
|
385
|
-
if (
|
|
386
|
-
|
|
399
|
+
const fromLocale = getCurrentLocale(currentRoute, i18nConfig, hashLocaleDefault, noPrefixDefault);
|
|
400
|
+
const currentLocale = toLocale ?? fromLocale;
|
|
401
|
+
if (typeof route === "string") {
|
|
402
|
+
if (currentLocale !== i18nConfig.defaultLocale || withPrefixStrategy(i18nConfig.strategy)) {
|
|
403
|
+
const currentRoute2 = router.currentRoute.value;
|
|
404
|
+
const fromLocale2 = getCurrentLocale(currentRoute2, i18nConfig, hashLocaleDefault, noPrefixDefault);
|
|
405
|
+
route = router.resolve("/" + fromLocale2 + route);
|
|
387
406
|
} else {
|
|
388
|
-
|
|
407
|
+
route = router.resolve(route);
|
|
389
408
|
}
|
|
390
409
|
}
|
|
391
|
-
if (
|
|
392
|
-
|
|
410
|
+
if (i18nConfig.hashMode && toLocale && toLocale !== fromLocale) {
|
|
411
|
+
hashLocaleDefault = toLocale ?? fromLocale;
|
|
412
|
+
useCookie("hash-locale").value = hashLocaleDefault;
|
|
413
|
+
}
|
|
414
|
+
if (isNoPrefixStrategy(i18nConfig.strategy) && toLocale && toLocale !== fromLocale) {
|
|
415
|
+
noPrefixDefault = toLocale ?? fromLocale;
|
|
416
|
+
useCookie("no-prefix-locale").value = noPrefixDefault;
|
|
393
417
|
}
|
|
394
|
-
switchLocale(
|
|
395
|
-
i18nHelper.getLocale(),
|
|
396
|
-
toLocale ?? fromLocale,
|
|
397
|
-
to,
|
|
398
|
-
router,
|
|
399
|
-
i18nConfig,
|
|
400
|
-
i18nRouteParams.value
|
|
401
|
-
);
|
|
418
|
+
switchLocale(fromLocale, toLocale ?? fromLocale, route, router, i18nConfig, i18nRouteParams.value);
|
|
402
419
|
},
|
|
403
420
|
localeRoute: (to, locale) => {
|
|
404
|
-
const
|
|
405
|
-
const
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
421
|
+
const currentRoute = router.currentRoute.value;
|
|
422
|
+
const fromLocale = getCurrentLocale(currentRoute, i18nConfig, hashLocaleDefault, noPrefixDefault);
|
|
423
|
+
const currentLocale = locale ?? fromLocale;
|
|
424
|
+
if (typeof to === "string") {
|
|
425
|
+
if (currentLocale !== i18nConfig.defaultLocale || withPrefixStrategy(i18nConfig.strategy)) {
|
|
426
|
+
const currentRoute2 = router.currentRoute.value;
|
|
427
|
+
const fromLocale2 = getCurrentLocale(currentRoute2, i18nConfig, hashLocaleDefault, noPrefixDefault);
|
|
428
|
+
to = router.resolve("/" + fromLocale2 + to);
|
|
409
429
|
} else {
|
|
410
430
|
to = router.resolve(to);
|
|
411
431
|
}
|
|
412
432
|
}
|
|
413
|
-
|
|
433
|
+
const route = router.currentRoute.value;
|
|
434
|
+
return getLocalizedRoute(to, router, route, i18nConfig, currentLocale, hashLocaleDefault, noPrefixDefault);
|
|
414
435
|
},
|
|
415
436
|
localePath: (to, locale) => {
|
|
416
|
-
const
|
|
437
|
+
const route = router.currentRoute.value;
|
|
438
|
+
const localeRoute = getLocalizedRoute(to, router, route, i18nConfig, locale, hashLocaleDefault, noPrefixDefault);
|
|
417
439
|
if (typeof localeRoute === "string") {
|
|
418
440
|
return localeRoute;
|
|
419
441
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { defineEventHandler } from "h3";
|
|
2
|
+
import { createError, useRuntimeConfig, useStorage } from "#imports";
|
|
3
|
+
export default defineEventHandler(async (event) => {
|
|
4
|
+
const { page, locale } = event.context.params;
|
|
5
|
+
const config = useRuntimeConfig();
|
|
6
|
+
const { customRegexMatcher, locales } = config.public.i18nConfig;
|
|
7
|
+
if (customRegexMatcher && locales && !locales.map((l) => l.code).includes(locale)) {
|
|
8
|
+
throw createError({ statusCode: 404 });
|
|
9
|
+
}
|
|
10
|
+
const cacheKey = `${locale}:${page}`;
|
|
11
|
+
const serverStorage = useStorage("i18n-locales");
|
|
12
|
+
if (await serverStorage.hasItem(cacheKey)) {
|
|
13
|
+
const rawContent = await serverStorage.getItem(cacheKey) || {};
|
|
14
|
+
return typeof rawContent === "string" ? JSON.parse(rawContent) : rawContent;
|
|
15
|
+
}
|
|
16
|
+
return {};
|
|
17
|
+
});
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { getQuery, getCookie } from "h3";
|
|
2
2
|
import { interpolate, useTranslationHelper } from "nuxt-i18n-micro-core";
|
|
3
|
-
const i18nHelper = useTranslationHelper();
|
|
4
3
|
async function fetchTranslations(locale) {
|
|
5
4
|
try {
|
|
6
5
|
const translations = await $fetch(`/_locales/general/${locale}/data.json`);
|
|
@@ -11,14 +10,14 @@ async function fetchTranslations(locale) {
|
|
|
11
10
|
}
|
|
12
11
|
}
|
|
13
12
|
export const useTranslationServerMiddleware = async (event, defaultLocale, currentLocale) => {
|
|
13
|
+
const { getTranslation, loadTranslations, hasGeneralTranslation } = useTranslationHelper();
|
|
14
14
|
const locale = (currentLocale || event.context.params?.locale || getQuery(event)?.locale || getCookie(event, "user-locale") || event.headers.get("accept-language")?.split(",")[0] || defaultLocale || "en").toString();
|
|
15
|
-
|
|
16
|
-
if (!i18nHelper.hasGeneralTranslation()) {
|
|
15
|
+
if (!hasGeneralTranslation(locale)) {
|
|
17
16
|
const translations = await fetchTranslations(locale);
|
|
18
|
-
await
|
|
17
|
+
await loadTranslations(locale, translations);
|
|
19
18
|
}
|
|
20
19
|
function t(key, params, defaultValue) {
|
|
21
|
-
let translation =
|
|
20
|
+
let translation = getTranslation(locale, "index", key);
|
|
22
21
|
if (!translation) {
|
|
23
22
|
translation = defaultValue || key;
|
|
24
23
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-i18n-micro",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.63.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",
|
|
@@ -48,31 +48,32 @@
|
|
|
48
48
|
],
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"@nuxt/devtools-kit": "^1.7.0",
|
|
51
|
-
"@nuxt/kit": "^3.15.
|
|
51
|
+
"@nuxt/kit": "^3.15.2",
|
|
52
52
|
"chokidar": "^3.6.0",
|
|
53
|
+
"globby": "^14.0.2",
|
|
53
54
|
"sirv": "^2.0.4",
|
|
54
55
|
"ufo": "^1.5.4",
|
|
55
|
-
"nuxt-i18n-micro-test-utils": "1.0.
|
|
56
|
-
"nuxt-i18n-micro-core": "1.0.
|
|
56
|
+
"nuxt-i18n-micro-test-utils": "1.0.5",
|
|
57
|
+
"nuxt-i18n-micro-core": "1.0.12"
|
|
57
58
|
},
|
|
58
59
|
"devDependencies": {
|
|
59
|
-
"@types/jest": "^29.5.14",
|
|
60
60
|
"@nuxt/devtools": "^1.7.0",
|
|
61
61
|
"@nuxt/devtools-ui-kit": "^1.7.0",
|
|
62
62
|
"@nuxt/eslint-config": "0.7.4",
|
|
63
63
|
"@nuxt/module-builder": "^0.8.4",
|
|
64
|
-
"@nuxt/schema": "^3.15.
|
|
65
|
-
"@nuxt/test-utils": "^3.15.
|
|
64
|
+
"@nuxt/schema": "^3.15.2",
|
|
65
|
+
"@nuxt/test-utils": "^3.15.4",
|
|
66
66
|
"@playwright/test": "^1.49.1",
|
|
67
|
+
"@types/jest": "^29.5.14",
|
|
67
68
|
"@types/node": "^20.17.10",
|
|
68
69
|
"changelogen": "^0.5.7",
|
|
69
70
|
"eslint": "^8.57.1",
|
|
70
|
-
"
|
|
71
|
+
"jest": "^29.7.0",
|
|
72
|
+
"nuxt": "^3.15.2",
|
|
73
|
+
"ts-jest": "^29.2.5",
|
|
71
74
|
"typescript": "5.6.3",
|
|
72
75
|
"vitepress": "^1.5.0",
|
|
73
76
|
"vitest": "^2.1.8",
|
|
74
|
-
"jest": "^29.7.0",
|
|
75
|
-
"ts-jest": "^29.2.5",
|
|
76
77
|
"vue-tsc": "2.1.10"
|
|
77
78
|
},
|
|
78
79
|
"optionalDependencies": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"id":"019df560-5b4f-4d25-8ca1-a8cad935e3d2","timestamp":1736953866014,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.spotlight[data-v-3074ece5]{background:linear-gradient(45deg,#00dc82,#36e4da 50%,#0047e1);bottom:-30vh;filter:blur(20vh);height:40vh}.gradient-border[data-v-3074ece5]{-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-radius:.5rem;position:relative}@media (prefers-color-scheme:light){.gradient-border[data-v-3074ece5]{background-color:#ffffff4d}.gradient-border[data-v-3074ece5]:before{background:linear-gradient(90deg,#e2e2e2,#e2e2e2 25%,#00dc82,#36e4da 75%,#0047e1)}}@media (prefers-color-scheme:dark){.gradient-border[data-v-3074ece5]{background-color:#1414144d}.gradient-border[data-v-3074ece5]:before{background:linear-gradient(90deg,#303030,#303030 25%,#00dc82,#36e4da 75%,#0047e1)}}.gradient-border[data-v-3074ece5]:before{background-size:400% auto;border-radius:.5rem;bottom:0;content:"";left:0;-webkit-mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);-webkit-mask-composite:xor;mask-composite:exclude;opacity:.5;padding:2px;position:absolute;right:0;top:0;transition:background-position .3s ease-in-out,opacity .2s ease-in-out;width:100%}.gradient-border[data-v-3074ece5]:hover:before{background-position:-50% 0;opacity:1}.fixed[data-v-3074ece5]{position:fixed}.left-0[data-v-3074ece5]{left:0}.right-0[data-v-3074ece5]{right:0}.z-10[data-v-3074ece5]{z-index:10}.z-20[data-v-3074ece5]{z-index:20}.grid[data-v-3074ece5]{display:grid}.mb-16[data-v-3074ece5]{margin-bottom:4rem}.mb-8[data-v-3074ece5]{margin-bottom:2rem}.max-w-520px[data-v-3074ece5]{max-width:520px}.min-h-screen[data-v-3074ece5]{min-height:100vh}.w-full[data-v-3074ece5]{width:100%}.flex[data-v-3074ece5]{display:flex}.cursor-pointer[data-v-3074ece5]{cursor:pointer}.place-content-center[data-v-3074ece5]{place-content:center}.items-center[data-v-3074ece5]{align-items:center}.justify-center[data-v-3074ece5]{justify-content:center}.overflow-hidden[data-v-3074ece5]{overflow:hidden}.bg-white[data-v-3074ece5]{--un-bg-opacity:1;background-color:rgb(255 255 255/var(--un-bg-opacity))}.px-4[data-v-3074ece5]{padding-left:1rem;padding-right:1rem}.px-8[data-v-3074ece5]{padding-left:2rem;padding-right:2rem}.py-2[data-v-3074ece5]{padding-bottom:.5rem;padding-top:.5rem}.text-center[data-v-3074ece5]{text-align:center}.text-8xl[data-v-3074ece5]{font-size:6rem;line-height:1}.text-xl[data-v-3074ece5]{font-size:1.25rem;line-height:1.75rem}.text-black[data-v-3074ece5]{--un-text-opacity:1;color:rgb(0 0 0/var(--un-text-opacity))}.font-light[data-v-3074ece5]{font-weight:300}.font-medium[data-v-3074ece5]{font-weight:500}.leading-tight[data-v-3074ece5]{line-height:1.25}.font-sans[data-v-3074ece5]{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.antialiased[data-v-3074ece5]{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@media (prefers-color-scheme:dark){.dark\:bg-black[data-v-3074ece5]{--un-bg-opacity:1;background-color:rgb(0 0 0/var(--un-bg-opacity))}.dark\:text-white[data-v-3074ece5]{--un-text-opacity:1;color:rgb(255 255 255/var(--un-text-opacity))}}@media (min-width:640px){.sm\:px-0[data-v-3074ece5]{padding-left:0;padding-right:0}.sm\:px-6[data-v-3074ece5]{padding-left:1.5rem;padding-right:1.5rem}.sm\:py-3[data-v-3074ece5]{padding-bottom:.75rem;padding-top:.75rem}.sm\:text-4xl[data-v-3074ece5]{font-size:2.25rem;line-height:2.5rem}.sm\:text-xl[data-v-3074ece5]{font-size:1.25rem;line-height:1.75rem}}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.spotlight[data-v-44593346]{background:linear-gradient(45deg,#00dc82,#36e4da 50%,#0047e1);filter:blur(20vh)}.fixed[data-v-44593346]{position:fixed}.-bottom-1\/2[data-v-44593346]{bottom:-50%}.left-0[data-v-44593346]{left:0}.right-0[data-v-44593346]{right:0}.grid[data-v-44593346]{display:grid}.mb-16[data-v-44593346]{margin-bottom:4rem}.mb-8[data-v-44593346]{margin-bottom:2rem}.h-1\/2[data-v-44593346]{height:50%}.max-w-520px[data-v-44593346]{max-width:520px}.min-h-screen[data-v-44593346]{min-height:100vh}.place-content-center[data-v-44593346]{place-content:center}.overflow-hidden[data-v-44593346]{overflow:hidden}.bg-white[data-v-44593346]{--un-bg-opacity:1;background-color:rgb(255 255 255/var(--un-bg-opacity))}.px-8[data-v-44593346]{padding-left:2rem;padding-right:2rem}.text-center[data-v-44593346]{text-align:center}.text-8xl[data-v-44593346]{font-size:6rem;line-height:1}.text-xl[data-v-44593346]{font-size:1.25rem;line-height:1.75rem}.text-black[data-v-44593346]{--un-text-opacity:1;color:rgb(0 0 0/var(--un-text-opacity))}.font-light[data-v-44593346]{font-weight:300}.font-medium[data-v-44593346]{font-weight:500}.leading-tight[data-v-44593346]{line-height:1.25}.font-sans[data-v-44593346]{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.antialiased[data-v-44593346]{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@media (prefers-color-scheme:dark){.dark\:bg-black[data-v-44593346]{--un-bg-opacity:1;background-color:rgb(0 0 0/var(--un-bg-opacity))}.dark\:text-white[data-v-44593346]{--un-text-opacity:1;color:rgb(255 255 255/var(--un-text-opacity))}}@media (min-width:640px){.sm\:px-0[data-v-44593346]{padding-left:0;padding-right:0}.sm\:text-4xl[data-v-44593346]{font-size:2.25rem;line-height:2.5rem}}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { resolve, join } from "node:path";
|
|
2
|
-
import { readFile } from "node:fs/promises";
|
|
3
|
-
import { defineEventHandler } from "h3";
|
|
4
|
-
import { useRuntimeConfig, createError, useStorage } from "#imports";
|
|
5
|
-
let storageInit = false;
|
|
6
|
-
function deepMerge(target, source) {
|
|
7
|
-
for (const key in source) {
|
|
8
|
-
if (key === "__proto__" || key === "constructor") continue;
|
|
9
|
-
if (Array.isArray(source[key])) {
|
|
10
|
-
target[key] = source[key];
|
|
11
|
-
} else if (source[key] instanceof Object) {
|
|
12
|
-
target[key] = target[key] instanceof Object ? deepMerge(target[key], source[key]) : source[key];
|
|
13
|
-
} else {
|
|
14
|
-
target[key] = source[key];
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
return target;
|
|
18
|
-
}
|
|
19
|
-
export default defineEventHandler(async (event) => {
|
|
20
|
-
const { page, locale } = event.context.params;
|
|
21
|
-
const config = useRuntimeConfig();
|
|
22
|
-
const { rootDirs, debug } = config.i18nConfig;
|
|
23
|
-
const { translationDir, fallbackLocale, customRegexMatcher, locales } = config.public.i18nConfig;
|
|
24
|
-
if (customRegexMatcher && locales && !locales.map((l) => l.code).includes(locale)) {
|
|
25
|
-
throw createError({ statusCode: 404 });
|
|
26
|
-
}
|
|
27
|
-
const getTranslationPath = (locale2, page2) => page2 === "general" ? `${locale2}.json` : `pages/${page2}/${locale2}.json`;
|
|
28
|
-
const createPaths = (locale2) => rootDirs.map((dir) => ({
|
|
29
|
-
translationPath: resolve(dir, translationDir, getTranslationPath(locale2, page)),
|
|
30
|
-
name: `_locales/${getTranslationPath(locale2, page)}`
|
|
31
|
-
}));
|
|
32
|
-
const paths = [
|
|
33
|
-
...fallbackLocale && fallbackLocale !== locale ? createPaths(fallbackLocale) : [],
|
|
34
|
-
...createPaths(locale)
|
|
35
|
-
];
|
|
36
|
-
let translations = {};
|
|
37
|
-
const serverStorage = await useStorage("assets:server");
|
|
38
|
-
if (!storageInit) {
|
|
39
|
-
if (debug) console.log("[nuxt-i18n-micro] clear storage cache");
|
|
40
|
-
await Promise.all((await serverStorage.getKeys()).map((key) => serverStorage.removeItem(key)));
|
|
41
|
-
storageInit = true;
|
|
42
|
-
}
|
|
43
|
-
const cacheName = join("_locales", getTranslationPath(locale, page));
|
|
44
|
-
const isThereAsset = await serverStorage.hasItem(cacheName);
|
|
45
|
-
if (isThereAsset) {
|
|
46
|
-
const rawContent = await serverStorage.getItem(cacheName) ?? {};
|
|
47
|
-
return typeof rawContent === "string" ? JSON.parse(rawContent) : rawContent;
|
|
48
|
-
}
|
|
49
|
-
for (const { translationPath, name } of paths) {
|
|
50
|
-
try {
|
|
51
|
-
if (debug) console.log("[nuxt-i18n-micro] load locale", translationPath, name);
|
|
52
|
-
const content = await readFile(translationPath, "utf-8");
|
|
53
|
-
const fileContent = JSON.parse(content);
|
|
54
|
-
translations = deepMerge(translations, fileContent);
|
|
55
|
-
} catch (e) {
|
|
56
|
-
if (debug) console.error("[nuxt-i18n-micro] load locale error", e);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
await serverStorage.setItem(cacheName, translations);
|
|
60
|
-
return translations;
|
|
61
|
-
});
|
|
File without changes
|