nuxt-i18n-micro 1.1.8 → 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:"7d3d3cf9-6064-4ba3-a2ec-347447f8edd0",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:"7d3d3cf9-6064-4ba3-a2ec-347447f8edd0",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":"7d3d3cf9-6064-4ba3-a2ec-347447f8edd0","timestamp":1723968282041}
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:"7d3d3cf9-6064-4ba3-a2ec-347447f8edd0",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.d.mts CHANGED
@@ -13,6 +13,7 @@ interface ModuleOptions {
13
13
  translationDir?: string;
14
14
  autoDetectLanguage?: boolean;
15
15
  includeDefaultLocaleRoute?: boolean;
16
+ cache?: boolean;
16
17
  plural?: string;
17
18
  }
18
19
  declare const _default: _nuxt_schema.NuxtModule<ModuleOptions>;
package/dist/module.d.ts CHANGED
@@ -13,6 +13,7 @@ interface ModuleOptions {
13
13
  translationDir?: string;
14
14
  autoDetectLanguage?: boolean;
15
15
  includeDefaultLocaleRoute?: boolean;
16
+ cache?: boolean;
16
17
  plural?: string;
17
18
  }
18
19
  declare const _default: _nuxt_schema.NuxtModule<ModuleOptions>;
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.8",
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;
@@ -79,6 +79,7 @@ const module = defineNuxtModule({
79
79
  translationDir: "locales",
80
80
  autoDetectLanguage: true,
81
81
  includeDefaultLocaleRoute: false,
82
+ cache: false,
82
83
  plural: `function (translation, count, _locale) {
83
84
  const forms = translation.toString().split('|')
84
85
  if (count === 0 && forms.length > 2) {
@@ -90,7 +91,7 @@ const module = defineNuxtModule({
90
91
  return (forms.length > 2 ? forms[2].trim() : forms[forms.length - 1].trim()).replace('{count}', count.toString())
91
92
  }`
92
93
  },
93
- setup(options, nuxt) {
94
+ setup: function(options, nuxt) {
94
95
  const resolver = createResolver(import.meta.url);
95
96
  nuxt.options.runtimeConfig.public.i18nConfig = {
96
97
  rootDir: nuxt.options.rootDir,
@@ -100,38 +101,45 @@ const module = defineNuxtModule({
100
101
  defaultLocale: options.defaultLocale ?? "en",
101
102
  translationDir: options.translationDir ?? "locales",
102
103
  autoDetectLanguage: options.autoDetectLanguage ?? true,
103
- includeDefaultLocaleRoute: options.includeDefaultLocaleRoute ?? false
104
+ includeDefaultLocaleRoute: options.includeDefaultLocaleRoute ?? false,
105
+ cache: options.cache ?? false
104
106
  };
105
107
  addPlugin({
106
- src: resolver.resolve("./runtime/01.plugin"),
108
+ src: resolver.resolve("./runtime/plugins/01.plugin"),
107
109
  order: 1
108
110
  });
111
+ if (options.mata) {
112
+ addPlugin({
113
+ src: resolver.resolve("./runtime/plugins/02.meta"),
114
+ order: 2
115
+ });
116
+ }
109
117
  addPlugin({
110
- src: resolver.resolve("./runtime/02.meta"),
111
- order: 2
112
- });
113
- addPlugin({
114
- src: resolver.resolve("./runtime/03.define"),
115
- order: 2
118
+ src: resolver.resolve("./runtime/plugins/03.define"),
119
+ order: 3
116
120
  });
117
121
  if (options.autoDetectLanguage) {
118
122
  addPlugin({
119
- src: resolver.resolve("./runtime/04.auto-detect"),
123
+ src: resolver.resolve("./runtime/plugins/04.auto-detect"),
120
124
  mode: "client",
121
- order: 3
125
+ order: 4
122
126
  });
123
127
  }
124
128
  addImportsDir(resolver.resolve("./runtime/composables"));
125
129
  if (options.includeDefaultLocaleRoute) {
126
130
  addServerHandler({
127
131
  middleware: true,
128
- handler: resolver.resolve("./runtime/server/middleware/i18n-redirect.ts")
132
+ handler: resolver.resolve("./runtime/server/middleware/i18n-redirect")
129
133
  });
130
134
  }
135
+ addServerHandler({
136
+ route: "/_locales/:page/:locale/data.json",
137
+ handler: resolver.resolve("./runtime/server/middleware/i18n-loader")
138
+ });
131
139
  const localeRegex = options.locales.filter((locale) => locale.code !== options.defaultLocale || options.includeDefaultLocaleRoute).map((locale) => locale.code).join("|");
132
140
  const pagesDir = path.resolve(nuxt.options.rootDir, options.translationDir, "pages");
133
141
  extendPages((pages) => {
134
- nuxt.options.generate.routes = Array.isArray(nuxt.options.generate.routes) ? nuxt.options.generate.routes : [];
142
+ const pagesNames = pages.map((page) => page.name);
135
143
  const newRoutes = pages.map((page) => {
136
144
  options.locales.forEach((locale) => {
137
145
  pages.forEach((page2) => {
@@ -155,6 +163,15 @@ const module = defineNuxtModule({
155
163
  };
156
164
  });
157
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
+ }
158
175
  });
159
176
  nuxt.hook("nitro:config", (nitroConfig) => {
160
177
  const routes = nitroConfig.prerender?.routes || [];
@@ -163,15 +180,16 @@ const module = defineNuxtModule({
163
180
  options.locales.forEach((locale) => {
164
181
  if (locale.code !== options.defaultLocale || options.includeDefaultLocaleRoute) {
165
182
  pages.forEach((page) => {
166
- routes.push(`/${locale}${page}`);
183
+ routes.push(`/${locale.code}${page}`);
167
184
  });
168
185
  }
169
186
  });
170
187
  nitroConfig.prerender = nitroConfig.prerender || {};
171
188
  nitroConfig.prerender.routes = routes;
172
189
  });
173
- if (nuxt.options.dev)
190
+ if (nuxt.options.dev) {
174
191
  setupDevToolsUI(options, resolver.resolve);
192
+ }
175
193
  }
176
194
  });
177
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' {
@@ -0,0 +1,159 @@
1
+ import { useTranslationHelper } from "../translationHelper.js";
2
+ import { defineNuxtPlugin, useRuntimeConfig } from "#app";
3
+ import { useFetch, useRoute, useRouter } from "#imports";
4
+ const i18nHelper = useTranslationHelper();
5
+ const isDev = process.env.NODE_ENV !== "production";
6
+ function interpolate(template, params) {
7
+ return template.replace(/\{(\w+)\}/g, (_, match) => {
8
+ return params[match] !== void 0 ? String(params[match]) : `{${match}}`;
9
+ });
10
+ }
11
+ function switchLocale(locale, route, router, i18nConfig) {
12
+ const checkLocale = i18nConfig.locales?.find((l) => l.code === locale);
13
+ if (!checkLocale) {
14
+ console.warn(`Locale ${locale} is not available`);
15
+ return Promise.reject(`Locale ${locale} is not available`);
16
+ }
17
+ const { defaultLocale } = i18nConfig;
18
+ const routeName = route.name.replace(`localized-`, "");
19
+ const newRouteName = locale !== defaultLocale || i18nConfig.includeDefaultLocaleRoute ? `localized-${routeName}` : routeName;
20
+ const newParams = { ...route.params };
21
+ delete newParams.locale;
22
+ if (locale !== defaultLocale || i18nConfig.includeDefaultLocaleRoute) {
23
+ newParams.locale = locale;
24
+ }
25
+ return router.push({ name: newRouteName, params: newParams });
26
+ }
27
+ function getLocalizedRoute(to, router, route, i18nConfig, locale) {
28
+ const { defaultLocale } = i18nConfig;
29
+ const currentLocale = (locale || route.params.locale || defaultLocale).toString();
30
+ const selectRoute = router.resolve(to);
31
+ const routeName = selectRoute.name.replace(`localized-`, "");
32
+ const newRouteName = currentLocale !== defaultLocale || i18nConfig.includeDefaultLocaleRoute ? `localized-${routeName}` : routeName;
33
+ const newParams = { ...route.params };
34
+ delete newParams.locale;
35
+ if (currentLocale !== defaultLocale || i18nConfig.includeDefaultLocaleRoute) {
36
+ newParams.locale = currentLocale;
37
+ }
38
+ return router.resolve({ name: newRouteName, params: newParams });
39
+ }
40
+ export default defineNuxtPlugin(async (nuxtApp) => {
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
+ }
66
+ const route = useRoute();
67
+ const config = useRuntimeConfig();
68
+ const i18nConfig = config.public.i18nConfig;
69
+ const initialLocale = (route.params?.locale ?? i18nConfig.defaultLocale).toString();
70
+ const initialRouteName = route.name.replace(`localized-`, "");
71
+ const plural = new Function("return " + i18nConfig.plural)();
72
+ router.beforeEach(async (to, from, next) => {
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
+ }
82
+ }
83
+ next();
84
+ });
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
+ }
93
+ return {
94
+ provide: {
95
+ getLocale: () => {
96
+ const route2 = useRoute();
97
+ return (route2.params?.locale ?? i18nConfig.defaultLocale).toString();
98
+ },
99
+ getLocales: () => i18nConfig.locales || [],
100
+ t: (key, params, defaultValue) => {
101
+ if (!key) {
102
+ console.log(`$t: key not exist`);
103
+ return "";
104
+ }
105
+ const route2 = useRoute();
106
+ const locale = (route2.params?.locale ?? i18nConfig.defaultLocale).toString();
107
+ const routeName = route2.name.replace(`localized-`, "");
108
+ let value = i18nHelper.getTranslation(locale, routeName, key, !!i18nConfig.cache);
109
+ if (!value) {
110
+ if (isDev && import.meta.client) {
111
+ }
112
+ value = defaultValue || key;
113
+ }
114
+ if (typeof value === "string" && params) {
115
+ value = interpolate(value, params);
116
+ }
117
+ return value;
118
+ },
119
+ tc: (key, count, defaultValue) => {
120
+ if (!key) {
121
+ console.log(`$tc: key not exist`);
122
+ return "";
123
+ }
124
+ const route2 = useRoute();
125
+ const locale = (route2.params?.locale ?? i18nConfig.defaultLocale).toString();
126
+ const routeName = route2.name.replace(`localized-`, "");
127
+ let translation = i18nHelper.getTranslation(locale, routeName, key, !!i18nConfig.cache);
128
+ if (!translation) {
129
+ if (isDev && import.meta.client) {
130
+ console.warn(`Not found '${key}' key in '${locale}' locale messages.`);
131
+ }
132
+ translation = defaultValue || key;
133
+ }
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;
142
+ },
143
+ mergeTranslations: (newTranslations) => {
144
+ const route2 = useRoute();
145
+ const routeName = route2.name.replace(`localized-`, "");
146
+ const locale = (route2.params?.locale ?? i18nConfig.defaultLocale).toString();
147
+ i18nHelper.margeTranslation(routeName, locale, newTranslations);
148
+ },
149
+ switchLocale: (locale) => {
150
+ const route2 = useRoute();
151
+ switchLocale(locale, route2, router, i18nConfig);
152
+ },
153
+ localeRoute: (to, locale) => {
154
+ const route2 = useRoute();
155
+ return getLocalizedRoute(to, router, route2, i18nConfig, locale);
156
+ }
157
+ }
158
+ };
159
+ });
@@ -10,8 +10,14 @@ export default defineNuxtPlugin((_nuxtApp) => {
10
10
  const { locales } = routeDefinition;
11
11
  const { name } = route;
12
12
  if (locales && !locales.includes(currentLocale)) {
13
- const defaultRouteName = i18nConfig.defaultLocale !== i18nConfig.defaultLocale ? `localized-${name?.toString}` : name;
13
+ let defaultRouteName = name?.toString().replace("localized-", "");
14
14
  const resolvedRoute = router.resolve({ name: defaultRouteName });
15
+ const newParams = { ...route.params };
16
+ delete newParams.locale;
17
+ if (i18nConfig.includeDefaultLocaleRoute) {
18
+ defaultRouteName = `localized-${defaultRouteName}`;
19
+ newParams.locale = i18nConfig.defaultLocale;
20
+ }
15
21
  return router.push(resolvedRoute);
16
22
  }
17
23
  };
@@ -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.8",
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":"7d3d3cf9-6064-4ba3-a2ec-347447f8edd0","timestamp":1723968282041,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":[]}
@@ -1,150 +0,0 @@
1
- import { defineNuxtPlugin, useRuntimeConfig } from "#app";
2
- import { useRoute, useRouter } from "#imports";
3
- const generalLocaleCache = {};
4
- const routeLocaleCache = {};
5
- const dynamicTranslationsCaches = [];
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 getTranslation(translations, key) {
15
- const value = key.split(".").reduce((acc, part) => {
16
- if (typeof acc === "object" && acc !== null && part in acc) {
17
- return acc[part];
18
- }
19
- return void 0;
20
- }, translations);
21
- if (value && typeof value === "object") {
22
- return deepClone(value);
23
- }
24
- return value ?? null;
25
- }
26
- function interpolate(template, params) {
27
- return template.replace(/\{(\w+)\}/g, (_, match) => {
28
- return params[match] !== void 0 ? String(params[match]) : `{${match}}`;
29
- });
30
- }
31
- function getPluralTranslation(translations, key) {
32
- return getTranslation(translations, key);
33
- }
34
- async function loadTranslations(locale, routeName, translationDir) {
35
- try {
36
- if (!generalLocaleCache[locale]) {
37
- const translations = await import(`~/${translationDir}/${locale}.json`);
38
- generalLocaleCache[locale] = { ...translations.default };
39
- }
40
- if (!routeLocaleCache[`${locale}:${routeName}`]) {
41
- const translations = await import(`~/${translationDir}/pages/${routeName}/${locale}.json`);
42
- routeLocaleCache[`${locale}:${routeName}`] = { ...translations.default };
43
- }
44
- } catch (error) {
45
- console.error(`Error loading translations for ${locale} and ${routeName}:`, error);
46
- }
47
- }
48
- function mergeTranslations(routeName, locale, newTranslations) {
49
- routeLocaleCache[`${locale}:${routeName}`] = {
50
- ...generalLocaleCache[locale],
51
- ...newTranslations
52
- };
53
- }
54
- function switchLocale(locale, route, router, i18nConfig) {
55
- const checkLocale = i18nConfig.locales?.find((l) => l.code === locale);
56
- if (!checkLocale) {
57
- console.warn(`Locale ${locale} is not available`);
58
- return;
59
- }
60
- const { defaultLocale } = i18nConfig;
61
- const routeName = route.name.replace(`localized-`, "");
62
- const newRouteName = locale !== defaultLocale || i18nConfig.includeDefaultLocaleRoute ? `localized-${routeName}` : routeName;
63
- const newParams = { ...route.params };
64
- delete newParams.locale;
65
- if (locale !== defaultLocale || i18nConfig.includeDefaultLocaleRoute) {
66
- newParams.locale = locale;
67
- }
68
- router.push({ name: newRouteName, params: newParams });
69
- }
70
- function getLocalizedRoute(to, router, route, i18nConfig, locale) {
71
- const { defaultLocale } = i18nConfig;
72
- const currentLocale = (locale || route.params.locale || defaultLocale).toString();
73
- const selectRoute = router.resolve(to);
74
- const routeName = selectRoute.name.replace(`localized-`, "");
75
- const newRouteName = currentLocale !== defaultLocale || i18nConfig.includeDefaultLocaleRoute ? `localized-${routeName}` : routeName;
76
- const newParams = { ...route.params };
77
- delete newParams.locale;
78
- if (currentLocale !== defaultLocale || i18nConfig.includeDefaultLocaleRoute) {
79
- newParams.locale = currentLocale;
80
- }
81
- return router.resolve({ name: newRouteName, params: newParams });
82
- }
83
- export default defineNuxtPlugin(async (_nuxtApp) => {
84
- const router = useRouter();
85
- const route = useRoute();
86
- const config = useRuntimeConfig();
87
- const i18nConfig = config.public.i18nConfig;
88
- const initialLocale = (route.params?.locale ?? i18nConfig.defaultLocale).toString();
89
- const initialRouteName = route.name.replace(`localized-`, "");
90
- const plural = new Function("return " + i18nConfig.plural)();
91
- router.beforeEach(async (to, from, next) => {
92
- const locale = (to.params?.locale ?? i18nConfig.defaultLocale).toString();
93
- const routeName = to.name.replace(`localized-`, "");
94
- if (!routeLocaleCache[`${locale}:${routeName}`]) {
95
- await loadTranslations(locale, routeName, i18nConfig.translationDir);
96
- }
97
- next();
98
- });
99
- await loadTranslations(initialLocale, initialRouteName, i18nConfig.translationDir);
100
- return {
101
- provide: {
102
- getLocale: () => (route.params?.locale ?? i18nConfig.defaultLocale).toString(),
103
- getLocales: () => i18nConfig.locales || [],
104
- t: (key, params, defaultValue) => {
105
- if (!key) {
106
- console.log(`$t: key not exist`);
107
- return "";
108
- }
109
- const locale = (route.params?.locale ?? i18nConfig.defaultLocale).toString();
110
- const routeName = route.name.replace(`localized-`, "");
111
- let value = getTranslation(routeLocaleCache[`${locale}:${routeName}`] ?? {}, key) || getTranslation(generalLocaleCache[locale] ?? {}, key) || dynamicTranslationsCaches.reduce((result, cache) => {
112
- return result || getTranslation(cache[locale] ?? {}, key);
113
- }, null);
114
- if (!value) {
115
- value = defaultValue || key;
116
- }
117
- if (typeof value === "string" && params) {
118
- value = interpolate(value, params);
119
- }
120
- return value;
121
- },
122
- tc: (key, count, defaultValue) => {
123
- if (!key) {
124
- console.log(`$tc: key not exist`);
125
- return "";
126
- }
127
- const locale = (route.params?.locale ?? i18nConfig.defaultLocale).toString();
128
- const routeName = route.name.replace(`localized-`, "");
129
- let translation = getPluralTranslation(routeLocaleCache[`${locale}:${routeName}`] ?? {}, key) || getPluralTranslation(generalLocaleCache[locale] ?? {}, key) || dynamicTranslationsCaches.reduce((result, cache) => {
130
- return result || getPluralTranslation(cache[locale] ?? {}, key);
131
- }, null);
132
- if (!translation) {
133
- translation = defaultValue || key;
134
- }
135
- return plural(translation.toString(), count, locale);
136
- },
137
- mergeTranslations: (newTranslations) => {
138
- const routeName = route.name.replace(`localized-`, "");
139
- const locale = (route.params?.locale ?? i18nConfig.defaultLocale).toString();
140
- mergeTranslations(routeName, locale, newTranslations);
141
- },
142
- switchLocale: (locale) => {
143
- switchLocale(locale, route, router, i18nConfig);
144
- },
145
- localeRoute: (to, locale) => {
146
- return getLocalizedRoute(to, router, route, i18nConfig, locale);
147
- }
148
- }
149
- };
150
- });
File without changes