nuxt-i18n-micro 1.1.9 → 1.1.10

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.
@@ -8,4 +8,4 @@
8
8
  <link rel="prefetch" as="style" href="/__nuxt-i18n-micro/_nuxt/error-500.B4KzowuE.css">
9
9
  <link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/HZLiFEh-.js">
10
10
  <script type="module" src="/__nuxt-i18n-micro/_nuxt/6EJ4fAZ2.js" crossorigin></script></head><body><div id="__nuxt"></div><div id="teleports"></div><script type="application/json" id="__NUXT_DATA__" data-ssr="false">[{"serverRendered":1},false]</script>
11
- <script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"3c9001bb-920a-4988-9ad0-29eff844b06b",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
11
+ <script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"f1ddbdf9-9b7b-4ddb-bddb-a5d520509f71",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
@@ -8,4 +8,4 @@
8
8
  <link rel="prefetch" as="style" href="/__nuxt-i18n-micro/_nuxt/error-500.B4KzowuE.css">
9
9
  <link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/HZLiFEh-.js">
10
10
  <script type="module" src="/__nuxt-i18n-micro/_nuxt/6EJ4fAZ2.js" crossorigin></script></head><body><div id="__nuxt"></div><div id="teleports"></div><script type="application/json" id="__NUXT_DATA__" data-ssr="false">[{"serverRendered":1},false]</script>
11
- <script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"3c9001bb-920a-4988-9ad0-29eff844b06b",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
11
+ <script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"f1ddbdf9-9b7b-4ddb-bddb-a5d520509f71",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
@@ -1 +1 @@
1
- {"id":"3c9001bb-920a-4988-9ad0-29eff844b06b","timestamp":1723999902563}
1
+ {"id":"f1ddbdf9-9b7b-4ddb-bddb-a5d520509f71","timestamp":1724070947234}
@@ -0,0 +1 @@
1
+ {"id":"f1ddbdf9-9b7b-4ddb-bddb-a5d520509f71","timestamp":1724070947234,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":[]}
@@ -8,4 +8,4 @@
8
8
  <link rel="prefetch" as="style" href="/__nuxt-i18n-micro/_nuxt/error-500.B4KzowuE.css">
9
9
  <link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/HZLiFEh-.js">
10
10
  <script type="module" src="/__nuxt-i18n-micro/_nuxt/6EJ4fAZ2.js" crossorigin></script></head><body><div id="__nuxt"></div><div id="teleports"></div><script type="application/json" id="__NUXT_DATA__" data-ssr="false">[{"serverRendered":1},false]</script>
11
- <script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"3c9001bb-920a-4988-9ad0-29eff844b06b",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
11
+ <script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"f1ddbdf9-9b7b-4ddb-bddb-a5d520509f71",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nuxt-i18n-micro",
3
3
  "configKey": "i18n",
4
- "version": "1.1.9",
4
+ "version": "1.1.10",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "0.8.3",
7
7
  "unbuild": "2.0.0"
package/dist/module.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import path from 'node:path';
2
2
  import * as fs from 'node:fs';
3
3
  import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
4
- import { useNuxt, defineNuxtModule, createResolver, addPlugin, addImportsDir, addServerHandler, extendPages } from '@nuxt/kit';
4
+ import { useNuxt, defineNuxtModule, createResolver, addPlugin, addImportsDir, addServerHandler, extendPages, addPrerenderRoutes } from '@nuxt/kit';
5
5
  import { onDevToolsInitialized, extendServerRpc } from '@nuxt/devtools-kit';
6
6
 
7
7
  const DEVTOOLS_UI_PORT = 3030;
@@ -91,7 +91,7 @@ const module = defineNuxtModule({
91
91
  return (forms.length > 2 ? forms[2].trim() : forms[forms.length - 1].trim()).replace('{count}', count.toString())
92
92
  }`
93
93
  },
94
- setup(options, nuxt) {
94
+ setup: function(options, nuxt) {
95
95
  const resolver = createResolver(import.meta.url);
96
96
  nuxt.options.runtimeConfig.public.i18nConfig = {
97
97
  rootDir: nuxt.options.rootDir,
@@ -105,35 +105,41 @@ const module = defineNuxtModule({
105
105
  cache: options.cache ?? false
106
106
  };
107
107
  addPlugin({
108
- src: resolver.resolve("./runtime/01.plugin"),
108
+ src: resolver.resolve("./runtime/plugins/01.plugin"),
109
109
  order: 1
110
110
  });
111
+ if (options.mata) {
112
+ addPlugin({
113
+ src: resolver.resolve("./runtime/plugins/02.meta"),
114
+ order: 2
115
+ });
116
+ }
111
117
  addPlugin({
112
- src: resolver.resolve("./runtime/02.meta"),
113
- order: 2
114
- });
115
- addPlugin({
116
- src: resolver.resolve("./runtime/03.define"),
117
- order: 2
118
+ src: resolver.resolve("./runtime/plugins/03.define"),
119
+ order: 3
118
120
  });
119
121
  if (options.autoDetectLanguage) {
120
122
  addPlugin({
121
- src: resolver.resolve("./runtime/04.auto-detect"),
123
+ src: resolver.resolve("./runtime/plugins/04.auto-detect"),
122
124
  mode: "client",
123
- order: 3
125
+ order: 4
124
126
  });
125
127
  }
126
128
  addImportsDir(resolver.resolve("./runtime/composables"));
127
129
  if (options.includeDefaultLocaleRoute) {
128
130
  addServerHandler({
129
131
  middleware: true,
130
- handler: resolver.resolve("./runtime/server/middleware/i18n-redirect.ts")
132
+ handler: resolver.resolve("./runtime/server/middleware/i18n-redirect")
131
133
  });
132
134
  }
135
+ addServerHandler({
136
+ route: "/_locales/:page/:locale/data.json",
137
+ handler: resolver.resolve("./runtime/server/middleware/i18n-loader")
138
+ });
133
139
  const localeRegex = options.locales.filter((locale) => locale.code !== options.defaultLocale || options.includeDefaultLocaleRoute).map((locale) => locale.code).join("|");
134
140
  const pagesDir = path.resolve(nuxt.options.rootDir, options.translationDir, "pages");
135
141
  extendPages((pages) => {
136
- nuxt.options.generate.routes = Array.isArray(nuxt.options.generate.routes) ? nuxt.options.generate.routes : [];
142
+ const pagesNames = pages.map((page) => page.name);
137
143
  const newRoutes = pages.map((page) => {
138
144
  options.locales.forEach((locale) => {
139
145
  pages.forEach((page2) => {
@@ -157,6 +163,15 @@ const module = defineNuxtModule({
157
163
  };
158
164
  });
159
165
  pages.push(...newRoutes);
166
+ nuxt.options.generate.routes = Array.isArray(nuxt.options.generate.routes) ? nuxt.options.generate.routes : [];
167
+ if (nuxt.options?._generate) {
168
+ options.locales?.forEach((locale) => {
169
+ pagesNames.forEach((name) => {
170
+ addPrerenderRoutes(`/_locales/${name}/${locale.code}/data.json`);
171
+ });
172
+ addPrerenderRoutes(`/_locales/general/${locale.code}/data.json`);
173
+ });
174
+ }
160
175
  });
161
176
  nuxt.hook("nitro:config", (nitroConfig) => {
162
177
  const routes = nitroConfig.prerender?.routes || [];
@@ -165,15 +180,16 @@ const module = defineNuxtModule({
165
180
  options.locales.forEach((locale) => {
166
181
  if (locale.code !== options.defaultLocale || options.includeDefaultLocaleRoute) {
167
182
  pages.forEach((page) => {
168
- routes.push(`/${locale}${page}`);
183
+ routes.push(`/${locale.code}${page}`);
169
184
  });
170
185
  }
171
186
  });
172
187
  nitroConfig.prerender = nitroConfig.prerender || {};
173
188
  nitroConfig.prerender.routes = routes;
174
189
  });
175
- if (nuxt.options.dev)
190
+ if (nuxt.options.dev) {
176
191
  setupDevToolsUI(options, resolver.resolve);
192
+ }
177
193
  }
178
194
  });
179
195
 
@@ -1,2 +1,2 @@
1
- import type { PluginsInjections } from '../01.plugin.js';
1
+ import type { PluginsInjections } from '../plugins/01.plugin.js';
2
2
  export declare function useI18n(): PluginsInjections;
@@ -5,6 +5,7 @@ export function useI18n() {
5
5
  $getLocale: nuxtApp.$getLocale,
6
6
  $getLocales: nuxtApp.$getLocales,
7
7
  $t: nuxtApp.$t,
8
+ $has: nuxtApp.$has,
8
9
  $tc: nuxtApp.$tc,
9
10
  $mergeTranslations: nuxtApp.$mergeTranslations,
10
11
  $switchLocale: nuxtApp.$switchLocale,
@@ -1,5 +1,5 @@
1
1
  import type { RouteLocationRaw } from 'vue-router';
2
- interface Translations {
2
+ export interface Translations {
3
3
  [key: string]: string | number | boolean | Translations | PluralTranslations | unknown[] | null;
4
4
  }
5
5
  interface PluralTranslations {
@@ -8,17 +8,19 @@ interface PluralTranslations {
8
8
  }
9
9
  declare const _default: import("#app").Plugin<{
10
10
  getLocale: () => string;
11
- getLocales: () => import("../module").Locale[];
11
+ getLocales: () => import("../../module").Locale[];
12
12
  t: <T extends Record<string, string | number | boolean>>(key: string, params?: T, defaultValue?: string) => string | number | boolean | Translations | PluralTranslations | unknown[] | unknown | null;
13
13
  tc: (key: string, count: number, defaultValue?: string) => string;
14
+ has: (key: string) => boolean;
14
15
  mergeTranslations: (newTranslations: Translations) => void;
15
16
  switchLocale: (locale: string) => void;
16
17
  localeRoute: (to: RouteLocationRaw, locale?: string) => RouteLocationRaw;
17
18
  }> & import("#app").ObjectPlugin<{
18
19
  getLocale: () => string;
19
- getLocales: () => import("../module").Locale[];
20
+ getLocales: () => import("../../module").Locale[];
20
21
  t: <T extends Record<string, string | number | boolean>>(key: string, params?: T, defaultValue?: string) => string | number | boolean | Translations | PluralTranslations | unknown[] | unknown | null;
21
22
  tc: (key: string, count: number, defaultValue?: string) => string;
23
+ has: (key: string) => boolean;
22
24
  mergeTranslations: (newTranslations: Translations) => void;
23
25
  switchLocale: (locale: string) => void;
24
26
  localeRoute: (to: RouteLocationRaw, locale?: string) => RouteLocationRaw;
@@ -29,6 +31,7 @@ export interface PluginsInjections {
29
31
  $getLocales: () => string[];
30
32
  $t: <T extends Record<string, string | number | boolean>>(key: string, params?: T, defaultValue?: string) => string | number | boolean | Translations | PluralTranslations | unknown[] | unknown | null;
31
33
  $tc: (key: string, count: number, defaultValue?: string) => string;
34
+ $has: (key: string) => boolean;
32
35
  $mergeTranslations: (newTranslations: Translations) => void;
33
36
  $switchLocale: (locale: string) => void;
34
37
  $localeRoute: (to: RouteLocationRaw, locale?: string) => RouteLocationRaw;
@@ -43,7 +46,16 @@ declare module 'nuxt/dist/app/nuxt' {
43
46
  }
44
47
  }
45
48
  declare module '@vue/runtime-core' {
46
- interface ComponentCustomProperties extends PluginsInjections {
49
+ interface ComponentCustomProperties {
50
+ $getLocale: () => string;
51
+ $getLocales: () => string[];
52
+ $t: <T extends Record<string, string | number | boolean>>(key: string, params?: T, defaultValue?: string) => string | number | boolean | Translations | PluralTranslations | unknown[] | unknown | null;
53
+ $tc: (key: string, count: number, defaultValue?: string) => string;
54
+ $has: (key: string) => boolean;
55
+ $mergeTranslations: (newTranslations: Translations) => void;
56
+ $switchLocale: (locale: string) => void;
57
+ $localeRoute: (to: RouteLocationRaw, locale?: string) => RouteLocationRaw;
58
+ $loadPageTranslations: (locale: string, routeName: string) => Promise<void>;
47
59
  }
48
60
  }
49
61
  declare module 'vue' {
@@ -1,61 +1,13 @@
1
+ import { useTranslationHelper } from "../translationHelper.js";
1
2
  import { defineNuxtPlugin, useRuntimeConfig } from "#app";
2
- import { useRoute, useRouter } from "#imports";
3
+ import { useFetch, useRoute, useRouter } from "#imports";
4
+ const i18nHelper = useTranslationHelper();
3
5
  const isDev = process.env.NODE_ENV !== "production";
4
- const generalLocaleCache = {};
5
- const routeLocaleCache = {};
6
- const dynamicTranslationsCaches = [];
7
- const translationCache = { map: /* @__PURE__ */ new Map() };
8
- function deepClone(value) {
9
- if (Array.isArray(value)) {
10
- return value.slice();
11
- } else if (typeof value === "object" && value !== null) {
12
- return { ...value };
13
- }
14
- return value;
15
- }
16
- function getTranslation(translations, key) {
17
- const parts = key.split(".");
18
- let value = translations;
19
- for (let i = 0; i < parts.length; i++) {
20
- if (value && typeof value === "object" && parts[i] in value) {
21
- value = value[parts[i]];
22
- } else {
23
- return null;
24
- }
25
- }
26
- if (typeof value === "object" && value !== null) {
27
- return deepClone(value);
28
- }
29
- return value ?? null;
30
- }
31
6
  function interpolate(template, params) {
32
7
  return template.replace(/\{(\w+)\}/g, (_, match) => {
33
8
  return params[match] !== void 0 ? String(params[match]) : `{${match}}`;
34
9
  });
35
10
  }
36
- function getPluralTranslation(translations, key) {
37
- return getTranslation(translations, key);
38
- }
39
- async function loadTranslations(locale, routeName, translationDir) {
40
- try {
41
- if (!generalLocaleCache[locale]) {
42
- const translations = await import(`~/${translationDir}/${locale}.json`);
43
- generalLocaleCache[locale] = { ...translations.default };
44
- }
45
- if (!routeLocaleCache[`${locale}:${routeName}`]) {
46
- const translations = await import(`~/${translationDir}/pages/${routeName}/${locale}.json`);
47
- routeLocaleCache[`${locale}:${routeName}`] = { ...translations.default };
48
- }
49
- } catch (error) {
50
- console.error(`Error loading translations for ${locale} and ${routeName}:`, error);
51
- }
52
- }
53
- function mergeTranslations(routeName, locale, newTranslations) {
54
- routeLocaleCache[`${locale}:${routeName}`] = {
55
- ...generalLocaleCache[locale],
56
- ...newTranslations
57
- };
58
- }
59
11
  function switchLocale(locale, route, router, i18nConfig) {
60
12
  const checkLocale = i18nConfig.locales?.find((l) => l.code === locale);
61
13
  if (!checkLocale) {
@@ -85,8 +37,32 @@ function getLocalizedRoute(to, router, route, i18nConfig, locale) {
85
37
  }
86
38
  return router.resolve({ name: newRouteName, params: newParams });
87
39
  }
88
- export default defineNuxtPlugin(async (_nuxtApp) => {
40
+ export default defineNuxtPlugin(async (nuxtApp) => {
89
41
  const router = useRouter();
42
+ if (!nuxtApp.payload.data.translations) {
43
+ nuxtApp.payload.data.translations = {};
44
+ }
45
+ if (import.meta.server) {
46
+ nuxtApp.hook("app:rendered", async () => {
47
+ if (import.meta.server) {
48
+ const route2 = useRoute();
49
+ const locale = (route2.params?.locale ?? i18nConfig.defaultLocale).toString();
50
+ const routeName = (route2?.name ?? "").toString().replace(`localized-`, "");
51
+ const cacheKey = `${locale}:${routeName}`;
52
+ nuxtApp.payload.data.translations[cacheKey] = i18nHelper.getCache(locale, routeName) ?? /* @__PURE__ */ new Map();
53
+ }
54
+ });
55
+ } else {
56
+ router.beforeEach(async (to, from, next) => {
57
+ const locale = (to.params?.locale ?? i18nConfig.defaultLocale).toString();
58
+ const routeName = to.name.replace(`localized-`, "");
59
+ const cacheKey = `${locale}:${routeName}`;
60
+ if (nuxtApp.payload.data.translations) {
61
+ i18nHelper.setCache(locale, routeName, nuxtApp.payload.data.translations[cacheKey] || /* @__PURE__ */ new Map());
62
+ }
63
+ next();
64
+ });
65
+ }
90
66
  const route = useRoute();
91
67
  const config = useRuntimeConfig();
92
68
  const i18nConfig = config.public.i18nConfig;
@@ -94,14 +70,26 @@ export default defineNuxtPlugin(async (_nuxtApp) => {
94
70
  const initialRouteName = route.name.replace(`localized-`, "");
95
71
  const plural = new Function("return " + i18nConfig.plural)();
96
72
  router.beforeEach(async (to, from, next) => {
97
- const locale = (to.params?.locale ?? i18nConfig.defaultLocale).toString();
98
- const routeName = to.name.replace(`localized-`, "");
99
- if (!routeLocaleCache[`${locale}:${routeName}`]) {
100
- await loadTranslations(locale, routeName, i18nConfig.translationDir);
73
+ if (import.meta.client) {
74
+ const locale = (to.params?.locale ?? i18nConfig.defaultLocale).toString();
75
+ const routeName = to.name.replace(`localized-`, "");
76
+ if (!i18nHelper.hasPageTranslation(locale, routeName)) {
77
+ const resp = await fetch(`/_locales/${routeName}/${locale}/data.json`);
78
+ if (resp.ok) {
79
+ await i18nHelper.loadPageTranslations(locale, routeName, await resp.json());
80
+ }
81
+ }
101
82
  }
102
83
  next();
103
84
  });
104
- await loadTranslations(initialLocale, initialRouteName, i18nConfig.translationDir);
85
+ const { data } = await useFetch(`/_locales/general/${initialLocale}/data.json`);
86
+ await i18nHelper.loadTranslations(initialLocale, initialRouteName, data.value ?? {});
87
+ if (import.meta.server) {
88
+ const locale = (route.params?.locale ?? i18nConfig.defaultLocale).toString();
89
+ const routeName = route.name.replace(`localized-`, "");
90
+ const { data: data2 } = await useFetch(`/_locales/${routeName}/${locale}/data.json`);
91
+ await i18nHelper.loadPageTranslations(initialLocale, initialRouteName, data2.value ?? {});
92
+ }
105
93
  return {
106
94
  provide: {
107
95
  getLocale: () => {
@@ -116,26 +104,16 @@ export default defineNuxtPlugin(async (_nuxtApp) => {
116
104
  }
117
105
  const route2 = useRoute();
118
106
  const locale = (route2.params?.locale ?? i18nConfig.defaultLocale).toString();
119
- const cacheKey = locale + ":" + key;
120
- if (i18nConfig.cache && translationCache.map.has(cacheKey)) {
121
- return translationCache.map.get(cacheKey);
122
- }
123
107
  const routeName = route2.name.replace(`localized-`, "");
124
- let value = getTranslation(routeLocaleCache[`${locale}:${routeName}`] ?? {}, key) || getTranslation(generalLocaleCache[locale] ?? {}, key) || dynamicTranslationsCaches.reduce((result, cache) => {
125
- return result || getTranslation(cache[locale] ?? {}, key);
126
- }, null);
108
+ let value = i18nHelper.getTranslation(locale, routeName, key, !!i18nConfig.cache);
127
109
  if (!value) {
128
110
  if (isDev && import.meta.client) {
129
- console.warn(`Not found '${key}' key in '${locale}' locale messages.`);
130
111
  }
131
112
  value = defaultValue || key;
132
113
  }
133
114
  if (typeof value === "string" && params) {
134
115
  value = interpolate(value, params);
135
116
  }
136
- if (i18nConfig.cache) {
137
- translationCache.map.set(cacheKey, value);
138
- }
139
117
  return value;
140
118
  },
141
119
  tc: (key, count, defaultValue) => {
@@ -145,31 +123,28 @@ export default defineNuxtPlugin(async (_nuxtApp) => {
145
123
  }
146
124
  const route2 = useRoute();
147
125
  const locale = (route2.params?.locale ?? i18nConfig.defaultLocale).toString();
148
- const cacheKey = locale + ":" + key + ":" + count;
149
- if (i18nConfig.cache && translationCache.map.has(cacheKey)) {
150
- return translationCache.map.get(cacheKey);
151
- }
152
126
  const routeName = route2.name.replace(`localized-`, "");
153
- let translation = getPluralTranslation(routeLocaleCache[`${locale}:${routeName}`] ?? {}, key) || getPluralTranslation(generalLocaleCache[locale] ?? {}, key) || dynamicTranslationsCaches.reduce((result, cache) => {
154
- return result || getPluralTranslation(cache[locale] ?? {}, key);
155
- }, null);
127
+ let translation = i18nHelper.getTranslation(locale, routeName, key, !!i18nConfig.cache);
156
128
  if (!translation) {
157
129
  if (isDev && import.meta.client) {
158
130
  console.warn(`Not found '${key}' key in '${locale}' locale messages.`);
159
131
  }
160
132
  translation = defaultValue || key;
161
133
  }
162
- const value = plural(translation.toString(), count, locale);
163
- if (i18nConfig.cache) {
164
- translationCache.map.set(cacheKey, value);
165
- }
166
- return value;
134
+ return plural(translation.toString(), count, locale);
135
+ },
136
+ has: (key) => {
137
+ const route2 = useRoute();
138
+ const locale = (route2.params?.locale ?? i18nConfig.defaultLocale).toString();
139
+ const routeName = route2.name.replace(`localized-`, "");
140
+ const translation = i18nHelper.getTranslation(locale, routeName, key, !!i18nConfig.cache);
141
+ return !!translation;
167
142
  },
168
143
  mergeTranslations: (newTranslations) => {
169
144
  const route2 = useRoute();
170
145
  const routeName = route2.name.replace(`localized-`, "");
171
146
  const locale = (route2.params?.locale ?? i18nConfig.defaultLocale).toString();
172
- mergeTranslations(routeName, locale, newTranslations);
147
+ i18nHelper.margeTranslation(routeName, locale, newTranslations);
173
148
  },
174
149
  switchLocale: (locale) => {
175
150
  const route2 = useRoute();
@@ -0,0 +1,6 @@
1
+ import type { ModuleOptions } from '../../../module.js';
2
+ export interface ModuleOptionsExtend extends ModuleOptions {
3
+ rootDir?: string;
4
+ }
5
+ declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<any>>;
6
+ export default _default;
@@ -0,0 +1,22 @@
1
+ import { resolve } from "node:path";
2
+ import { readFile } from "node:fs/promises";
3
+ import { defineEventHandler } from "h3";
4
+ import { useRuntimeConfig } from "#imports";
5
+ export default defineEventHandler(async (event) => {
6
+ const { page, locale } = event.context.params;
7
+ const config = useRuntimeConfig();
8
+ const { rootDir, translationDir } = config.public.i18nConfig;
9
+ let path = `${locale}.json`;
10
+ if (page !== "general") {
11
+ path = `pages/${page}/${locale}.json`;
12
+ }
13
+ const translationPath = resolve(rootDir, translationDir, path);
14
+ try {
15
+ const fileContent = await readFile(translationPath, "utf-8");
16
+ return JSON.parse(fileContent);
17
+ } catch (error) {
18
+ console.log("error", error);
19
+ event.node.res.statusCode = 404;
20
+ return { error: "Translations not found" };
21
+ }
22
+ });
@@ -0,0 +1,12 @@
1
+ import type { Translations } from './plugins/01.plugin.js';
2
+ export declare function useTranslationHelper(): {
3
+ hasCache(locale: string, page: string): boolean;
4
+ getCache(locale: string, routeName: string): Map<string, unknown>;
5
+ setCache(locale: string, routeName: string, cache: Map<string, Translations | unknown>): void;
6
+ margeTranslation(locale: string, routeName: string, newTranslations: Translations): void;
7
+ hasGeneralTranslation(locale: string): boolean;
8
+ hasPageTranslation(locale: string, routeName: string): boolean;
9
+ getTranslation: <T = unknown>(locale: string, routeName: string, key: string, useCache: boolean) => T | null;
10
+ loadPageTranslations: (locale: string, routeName: string, translations: Translations) => Promise<void>;
11
+ loadTranslations: (locale: string, routeName: string, translations: Translations) => Promise<void>;
12
+ };
@@ -0,0 +1,115 @@
1
+ const generalLocaleCache = {};
2
+ const routeLocaleCache = {};
3
+ const dynamicTranslationsCaches = [];
4
+ const serverTranslationCache = {};
5
+ const serverTranslationInit = {};
6
+ function deepClone(value) {
7
+ if (Array.isArray(value)) {
8
+ return value.slice();
9
+ } else if (typeof value === "object" && value !== null) {
10
+ return { ...value };
11
+ }
12
+ return value;
13
+ }
14
+ function findTranslation(translations, parts) {
15
+ let value = translations;
16
+ for (let i = 0; i < parts.length; i++) {
17
+ if (value && typeof value === "object" && parts[i] in value) {
18
+ value = value[parts[i]];
19
+ } else {
20
+ return null;
21
+ }
22
+ }
23
+ if (typeof value === "object" && value !== null) {
24
+ return deepClone(value);
25
+ }
26
+ return value ?? null;
27
+ }
28
+ export function useTranslationHelper() {
29
+ return {
30
+ hasCache(locale, page) {
31
+ return serverTranslationInit[`${locale}:${page}`] ?? false;
32
+ },
33
+ getCache(locale, routeName) {
34
+ return serverTranslationCache[`${locale}:${routeName}`];
35
+ },
36
+ setCache(locale, routeName, cache) {
37
+ serverTranslationCache[`${locale}:${routeName}`] = cache;
38
+ serverTranslationInit[`${locale}:index`] = true;
39
+ serverTranslationInit[`${locale}:${routeName}`] = true;
40
+ },
41
+ margeTranslation(locale, routeName, newTranslations) {
42
+ if (!routeLocaleCache[`${locale}:${routeName}`]) {
43
+ console.error(`marge: route ${routeName} not loaded`);
44
+ }
45
+ routeLocaleCache[`${locale}:${routeName}`] = {
46
+ ...generalLocaleCache[locale],
47
+ ...newTranslations
48
+ };
49
+ },
50
+ hasGeneralTranslation(locale) {
51
+ return !!generalLocaleCache[locale];
52
+ },
53
+ hasPageTranslation(locale, routeName) {
54
+ return !!routeLocaleCache[`${locale}:${routeName}`];
55
+ },
56
+ getTranslation: (locale, routeName, key, useCache) => {
57
+ const cacheKey = `${locale}:${routeName}`;
58
+ if (useCache && serverTranslationCache[cacheKey]) {
59
+ const cached = serverTranslationCache[cacheKey].get(key);
60
+ if (cached) {
61
+ return cached;
62
+ }
63
+ }
64
+ const parts = key.split(".");
65
+ let result = null;
66
+ if (dynamicTranslationsCaches.length) {
67
+ for (const dynamicCache of dynamicTranslationsCaches) {
68
+ const value = findTranslation(dynamicCache[locale], parts);
69
+ if (value !== null) {
70
+ result = value;
71
+ }
72
+ }
73
+ }
74
+ if (!result) {
75
+ const value = findTranslation(routeLocaleCache[`${locale}:${routeName}`], parts);
76
+ if (value !== null) {
77
+ result = value;
78
+ }
79
+ }
80
+ if (!result) {
81
+ const value = findTranslation(generalLocaleCache[locale], parts);
82
+ if (value !== null) {
83
+ return value;
84
+ }
85
+ }
86
+ if (useCache && result) {
87
+ if (!serverTranslationCache[cacheKey]) {
88
+ serverTranslationCache[cacheKey] = /* @__PURE__ */ new Map();
89
+ }
90
+ serverTranslationCache[cacheKey].set(key, result);
91
+ }
92
+ return result;
93
+ },
94
+ loadPageTranslations: async (locale, routeName, translations) => {
95
+ try {
96
+ if (!routeLocaleCache[`${locale}:${routeName}`]) {
97
+ routeLocaleCache[`${locale}:${routeName}`] = { ...translations };
98
+ serverTranslationInit[`${locale}:${routeName}`] = true;
99
+ }
100
+ } catch (error) {
101
+ console.error(`Error loading translations for ${locale} and ${routeName}:`, error);
102
+ }
103
+ },
104
+ loadTranslations: async (locale, routeName, translations) => {
105
+ try {
106
+ if (!generalLocaleCache[locale]) {
107
+ generalLocaleCache[locale] = { ...translations };
108
+ serverTranslationInit[`${locale}:index`] = true;
109
+ }
110
+ } catch (error) {
111
+ console.error(`Error loading translations for general ${locale}:`, error);
112
+ }
113
+ }
114
+ };
115
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-i18n-micro",
3
- "version": "1.1.9",
3
+ "version": "1.1.10",
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",
@@ -1 +0,0 @@
1
- {"id":"3c9001bb-920a-4988-9ad0-29eff844b06b","timestamp":1723999902563,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":[]}
@@ -1 +0,0 @@
1
- export {};
File without changes
File without changes