nuxt-i18n-micro 1.12.1 → 1.12.3
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/dist/client/200.html +1 -1
- package/dist/client/404.html +1 -1
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/e3198b53-a0ca-4886-aad7-085d6bae4a55.json +1 -0
- package/dist/client/index.html +1 -1
- package/dist/module.d.mts +3 -2
- package/dist/module.d.ts +3 -2
- package/dist/module.json +1 -1
- package/dist/module.mjs +251 -194
- package/dist/runtime/components/i18n-link.vue +2 -2
- package/dist/runtime/plugins/01.plugin.d.ts +2 -2
- package/dist/types.d.mts +6 -2
- package/dist/types.d.ts +6 -2
- package/package.json +1 -1
- package/dist/client/_nuxt/builds/meta/1ab60d52-2c05-4618-8e25-19d2de5cb6af.json +0 -1
package/dist/client/200.html
CHANGED
|
@@ -9,4 +9,4 @@
|
|
|
9
9
|
<link rel="prefetch" as="style" href="/__nuxt-i18n-micro/_nuxt/error-500.21ZDxC33.css">
|
|
10
10
|
<link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/DzdJBprQ.js">
|
|
11
11
|
<script type="module" src="/__nuxt-i18n-micro/_nuxt/D1fvHJQV.js" crossorigin></script></head><body><div id="__nuxt"></div><div id="teleports"></div><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"serverRendered":1},false]</script>
|
|
12
|
-
<script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"
|
|
12
|
+
<script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"e3198b53-a0ca-4886-aad7-085d6bae4a55",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
|
package/dist/client/404.html
CHANGED
|
@@ -9,4 +9,4 @@
|
|
|
9
9
|
<link rel="prefetch" as="style" href="/__nuxt-i18n-micro/_nuxt/error-500.21ZDxC33.css">
|
|
10
10
|
<link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/DzdJBprQ.js">
|
|
11
11
|
<script type="module" src="/__nuxt-i18n-micro/_nuxt/D1fvHJQV.js" crossorigin></script></head><body><div id="__nuxt"></div><div id="teleports"></div><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"serverRendered":1},false]</script>
|
|
12
|
-
<script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"
|
|
12
|
+
<script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"e3198b53-a0ca-4886-aad7-085d6bae4a55",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"id":"
|
|
1
|
+
{"id":"e3198b53-a0ca-4886-aad7-085d6bae4a55","timestamp":1725274464836}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"id":"e3198b53-a0ca-4886-aad7-085d6bae4a55","timestamp":1725274464836,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":[]}
|
package/dist/client/index.html
CHANGED
|
@@ -9,4 +9,4 @@
|
|
|
9
9
|
<link rel="prefetch" as="style" href="/__nuxt-i18n-micro/_nuxt/error-500.21ZDxC33.css">
|
|
10
10
|
<link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/DzdJBprQ.js">
|
|
11
11
|
<script type="module" src="/__nuxt-i18n-micro/_nuxt/D1fvHJQV.js" crossorigin></script></head><body><div id="__nuxt"></div><div id="teleports"></div><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"serverRendered":1},false]</script>
|
|
12
|
-
<script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"
|
|
12
|
+
<script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"e3198b53-a0ca-4886-aad7-085d6bae4a55",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
|
package/dist/module.d.mts
CHANGED
|
@@ -23,11 +23,12 @@ interface ModuleOptions {
|
|
|
23
23
|
}
|
|
24
24
|
interface ModuleOptionsExtend extends ModuleOptions {
|
|
25
25
|
rootDir: string;
|
|
26
|
-
|
|
26
|
+
plural: string;
|
|
27
27
|
rootDirs: string[];
|
|
28
28
|
dateBuild: number;
|
|
29
29
|
baseURL: string;
|
|
30
30
|
}
|
|
31
|
+
|
|
31
32
|
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
|
|
32
33
|
|
|
33
34
|
interface ModuleHooks {
|
|
@@ -51,4 +52,4 @@ declare module '@nuxt/schema' {
|
|
|
51
52
|
}
|
|
52
53
|
}
|
|
53
54
|
|
|
54
|
-
export { type
|
|
55
|
+
export { type ModuleHooks, _default as default };
|
package/dist/module.d.ts
CHANGED
|
@@ -23,11 +23,12 @@ interface ModuleOptions {
|
|
|
23
23
|
}
|
|
24
24
|
interface ModuleOptionsExtend extends ModuleOptions {
|
|
25
25
|
rootDir: string;
|
|
26
|
-
|
|
26
|
+
plural: string;
|
|
27
27
|
rootDirs: string[];
|
|
28
28
|
dateBuild: number;
|
|
29
29
|
baseURL: string;
|
|
30
30
|
}
|
|
31
|
+
|
|
31
32
|
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
|
|
32
33
|
|
|
33
34
|
interface ModuleHooks {
|
|
@@ -51,4 +52,4 @@ declare module '@nuxt/schema' {
|
|
|
51
52
|
}
|
|
52
53
|
}
|
|
53
54
|
|
|
54
|
-
export { type
|
|
55
|
+
export { type ModuleHooks, _default as default };
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
+
import { useNuxt, defineNuxtModule, createResolver, addPlugin, addImportsDir, addServerHandler, addComponentsDir, extendPages } from '@nuxt/kit';
|
|
3
|
+
import { watch } from 'chokidar';
|
|
2
4
|
import * as fs from 'node:fs';
|
|
3
5
|
import { readFileSync, existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
4
|
-
import { useNuxt, defineNuxtModule, createResolver, addPlugin, addImportsDir, addServerHandler, addComponentsDir, extendPages, addPrerenderRoutes } from '@nuxt/kit';
|
|
5
|
-
import { watch } from 'chokidar';
|
|
6
6
|
import { onDevToolsInitialized, extendServerRpc } from '@nuxt/devtools-kit';
|
|
7
7
|
|
|
8
8
|
const DEVTOOLS_UI_PORT = 3030;
|
|
@@ -88,6 +88,248 @@ function setupDevToolsUI(options, resolve) {
|
|
|
88
88
|
});
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
function extractDefineI18nRouteConfig(content, filePath) {
|
|
92
|
+
const match = content.match(/^[ \t]*\$defineI18nRoute\((\{[\s\S]*?\})\)/m);
|
|
93
|
+
if (match && match[1]) {
|
|
94
|
+
try {
|
|
95
|
+
const parsedObject = Function('"use strict";return (' + match[1] + ")")();
|
|
96
|
+
if (validateDefineI18nRouteConfig(parsedObject)) {
|
|
97
|
+
return parsedObject;
|
|
98
|
+
} else {
|
|
99
|
+
console.error("Invalid defineI18nRoute configuration format:", parsedObject, "in file: ", filePath);
|
|
100
|
+
}
|
|
101
|
+
} catch (error) {
|
|
102
|
+
console.error("Failed to parse defineI18nRoute configuration:", error, "in file: ", filePath);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
function validateDefineI18nRouteConfig(obj) {
|
|
108
|
+
if (typeof obj !== "object" || obj === null)
|
|
109
|
+
return false;
|
|
110
|
+
if (obj.locales) {
|
|
111
|
+
if (typeof obj.locales !== "object")
|
|
112
|
+
return false;
|
|
113
|
+
for (const localeKey in obj.locales) {
|
|
114
|
+
const translations = obj.locales[localeKey];
|
|
115
|
+
if (typeof translations !== "object" || translations === null)
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (obj.localeRoutes) {
|
|
120
|
+
if (typeof obj.localeRoutes !== "object")
|
|
121
|
+
return false;
|
|
122
|
+
for (const routeKey in obj.localeRoutes) {
|
|
123
|
+
if (typeof obj.localeRoutes[routeKey] !== "string")
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
const normalizePath = (routePath) => path.posix.normalize(routePath).replace(/\/+$/, "");
|
|
130
|
+
const cloneArray = (array) => [...array];
|
|
131
|
+
const isPageRedirectOnly = (page) => !!(page.redirect && !page.file);
|
|
132
|
+
const removeLeadingSlash = (routePath) => routePath.startsWith("/") ? routePath.slice(1) : routePath;
|
|
133
|
+
const buildRouteName = (baseName, localeCode, isCustom) => isCustom ? `localized-${baseName}-${localeCode}` : `localized-${baseName}`;
|
|
134
|
+
const shouldAddLocalePrefix = (locale, defaultLocale, addLocalePrefix, includeDefaultLocaleRoute) => addLocalePrefix && !(locale === defaultLocale.code && !includeDefaultLocaleRoute);
|
|
135
|
+
const isLocaleDefault = (locale, defaultLocale, includeDefaultLocaleRoute) => {
|
|
136
|
+
const localeCode = typeof locale === "string" ? locale : locale.code;
|
|
137
|
+
return localeCode === defaultLocale.code && !includeDefaultLocaleRoute;
|
|
138
|
+
};
|
|
139
|
+
const buildFullPath = (locale, basePath) => {
|
|
140
|
+
const localeParam = Array.isArray(locale) ? locale.join("|") : locale;
|
|
141
|
+
return normalizePath(path.join(`/:locale(${localeParam})`, basePath));
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
class PageManager {
|
|
145
|
+
locales;
|
|
146
|
+
defaultLocale;
|
|
147
|
+
includeDefaultLocaleRoute;
|
|
148
|
+
localizedPaths = {};
|
|
149
|
+
activeLocaleCodes;
|
|
150
|
+
constructor(locales, defaultLocaleCode, includeDefaultLocaleRoute) {
|
|
151
|
+
this.locales = locales;
|
|
152
|
+
this.defaultLocale = this.findDefaultLocale(defaultLocaleCode);
|
|
153
|
+
this.includeDefaultLocaleRoute = includeDefaultLocaleRoute;
|
|
154
|
+
this.activeLocaleCodes = this.calculateActiveLocaleCodes();
|
|
155
|
+
}
|
|
156
|
+
findDefaultLocale(defaultLocaleCode) {
|
|
157
|
+
return this.locales.find((locale) => locale.code === defaultLocaleCode) || { code: defaultLocaleCode };
|
|
158
|
+
}
|
|
159
|
+
extendPages(pages, options, rootDir) {
|
|
160
|
+
this.localizedPaths = this.extractLocalizedPaths(pages, rootDir);
|
|
161
|
+
const additionalRoutes = [];
|
|
162
|
+
pages.forEach((page) => this.localizePage(page, additionalRoutes));
|
|
163
|
+
pages.push(...additionalRoutes);
|
|
164
|
+
}
|
|
165
|
+
calculateActiveLocaleCodes() {
|
|
166
|
+
return this.locales.filter((locale) => locale.code !== this.defaultLocale.code || this.includeDefaultLocaleRoute).map((locale) => locale.code);
|
|
167
|
+
}
|
|
168
|
+
extractLocalizedPaths(pages, rootDir, parentPath = "") {
|
|
169
|
+
const localizedPaths = {};
|
|
170
|
+
pages.forEach((page) => {
|
|
171
|
+
if (page.file) {
|
|
172
|
+
const filePath = path.resolve(rootDir, page.file);
|
|
173
|
+
const fileContent = readFileSync(filePath, "utf-8");
|
|
174
|
+
const i18nRouteConfig = extractDefineI18nRouteConfig(fileContent, filePath);
|
|
175
|
+
if (i18nRouteConfig?.localeRoutes) {
|
|
176
|
+
const normalizedFullPath = normalizePath(path.join(parentPath, page.path));
|
|
177
|
+
localizedPaths[normalizedFullPath] = i18nRouteConfig.localeRoutes;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (page.children?.length) {
|
|
181
|
+
const parentFullPath = normalizePath(path.join(parentPath, page.path));
|
|
182
|
+
Object.assign(localizedPaths, this.extractLocalizedPaths(page.children, rootDir, parentFullPath));
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
return localizedPaths;
|
|
186
|
+
}
|
|
187
|
+
localizePage(page, additionalRoutes) {
|
|
188
|
+
if (isPageRedirectOnly(page))
|
|
189
|
+
return;
|
|
190
|
+
const originalChildren = cloneArray(page.children ?? []);
|
|
191
|
+
const normalizedFullPath = normalizePath(page.path);
|
|
192
|
+
const localeCodesWithoutCustomPaths = this.filterLocaleCodesWithoutCustomPaths(normalizedFullPath);
|
|
193
|
+
if (localeCodesWithoutCustomPaths.length) {
|
|
194
|
+
additionalRoutes.push(this.createLocalizedRoute(page, localeCodesWithoutCustomPaths, originalChildren, false));
|
|
195
|
+
}
|
|
196
|
+
this.addCustomLocalizedRoutes(page, normalizedFullPath, originalChildren, additionalRoutes);
|
|
197
|
+
this.adjustRouteForDefaultLocale(page, originalChildren);
|
|
198
|
+
}
|
|
199
|
+
filterLocaleCodesWithoutCustomPaths(fullPath) {
|
|
200
|
+
return this.activeLocaleCodes.filter((code) => !this.localizedPaths[fullPath]?.[code]);
|
|
201
|
+
}
|
|
202
|
+
adjustRouteForDefaultLocale(page, originalChildren) {
|
|
203
|
+
const defaultLocalePath = this.localizedPaths[page.path]?.[this.defaultLocale.code];
|
|
204
|
+
if (defaultLocalePath) {
|
|
205
|
+
page.path = normalizePath(defaultLocalePath);
|
|
206
|
+
}
|
|
207
|
+
const currentChildren = page.children ? [...page.children] : [];
|
|
208
|
+
if (originalChildren.length) {
|
|
209
|
+
const newName = normalizePath(path.join("/", page.name ?? ""));
|
|
210
|
+
const localizedChildren = this.mergeChildren(originalChildren, newName, [this.defaultLocale.code]);
|
|
211
|
+
const childrenMap = new Map(currentChildren.map((child) => [child.name, child]));
|
|
212
|
+
localizedChildren.forEach((localizedChild) => {
|
|
213
|
+
if (childrenMap.has(localizedChild.name)) {
|
|
214
|
+
const existingChild = childrenMap.get(localizedChild.name);
|
|
215
|
+
if (existingChild) {
|
|
216
|
+
Object.assign(existingChild, localizedChild);
|
|
217
|
+
}
|
|
218
|
+
} else {
|
|
219
|
+
currentChildren.push(localizedChild);
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
page.children = currentChildren;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
mergeChildren(originalChildren, parentPath, localeCodes) {
|
|
226
|
+
const localizedChildren = this.createLocalizedChildren(originalChildren, parentPath, localeCodes, false);
|
|
227
|
+
return [...originalChildren, ...localizedChildren];
|
|
228
|
+
}
|
|
229
|
+
addCustomLocalizedRoutes(page, fullPath, originalChildren, additionalRoutes) {
|
|
230
|
+
this.locales.forEach((locale) => {
|
|
231
|
+
const customPath = this.localizedPaths[fullPath]?.[locale.code];
|
|
232
|
+
if (!customPath)
|
|
233
|
+
return;
|
|
234
|
+
const isDefaultLocale = isLocaleDefault(locale, this.defaultLocale, this.includeDefaultLocaleRoute);
|
|
235
|
+
if (isDefaultLocale) {
|
|
236
|
+
page.children = this.createLocalizedChildren(originalChildren, "", [locale.code], false);
|
|
237
|
+
} else {
|
|
238
|
+
additionalRoutes.push(this.createLocalizedRoute(page, [locale.code], originalChildren, true, customPath));
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
createLocalizedChildren(routes, parentPath, localeCodes, modifyName = true, addLocalePrefix = false) {
|
|
243
|
+
return routes.flatMap((route) => this.createLocalizedVariants(route, parentPath, localeCodes, modifyName, addLocalePrefix));
|
|
244
|
+
}
|
|
245
|
+
createLocalizedVariants(route, parentPath, localeCodes, modifyName, addLocalePrefix) {
|
|
246
|
+
const routePath = normalizePath(route.path);
|
|
247
|
+
const fullPath = normalizePath(path.join(parentPath, routePath));
|
|
248
|
+
const customLocalePaths = this.localizedPaths[fullPath];
|
|
249
|
+
const localizedChildren = this.createLocalizedChildren(route.children ?? [], fullPath, localeCodes, modifyName);
|
|
250
|
+
return localeCodes.map((locale) => this.createLocalizedChildRoute(route, routePath, locale, customLocalePaths, localizedChildren, modifyName, addLocalePrefix));
|
|
251
|
+
}
|
|
252
|
+
createLocalizedRoute(page, localeCodes, originalChildren, isCustom, customPath = "") {
|
|
253
|
+
const routePath = this.buildRoutePath(localeCodes, page.path, customPath, isCustom);
|
|
254
|
+
const routeName = buildRouteName(page.name ?? "", localeCodes[0], isCustom);
|
|
255
|
+
return {
|
|
256
|
+
...page,
|
|
257
|
+
children: this.createLocalizedChildren(originalChildren, page.path, localeCodes, true),
|
|
258
|
+
path: routePath,
|
|
259
|
+
name: routeName
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
createLocalizedChildRoute(route, routePath, locale, customLocalePaths, children, modifyName, addLocalePrefix) {
|
|
263
|
+
const finalPath = this.buildLocalizedRoutePath(routePath, locale, customLocalePaths, addLocalePrefix);
|
|
264
|
+
const routeName = this.buildLocalizedRouteName(route.name ?? "", locale, modifyName);
|
|
265
|
+
return {
|
|
266
|
+
...route,
|
|
267
|
+
name: routeName,
|
|
268
|
+
path: removeLeadingSlash(finalPath),
|
|
269
|
+
children
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
buildLocalizedRoutePath(routePath, locale, customLocalePaths, addLocalePrefix) {
|
|
273
|
+
const basePath = customLocalePaths?.[locale] || routePath;
|
|
274
|
+
const normalizedBasePath = normalizePath(basePath);
|
|
275
|
+
return shouldAddLocalePrefix(locale, this.defaultLocale, addLocalePrefix, this.includeDefaultLocaleRoute) ? buildFullPath(locale, normalizedBasePath) : normalizedBasePath;
|
|
276
|
+
}
|
|
277
|
+
buildLocalizedRouteName(baseName, locale, modifyName) {
|
|
278
|
+
return modifyName && !isLocaleDefault(locale, this.defaultLocale, this.includeDefaultLocaleRoute) ? `localized-${baseName}-${locale}` : baseName;
|
|
279
|
+
}
|
|
280
|
+
buildRoutePath(localeCodes, originalPath, customPath, isCustom) {
|
|
281
|
+
if (isCustom) {
|
|
282
|
+
return this.includeDefaultLocaleRoute || !localeCodes.includes(this.defaultLocale.code) ? buildFullPath(localeCodes, customPath) : normalizePath(customPath);
|
|
283
|
+
}
|
|
284
|
+
return buildFullPath(localeCodes, originalPath);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
class LocaleManager {
|
|
289
|
+
locales;
|
|
290
|
+
options;
|
|
291
|
+
rootDirs;
|
|
292
|
+
defaultLocale;
|
|
293
|
+
constructor(options, rootDirs) {
|
|
294
|
+
this.options = options;
|
|
295
|
+
this.rootDirs = rootDirs;
|
|
296
|
+
this.locales = this.mergeLocales(options.locales ?? []);
|
|
297
|
+
this.defaultLocale = options.defaultLocale ?? "en";
|
|
298
|
+
}
|
|
299
|
+
mergeLocales(locales) {
|
|
300
|
+
return locales.reduce((acc, locale) => {
|
|
301
|
+
const existingLocale = acc.find((l) => l.code === locale.code);
|
|
302
|
+
if (existingLocale) {
|
|
303
|
+
Object.assign(existingLocale, locale);
|
|
304
|
+
} else {
|
|
305
|
+
acc.push(locale);
|
|
306
|
+
}
|
|
307
|
+
return acc;
|
|
308
|
+
}, []).filter((locale) => !locale.disabled);
|
|
309
|
+
}
|
|
310
|
+
ensureTranslationFilesExist(pagesNames, translationDir, rootDir) {
|
|
311
|
+
this.locales.forEach((locale) => {
|
|
312
|
+
const globalFilePath = path.join(rootDir, translationDir, `${locale.code}.json`);
|
|
313
|
+
this.ensureFileExists(globalFilePath);
|
|
314
|
+
if (!this.options.disablePageLocales) {
|
|
315
|
+
pagesNames.forEach((name) => {
|
|
316
|
+
const pageFilePath = path.join(rootDir, translationDir, "pages", `${name}/${locale.code}.json`);
|
|
317
|
+
this.ensureFileExists(pageFilePath);
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
ensureFileExists(filePath) {
|
|
323
|
+
const fileDir = path.dirname(filePath);
|
|
324
|
+
if (!existsSync(fileDir)) {
|
|
325
|
+
mkdirSync(fileDir, { recursive: true });
|
|
326
|
+
}
|
|
327
|
+
if (!existsSync(filePath)) {
|
|
328
|
+
writeFileSync(filePath, JSON.stringify({}), "utf-8");
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
91
333
|
const module = defineNuxtModule({
|
|
92
334
|
meta: {
|
|
93
335
|
name: "nuxt-i18n-micro",
|
|
@@ -119,20 +361,13 @@ const module = defineNuxtModule({
|
|
|
119
361
|
async setup(options, nuxt) {
|
|
120
362
|
const resolver = createResolver(import.meta.url);
|
|
121
363
|
const rootDirs = nuxt.options._layers.map((layer) => layer.config.rootDir).reverse();
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
if (existingLocale) {
|
|
125
|
-
Object.assign(existingLocale, locale);
|
|
126
|
-
} else {
|
|
127
|
-
acc.push(locale);
|
|
128
|
-
}
|
|
129
|
-
return acc;
|
|
130
|
-
}, []).filter((locale) => !locale.disabled);
|
|
364
|
+
const localeManager = new LocaleManager(options, rootDirs);
|
|
365
|
+
const pageManager = new PageManager(localeManager.locales, options.defaultLocale, options.includeDefaultLocaleRoute);
|
|
131
366
|
nuxt.options.runtimeConfig.public.i18nConfig = {
|
|
132
367
|
rootDir: nuxt.options.rootDir,
|
|
133
368
|
rootDirs,
|
|
134
369
|
plural: options.plural,
|
|
135
|
-
locales: locales ?? [],
|
|
370
|
+
locales: localeManager.locales ?? [],
|
|
136
371
|
meta: options.meta ?? true,
|
|
137
372
|
metaBaseUrl: options.metaBaseUrl ?? void 0,
|
|
138
373
|
define: options.define ?? true,
|
|
@@ -184,144 +419,18 @@ const module = defineNuxtModule({
|
|
|
184
419
|
pathPrefix: false,
|
|
185
420
|
extensions: ["vue"]
|
|
186
421
|
});
|
|
187
|
-
const localeRegex = locales.filter((locale) => locale.code !== options.defaultLocale || options.includeDefaultLocaleRoute).map((locale) => locale.code);
|
|
188
|
-
const pagesDir = path.resolve(nuxt.options.rootDir, options.translationDir, "pages");
|
|
189
422
|
extendPages((pages) => {
|
|
190
|
-
const customPaths = {};
|
|
191
|
-
function extractCustomPaths(pages2, parentPath = "") {
|
|
192
|
-
for (const page of pages2) {
|
|
193
|
-
if (page.file) {
|
|
194
|
-
const filePath = path.resolve(nuxt.options.rootDir, page.file);
|
|
195
|
-
const fileContent = readFileSync(filePath, "utf-8");
|
|
196
|
-
const i18nRouteConfig = extractDefineI18nRouteConfig(fileContent, filePath);
|
|
197
|
-
if (i18nRouteConfig && i18nRouteConfig.localeRoutes) {
|
|
198
|
-
const fullPath = parentPath ? `${parentPath}/${page.path}` : page.path;
|
|
199
|
-
customPaths[fullPath] = i18nRouteConfig.localeRoutes;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
if (page.children && page.children.length > 0) {
|
|
203
|
-
const fullParentName = parentPath ? `${parentPath}/${page.path}` : page.path;
|
|
204
|
-
extractCustomPaths(page.children, fullParentName);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
extractCustomPaths(pages);
|
|
209
|
-
const pagesNames = pages.map((page) => page.name).filter((name) => name && (!options.routesLocaleLinks || !options.routesLocaleLinks[name]));
|
|
210
|
-
function ensureFileExists(filePath) {
|
|
211
|
-
const fileDir = path.dirname(filePath);
|
|
212
|
-
if (!existsSync(fileDir)) {
|
|
213
|
-
mkdirSync(fileDir, { recursive: true });
|
|
214
|
-
}
|
|
215
|
-
if (!existsSync(filePath)) {
|
|
216
|
-
writeFileSync(filePath, JSON.stringify({}), "utf-8");
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
423
|
if (!options.disableWatcher) {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
ensureFileExists(globalFilePath);
|
|
223
|
-
if (!options.disablePageLocales) {
|
|
224
|
-
pagesNames.forEach((name) => {
|
|
225
|
-
const pageFilePath = path.join(pagesDir, `${name}/${locale.code}.json`);
|
|
226
|
-
ensureFileExists(pageFilePath);
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
const newRoutes = [];
|
|
232
|
-
for (let i = 0; i < pages.length; i++) {
|
|
233
|
-
let localizeChildren = function(routes, parentPath = "") {
|
|
234
|
-
if (!parentPath.startsWith("/")) {
|
|
235
|
-
parentPath = "/" + parentPath;
|
|
236
|
-
}
|
|
237
|
-
return routes.map((route) => {
|
|
238
|
-
const fullPath = parentPath ? `${parentPath}/${route.path}` : route.path;
|
|
239
|
-
const customLocalePaths = customPaths[fullPath];
|
|
240
|
-
const localizedChildren = route.children ? localizeChildren(route.children, fullPath) : [];
|
|
241
|
-
const localizedRoutes = locales.map((locale) => {
|
|
242
|
-
let path2 = customLocalePaths && customLocalePaths[locale.code] ? `${customLocalePaths[locale.code]}` : `${fullPath}`;
|
|
243
|
-
if (path2.startsWith("/")) {
|
|
244
|
-
path2 = path2.slice(1);
|
|
245
|
-
}
|
|
246
|
-
return {
|
|
247
|
-
...route,
|
|
248
|
-
name: `localized-${route.name}-${locale.code}`,
|
|
249
|
-
path: path2,
|
|
250
|
-
children: localizedChildren
|
|
251
|
-
// Use localized children
|
|
252
|
-
};
|
|
253
|
-
});
|
|
254
|
-
if (customLocalePaths) {
|
|
255
|
-
return localizedRoutes;
|
|
256
|
-
}
|
|
257
|
-
return {
|
|
258
|
-
...route,
|
|
259
|
-
name: `localized-${route.name}`,
|
|
260
|
-
children: localizedChildren
|
|
261
|
-
// Use localized children
|
|
262
|
-
};
|
|
263
|
-
}).flat();
|
|
264
|
-
};
|
|
265
|
-
const page = pages[i];
|
|
266
|
-
if (page.redirect && !page.file) {
|
|
267
|
-
continue;
|
|
268
|
-
}
|
|
269
|
-
let modLocaleRegex = localeRegex;
|
|
270
|
-
locales.forEach((locale) => {
|
|
271
|
-
if (customPaths[page.path] && customPaths[page.path][locale.code]) {
|
|
272
|
-
modLocaleRegex = modLocaleRegex.filter((locale2) => {
|
|
273
|
-
return !Object.values(customPaths).some((paths) => paths[locale2]);
|
|
274
|
-
});
|
|
275
|
-
}
|
|
276
|
-
});
|
|
277
|
-
if (customPaths[page.path]) {
|
|
278
|
-
locales.forEach((locale) => {
|
|
279
|
-
if (customPaths[page.path][locale.code]) {
|
|
280
|
-
const newRoute2 = {
|
|
281
|
-
file: page.file,
|
|
282
|
-
meta: { ...page.meta },
|
|
283
|
-
alias: page.alias,
|
|
284
|
-
redirect: page.redirect,
|
|
285
|
-
children: page.children,
|
|
286
|
-
mode: page.mode,
|
|
287
|
-
path: `/:locale(${locale.code})${customPaths[page.path][locale.code]}`,
|
|
288
|
-
name: `localized-${page.name}-${locale.code}`
|
|
289
|
-
};
|
|
290
|
-
newRoutes.push(newRoute2);
|
|
291
|
-
}
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
|
-
if (!modLocaleRegex.length && !page.children?.length) {
|
|
295
|
-
continue;
|
|
296
|
-
}
|
|
297
|
-
const newRoute = {
|
|
298
|
-
file: page.file,
|
|
299
|
-
meta: { ...page.meta },
|
|
300
|
-
alias: page.alias,
|
|
301
|
-
redirect: page.redirect,
|
|
302
|
-
children: page.children ? localizeChildren(page.children, page.name) : [],
|
|
303
|
-
mode: page.mode,
|
|
304
|
-
path: `/:locale(${modLocaleRegex.join("|")})${page.path}`,
|
|
305
|
-
name: `localized-${page.name}`
|
|
306
|
-
};
|
|
307
|
-
newRoutes.push(newRoute);
|
|
424
|
+
const pagesNames = pages.map((page) => page.name).filter((name) => name !== void 0 && (!options.routesLocaleLinks || !options.routesLocaleLinks[name]));
|
|
425
|
+
localeManager.ensureTranslationFilesExist(pagesNames, options.translationDir, nuxt.options.rootDir);
|
|
308
426
|
}
|
|
309
|
-
pages.
|
|
310
|
-
nuxt.options.generate.routes = Array.isArray(nuxt.options.generate.routes) ? nuxt.options.generate.routes : [];
|
|
311
|
-
locales.forEach((locale) => {
|
|
312
|
-
if (!options.disablePageLocales) {
|
|
313
|
-
pagesNames.forEach((name) => {
|
|
314
|
-
addPrerenderRoutes(`/_locales/${name}/${locale.code}/data.json`);
|
|
315
|
-
});
|
|
316
|
-
}
|
|
317
|
-
addPrerenderRoutes(`/_locales/general/${locale.code}/data.json`);
|
|
318
|
-
});
|
|
427
|
+
pageManager.extendPages(pages, options, nuxt.options.rootDir);
|
|
319
428
|
});
|
|
320
429
|
nuxt.hook("nitro:config", (nitroConfig) => {
|
|
321
430
|
const routes = nitroConfig.prerender?.routes || [];
|
|
322
431
|
nuxt.options.generate.routes = Array.isArray(nuxt.options.generate.routes) ? nuxt.options.generate.routes : [];
|
|
323
432
|
const pages = nuxt.options.generate.routes || [];
|
|
324
|
-
locales.forEach((locale) => {
|
|
433
|
+
localeManager.locales.forEach((locale) => {
|
|
325
434
|
if (locale.code !== options.defaultLocale || options.includeDefaultLocaleRoute) {
|
|
326
435
|
pages.forEach((page) => {
|
|
327
436
|
routes.push(`/${locale.code}${page}`);
|
|
@@ -368,57 +477,5 @@ const module = defineNuxtModule({
|
|
|
368
477
|
}
|
|
369
478
|
}
|
|
370
479
|
});
|
|
371
|
-
function cleanObjectString(objectString) {
|
|
372
|
-
let cleanedString = objectString.replace(/'/g, '"');
|
|
373
|
-
cleanedString = cleanedString.replace(/([{,]\s*)(\w+)(\s*:)/g, '$1"$2"$3');
|
|
374
|
-
cleanedString = cleanedString.replace(/,(\s*[}\]])/g, "$1");
|
|
375
|
-
cleanedString = cleanedString.replace(/,+/g, ",");
|
|
376
|
-
cleanedString = cleanedString.replace(/(\{|\[)\s*,/g, "$1");
|
|
377
|
-
cleanedString = cleanedString.replace(/,(\s*[}\]])/g, "$1");
|
|
378
|
-
cleanedString = cleanedString.trim();
|
|
379
|
-
if (!cleanedString.startsWith("{") || !cleanedString.endsWith("}")) {
|
|
380
|
-
throw new Error("Invalid object format after cleaning");
|
|
381
|
-
}
|
|
382
|
-
return cleanedString;
|
|
383
|
-
}
|
|
384
|
-
function extractDefineI18nRouteConfig(content, path2) {
|
|
385
|
-
const match = content.match(/\$defineI18nRoute\((\{[\s\S]*?\})\)/);
|
|
386
|
-
if (match && match[1]) {
|
|
387
|
-
try {
|
|
388
|
-
const cleanedString = cleanObjectString(match[1]);
|
|
389
|
-
const configObject = JSON.parse(cleanedString);
|
|
390
|
-
if (validateDefineI18nRouteConfig(configObject)) {
|
|
391
|
-
return configObject;
|
|
392
|
-
} else {
|
|
393
|
-
console.error("Invalid defineI18nRoute configuration format:", configObject, "in file: ", path2);
|
|
394
|
-
}
|
|
395
|
-
} catch (error) {
|
|
396
|
-
console.error("Failed to parse defineI18nRoute configuration:", error, "in file: ", path2);
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
return null;
|
|
400
|
-
}
|
|
401
|
-
function validateDefineI18nRouteConfig(obj) {
|
|
402
|
-
if (typeof obj !== "object" || obj === null)
|
|
403
|
-
return false;
|
|
404
|
-
if (obj.locales) {
|
|
405
|
-
if (typeof obj.locales !== "object")
|
|
406
|
-
return false;
|
|
407
|
-
for (const localeKey in obj.locales) {
|
|
408
|
-
const translations = obj.locales[localeKey];
|
|
409
|
-
if (typeof translations !== "object" || translations === null)
|
|
410
|
-
return false;
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
if (obj.localeRoutes) {
|
|
414
|
-
if (typeof obj.localeRoutes !== "object")
|
|
415
|
-
return false;
|
|
416
|
-
for (const routeKey in obj.localeRoutes) {
|
|
417
|
-
if (typeof obj.localeRoutes[routeKey] !== "string")
|
|
418
|
-
return false;
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
return true;
|
|
422
|
-
}
|
|
423
480
|
|
|
424
481
|
export { module as default };
|
|
@@ -8,13 +8,13 @@
|
|
|
8
8
|
</template>
|
|
9
9
|
|
|
10
10
|
<script lang="ts" setup>
|
|
11
|
+
import type { RouteLocationRaw } from 'vue-router'
|
|
11
12
|
import { useNuxtApp, computed, useRoute, useRouter } from '#imports'
|
|
12
|
-
import type { NuxtLinkProps } from '#app/components/nuxt-link'
|
|
13
13
|
|
|
14
14
|
const { $localeRoute } = useNuxtApp()
|
|
15
15
|
|
|
16
16
|
interface Props {
|
|
17
|
-
to:
|
|
17
|
+
to: RouteLocationRaw | string
|
|
18
18
|
activeStyle?: Partial<CSSStyleDeclaration>
|
|
19
19
|
}
|
|
20
20
|
|
|
@@ -9,7 +9,7 @@ interface PluralTranslations {
|
|
|
9
9
|
}
|
|
10
10
|
declare const _default: import("#app").Plugin<{
|
|
11
11
|
getLocale: () => string;
|
|
12
|
-
getLocales: () =>
|
|
12
|
+
getLocales: () => any;
|
|
13
13
|
t: (key: string, params?: Record<string, string | number | boolean>, defaultValue?: string) => unknown;
|
|
14
14
|
tc: (key: string, count: number, defaultValue?: string) => string;
|
|
15
15
|
tn: (value: number, options?: Intl.NumberFormatOptions) => string;
|
|
@@ -20,7 +20,7 @@ declare const _default: import("#app").Plugin<{
|
|
|
20
20
|
localeRoute: (to: RouteLocationRaw, locale?: string) => RouteLocationRaw;
|
|
21
21
|
}> & import("#app").ObjectPlugin<{
|
|
22
22
|
getLocale: () => string;
|
|
23
|
-
getLocales: () =>
|
|
23
|
+
getLocales: () => any;
|
|
24
24
|
t: (key: string, params?: Record<string, string | number | boolean>, defaultValue?: string) => unknown;
|
|
25
25
|
tc: (key: string, count: number, defaultValue?: string) => string;
|
|
26
26
|
tn: (value: number, options?: Intl.NumberFormatOptions) => string;
|
package/dist/types.d.mts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { NuxtModule } from '@nuxt/schema'
|
|
2
|
+
|
|
3
|
+
import type { default as Module, ModuleHooks } from './module.js'
|
|
2
4
|
|
|
3
5
|
declare module '@nuxt/schema' {
|
|
4
6
|
interface NuxtHooks extends ModuleHooks {}
|
|
@@ -8,4 +10,6 @@ declare module 'nuxt/schema' {
|
|
|
8
10
|
interface NuxtHooks extends ModuleHooks {}
|
|
9
11
|
}
|
|
10
12
|
|
|
11
|
-
export
|
|
13
|
+
export type ModuleOptions = typeof Module extends NuxtModule<infer O> ? Partial<O> : Record<string, any>
|
|
14
|
+
|
|
15
|
+
export { type ModuleHooks, default } from './module.js'
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { NuxtModule } from '@nuxt/schema'
|
|
2
|
+
|
|
3
|
+
import type { default as Module, ModuleHooks } from './module'
|
|
2
4
|
|
|
3
5
|
declare module '@nuxt/schema' {
|
|
4
6
|
interface NuxtHooks extends ModuleHooks {}
|
|
@@ -8,4 +10,6 @@ declare module 'nuxt/schema' {
|
|
|
8
10
|
interface NuxtHooks extends ModuleHooks {}
|
|
9
11
|
}
|
|
10
12
|
|
|
11
|
-
export
|
|
13
|
+
export type ModuleOptions = typeof Module extends NuxtModule<infer O> ? Partial<O> : Record<string, any>
|
|
14
|
+
|
|
15
|
+
export { type ModuleHooks, default } from './module'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-i18n-micro",
|
|
3
|
-
"version": "1.12.
|
|
3
|
+
"version": "1.12.3",
|
|
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":"1ab60d52-2c05-4618-8e25-19d2de5cb6af","timestamp":1725115421029,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":[]}
|