nuxt-i18n-micro 3.18.2 → 3.19.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/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/bbe443af-4371-4ec3-b41c-7a5e9deb9b9b.json +1 -0
- package/dist/client/index.html +1 -1
- package/dist/module.d.mts +1 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +57 -149
- package/dist/runtime/composables/useI18nLocale.js +3 -3
- package/dist/runtime/composables/useLocaleHead.js +1 -1
- package/dist/runtime/plugins/01.plugin.js +6 -3
- package/dist/runtime/plugins/02.meta.js +2 -2
- package/dist/runtime/plugins/05.hooks.js +1 -1
- package/dist/runtime/plugins/06.redirect.js +14 -36
- package/dist/runtime/server/middleware/i18n.global.js +17 -35
- package/dist/runtime/server/plugins/watcher.dev.js +36 -66
- package/dist/runtime/server/routes/i18n.js +2 -2
- package/dist/runtime/server/utils/locale-detector.js +11 -1
- package/dist/runtime/server/utils/locale-server-middleware.js +2 -2
- package/dist/runtime/server/utils/server-loader.d.ts +3 -3
- package/dist/runtime/server/utils/server-loader.js +32 -8
- package/dist/runtime/server/utils/translation-server-middleware.js +2 -2
- package/dist/runtime/utils/storage.d.ts +4 -6
- package/dist/runtime/utils/storage.js +20 -11
- package/dist/types.d.mts +2 -0
- package/package.json +11 -8
- package/dist/client/_nuxt/builds/meta/a653a17d-86f7-440a-a09c-9871b01bc761.json +0 -1
- package/dist/runtime/utils/active-locales.d.ts +0 -4
- package/dist/runtime/utils/active-locales.js +0 -9
- package/dist/runtime/utils/cache-control.d.ts +0 -50
- package/dist/runtime/utils/cache-control.js +0 -88
- package/dist/runtime/utils/cookie.d.ts +0 -24
- package/dist/runtime/utils/cookie.js +0 -22
- package/dist/runtime/utils/deep-merge.d.ts +0 -15
- package/dist/runtime/utils/deep-merge.js +0 -14
- package/dist/runtime/utils/route-utils.d.ts +0 -33
- package/dist/runtime/utils/route-utils.js +0 -63
- package/dist/runtime/utils/runtime-i18n-config.d.ts +0 -8
- package/dist/runtime/utils/runtime-i18n-config.js +0 -90
package/dist/client/200.html
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/entry.Kj_DYE7z.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/B-cq5x_h.js"><script type="module" src="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/B-cq5x_h.js" crossorigin></script><link rel="prefetch" as="style" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/error-404.CyBDSRXN.css"><link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/BCTbvRLO.js"><link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/D6byAye8.js"><link rel="prefetch" as="style" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/error-500.DJtCwW7w.css"><link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/BNXusRXY.js"></head><body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__NUXT_DEVTOOLS_I18N_BASE__/",buildId:"
|
|
1
|
+
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/entry.Kj_DYE7z.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/B-cq5x_h.js"><script type="module" src="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/B-cq5x_h.js" crossorigin></script><link rel="prefetch" as="style" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/error-404.CyBDSRXN.css"><link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/BCTbvRLO.js"><link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/D6byAye8.js"><link rel="prefetch" as="style" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/error-500.DJtCwW7w.css"><link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/BNXusRXY.js"></head><body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__NUXT_DEVTOOLS_I18N_BASE__/",buildId:"bbe443af-4371-4ec3-b41c-7a5e9deb9b9b",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1781425543266,false]</script></body></html>
|
package/dist/client/404.html
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/entry.Kj_DYE7z.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/B-cq5x_h.js"><script type="module" src="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/B-cq5x_h.js" crossorigin></script><link rel="prefetch" as="style" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/error-404.CyBDSRXN.css"><link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/BCTbvRLO.js"><link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/D6byAye8.js"><link rel="prefetch" as="style" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/error-500.DJtCwW7w.css"><link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/BNXusRXY.js"></head><body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__NUXT_DEVTOOLS_I18N_BASE__/",buildId:"
|
|
1
|
+
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/entry.Kj_DYE7z.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/B-cq5x_h.js"><script type="module" src="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/B-cq5x_h.js" crossorigin></script><link rel="prefetch" as="style" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/error-404.CyBDSRXN.css"><link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/BCTbvRLO.js"><link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/D6byAye8.js"><link rel="prefetch" as="style" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/error-500.DJtCwW7w.css"><link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/BNXusRXY.js"></head><body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__NUXT_DEVTOOLS_I18N_BASE__/",buildId:"bbe443af-4371-4ec3-b41c-7a5e9deb9b9b",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1781425543266,false]</script></body></html>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"id":"
|
|
1
|
+
{"id":"bbe443af-4371-4ec3-b41c-7a5e9deb9b9b","timestamp":1781425540376}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"id":"bbe443af-4371-4ec3-b41c-7a5e9deb9b9b","timestamp":1781425540376,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":[]}
|
package/dist/client/index.html
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/entry.Kj_DYE7z.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/B-cq5x_h.js"><script type="module" src="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/B-cq5x_h.js" crossorigin></script><link rel="prefetch" as="style" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/error-404.CyBDSRXN.css"><link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/BCTbvRLO.js"><link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/D6byAye8.js"><link rel="prefetch" as="style" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/error-500.DJtCwW7w.css"><link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/BNXusRXY.js"></head><body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__NUXT_DEVTOOLS_I18N_BASE__/",buildId:"
|
|
1
|
+
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/entry.Kj_DYE7z.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/B-cq5x_h.js"><script type="module" src="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/B-cq5x_h.js" crossorigin></script><link rel="prefetch" as="style" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/error-404.CyBDSRXN.css"><link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/BCTbvRLO.js"><link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/D6byAye8.js"><link rel="prefetch" as="style" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/error-500.DJtCwW7w.css"><link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/BNXusRXY.js"></head><body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__NUXT_DEVTOOLS_I18N_BASE__/",buildId:"bbe443af-4371-4ec3-b41c-7a5e9deb9b9b",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1781425543266,false]</script></body></html>
|
package/dist/module.d.mts
CHANGED
|
@@ -3,6 +3,7 @@ import { HookResult } from '@nuxt/schema';
|
|
|
3
3
|
import { ModuleOptions } from '@i18n-micro/types';
|
|
4
4
|
export { Getter, GlobalLocaleRoutes, Locale, LocaleCode, ModuleOptions, PluralFunc, Strategies } from '@i18n-micro/types';
|
|
5
5
|
export { PluginsInjections } from '../dist/runtime/plugins/01.plugin.js';
|
|
6
|
+
export { TranslationPayloadMode, resolveTranslationPayloadMode, resolveTranslationPayloadOptions, resolveTranslationPayloadPublicDir } from '@i18n-micro/utils/payload-config';
|
|
6
7
|
|
|
7
8
|
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
|
|
8
9
|
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import * as fs from 'node:fs';
|
|
2
|
-
import fs__default, { readFileSync, existsSync
|
|
2
|
+
import fs__default, { readFileSync, existsSync } from 'node:fs';
|
|
3
3
|
import { createRequire } from 'node:module';
|
|
4
4
|
import path, { resolve, join, dirname } from 'node:path';
|
|
5
5
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
6
6
|
import { defaultPlural, isNoPrefixStrategy, withPrefixStrategy } from '@i18n-micro/core';
|
|
7
|
+
import { generateHmrPlugin } from '@i18n-micro/hmr/generate-plugin';
|
|
7
8
|
import { RouteGenerator, isLocaleAllowedForUnlocalizedRoute, normalizePath, isInternalPath } from '@i18n-micro/route-strategy';
|
|
9
|
+
import { buildTranslationSourceLayers, preMergeLocales } from '@i18n-micro/utils/build';
|
|
10
|
+
import { resolveTranslationPayloadOptions, getTranslationPayloadMisconfigurationWarnings, getTranslationPayloadSizeWarning, resolveTranslationPayloadWarningThresholds, resolveTranslationPayloadPublicDir } from '@i18n-micro/utils/payload-config';
|
|
11
|
+
export { resolveTranslationPayloadMode, resolveTranslationPayloadOptions, resolveTranslationPayloadPublicDir } from '@i18n-micro/utils/payload-config';
|
|
12
|
+
import { scanTranslationPayloadDirectory } from '@i18n-micro/utils/payload-stats';
|
|
8
13
|
import { useNuxt, defineNuxtModule, useLogger, createResolver, addTemplate, addImportsDir, addPlugin, addServerHandler, addComponentsDir, addTypeTemplate, addPrerenderRoutes } from '@nuxt/kit';
|
|
9
14
|
import { globby } from 'globby';
|
|
10
15
|
import { onDevToolsInitialized, extendServerRpc } from '@nuxt/devtools-kit';
|
|
@@ -118,46 +123,6 @@ function setupDevToolsUI(options, resolve2, rootDirs) {
|
|
|
118
123
|
});
|
|
119
124
|
}
|
|
120
125
|
|
|
121
|
-
function generateHmrPlugin(files) {
|
|
122
|
-
const accepts = files.map((file) => {
|
|
123
|
-
const isPage = /\/pages\//.test(file);
|
|
124
|
-
let pageName = "";
|
|
125
|
-
let locale = "";
|
|
126
|
-
if (isPage) {
|
|
127
|
-
const m = /\/pages\/(.+)\/([^/]+)\.json$/.exec(file);
|
|
128
|
-
pageName = m?.[1] || "";
|
|
129
|
-
locale = m?.[2] || "";
|
|
130
|
-
} else {
|
|
131
|
-
const m = /\/([^/]+)\.json$/.exec(file);
|
|
132
|
-
locale = m?.[1] || "";
|
|
133
|
-
}
|
|
134
|
-
return `
|
|
135
|
-
if (import.meta.hot) {
|
|
136
|
-
import.meta.hot.accept('${file}', async (mod) => {
|
|
137
|
-
const nuxtApp = useNuxtApp()
|
|
138
|
-
const data = (mod && typeof mod === 'object' && Object.prototype.hasOwnProperty.call(mod, 'default'))
|
|
139
|
-
? mod.default
|
|
140
|
-
: mod
|
|
141
|
-
try {
|
|
142
|
-
${isPage ? `await nuxtApp.$loadPageTranslations('${locale}', '${pageName}', data)` : `await nuxtApp.$loadTranslations('${locale}', data)`}
|
|
143
|
-
console.log('[i18n HMR] Translations reloaded:', '${isPage ? "page" : "global"}', '${locale}'${isPage ? `, '${pageName}'` : ""})
|
|
144
|
-
}
|
|
145
|
-
catch (e) {
|
|
146
|
-
console.warn('[i18n HMR] Failed to reload translations for', '${file}', e)
|
|
147
|
-
}
|
|
148
|
-
})
|
|
149
|
-
}
|
|
150
|
-
`.trim();
|
|
151
|
-
}).join("\n");
|
|
152
|
-
return `
|
|
153
|
-
import { defineNuxtPlugin, useNuxtApp } from '#imports'
|
|
154
|
-
|
|
155
|
-
export default defineNuxtPlugin(() => {
|
|
156
|
-
${accepts}
|
|
157
|
-
})
|
|
158
|
-
`.trim();
|
|
159
|
-
}
|
|
160
|
-
|
|
161
126
|
function shouldLocalizeRouteRulePath(originalPath) {
|
|
162
127
|
const routeRulePath = originalPath.trim();
|
|
163
128
|
if (!routeRulePath) return true;
|
|
@@ -286,97 +251,7 @@ function extractDefineI18nRouteData(content, _filePath) {
|
|
|
286
251
|
}
|
|
287
252
|
}
|
|
288
253
|
|
|
289
|
-
function deepMergeTranslations(target, source) {
|
|
290
|
-
if (!target || Object.keys(target).length === 0) return { ...source };
|
|
291
|
-
const output = { ...target };
|
|
292
|
-
for (const key in source) {
|
|
293
|
-
if (key === "__proto__" || key === "constructor") continue;
|
|
294
|
-
const src = source[key];
|
|
295
|
-
const dst = output[key];
|
|
296
|
-
if (src && typeof src === "object" && !Array.isArray(src) && dst && typeof dst === "object" && !Array.isArray(dst)) {
|
|
297
|
-
output[key] = deepMergeTranslations(dst, src);
|
|
298
|
-
} else {
|
|
299
|
-
output[key] = src;
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
return output;
|
|
303
|
-
}
|
|
304
254
|
const DEFAULT_CANONICAL_QUERY_WHITELIST = ["page", "sort", "filter", "search", "q", "query", "tag"];
|
|
305
|
-
async function preMergeLocales(rootDirs, translationDirName, outputDir, locales, globalFallbackLocale, disablePageLocales) {
|
|
306
|
-
if (existsSync(outputDir)) fs__default.rmSync(outputDir, { recursive: true, force: true });
|
|
307
|
-
mkdirSync(outputDir, { recursive: true });
|
|
308
|
-
const layerPaths = rootDirs.map((dir) => join(dir, translationDirName));
|
|
309
|
-
const allFiles = /* @__PURE__ */ new Set();
|
|
310
|
-
for (const lp of layerPaths) {
|
|
311
|
-
if (!existsSync(lp)) continue;
|
|
312
|
-
const files = await globby("**/*.json", { cwd: lp });
|
|
313
|
-
files.forEach((f) => allFiles.add(f));
|
|
314
|
-
}
|
|
315
|
-
const merged = /* @__PURE__ */ new Map();
|
|
316
|
-
for (const file of allFiles) {
|
|
317
|
-
let content = {};
|
|
318
|
-
for (const lp of layerPaths) {
|
|
319
|
-
const fp = join(lp, file);
|
|
320
|
-
if (existsSync(fp)) {
|
|
321
|
-
try {
|
|
322
|
-
content = deepMergeTranslations(content, JSON.parse(readFileSync(fp, "utf-8")));
|
|
323
|
-
} catch {
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
merged.set(file, content);
|
|
328
|
-
}
|
|
329
|
-
const rootMap = /* @__PURE__ */ new Map();
|
|
330
|
-
const pageMap = /* @__PURE__ */ new Map();
|
|
331
|
-
for (const [file, content] of merged) {
|
|
332
|
-
const dir = dirname(file);
|
|
333
|
-
const locale = file.slice(file.lastIndexOf("/") + 1).replace(".json", "");
|
|
334
|
-
if (dir === ".") {
|
|
335
|
-
rootMap.set(locale, content);
|
|
336
|
-
} else {
|
|
337
|
-
if (!pageMap.has(dir)) pageMap.set(dir, /* @__PURE__ */ new Map());
|
|
338
|
-
pageMap.get(dir).set(locale, content);
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
const knownCodes = new Set(locales.map((l) => l.code));
|
|
342
|
-
const applyFallback = (map) => {
|
|
343
|
-
for (const locale of locales) {
|
|
344
|
-
const chain = [globalFallbackLocale, locale.fallbackLocale, locale.code].filter((l) => !!l && knownCodes.has(l)).filter((v, i, arr) => arr.indexOf(v) === i);
|
|
345
|
-
if (chain.length <= 1) continue;
|
|
346
|
-
let result = {};
|
|
347
|
-
for (const code of chain) {
|
|
348
|
-
const data = map.get(code);
|
|
349
|
-
if (data) result = deepMergeTranslations(result, data);
|
|
350
|
-
}
|
|
351
|
-
map.set(locale.code, result);
|
|
352
|
-
}
|
|
353
|
-
};
|
|
354
|
-
applyFallback(rootMap);
|
|
355
|
-
for (const localeMap of pageMap.values()) {
|
|
356
|
-
applyFallback(localeMap);
|
|
357
|
-
}
|
|
358
|
-
if (disablePageLocales || pageMap.size === 0) {
|
|
359
|
-
const indexMap = /* @__PURE__ */ new Map();
|
|
360
|
-
for (const [locale, data] of rootMap) {
|
|
361
|
-
indexMap.set(locale, { ...data });
|
|
362
|
-
}
|
|
363
|
-
pageMap.set("pages/index", indexMap);
|
|
364
|
-
} else {
|
|
365
|
-
for (const [, localeMap] of pageMap) {
|
|
366
|
-
for (const [locale, rootData] of rootMap) {
|
|
367
|
-
const pageData = localeMap.get(locale);
|
|
368
|
-
localeMap.set(locale, pageData ? deepMergeTranslations(rootData, pageData) : { ...rootData });
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
for (const [context, localeMap] of pageMap) {
|
|
373
|
-
for (const [locale, data] of localeMap) {
|
|
374
|
-
const targetPath = join(outputDir, context, `${locale}.json`);
|
|
375
|
-
mkdirSync(dirname(targetPath), { recursive: true });
|
|
376
|
-
writeFileSync(targetPath, JSON.stringify(data));
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
255
|
function generateI18nTypes() {
|
|
381
256
|
return `
|
|
382
257
|
import type {PluginsInjections} from "nuxt-i18n-micro";
|
|
@@ -425,6 +300,13 @@ const module = defineNuxtModule({
|
|
|
425
300
|
apiBaseUrl: "_locales",
|
|
426
301
|
apiBaseClientHost: void 0,
|
|
427
302
|
apiBaseServerHost: void 0,
|
|
303
|
+
translationPayloads: {
|
|
304
|
+
mode: "premerged",
|
|
305
|
+
serverAssets: true,
|
|
306
|
+
serverHandler: true,
|
|
307
|
+
publicAssets: true,
|
|
308
|
+
prerenderRoutes: true
|
|
309
|
+
},
|
|
428
310
|
routesLocaleLinks: {},
|
|
429
311
|
globalLocaleRoutes: {},
|
|
430
312
|
canonicalQueryWhitelist: void 0,
|
|
@@ -452,13 +334,33 @@ const module = defineNuxtModule({
|
|
|
452
334
|
const resolver = createResolver(import.meta.url);
|
|
453
335
|
const rootDirs = nuxt.options._layers.map((layer) => layer.config.rootDir).reverse();
|
|
454
336
|
const mergedLocalesDir = resolve(nuxt.options.buildDir, "i18n-merged");
|
|
337
|
+
const sourceLocalesDir = resolve(nuxt.options.buildDir, "i18n-source");
|
|
455
338
|
const translationDirName = options.translationDir || "locales";
|
|
339
|
+
const translationPayloads = resolveTranslationPayloadOptions(options);
|
|
340
|
+
const translationAssetsDir = translationPayloads.mode === "source" ? sourceLocalesDir : mergedLocalesDir;
|
|
341
|
+
for (const warning of getTranslationPayloadMisconfigurationWarnings({
|
|
342
|
+
translationPayloads,
|
|
343
|
+
apiBaseClientHost: options.apiBaseClientHost,
|
|
344
|
+
apiBaseServerHost: options.apiBaseServerHost
|
|
345
|
+
})) {
|
|
346
|
+
logger.warn(warning.replace("[nuxt-i18n-micro] ", ""));
|
|
347
|
+
}
|
|
456
348
|
const localeInfos = (options.locales ?? []).map(
|
|
457
349
|
(l) => typeof l === "string" ? { code: l } : { code: l.code, fallbackLocale: l.fallbackLocale }
|
|
458
350
|
);
|
|
459
351
|
nuxt.hook("build:before", async () => {
|
|
460
|
-
|
|
461
|
-
|
|
352
|
+
if (translationPayloads.mode === "source") {
|
|
353
|
+
await buildTranslationSourceLayers(rootDirs, translationDirName, sourceLocalesDir);
|
|
354
|
+
logger.info(`Built compact translation source from ${rootDirs.length} layer(s) into ${sourceLocalesDir}`);
|
|
355
|
+
} else {
|
|
356
|
+
await preMergeLocales(rootDirs, translationDirName, mergedLocalesDir, localeInfos, options.fallbackLocale, options.disablePageLocales);
|
|
357
|
+
logger.info(`Pre-merged translations from ${rootDirs.length} layer(s) into ${mergedLocalesDir}`);
|
|
358
|
+
}
|
|
359
|
+
const payloadStats = scanTranslationPayloadDirectory(translationAssetsDir);
|
|
360
|
+
const sizeWarning = getTranslationPayloadSizeWarning(payloadStats, resolveTranslationPayloadWarningThresholds(options.translationPayloads));
|
|
361
|
+
if (sizeWarning) {
|
|
362
|
+
logger.warn(sizeWarning.replace("[nuxt-i18n-micro] ", ""));
|
|
363
|
+
}
|
|
462
364
|
});
|
|
463
365
|
const routeLocales = { ...options.routeLocales ?? {} };
|
|
464
366
|
const globalLocaleRoutes = {};
|
|
@@ -569,7 +471,8 @@ const module = defineNuxtModule({
|
|
|
569
471
|
debug: options.debug ?? false,
|
|
570
472
|
customRegexMatcher: options.customRegexMatcher instanceof RegExp ? options.customRegexMatcher.source : options.customRegexMatcher,
|
|
571
473
|
cacheMaxSize: options.cacheMaxSize ?? 0,
|
|
572
|
-
cacheTtl: options.cacheTtl ?? 0
|
|
474
|
+
cacheTtl: options.cacheTtl ?? 0,
|
|
475
|
+
translationPayloadMode: translationPayloads.mode
|
|
573
476
|
};
|
|
574
477
|
const fullConfigJson = JSON.stringify(fullConfig);
|
|
575
478
|
const strategyTemplate = addTemplate({
|
|
@@ -679,10 +582,12 @@ export function getI18nPrivateConfig() { return __privateConfig }
|
|
|
679
582
|
name: "i18n-plugin-redirect",
|
|
680
583
|
order: 10
|
|
681
584
|
});
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
585
|
+
if (translationPayloads.serverHandler) {
|
|
586
|
+
addServerHandler({
|
|
587
|
+
route: `/${apiBaseUrl}/:page/:locale/data.json`,
|
|
588
|
+
handler: resolver.resolve("./runtime/server/routes/i18n")
|
|
589
|
+
});
|
|
590
|
+
}
|
|
686
591
|
if (options.components !== false) {
|
|
687
592
|
addComponentsDir({
|
|
688
593
|
path: resolver.resolve("./runtime/components"),
|
|
@@ -758,6 +663,7 @@ declare module '#i18n-internal/plural' {
|
|
|
758
663
|
}
|
|
759
664
|
});
|
|
760
665
|
const addDataRoutes = (pages = []) => {
|
|
666
|
+
if (!translationPayloads.prerenderRoutes) return;
|
|
761
667
|
const pagesForDataRoutes = pages.filter((p) => p.name !== void 0 && (!options.routesLocaleLinks || !options.routesLocaleLinks[p.name]));
|
|
762
668
|
const dataRoutes = routeGenerator.generateDataRoutes(pagesForDataRoutes, apiBaseUrl, !!options.disablePageLocales);
|
|
763
669
|
addPrerenderRoutes(dataRoutes);
|
|
@@ -794,11 +700,13 @@ declare module '#i18n-internal/plural' {
|
|
|
794
700
|
nitroConfig.alias["#i18n-internal/plural"] = pluralTemplate.dst;
|
|
795
701
|
nitroConfig.alias["#i18n-internal/strategy"] = strategyTemplate.dst;
|
|
796
702
|
nitroConfig.alias["#i18n-internal/config"] = configTemplate.dst;
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
703
|
+
if (translationPayloads.serverAssets) {
|
|
704
|
+
nitroConfig.serverAssets = nitroConfig.serverAssets || [];
|
|
705
|
+
nitroConfig.serverAssets.push({
|
|
706
|
+
baseName: "i18n",
|
|
707
|
+
dir: translationAssetsDir
|
|
708
|
+
});
|
|
709
|
+
}
|
|
802
710
|
if (nitroConfig.imports) {
|
|
803
711
|
nitroConfig.imports.presets = nitroConfig.imports.presets || [];
|
|
804
712
|
nitroConfig.imports.presets.push({
|
|
@@ -838,14 +746,14 @@ declare module '#i18n-internal/plural' {
|
|
|
838
746
|
});
|
|
839
747
|
nuxt.hook("nitro:build:public-assets", (nitro) => {
|
|
840
748
|
const isProd = nuxt.options.dev === false;
|
|
841
|
-
if (isProd) {
|
|
842
|
-
const publicDir =
|
|
749
|
+
if (isProd && translationPayloads.publicAssets) {
|
|
750
|
+
const publicDir = resolveTranslationPayloadPublicDir(nitro.options.output.publicDir, options);
|
|
843
751
|
try {
|
|
844
|
-
if (existsSync(
|
|
845
|
-
fs__default.cpSync(
|
|
846
|
-
logger.log(`
|
|
752
|
+
if (existsSync(translationAssetsDir)) {
|
|
753
|
+
fs__default.cpSync(translationAssetsDir, publicDir, { recursive: true });
|
|
754
|
+
logger.log(`Translation payloads copied to public directory`);
|
|
847
755
|
} else {
|
|
848
|
-
logger.warn(`
|
|
756
|
+
logger.warn(`Translation assets directory not found: ${translationAssetsDir}`);
|
|
849
757
|
}
|
|
850
758
|
} catch (err) {
|
|
851
759
|
logger.error("Error copying translations:", err);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { getEnabledLocaleCodes } from "@i18n-micro/utils/active-locales";
|
|
2
|
+
import { getHashCookieName, getLocaleCookieName, getLocaleCookieOptions } from "@i18n-micro/utils/cookie";
|
|
3
|
+
import { resolveI18nConfigWithRuntimeOverrides } from "@i18n-micro/utils/runtime-config";
|
|
1
4
|
import { useNuxtApp, useState } from "#app";
|
|
2
5
|
import { getI18nConfig } from "#build/i18n.strategy.mjs";
|
|
3
6
|
import { useCookie } from "#imports";
|
|
4
|
-
import { getEnabledLocaleCodes } from "../utils/active-locales.js";
|
|
5
|
-
import { getHashCookieName, getLocaleCookieName, getLocaleCookieOptions } from "../utils/cookie.js";
|
|
6
|
-
import { resolveI18nConfigWithRuntimeOverrides } from "../utils/runtime-i18n-config.js";
|
|
7
7
|
export function useI18nLocale() {
|
|
8
8
|
const nuxtApp = useNuxtApp();
|
|
9
9
|
const i18nConfig = resolveI18nConfigWithRuntimeOverrides(nuxtApp.$getI18nConfig?.() ?? getI18nConfig());
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { isNoPrefixStrategy } from "@i18n-micro/core";
|
|
2
|
+
import { findAllowedLocalesForRoute } from "@i18n-micro/utils/route";
|
|
2
3
|
import { joinURL, parseURL, withQuery } from "ufo";
|
|
3
4
|
import { ref, unref, watch } from "vue";
|
|
4
5
|
import { useNuxtApp, useRoute } from "#imports";
|
|
5
|
-
import { findAllowedLocalesForRoute } from "../utils/route-utils.js";
|
|
6
6
|
export const useLocaleHead = ({
|
|
7
7
|
addDirAttribute = true,
|
|
8
8
|
identifierAttribute = "id",
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { FormatService, isNoPrefixStrategy } from "@i18n-micro/core";
|
|
2
|
+
import { deepMergeTranslations } from "@i18n-micro/utils/deep-merge";
|
|
3
|
+
import { resolveI18nConfigWithRuntimeOverrides } from "@i18n-micro/utils/runtime-config";
|
|
2
4
|
import { shallowRef, triggerRef, unref } from "vue";
|
|
3
5
|
import { useState } from "#app";
|
|
4
6
|
import { plural } from "#build/i18n.plural.mjs";
|
|
5
7
|
import { createI18nStrategy, getI18nConfig } from "#build/i18n.strategy.mjs";
|
|
6
8
|
import { createError, defineNuxtPlugin, navigateTo, useHead, useRouter, useRuntimeConfig } from "#imports";
|
|
7
9
|
import { useI18nLocale } from "../composables/useI18nLocale.js";
|
|
8
|
-
import { deepMergeTranslations } from "../utils/deep-merge.js";
|
|
9
|
-
import { resolveI18nConfigWithRuntimeOverrides } from "../utils/runtime-i18n-config.js";
|
|
10
10
|
import { translationStorage } from "../utils/storage.js";
|
|
11
11
|
const isDev = process.env.NODE_ENV !== "production";
|
|
12
12
|
const RE_TOKEN = /\{(\w+)\}/g;
|
|
@@ -81,7 +81,10 @@ export default defineNuxtPlugin(async (nuxtApp) => {
|
|
|
81
81
|
const loadOptions = {
|
|
82
82
|
apiBaseUrl: i18nConfig.apiBaseUrl ?? "_locales",
|
|
83
83
|
baseURL: runtimeConfig.app.baseURL,
|
|
84
|
-
|
|
84
|
+
apiBaseClientHost: i18nConfig.apiBaseClientHost,
|
|
85
|
+
apiBaseServerHost: i18nConfig.apiBaseServerHost,
|
|
86
|
+
dateBuild: i18nConfig.dateBuild,
|
|
87
|
+
routesLocaleLinks: i18nConfig.routesLocaleLinks
|
|
85
88
|
};
|
|
86
89
|
const getCacheKey = (locale, routeName) => {
|
|
87
90
|
return `${locale}:${routeName || "index"}`;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { isMetaDisabledForRoute } from "@i18n-micro/utils/route";
|
|
2
|
+
import { resolveI18nConfigWithRuntimeOverrides } from "@i18n-micro/utils/runtime-config";
|
|
1
3
|
import { watch } from "vue";
|
|
2
4
|
import { getI18nConfig } from "#build/i18n.strategy.mjs";
|
|
3
5
|
import { defineNuxtPlugin, useHead, useRequestURL, useRoute } from "#imports";
|
|
4
6
|
import { useLocaleHead } from "../composables/useLocaleHead.js";
|
|
5
|
-
import { isMetaDisabledForRoute } from "../utils/route-utils.js";
|
|
6
|
-
import { resolveI18nConfigWithRuntimeOverrides } from "../utils/runtime-i18n-config.js";
|
|
7
7
|
export default defineNuxtPlugin((nuxtApp) => {
|
|
8
8
|
const route = useRoute();
|
|
9
9
|
const getRuntimeConfig = nuxtApp.$getI18nConfig;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isNoPrefixStrategy } from "@i18n-micro/core";
|
|
2
|
+
import { resolveI18nConfigWithRuntimeOverrides } from "@i18n-micro/utils/runtime-config";
|
|
2
3
|
import { getI18nConfig } from "#build/i18n.strategy.mjs";
|
|
3
4
|
import { defineNuxtPlugin, useNuxtApp, useRouter } from "#imports";
|
|
4
|
-
import { resolveI18nConfigWithRuntimeOverrides } from "../utils/runtime-i18n-config.js";
|
|
5
5
|
const isDev = process.env.NODE_ENV !== "production";
|
|
6
6
|
export default defineNuxtPlugin(async (nuxtApp) => {
|
|
7
7
|
const getRuntimeConfig = nuxtApp.$getI18nConfig;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { getEnabledLocaleCodes } from "@i18n-micro/utils/active-locales";
|
|
2
|
+
import { getLocaleCookieName, getLocaleCookieOptions } from "@i18n-micro/utils/cookie";
|
|
3
|
+
import { resolvePreferredLocale } from "@i18n-micro/utils/resolve-locale";
|
|
4
|
+
import { resolveI18nConfigWithRuntimeOverrides } from "@i18n-micro/utils/runtime-config";
|
|
1
5
|
import { getCookie, getHeader, getRequestURL, setCookie } from "h3";
|
|
2
6
|
import { createI18nStrategy, getI18nConfig } from "#build/i18n.strategy.mjs";
|
|
3
7
|
import { createError, defineNuxtPlugin, navigateTo, useRequestEvent, useRoute, useRouter, useState } from "#imports";
|
|
4
8
|
import { useI18nLocale } from "../composables/useI18nLocale.js";
|
|
5
|
-
import { getEnabledLocaleCodes } from "../utils/active-locales.js";
|
|
6
|
-
import { getLocaleCookieName, getLocaleCookieOptions } from "../utils/cookie.js";
|
|
7
|
-
import { resolveI18nConfigWithRuntimeOverrides } from "../utils/runtime-i18n-config.js";
|
|
8
9
|
const DEBUG = process.env.NUXT_I18N_DEBUG_REDIRECT === "1";
|
|
9
10
|
const DEFAULT_STATIC_PATTERNS = [
|
|
10
11
|
/^\/sitemap.*\.xml$/,
|
|
@@ -42,13 +43,6 @@ function isInternalPath(path, excludePatterns) {
|
|
|
42
43
|
}
|
|
43
44
|
return false;
|
|
44
45
|
}
|
|
45
|
-
function parseAcceptLanguage(header) {
|
|
46
|
-
if (!header) return [];
|
|
47
|
-
return header.split(",").map((entry) => {
|
|
48
|
-
const [lang] = entry.split(";");
|
|
49
|
-
return (lang ?? "").trim();
|
|
50
|
-
}).filter((s) => s.length > 0);
|
|
51
|
-
}
|
|
52
46
|
export default defineNuxtPlugin({
|
|
53
47
|
name: "i18n-redirect",
|
|
54
48
|
enforce: "pre",
|
|
@@ -107,32 +101,16 @@ export default defineNuxtPlugin({
|
|
|
107
101
|
const isPrerenderOrBot = !!(prerenderHeader || userAgent.includes("Nitro") || !userAgent);
|
|
108
102
|
const skipRedirect = !isRootPath && autoDetectPath !== "*" && isPrerenderOrBot;
|
|
109
103
|
if (!skipRedirect) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
preferredLocale = cookieVal;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
if (i18nConfig.autoDetectLanguage && preferredLocale === defaultLocale) {
|
|
124
|
-
const acceptHeader = getHeader(event, "accept-language");
|
|
125
|
-
const langs = parseAcceptLanguage(acceptHeader);
|
|
126
|
-
for (const lang of langs) {
|
|
127
|
-
const lowerCaseLanguage = lang.toLowerCase();
|
|
128
|
-
const primaryLanguage = lowerCaseLanguage.split("-")[0];
|
|
129
|
-
const found = validLocales.find((l) => l.toLowerCase() === lowerCaseLanguage || l.toLowerCase() === primaryLanguage);
|
|
130
|
-
if (found) {
|
|
131
|
-
preferredLocale = found;
|
|
132
|
-
break;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
104
|
+
const localeState = autoDetectPath !== "*" ? useState("i18n-locale", () => null) : null;
|
|
105
|
+
let preferredLocale = resolvePreferredLocale({
|
|
106
|
+
defaultLocale,
|
|
107
|
+
validLocales,
|
|
108
|
+
autoDetectLanguage: i18nConfig.autoDetectLanguage,
|
|
109
|
+
stateLocale: localeState?.value ?? null,
|
|
110
|
+
cookieLocale: cookieName ? getCookie(event, cookieName) : null,
|
|
111
|
+
acceptLanguageHeader: getHeader(event, "accept-language"),
|
|
112
|
+
ignoreStateLocale: autoDetectPath === "*"
|
|
113
|
+
});
|
|
136
114
|
if (autoDetectPath === "*" && !hasLocalePrefix) {
|
|
137
115
|
preferredLocale = defaultLocale;
|
|
138
116
|
}
|
|
@@ -1,16 +1,10 @@
|
|
|
1
|
+
import { getEnabledLocaleCodes } from "@i18n-micro/utils/active-locales";
|
|
2
|
+
import { getLocaleCookieName } from "@i18n-micro/utils/cookie";
|
|
3
|
+
import { resolveServerLocale } from "@i18n-micro/utils/resolve-locale";
|
|
4
|
+
import { resolveI18nConfigWithRuntimeOverrides } from "@i18n-micro/utils/runtime-config";
|
|
1
5
|
import { defineEventHandler, getCookie, getHeader, getQuery, getRequestURL } from "h3";
|
|
2
6
|
import { getI18nConfig } from "#i18n-internal/strategy";
|
|
3
7
|
import { useRuntimeConfig } from "#imports";
|
|
4
|
-
import { getEnabledLocaleCodes } from "../../utils/active-locales.js";
|
|
5
|
-
import { getLocaleCookieName } from "../../utils/cookie.js";
|
|
6
|
-
import { resolveI18nConfigWithRuntimeOverrides } from "../../utils/runtime-i18n-config.js";
|
|
7
|
-
function parseAcceptLanguage(header) {
|
|
8
|
-
if (!header) return [];
|
|
9
|
-
return header.split(",").map((entry) => {
|
|
10
|
-
const [lang] = entry.split(";");
|
|
11
|
-
return (lang ?? "").trim();
|
|
12
|
-
}).filter((s) => s.length > 0);
|
|
13
|
-
}
|
|
14
8
|
export default defineEventHandler(async (event) => {
|
|
15
9
|
const path = event.path || getRequestURL(event).pathname;
|
|
16
10
|
if (path.startsWith("/api") || path.startsWith("/_nuxt") || path.startsWith("/_locales") || path.startsWith("/__")) return;
|
|
@@ -24,31 +18,19 @@ export default defineEventHandler(async (event) => {
|
|
|
24
18
|
const pathSegments = path.split("/").filter(Boolean);
|
|
25
19
|
const firstSegment = pathSegments[0];
|
|
26
20
|
const hasLocaleInUrl = Boolean(firstSegment && validLocales.includes(firstSegment));
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const acceptHeader = getHeader(event, "accept-language");
|
|
41
|
-
const langs = parseAcceptLanguage(acceptHeader);
|
|
42
|
-
for (const lang of langs) {
|
|
43
|
-
const lowerCaseLanguage = lang.toLowerCase();
|
|
44
|
-
const primaryLanguage = lowerCaseLanguage.split("-")[0];
|
|
45
|
-
const found = validLocales.find((l) => l.toLowerCase() === lowerCaseLanguage || l.toLowerCase() === primaryLanguage);
|
|
46
|
-
if (found) {
|
|
47
|
-
locale = found;
|
|
48
|
-
break;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
21
|
+
const cookieName = getLocaleCookieName(config);
|
|
22
|
+
const queryLocale = getQuery(event).locale ? String(getQuery(event).locale) : null;
|
|
23
|
+
const cookieLocale = cookieName ? getCookie(event, cookieName) : null;
|
|
24
|
+
const locale = resolveServerLocale({
|
|
25
|
+
defaultLocale,
|
|
26
|
+
validLocales,
|
|
27
|
+
autoDetectLanguage: config.autoDetectLanguage,
|
|
28
|
+
hasLocaleInUrl,
|
|
29
|
+
urlLocale: firstSegment ?? null,
|
|
30
|
+
queryLocale,
|
|
31
|
+
cookieLocale,
|
|
32
|
+
acceptLanguageHeader: getHeader(event, "accept-language")
|
|
33
|
+
});
|
|
52
34
|
event.context.i18n = {
|
|
53
35
|
locale,
|
|
54
36
|
translations: {}
|