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.
@@ -1,12 +1,21 @@
1
- import { interpolate, useTranslationHelper } from "nuxt-i18n-micro-core";
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 { navigateTo, useCookie, useRouter, useState } from "#imports";
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 getCurrentName(i18nConfig) {
9
- const currentLocaleCode = i18nHelper.getLocale();
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 || i18nHelper.getLocale();
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
- const router = useRouter();
224
- const route = router.currentRoute.value;
225
- const currentHashLocale = i18nConfig.hashMode ? (useCookie("hash-locale").value ?? i18nConfig.defaultLocale).toString() : null;
226
- const currentNoPrefixDefault = isNoPrefixStrategy(i18nConfig.strategy) ? useCookie("no-prefix-locale").value ?? i18nConfig.defaultLocale : null;
227
- const currentLocale = (route.params?.locale ?? i18nConfig.defaultLocale).toString();
228
- i18nHelper.setLocale(currentLocale);
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 (currentHashLocale) {
233
- i18nHelper.setLocale(currentHashLocale);
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 locale = i18nHelper.getLocale();
247
- const url = `/${apiBaseUrl}/${fRouteName}/${locale}/data.json?v=${i18nConfig.dateBuild}`.replace(/\/{2,}/g, "/");
248
- const data = await $fetch(url, { baseURL: runtimeConfig.app.baseURL });
249
- await i18nHelper.loadPageTranslations(routeName, data ?? {});
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
- const localeRoute = (to.params?.locale ?? i18nConfig.defaultLocale).toString();
256
- i18nHelper.setLocale(localeRoute);
257
- if (isNoPrefixStrategy(i18nConfig.strategy)) {
258
- await nuxtApp.runWithContext(() => {
259
- const locale = (useCookie("no-prefix-locale").value ?? i18nConfig.defaultLocale).toString();
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.hashMode) {
265
- await nuxtApp.runWithContext(() => {
266
- const locale = (useCookie("hash-locale").value ?? i18nConfig.defaultLocale).toString();
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
- if (!i18nHelper.hasGeneralTranslation()) {
272
- const locale = i18nHelper.getLocale();
273
- const url = `/${apiBaseUrl}/general/${locale}/data.json?v=${i18nConfig.dateBuild}`.replace(/\/{2,}/g, "/");
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, i18nHelper.getLocale());
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
- if (selectedLocale !== i18nHelper.getLocale()) return;
285
- const routeName = getRouteName(to);
286
- i18nHelper.mergeTranslation(routeName, translations, true);
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.fullPath !== from.fullPath || isNoPrefixStrategy(i18nConfig.strategy)) {
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 locale = i18nHelper.getLocale();
301
- const route2 = router.currentRoute.value;
302
- const routeName = getRouteName(route2, locale);
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: () => i18nHelper.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: (route2, locale) => {
324
- const selectedRoute = route2 ?? router.currentRoute.value;
325
- return getRouteName(selectedRoute, locale ?? i18nHelper.getLocale());
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 currentLocale2 = i18nHelper.getLocale();
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, currentLocale2, getTranslation) ?? defaultValue ?? key;
336
+ return plural(key, Number.parseInt(count.toString()), _params, currentLocale, getTranslation) ?? defaultValue ?? key;
336
337
  },
337
338
  tn: (value, options) => {
338
- const locale = i18nHelper.getLocale();
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 locale = i18nHelper.getLocale();
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 locale = i18nHelper.getLocale();
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 route2 = router.currentRoute.value;
354
- const locale = (route2.params?.locale ?? i18nConfig.defaultLocale).toString();
355
- const routeName = getRouteName(route2, locale);
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
- i18nHelper.mergeGlobalTranslation(newTranslations, true);
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 route2 = router.currentRoute.value;
363
- return switchLocaleRoute(i18nHelper.getLocale(), toLocale, route2, router, i18nConfig, i18nRouteParams.value);
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 route2 = router.currentRoute.value;
367
- const localeRoute = switchLocaleRoute(i18nHelper.getLocale(), toLocale, route2, router, i18nConfig, i18nRouteParams.value);
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 route2 = router.currentRoute.value;
378
- switchLocale(i18nHelper.getLocale(), toLocale, route2, router, i18nConfig, i18nRouteParams.value);
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: (to, toLocale) => {
397
+ switchRoute: (route, toLocale) => {
381
398
  const currentRoute = router.currentRoute.value;
382
- const fromLocale = (currentRoute.params?.locale ?? i18nConfig.defaultLocale).toString();
383
- const currentLocale2 = toLocale ?? fromLocale;
384
- if (typeof to === "string" && !isNoPrefixStrategy(i18nConfig.strategy)) {
385
- if (currentLocale2 !== i18nConfig.defaultLocale || withPrefixStrategy(i18nConfig.strategy)) {
386
- to = router.resolve("/" + fromLocale + to);
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
- to = router.resolve(route);
407
+ route = router.resolve(route);
389
408
  }
390
409
  }
391
- if (!to) {
392
- return;
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 fromLocale = i18nHelper.getLocale();
405
- const currentLocale2 = locale ?? fromLocale;
406
- if (typeof to === "string" && !isNoPrefixStrategy(i18nConfig.strategy)) {
407
- if (currentLocale2 !== i18nConfig.defaultLocale || withPrefixStrategy(i18nConfig.strategy)) {
408
- to = router.resolve("/" + fromLocale + to);
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
- return getLocalizedRoute(to, router, i18nConfig, currentLocale2);
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 localeRoute = getLocalizedRoute(to, router, i18nConfig, locale);
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
- i18nHelper.setLocale(locale);
16
- if (!i18nHelper.hasGeneralTranslation()) {
15
+ if (!hasGeneralTranslation(locale)) {
17
16
  const translations = await fetchTranslations(locale);
18
- await i18nHelper.loadTranslations(translations);
17
+ await loadTranslations(locale, translations);
19
18
  }
20
19
  function t(key, params, defaultValue) {
21
- let translation = i18nHelper.getTranslation("index", key);
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.61.0",
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.1",
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.4",
56
- "nuxt-i18n-micro-core": "1.0.11"
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.1",
65
- "@nuxt/test-utils": "^3.15.1",
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
- "nuxt": "^3.15.1",
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
- });