nuxt-i18n-micro 1.0.2 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -172,6 +172,49 @@ $mergeTranslations({
172
172
  })
173
173
  ```
174
174
 
175
+ ## Example
176
+
177
+ ```vue
178
+ <template>
179
+ <div>
180
+ <p>{{ $t('key2.key2.key2.key2.key2') }}</p>
181
+ <p>Current Locale: {{ $getLocale() }}</p>
182
+
183
+ <div>
184
+ {{ $t('welcome', { username: 'Alice', unreadCount: 5 }) }}
185
+ </div>
186
+ <div>
187
+ {{ $tc('apples', 10) }}
188
+ </div>
189
+
190
+ <!-- Ссылки для переключения локалей -->
191
+ <div>
192
+ <button
193
+ v-for="locale in $getLocales()"
194
+ :key="locale"
195
+ :disabled="locale === $getLocale()"
196
+ @click="$switchLocale(locale.code)"
197
+ >
198
+ Switch to {{ locale.code }}
199
+ </button>
200
+ </div>
201
+
202
+ <div>
203
+ <NuxtLink :to="$localeRoute({ name: 'index' })">
204
+ Go to Index
205
+ </NuxtLink>
206
+ </div>
207
+ </div>
208
+ </template>
209
+
210
+ <script setup>
211
+ import { useNuxtApp } from '#imports'
212
+
213
+ const { $getLocale, $switchLocale, $getLocales, $localeRoute, $t, $tc } = useNuxtApp()
214
+ </script>
215
+
216
+ ```
217
+
175
218
  ## Module Options
176
219
 
177
220
  The module accepts the following options in the Nuxt configuration:
@@ -190,6 +233,7 @@ The module accepts the following options in the Nuxt configuration:
190
233
  - **translationDir**: The directory where translation files are stored (e.g., `'locales'`).
191
234
  - **autoDetectLanguage**: If `true`, automatically detects the user's preferred language and redirects accordingly.
192
235
  - **plural**: A custom function for handling pluralization.
236
+ - **includeDefaultLocaleRoute**: A boolean. If enabled, all routes without a locale prefix will redirect to the default locale route.
193
237
 
194
238
  ## Conclusion
195
239
 
@@ -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:"6fa5f1c4-7792-4532-81ae-df404f7e3080",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
11
+ <script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"c53d284f-1ca1-4e93-bf70-990155baabf5",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:"6fa5f1c4-7792-4532-81ae-df404f7e3080",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
11
+ <script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"c53d284f-1ca1-4e93-bf70-990155baabf5",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
@@ -1 +1 @@
1
- {"id":"6fa5f1c4-7792-4532-81ae-df404f7e3080","timestamp":1723833597061}
1
+ {"id":"c53d284f-1ca1-4e93-bf70-990155baabf5","timestamp":1723869304838}
@@ -0,0 +1 @@
1
+ {"id":"c53d284f-1ca1-4e93-bf70-990155baabf5","timestamp":1723869304838,"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:"6fa5f1c4-7792-4532-81ae-df404f7e3080",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
11
+ <script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"c53d284f-1ca1-4e93-bf70-990155baabf5",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
package/dist/module.d.mts CHANGED
@@ -12,6 +12,7 @@ interface ModuleOptions {
12
12
  defaultLocale?: string;
13
13
  translationDir?: string;
14
14
  autoDetectLanguage?: boolean;
15
+ includeDefaultLocaleRoute?: boolean;
15
16
  plural?: string;
16
17
  }
17
18
  declare const _default: _nuxt_schema.NuxtModule<ModuleOptions>;
package/dist/module.d.ts CHANGED
@@ -12,6 +12,7 @@ interface ModuleOptions {
12
12
  defaultLocale?: string;
13
13
  translationDir?: string;
14
14
  autoDetectLanguage?: boolean;
15
+ includeDefaultLocaleRoute?: boolean;
15
16
  plural?: string;
16
17
  }
17
18
  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.0.2",
4
+ "version": "1.1.1",
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, extendPages } from '@nuxt/kit';
4
+ import { useNuxt, defineNuxtModule, createResolver, addPlugin, extendPages, addTypeTemplate } from '@nuxt/kit';
5
5
  import { onDevToolsInitialized, extendServerRpc } from '@nuxt/devtools-kit';
6
6
 
7
7
  const DEVTOOLS_UI_PORT = 3030;
@@ -78,6 +78,7 @@ const module = defineNuxtModule({
78
78
  defaultLocale: "en",
79
79
  translationDir: "locales",
80
80
  autoDetectLanguage: true,
81
+ includeDefaultLocaleRoute: false,
81
82
  plural: `function (translation, count, _locale) {
82
83
  const forms = translation.toString().split('|')
83
84
  if (count === 0 && forms.length > 2) {
@@ -98,7 +99,8 @@ const module = defineNuxtModule({
98
99
  mata: options.mata ?? true,
99
100
  defaultLocale: options.defaultLocale ?? "en",
100
101
  translationDir: options.translationDir ?? "locales",
101
- autoDetectLanguage: options.autoDetectLanguage ?? true
102
+ autoDetectLanguage: options.autoDetectLanguage ?? true,
103
+ includeDefaultLocaleRoute: options.includeDefaultLocaleRoute ?? false
102
104
  };
103
105
  addPlugin({
104
106
  src: resolver.resolve("./runtime/01.plugin"),
@@ -119,7 +121,13 @@ const module = defineNuxtModule({
119
121
  order: 3
120
122
  });
121
123
  }
122
- const localeRegex = options.locales.filter((locale) => locale.code !== options.defaultLocale).map((locale) => locale.code).join("|");
124
+ if (options.includeDefaultLocaleRoute) {
125
+ addPlugin({
126
+ src: resolver.resolve("./runtime/05.default-locale-redirect"),
127
+ order: 4
128
+ });
129
+ }
130
+ const localeRegex = options.locales.filter((locale) => locale.code !== options.defaultLocale || options.includeDefaultLocaleRoute).map((locale) => locale.code).join("|");
123
131
  const pagesDir = path.resolve(nuxt.options.rootDir, options.translationDir, "pages");
124
132
  extendPages((pages) => {
125
133
  nuxt.options.generate.routes = Array.isArray(nuxt.options.generate.routes) ? nuxt.options.generate.routes : [];
@@ -152,7 +160,7 @@ const module = defineNuxtModule({
152
160
  nuxt.options.generate.routes = Array.isArray(nuxt.options.generate.routes) ? nuxt.options.generate.routes : [];
153
161
  const pages = nuxt.options.generate.routes || [];
154
162
  options.locales.forEach((locale) => {
155
- if (locale.code !== options.defaultLocale) {
163
+ if (locale.code !== options.defaultLocale || options.includeDefaultLocaleRoute) {
156
164
  pages.forEach((page) => {
157
165
  routes.push(`/${locale}${page}`);
158
166
  });
@@ -161,6 +169,40 @@ const module = defineNuxtModule({
161
169
  nitroConfig.prerender = nitroConfig.prerender || {};
162
170
  nitroConfig.prerender.routes = routes;
163
171
  });
172
+ addTypeTemplate({
173
+ filename: "types/i18n.d.ts",
174
+ getContents() {
175
+ return `
176
+ interface PluralTranslations {
177
+ singular: string;
178
+ plural: string;
179
+ }
180
+
181
+ interface Translations {
182
+ [key: string]: string | number | boolean | Translations | PluralTranslations | unknown[] | null;
183
+ }
184
+
185
+ declare module '#app' {
186
+ interface NuxtApp {
187
+ $getLocale: () => string;
188
+ $getLocales: () => string[];
189
+ $t: <T extends Record<string, string | number | boolean>>(
190
+ key: string,
191
+ params?: T,
192
+ defaultValue?: string
193
+ ) => string | number | boolean | Translations | PluralTranslations | unknown[] | unknown | null;
194
+ $tc: (key: string, count: number, defaultValue?: string) => string;
195
+ $mergeTranslations: (newTranslations: Translations) => void;
196
+ $switchLocale: (locale: string) => void;
197
+ $localeRoute: (to: RouteLocationRaw, locale?: string) => RouteLocationRaw;
198
+ $loadPageTranslations: (locale: string, routeName: string) => Promise<void>;
199
+ }
200
+ }
201
+
202
+ export {};
203
+ `;
204
+ }
205
+ });
164
206
  if (nuxt.options.dev)
165
207
  setupDevToolsUI(options, resolver.resolve);
166
208
  }
@@ -13,7 +13,7 @@ declare const _default: import("#app").Plugin<{
13
13
  tc: (key: string, count: number, defaultValue?: string) => string;
14
14
  mergeTranslations: (newTranslations: Translations) => void;
15
15
  switchLocale: (locale: string) => void;
16
- localeRoute: (to: RouteLocationRaw) => RouteLocationRaw;
16
+ localeRoute: (to: RouteLocationRaw, locale?: string) => RouteLocationRaw;
17
17
  }> & import("#app").ObjectPlugin<{
18
18
  getLocale: () => string;
19
19
  getLocales: () => import("~/src/module").Locale[];
@@ -21,6 +21,6 @@ declare const _default: import("#app").Plugin<{
21
21
  tc: (key: string, count: number, defaultValue?: string) => string;
22
22
  mergeTranslations: (newTranslations: Translations) => void;
23
23
  switchLocale: (locale: string) => void;
24
- localeRoute: (to: RouteLocationRaw) => RouteLocationRaw;
24
+ localeRoute: (to: RouteLocationRaw, locale?: string) => RouteLocationRaw;
25
25
  }>;
26
26
  export default _default;
@@ -1,5 +1,5 @@
1
1
  import { defineNuxtPlugin, useRuntimeConfig } from "#app";
2
- import { useRoute, useRouter, watch } from "#imports";
2
+ import { useRoute, useRouter } from "#imports";
3
3
  const generalLocaleCache = {};
4
4
  const routeLocaleCache = {};
5
5
  const dynamicTranslationsCaches = [];
@@ -58,29 +58,26 @@ function switchLocale(locale, route, router, i18nConfig) {
58
58
  return;
59
59
  }
60
60
  const { defaultLocale } = i18nConfig;
61
- const currentLocale = route.params.locale || defaultLocale;
62
- let routeName = route.name;
63
- if (currentLocale !== defaultLocale) {
64
- routeName = routeName.replace(`localized-`, "");
65
- }
66
- const newRouteName = locale === defaultLocale ? routeName : `localized-${routeName}`;
61
+ const routeName = route.name.replace(`localized-`, "");
62
+ const newRouteName = locale !== defaultLocale || i18nConfig.includeDefaultLocaleRoute ? `localized-${routeName}` : routeName;
67
63
  const newParams = { ...route.params };
68
64
  delete newParams.locale;
69
- if (locale !== defaultLocale) {
65
+ if (locale !== defaultLocale || i18nConfig.includeDefaultLocaleRoute) {
70
66
  newParams.locale = locale;
71
67
  }
72
68
  window.location.href = router.resolve({ name: newRouteName, params: newParams }).fullPath;
73
69
  }
74
- function getLocalizedRoute(to, router, route, i18nConfig) {
70
+ function getLocalizedRoute(to, router, route, i18nConfig, locale) {
75
71
  const { defaultLocale } = i18nConfig;
76
- const currentLocale = (route.params.locale || defaultLocale).toString();
72
+ const currentLocale = (locale || route.params.locale || defaultLocale).toString();
77
73
  let resolvedRoute = router.resolve(to);
78
74
  if (typeof to === "object" && "name" in to) {
79
75
  resolvedRoute = router.resolve({ name: to.name, params: to.params, query: to.query, hash: to.hash });
80
76
  delete resolvedRoute.params.locale;
81
77
  if (resolvedRoute.name) {
82
- resolvedRoute.name = currentLocale === defaultLocale ? resolvedRoute.name.replace(`localized-`, "") : `localized-${resolvedRoute.name.toString()}`;
83
- if (defaultLocale !== currentLocale) {
78
+ const routeName = resolvedRoute.name.replace(`localized-`, "");
79
+ resolvedRoute.name = currentLocale !== defaultLocale || i18nConfig.includeDefaultLocaleRoute ? `localized-${routeName}` : routeName;
80
+ if (defaultLocale !== currentLocale || i18nConfig.includeDefaultLocaleRoute) {
84
81
  resolvedRoute.params.locale = currentLocale;
85
82
  }
86
83
  }
@@ -95,17 +92,15 @@ export default defineNuxtPlugin(async (_nuxtApp) => {
95
92
  const initialLocale = (route.params?.locale ?? i18nConfig.defaultLocale).toString();
96
93
  const initialRouteName = route.name.replace(`localized-`, "");
97
94
  const plural = new Function("return " + i18nConfig.plural)();
98
- await loadTranslations(initialLocale, initialRouteName, i18nConfig.translationDir);
99
- let init = false;
100
- watch(route, async () => {
101
- if (!init) {
102
- init = true;
103
- return;
95
+ router.beforeEach(async (to, from, next) => {
96
+ const locale = (to.params?.locale ?? i18nConfig.defaultLocale).toString();
97
+ const routeName = to.name.replace(`localized-`, "");
98
+ if (!routeLocaleCache[`${locale}:${routeName}`]) {
99
+ await loadTranslations(locale, routeName, i18nConfig.translationDir);
104
100
  }
105
- const locale = (route.params?.locale ?? i18nConfig.defaultLocale).toString();
106
- const routeName = route.name.replace(`localized-`, "");
107
- await loadTranslations(locale, routeName, i18nConfig.translationDir);
108
- }, { immediate: true });
101
+ next();
102
+ });
103
+ await loadTranslations(initialLocale, initialRouteName, i18nConfig.translationDir);
109
104
  return {
110
105
  provide: {
111
106
  getLocale: () => (route.params?.locale ?? i18nConfig.defaultLocale).toString(),
@@ -143,8 +138,8 @@ export default defineNuxtPlugin(async (_nuxtApp) => {
143
138
  switchLocale: (locale) => {
144
139
  switchLocale(locale, route, router, i18nConfig);
145
140
  },
146
- localeRoute: (to) => {
147
- return getLocalizedRoute(to, router, route, i18nConfig);
141
+ localeRoute: (to, locale) => {
142
+ return getLocalizedRoute(to, router, route, i18nConfig, locale);
148
143
  }
149
144
  }
150
145
  };
@@ -0,0 +1,2 @@
1
+ declare const _default: import("#app").Plugin<Record<string, unknown>> & import("#app").ObjectPlugin<Record<string, unknown>>;
2
+ export default _default;
@@ -0,0 +1,28 @@
1
+ import { defineNuxtPlugin, navigateTo } from "#app";
2
+ import { useRoute, useRouter, watch, computed } from "#imports";
3
+ export default defineNuxtPlugin(async ({ $config }) => {
4
+ const i18nConfig = $config.public.i18nConfig;
5
+ const router = useRouter();
6
+ const route = useRoute();
7
+ if (!route.params?.locale) {
8
+ const routeName = route.name;
9
+ const newRouteName = `localized-${routeName}`;
10
+ const newParams = { ...route.params, locale: i18nConfig.defaultLocale };
11
+ if (import.meta.client) {
12
+ location.href = router.resolve({ name: newRouteName, params: newParams }).href;
13
+ } else {
14
+ await navigateTo({ name: newRouteName, params: newParams }, { redirectCode: 301 });
15
+ }
16
+ }
17
+ if (import.meta.client) {
18
+ const routeName = computed(() => route.name);
19
+ watch(routeName, async () => {
20
+ if (!route.params?.locale) {
21
+ const routeName2 = route.name;
22
+ const newRouteName = `localized-${routeName2}`;
23
+ const newParams = { ...route.params, locale: i18nConfig.defaultLocale };
24
+ await navigateTo({ name: newRouteName, params: newParams }, { redirectCode: 301 });
25
+ }
26
+ });
27
+ }
28
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-i18n-micro",
3
- "version": "1.0.2",
3
+ "version": "1.1.1",
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":"6fa5f1c4-7792-4532-81ae-df404f7e3080","timestamp":1723833597061,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":[]}