nuxt-i18n-micro 1.0.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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:"3cd90d35-1876-4439-af68-a6e627aa85e6",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
11
+ <script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"edb9253f-37c1-4eb5-8989-26e4e090a752",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:"3cd90d35-1876-4439-af68-a6e627aa85e6",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
11
+ <script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"edb9253f-37c1-4eb5-8989-26e4e090a752",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
@@ -1 +1 @@
1
- {"id":"3cd90d35-1876-4439-af68-a6e627aa85e6","timestamp":1723833317042}
1
+ {"id":"edb9253f-37c1-4eb5-8989-26e4e090a752","timestamp":1723868299886}
@@ -0,0 +1 @@
1
+ {"id":"edb9253f-37c1-4eb5-8989-26e4e090a752","timestamp":1723868299886,"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:"3cd90d35-1876-4439-af68-a6e627aa85e6",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
11
+ <script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"edb9253f-37c1-4eb5-8989-26e4e090a752",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.1",
4
+ "version": "1.1.0",
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;
@@ -34,7 +34,6 @@ function setupDevToolsUI(options, resolve) {
34
34
  const pagesDir = path.join(nuxt.options.rootDir, options.translationDir || "locales", "pages");
35
35
  const localeFiles = fs.readdirSync(localesDir);
36
36
  const pageFiles = fs.readdirSync(pagesDir);
37
- console.log(1111, pageFiles);
38
37
  const locales = options.locales?.map((locale) => locale.code) || [];
39
38
  return locales.map((locale) => {
40
39
  const files = localeFiles.filter((file) => file.startsWith(locale));
@@ -79,6 +78,7 @@ const module = defineNuxtModule({
79
78
  defaultLocale: "en",
80
79
  translationDir: "locales",
81
80
  autoDetectLanguage: true,
81
+ includeDefaultLocaleRoute: false,
82
82
  plural: `function (translation, count, _locale) {
83
83
  const forms = translation.toString().split('|')
84
84
  if (count === 0 && forms.length > 2) {
@@ -99,7 +99,8 @@ const module = defineNuxtModule({
99
99
  mata: options.mata ?? true,
100
100
  defaultLocale: options.defaultLocale ?? "en",
101
101
  translationDir: options.translationDir ?? "locales",
102
- autoDetectLanguage: options.autoDetectLanguage ?? true
102
+ autoDetectLanguage: options.autoDetectLanguage ?? true,
103
+ includeDefaultLocaleRoute: options.includeDefaultLocaleRoute ?? false
103
104
  };
104
105
  addPlugin({
105
106
  src: resolver.resolve("./runtime/01.plugin"),
@@ -120,7 +121,13 @@ const module = defineNuxtModule({
120
121
  order: 3
121
122
  });
122
123
  }
123
- 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("|");
124
131
  const pagesDir = path.resolve(nuxt.options.rootDir, options.translationDir, "pages");
125
132
  extendPages((pages) => {
126
133
  nuxt.options.generate.routes = Array.isArray(nuxt.options.generate.routes) ? nuxt.options.generate.routes : [];
@@ -153,7 +160,7 @@ const module = defineNuxtModule({
153
160
  nuxt.options.generate.routes = Array.isArray(nuxt.options.generate.routes) ? nuxt.options.generate.routes : [];
154
161
  const pages = nuxt.options.generate.routes || [];
155
162
  options.locales.forEach((locale) => {
156
- if (locale.code !== options.defaultLocale) {
163
+ if (locale.code !== options.defaultLocale || options.includeDefaultLocaleRoute) {
157
164
  pages.forEach((page) => {
158
165
  routes.push(`/${locale}${page}`);
159
166
  });
@@ -162,6 +169,40 @@ const module = defineNuxtModule({
162
169
  nitroConfig.prerender = nitroConfig.prerender || {};
163
170
  nitroConfig.prerender.routes = routes;
164
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
+ });
165
206
  if (nuxt.options.dev)
166
207
  setupDevToolsUI(options, resolver.resolve);
167
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;
@@ -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
  }
@@ -143,8 +140,8 @@ export default defineNuxtPlugin(async (_nuxtApp) => {
143
140
  switchLocale: (locale) => {
144
141
  switchLocale(locale, route, router, i18nConfig);
145
142
  },
146
- localeRoute: (to) => {
147
- return getLocalizedRoute(to, router, route, i18nConfig);
143
+ localeRoute: (to, locale) => {
144
+ return getLocalizedRoute(to, router, route, i18nConfig, locale);
148
145
  }
149
146
  }
150
147
  };
@@ -10,7 +10,6 @@ export default defineNuxtPlugin(async ({ $config }) => {
10
10
  }
11
11
  const router = useRouter();
12
12
  const route = useRoute();
13
- console.log(navigator);
14
13
  const browserLanguages = navigator.languages || [navigator.language];
15
14
  let detectedLocale = defaultLocale;
16
15
  for (const language of browserLanguages) {
@@ -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.1",
3
+ "version": "1.1.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",
@@ -1 +0,0 @@
1
- {"id":"3cd90d35-1876-4439-af68-a6e627aa85e6","timestamp":1723833317042,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":[]}