nuxt-i18n-micro 1.102.0 → 2.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 +21 -27
- package/dist/client/200.html +8 -8
- package/dist/client/404.html +8 -8
- package/dist/client/_nuxt/{DTIY11lm.js → BYEpoBUk.js} +1 -1
- package/dist/client/_nuxt/{T7szCJDf.js → CBxwnKtU.js} +1 -1
- package/dist/client/_nuxt/{Df3aIBNA.js → CQupjgaS.js} +1 -1
- package/dist/client/_nuxt/{s7GTWWQo.js → XZXfxmri.js} +33 -33
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/df79903a-9996-4527-8269-e47de875a594.json +1 -0
- package/dist/client/_nuxt/error-404.Ba2SLv0l.css +1 -0
- package/dist/client/_nuxt/error-500.BqKd8Zt-.css +1 -0
- package/dist/client/index.html +8 -8
- package/dist/module.json +1 -1
- package/dist/module.mjs +79 -28
- package/dist/runtime/composables/useLocaleHead.d.ts +36 -33
- package/dist/runtime/composables/useLocaleHead.js +2 -13
- package/dist/runtime/plugins/01.plugin.d.ts +30 -0
- package/dist/runtime/plugins/01.plugin.js +52 -61
- package/dist/runtime/plugins/02.meta.js +12 -3
- package/dist/runtime/plugins/05.hooks.js +15 -7
- package/dist/runtime/server/plugins/watcher.dev.d.ts +2 -0
- package/dist/runtime/server/plugins/watcher.dev.js +60 -0
- package/dist/runtime/server/routes/get.js +62 -37
- package/dist/runtime/translation-server-middleware.js +11 -1
- package/package.json +4 -4
- package/dist/client/_nuxt/builds/meta/3b71a52e-40e0-4913-a13a-e722e382d06d.json +0 -1
- package/dist/client/_nuxt/error-404.B2VbLYbY.css +0 -1
- package/dist/client/_nuxt/error-500.DGwSTbEi.css +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"id":"
|
|
1
|
+
{"id":"df79903a-9996-4527-8269-e47de875a594","timestamp":1761933265840}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"id":"df79903a-9996-4527-8269-e47de875a594","timestamp":1761933265840,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.spotlight[data-v-f75a8935]{background:linear-gradient(45deg,#00dc82,#36e4da 50%,#0047e1);bottom:-30vh;filter:blur(20vh);height:40vh}.gradient-border[data-v-f75a8935]{-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-radius:.5rem;position:relative}@media (prefers-color-scheme:light){.gradient-border[data-v-f75a8935]{background-color:#ffffff4d}.gradient-border[data-v-f75a8935]:before{background:linear-gradient(90deg,#e2e2e2,#e2e2e2 25%,#00dc82,#36e4da 75%,#0047e1)}}@media (prefers-color-scheme:dark){.gradient-border[data-v-f75a8935]{background-color:#1414144d}.gradient-border[data-v-f75a8935]:before{background:linear-gradient(90deg,#303030,#303030 25%,#00dc82,#36e4da 75%,#0047e1)}}.gradient-border[data-v-f75a8935]:before{background-size:400% auto;border-radius:.5rem;content:"";inset:0;-webkit-mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);-webkit-mask-composite:xor;mask-composite:exclude;opacity:.5;padding:2px;position:absolute;transition:background-position .3s ease-in-out,opacity .2s ease-in-out;width:100%}.gradient-border[data-v-f75a8935]:hover:before{background-position:-50% 0;opacity:1}.fixed[data-v-f75a8935]{position:fixed}.left-0[data-v-f75a8935]{left:0}.right-0[data-v-f75a8935]{right:0}.z-10[data-v-f75a8935]{z-index:10}.z-20[data-v-f75a8935]{z-index:20}.grid[data-v-f75a8935]{display:grid}.mb-16[data-v-f75a8935]{margin-bottom:4rem}.mb-8[data-v-f75a8935]{margin-bottom:2rem}.max-w-520px[data-v-f75a8935]{max-width:520px}.min-h-screen[data-v-f75a8935]{min-height:100vh}.w-full[data-v-f75a8935]{width:100%}.flex[data-v-f75a8935]{display:flex}.cursor-pointer[data-v-f75a8935]{cursor:pointer}.place-content-center[data-v-f75a8935]{place-content:center}.items-center[data-v-f75a8935]{align-items:center}.justify-center[data-v-f75a8935]{justify-content:center}.overflow-hidden[data-v-f75a8935]{overflow:hidden}.bg-white[data-v-f75a8935]{--un-bg-opacity:1;background-color:rgb(255 255 255/var(--un-bg-opacity))}.px-4[data-v-f75a8935]{padding-left:1rem;padding-right:1rem}.px-8[data-v-f75a8935]{padding-left:2rem;padding-right:2rem}.py-2[data-v-f75a8935]{padding-bottom:.5rem;padding-top:.5rem}.text-center[data-v-f75a8935]{text-align:center}.text-8xl[data-v-f75a8935]{font-size:6rem;line-height:1}.text-xl[data-v-f75a8935]{font-size:1.25rem;line-height:1.75rem}.text-black[data-v-f75a8935]{--un-text-opacity:1;color:rgb(0 0 0/var(--un-text-opacity))}.font-light[data-v-f75a8935]{font-weight:300}.font-medium[data-v-f75a8935]{font-weight:500}.leading-tight[data-v-f75a8935]{line-height:1.25}.font-sans[data-v-f75a8935]{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.antialiased[data-v-f75a8935]{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@media (prefers-color-scheme:dark){.dark\:bg-black[data-v-f75a8935]{--un-bg-opacity:1;background-color:rgb(0 0 0/var(--un-bg-opacity))}.dark\:text-white[data-v-f75a8935]{--un-text-opacity:1;color:rgb(255 255 255/var(--un-text-opacity))}}@media (min-width:640px){.sm\:px-0[data-v-f75a8935]{padding-left:0;padding-right:0}.sm\:px-6[data-v-f75a8935]{padding-left:1.5rem;padding-right:1.5rem}.sm\:py-3[data-v-f75a8935]{padding-bottom:.75rem;padding-top:.75rem}.sm\:text-4xl[data-v-f75a8935]{font-size:2.25rem;line-height:2.5rem}.sm\:text-xl[data-v-f75a8935]{font-size:1.25rem;line-height:1.75rem}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.spotlight[data-v-8bb04cde]{background:linear-gradient(45deg,#00dc82,#36e4da 50%,#0047e1);filter:blur(20vh)}.fixed[data-v-8bb04cde]{position:fixed}.-bottom-1\/2[data-v-8bb04cde]{bottom:-50%}.left-0[data-v-8bb04cde]{left:0}.right-0[data-v-8bb04cde]{right:0}.grid[data-v-8bb04cde]{display:grid}.mb-16[data-v-8bb04cde]{margin-bottom:4rem}.mb-8[data-v-8bb04cde]{margin-bottom:2rem}.h-1\/2[data-v-8bb04cde]{height:50%}.max-w-520px[data-v-8bb04cde]{max-width:520px}.min-h-screen[data-v-8bb04cde]{min-height:100vh}.place-content-center[data-v-8bb04cde]{place-content:center}.overflow-hidden[data-v-8bb04cde]{overflow:hidden}.bg-white[data-v-8bb04cde]{--un-bg-opacity:1;background-color:rgb(255 255 255/var(--un-bg-opacity))}.px-8[data-v-8bb04cde]{padding-left:2rem;padding-right:2rem}.text-center[data-v-8bb04cde]{text-align:center}.text-8xl[data-v-8bb04cde]{font-size:6rem;line-height:1}.text-xl[data-v-8bb04cde]{font-size:1.25rem;line-height:1.75rem}.text-black[data-v-8bb04cde]{--un-text-opacity:1;color:rgb(0 0 0/var(--un-text-opacity))}.font-light[data-v-8bb04cde]{font-weight:300}.font-medium[data-v-8bb04cde]{font-weight:500}.leading-tight[data-v-8bb04cde]{line-height:1.25}.font-sans[data-v-8bb04cde]{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.antialiased[data-v-8bb04cde]{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@media (prefers-color-scheme:dark){.dark\:bg-black[data-v-8bb04cde]{--un-bg-opacity:1;background-color:rgb(0 0 0/var(--un-bg-opacity))}.dark\:text-white[data-v-8bb04cde]{--un-text-opacity:1;color:rgb(255 255 255/var(--un-text-opacity))}}@media (min-width:640px){.sm\:px-0[data-v-8bb04cde]{padding-left:0;padding-right:0}.sm\:text-4xl[data-v-8bb04cde]{font-size:2.25rem;line-height:2.5rem}}
|
package/dist/client/index.html
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
<!DOCTYPE html><html><head><meta charset="utf-8">
|
|
2
2
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
3
3
|
<link rel="stylesheet" href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/entry.Cq9tULRb.css" crossorigin>
|
|
4
|
-
<link rel="modulepreload" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/
|
|
4
|
+
<link rel="modulepreload" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/XZXfxmri.js">
|
|
5
5
|
<link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/l5rcX3cq.js">
|
|
6
|
-
<link rel="prefetch" as="style" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/error-404.
|
|
7
|
-
<link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/
|
|
8
|
-
<link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/
|
|
9
|
-
<link rel="prefetch" as="style" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/error-500.
|
|
10
|
-
<link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/
|
|
11
|
-
<script type="module" src="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/
|
|
12
|
-
<script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__NUXT_DEVTOOLS_I18N_BASE__/",buildId:"
|
|
6
|
+
<link rel="prefetch" as="style" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/error-404.Ba2SLv0l.css">
|
|
7
|
+
<link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/CQupjgaS.js">
|
|
8
|
+
<link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/CBxwnKtU.js">
|
|
9
|
+
<link rel="prefetch" as="style" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/error-500.BqKd8Zt-.css">
|
|
10
|
+
<link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/BYEpoBUk.js">
|
|
11
|
+
<script type="module" src="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/XZXfxmri.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__">[{"prerenderedAt":1,"serverRendered":2},1761933271956,false]</script>
|
|
12
|
+
<script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__NUXT_DEVTOOLS_I18N_BASE__/",buildId:"df79903a-9996-4527-8269-e47de875a594",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -2,7 +2,6 @@ import path, { resolve, join } from 'node:path';
|
|
|
2
2
|
import * as fs from 'node:fs';
|
|
3
3
|
import fs__default, { existsSync, mkdirSync, writeFileSync, readFileSync } from 'node:fs';
|
|
4
4
|
import { useNuxt, defineNuxtModule, useLogger, createResolver, addTemplate, addImportsDir, addPlugin, addServerHandler, addComponentsDir, addTypeTemplate, addPrerenderRoutes } from '@nuxt/kit';
|
|
5
|
-
import { watch } from 'chokidar';
|
|
6
5
|
import { isPrefixAndDefaultStrategy, isPrefixStrategy, isNoPrefixStrategy, isPrefixExceptDefaultStrategy, withPrefixStrategy } from 'nuxt-i18n-micro-core';
|
|
7
6
|
import { fileURLToPath } from 'node:url';
|
|
8
7
|
import { onDevToolsInitialized, extendServerRpc } from '@nuxt/devtools-kit';
|
|
@@ -576,7 +575,14 @@ class PageManager {
|
|
|
576
575
|
...page,
|
|
577
576
|
children: this.createLocalizedChildren(originalChildren, page.path, localeCodes, true, false, parentLocale, { [firstLocale]: customPath }),
|
|
578
577
|
path: routePath,
|
|
579
|
-
name: routeName
|
|
578
|
+
name: routeName,
|
|
579
|
+
alias: [],
|
|
580
|
+
// remove alias to prevent infinite recursion
|
|
581
|
+
meta: {
|
|
582
|
+
...page.meta,
|
|
583
|
+
alias: []
|
|
584
|
+
// remove alias to prevent infinite recursion
|
|
585
|
+
}
|
|
580
586
|
};
|
|
581
587
|
}
|
|
582
588
|
buildLocalizedRouteName(baseName, locale, modifyName, forceLocaleSuffixOrCustom = false) {
|
|
@@ -684,7 +690,7 @@ const module = defineNuxtModule({
|
|
|
684
690
|
autoDetectLanguage: true,
|
|
685
691
|
disablePageLocales: false,
|
|
686
692
|
disableWatcher: false,
|
|
687
|
-
|
|
693
|
+
// experimental kept in runtimeConfig only to avoid type drift here
|
|
688
694
|
noPrefixRedirect: false,
|
|
689
695
|
includeDefaultLocaleRoute: void 0,
|
|
690
696
|
fallbackLocale: void 0,
|
|
@@ -726,7 +732,7 @@ const module = defineNuxtModule({
|
|
|
726
732
|
const routeLocales = {};
|
|
727
733
|
const globalLocaleRoutes = {};
|
|
728
734
|
const routeDisableMeta = {};
|
|
729
|
-
const pageFiles = await globby("pages/**/*.vue", { cwd: nuxt.options.rootDir });
|
|
735
|
+
const pageFiles = await globby(["pages/**/*.vue", "app/pages/**/*.vue"], { cwd: nuxt.options.rootDir });
|
|
730
736
|
for (const pageFile of pageFiles) {
|
|
731
737
|
const fullPath = join(nuxt.options.rootDir, pageFile);
|
|
732
738
|
try {
|
|
@@ -734,7 +740,7 @@ const module = defineNuxtModule({
|
|
|
734
740
|
const config = extractDefineI18nRouteData(fileContent, fullPath);
|
|
735
741
|
if (!config) continue;
|
|
736
742
|
const { locales: extractedLocales, localeRoutes, disableMeta } = config;
|
|
737
|
-
const routePath = pageFile.replace(/^pages\//, "/").replace(/\/index\.vue$/, "").replace(/\.vue$/, "").replace(/\/$/, "") || "/";
|
|
743
|
+
const routePath = pageFile.replace(/^(app\/)?pages\//, "/").replace(/\/index\.vue$/, "").replace(/\.vue$/, "").replace(/\/$/, "") || "/";
|
|
738
744
|
if (extractedLocales) {
|
|
739
745
|
if (Array.isArray(extractedLocales)) {
|
|
740
746
|
routeLocales[routePath] = extractedLocales;
|
|
@@ -768,9 +774,6 @@ const module = defineNuxtModule({
|
|
|
768
774
|
localeCookie: options.localeCookie ?? "user-locale",
|
|
769
775
|
autoDetectPath: options.autoDetectPath ?? "/",
|
|
770
776
|
strategy: options.strategy ?? "prefix_except_default",
|
|
771
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
772
|
-
// @ts-ignore
|
|
773
|
-
routesLocaleLinks: options.routesLocaleLinks ?? {},
|
|
774
777
|
dateBuild: Date.now(),
|
|
775
778
|
hashMode: nuxt.options?.router?.options?.hashMode ?? false,
|
|
776
779
|
apiBaseUrl,
|
|
@@ -785,7 +788,10 @@ const module = defineNuxtModule({
|
|
|
785
788
|
// @ts-ignore
|
|
786
789
|
routeDisableMeta,
|
|
787
790
|
experimental: {
|
|
788
|
-
i18nPreviousPageFallback: options.experimental?.i18nPreviousPageFallback ?? false
|
|
791
|
+
i18nPreviousPageFallback: options.experimental?.i18nPreviousPageFallback ?? false,
|
|
792
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
793
|
+
// @ts-ignore
|
|
794
|
+
hmr: options.experimental?.hmr ?? true
|
|
789
795
|
}
|
|
790
796
|
};
|
|
791
797
|
if (typeof options.customRegexMatcher !== "undefined") {
|
|
@@ -802,7 +808,10 @@ const module = defineNuxtModule({
|
|
|
802
808
|
// @ts-ignore
|
|
803
809
|
fallbackLocale: options.fallbackLocale ?? void 0,
|
|
804
810
|
translationDir: options.translationDir ?? "locales",
|
|
805
|
-
customRegexMatcher: options.customRegexMatcher
|
|
811
|
+
customRegexMatcher: options.customRegexMatcher,
|
|
812
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
813
|
+
// @ts-ignore
|
|
814
|
+
routesLocaleLinks: options.routesLocaleLinks ?? {}
|
|
806
815
|
};
|
|
807
816
|
addImportsDir(resolver.resolve("./runtime/composables"));
|
|
808
817
|
if (process.env && process.env.TEST) {
|
|
@@ -862,12 +871,66 @@ const module = defineNuxtModule({
|
|
|
862
871
|
pathPrefix: false,
|
|
863
872
|
extensions: ["vue"]
|
|
864
873
|
});
|
|
874
|
+
if (nuxt.options.dev && (options.experimental?.hmr ?? true)) {
|
|
875
|
+
const translationsDir = join(nuxt.options.rootDir, options.translationDir || "locales");
|
|
876
|
+
const files = await globby(["**/*.json"], { cwd: translationsDir, absolute: true });
|
|
877
|
+
const tpl = addTemplate({
|
|
878
|
+
filename: "i18n-hmr-plugin.mjs",
|
|
879
|
+
write: true,
|
|
880
|
+
getContents: () => generateHmrPlugin(files.map((f) => f.replace(/\\/g, "/")))
|
|
881
|
+
});
|
|
882
|
+
addPlugin({
|
|
883
|
+
src: tpl.dst,
|
|
884
|
+
mode: "client",
|
|
885
|
+
name: "i18n-hmr-plugin",
|
|
886
|
+
order: 10
|
|
887
|
+
});
|
|
888
|
+
}
|
|
865
889
|
if (options.types) {
|
|
866
890
|
addTypeTemplate({
|
|
867
891
|
filename: "types/i18n-plugin.d.ts",
|
|
868
892
|
getContents: () => generateI18nTypes()
|
|
869
893
|
});
|
|
870
894
|
}
|
|
895
|
+
function generateHmrPlugin(files) {
|
|
896
|
+
const accepts = files.map((file) => {
|
|
897
|
+
const isPage = /\/pages\//.test(file);
|
|
898
|
+
let pageName = "";
|
|
899
|
+
let locale = "";
|
|
900
|
+
if (isPage) {
|
|
901
|
+
const m = /\/pages\/([^/]+)\/([^/]+)\.json$/.exec(file);
|
|
902
|
+
pageName = m?.[1] || "";
|
|
903
|
+
locale = m?.[2] || "";
|
|
904
|
+
} else {
|
|
905
|
+
const m = /\/([^/]+)\.json$/.exec(file);
|
|
906
|
+
locale = m?.[1] || "";
|
|
907
|
+
}
|
|
908
|
+
return `
|
|
909
|
+
if (import.meta.hot) {
|
|
910
|
+
import.meta.hot.accept('${file}', async (mod) => {
|
|
911
|
+
const nuxtApp = useNuxtApp()
|
|
912
|
+
const data = (mod && typeof mod === 'object' && Object.prototype.hasOwnProperty.call(mod, 'default'))
|
|
913
|
+
? mod.default
|
|
914
|
+
: mod
|
|
915
|
+
try {
|
|
916
|
+
${isPage ? `await nuxtApp.$loadPageTranslations('${locale}', '${pageName}', data)` : `await nuxtApp.$loadTranslations('${locale}', data)`}
|
|
917
|
+
console.log('[i18n HMR] Translations reloaded:', '${isPage ? "page" : "global"}', '${locale}'${isPage ? `, '${pageName}'` : ""})
|
|
918
|
+
}
|
|
919
|
+
catch (e) {
|
|
920
|
+
console.warn('[i18n HMR] Failed to reload translations for', '${file}', e)
|
|
921
|
+
}
|
|
922
|
+
})
|
|
923
|
+
}
|
|
924
|
+
`.trim();
|
|
925
|
+
}).join("\n");
|
|
926
|
+
return `
|
|
927
|
+
import { defineNuxtPlugin, useNuxtApp } from '#imports'
|
|
928
|
+
|
|
929
|
+
export default defineNuxtPlugin(() => {
|
|
930
|
+
${accepts}
|
|
931
|
+
})
|
|
932
|
+
`.trim();
|
|
933
|
+
}
|
|
871
934
|
nuxt.hook("pages:resolved", (pages) => {
|
|
872
935
|
const prerenderRoutes = [];
|
|
873
936
|
const routeRules = nuxt.options.routeRules || {};
|
|
@@ -1024,24 +1087,12 @@ const module = defineNuxtModule({
|
|
|
1024
1087
|
}
|
|
1025
1088
|
}
|
|
1026
1089
|
});
|
|
1027
|
-
|
|
1028
|
-
nuxt.
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
const watcherEvent = async (path2) => {
|
|
1034
|
-
await watcher.close();
|
|
1035
|
-
logger.log("\u21BB update store item: " + path2);
|
|
1036
|
-
nuxt.callHook("restart");
|
|
1037
|
-
};
|
|
1038
|
-
const watcher = watch(translationPath, { depth: 2, persistent: true }).on("change", watcherEvent);
|
|
1039
|
-
nuxt.hook("close", () => {
|
|
1040
|
-
watcher.close();
|
|
1041
|
-
});
|
|
1042
|
-
}
|
|
1043
|
-
});
|
|
1044
|
-
}
|
|
1090
|
+
nuxt.hook("nitro:config", (nitroConfig) => {
|
|
1091
|
+
if (nuxt.options.dev && (options.experimental?.hmr ?? true)) {
|
|
1092
|
+
nitroConfig.plugins = nitroConfig.plugins || [];
|
|
1093
|
+
nitroConfig.plugins.push(resolver.resolve("./runtime/server/plugins/watcher.dev"));
|
|
1094
|
+
}
|
|
1095
|
+
});
|
|
1045
1096
|
nuxt.hook("prerender:routes", async (prerenderRoutes) => {
|
|
1046
1097
|
if (isNoPrefixStrategy(options.strategy)) {
|
|
1047
1098
|
return;
|
|
@@ -22,37 +22,40 @@ export declare const useLocaleHead: ({ addDirAttribute, identifierAttribute, add
|
|
|
22
22
|
identifierAttribute?: string | undefined;
|
|
23
23
|
addSeoAttributes?: boolean | undefined;
|
|
24
24
|
baseUrl?: string | undefined;
|
|
25
|
-
}) =>
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
25
|
+
}) => {
|
|
26
|
+
metaObject: import("vue").Ref<{
|
|
27
|
+
htmlAttrs: {
|
|
28
|
+
lang?: string | undefined;
|
|
29
|
+
dir?: "ltr" | "rtl" | "auto" | undefined;
|
|
30
|
+
};
|
|
31
|
+
link: {
|
|
32
|
+
[x: string]: string | undefined;
|
|
33
|
+
rel: string;
|
|
34
|
+
href: string;
|
|
35
|
+
hreflang?: string | undefined;
|
|
36
|
+
}[];
|
|
37
|
+
meta: {
|
|
38
|
+
[x: string]: string;
|
|
39
|
+
property: string;
|
|
40
|
+
content: string;
|
|
41
|
+
}[];
|
|
42
|
+
}, MetaObject | {
|
|
43
|
+
htmlAttrs: {
|
|
44
|
+
lang?: string | undefined;
|
|
45
|
+
dir?: "ltr" | "rtl" | "auto" | undefined;
|
|
46
|
+
};
|
|
47
|
+
link: {
|
|
48
|
+
[x: string]: string | undefined;
|
|
49
|
+
rel: string;
|
|
50
|
+
href: string;
|
|
51
|
+
hreflang?: string | undefined;
|
|
52
|
+
}[];
|
|
53
|
+
meta: {
|
|
54
|
+
[x: string]: string;
|
|
55
|
+
property: string;
|
|
56
|
+
content: string;
|
|
57
|
+
}[];
|
|
58
|
+
}>;
|
|
59
|
+
updateMeta: () => void;
|
|
60
|
+
};
|
|
58
61
|
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { joinURL, parseURL, withQuery } from "ufo";
|
|
2
2
|
import { isPrefixExceptDefaultStrategy, isNoPrefixStrategy } from "nuxt-i18n-micro-core";
|
|
3
|
-
import { unref, useRoute, useRuntimeConfig,
|
|
3
|
+
import { unref, useRoute, useRuntimeConfig, ref, useNuxtApp } from "#imports";
|
|
4
4
|
import { findAllowedLocalesForRoute } from "../utils/route-utils.js";
|
|
5
5
|
export const useLocaleHead = ({ addDirAttribute = true, identifierAttribute = "id", addSeoAttributes = true, baseUrl = "/" } = {}) => {
|
|
6
6
|
const metaObject = ref({
|
|
@@ -101,16 +101,5 @@ export const useLocaleHead = ({ addDirAttribute = true, identifierAttribute = "i
|
|
|
101
101
|
metaObject.value.meta = [ogLocaleMeta, ogUrlMeta, ...alternateOgLocalesMeta];
|
|
102
102
|
metaObject.value.link = [canonicalLink, ...alternateLinks];
|
|
103
103
|
}
|
|
104
|
-
|
|
105
|
-
const route = useRoute();
|
|
106
|
-
const stop = watch(
|
|
107
|
-
() => route.fullPath,
|
|
108
|
-
() => updateMeta(),
|
|
109
|
-
{ immediate: true }
|
|
110
|
-
);
|
|
111
|
-
onUnmounted(() => stop());
|
|
112
|
-
} else {
|
|
113
|
-
updateMeta();
|
|
114
|
-
}
|
|
115
|
-
return metaObject;
|
|
104
|
+
return { metaObject, updateMeta };
|
|
116
105
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { RouteLocationNormalizedLoaded, RouteLocationRaw, RouteLocationResolved, RouteLocationResolvedGeneric, RouteLocationNamedRaw } from 'vue-router';
|
|
2
|
+
import { useTranslationHelper } from 'nuxt-i18n-micro-core';
|
|
2
3
|
import type { Locale, I18nRouteParams, Params, Translations, CleanTranslation } from 'nuxt-i18n-micro-types';
|
|
3
4
|
declare const _default: import("nuxt/app").Plugin<{
|
|
4
5
|
i18n: undefined;
|
|
@@ -28,6 +29,20 @@ declare const _default: import("nuxt/app").Plugin<{
|
|
|
28
29
|
localePath: (to: RouteLocationNamedRaw | RouteLocationResolvedGeneric | string, locale?: string) => string;
|
|
29
30
|
setI18nRouteParams: (value: I18nRouteParams) => I18nRouteParams;
|
|
30
31
|
loadPageTranslations: (locale: string, routeName: string, translations: Translations) => Promise<void>;
|
|
32
|
+
helper: {
|
|
33
|
+
hasCache(locale: string, page: string): boolean;
|
|
34
|
+
getCache(locale: string, routeName: string): Map<string, unknown> | undefined;
|
|
35
|
+
setCache(locale: string, routeName: string, cache: Map<string, Translations | unknown>): void;
|
|
36
|
+
mergeTranslation(locale: string, routeName: string, newTranslations: Translations, force?: boolean): void;
|
|
37
|
+
mergeGlobalTranslation(locale: string, newTranslations: Translations, force?: boolean): void;
|
|
38
|
+
hasGeneralTranslation(locale: string): boolean;
|
|
39
|
+
hasPageTranslation(locale: string, routeName: string): boolean;
|
|
40
|
+
hasTranslation: (locale: string, key: string) => boolean;
|
|
41
|
+
getTranslation: <T = unknown>(locale: string, routeName: string, key: string) => T | null;
|
|
42
|
+
loadPageTranslations(locale: string, routeName: string, translations: Translations): Promise<void>;
|
|
43
|
+
loadTranslations(locale: string, translations: Translations): Promise<void>;
|
|
44
|
+
clearCache(): void;
|
|
45
|
+
};
|
|
31
46
|
}> & import("nuxt/app").ObjectPlugin<{
|
|
32
47
|
i18n: undefined;
|
|
33
48
|
__micro: boolean;
|
|
@@ -56,6 +71,20 @@ declare const _default: import("nuxt/app").Plugin<{
|
|
|
56
71
|
localePath: (to: RouteLocationNamedRaw | RouteLocationResolvedGeneric | string, locale?: string) => string;
|
|
57
72
|
setI18nRouteParams: (value: I18nRouteParams) => I18nRouteParams;
|
|
58
73
|
loadPageTranslations: (locale: string, routeName: string, translations: Translations) => Promise<void>;
|
|
74
|
+
helper: {
|
|
75
|
+
hasCache(locale: string, page: string): boolean;
|
|
76
|
+
getCache(locale: string, routeName: string): Map<string, unknown> | undefined;
|
|
77
|
+
setCache(locale: string, routeName: string, cache: Map<string, Translations | unknown>): void;
|
|
78
|
+
mergeTranslation(locale: string, routeName: string, newTranslations: Translations, force?: boolean): void;
|
|
79
|
+
mergeGlobalTranslation(locale: string, newTranslations: Translations, force?: boolean): void;
|
|
80
|
+
hasGeneralTranslation(locale: string): boolean;
|
|
81
|
+
hasPageTranslation(locale: string, routeName: string): boolean;
|
|
82
|
+
hasTranslation: (locale: string, key: string) => boolean;
|
|
83
|
+
getTranslation: <T = unknown>(locale: string, routeName: string, key: string) => T | null;
|
|
84
|
+
loadPageTranslations(locale: string, routeName: string, translations: Translations): Promise<void>;
|
|
85
|
+
loadTranslations(locale: string, translations: Translations): Promise<void>;
|
|
86
|
+
clearCache(): void;
|
|
87
|
+
};
|
|
59
88
|
}>;
|
|
60
89
|
export default _default;
|
|
61
90
|
export interface PluginsInjections {
|
|
@@ -83,4 +112,5 @@ export interface PluginsInjections {
|
|
|
83
112
|
$localePath: (to: RouteLocationNamedRaw | RouteLocationResolvedGeneric | string, locale?: string) => string;
|
|
84
113
|
$setI18nRouteParams: (value: I18nRouteParams) => I18nRouteParams;
|
|
85
114
|
$loadPageTranslations: (locale: string, routeName: string, translations: Translations) => Promise<void>;
|
|
115
|
+
helper: ReturnType<typeof useTranslationHelper>;
|
|
86
116
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useTranslationHelper, interpolate, isNoPrefixStrategy, RouteService, FormatService } from "nuxt-i18n-micro-core";
|
|
2
|
-
import { useRouter, useCookie,
|
|
2
|
+
import { useRouter, useCookie, unref, navigateTo, defineNuxtPlugin, useRuntimeConfig, createError } from "#imports";
|
|
3
|
+
import { useState } from "#app";
|
|
3
4
|
import { plural } from "#build/i18n.plural.mjs";
|
|
4
|
-
const i18nHelper = useTranslationHelper();
|
|
5
5
|
const isDev = process.env.NODE_ENV !== "production";
|
|
6
6
|
export default defineNuxtPlugin(async (nuxtApp) => {
|
|
7
7
|
const config = useRuntimeConfig();
|
|
@@ -9,6 +9,17 @@ export default defineNuxtPlugin(async (nuxtApp) => {
|
|
|
9
9
|
const apiBaseUrl = i18nConfig.apiBaseUrl ?? "_locales";
|
|
10
10
|
const router = useRouter();
|
|
11
11
|
const runtimeConfig = useRuntimeConfig();
|
|
12
|
+
const generalLocaleCache = useState("i18n-general-cache", () => ({}));
|
|
13
|
+
const routeLocaleCache = useState("i18n-route-cache", () => ({}));
|
|
14
|
+
const dynamicTranslationsCaches = useState("i18n-dynamic-caches", () => []);
|
|
15
|
+
const serverTranslationCache = useState("i18n-server-cache", () => ({}));
|
|
16
|
+
const translationCaches = {
|
|
17
|
+
generalLocaleCache,
|
|
18
|
+
routeLocaleCache,
|
|
19
|
+
dynamicTranslationsCaches,
|
|
20
|
+
serverTranslationCache
|
|
21
|
+
};
|
|
22
|
+
const i18nHelper = useTranslationHelper(translationCaches);
|
|
12
23
|
let hashLocaleDefault = null;
|
|
13
24
|
let noPrefixDefault = null;
|
|
14
25
|
if (i18nConfig.hashMode) {
|
|
@@ -39,75 +50,56 @@ export default defineNuxtPlugin(async (nuxtApp) => {
|
|
|
39
50
|
previousPageInfo.value = null;
|
|
40
51
|
}
|
|
41
52
|
});
|
|
42
|
-
|
|
43
|
-
try {
|
|
44
|
-
if (!i18nHelper.hasPageTranslation(locale, routeName)) {
|
|
45
|
-
let fRouteName = routeName;
|
|
46
|
-
if (i18nConfig.routesLocaleLinks && fRouteName && i18nConfig.routesLocaleLinks[fRouteName]) {
|
|
47
|
-
const newRouteName = i18nConfig.routesLocaleLinks[fRouteName];
|
|
48
|
-
if (newRouteName) {
|
|
49
|
-
fRouteName = newRouteName;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
if (!fRouteName || fRouteName === "") {
|
|
53
|
-
console.warn(`[nuxt-i18n-next] The page name is missing in the path: ${path}. Please ensure that definePageMeta({ name: 'pageName' }) is set.`);
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
const url = `/${apiBaseUrl}/${fRouteName}/${locale}/data.json`.replace(/\/{2,}/g, "/");
|
|
57
|
-
const data = await $fetch(url, {
|
|
58
|
-
baseURL: runtimeConfig.app.baseURL,
|
|
59
|
-
params: {
|
|
60
|
-
v: i18nConfig.dateBuild
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
await i18nHelper.loadPageTranslations(locale, routeName, data ?? {});
|
|
64
|
-
}
|
|
65
|
-
} catch (_error) {
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
async function loadGlobalTranslations(to) {
|
|
53
|
+
async function loadPageAndGlobalTranslations(to) {
|
|
69
54
|
let locale = routeService.getCurrentLocale(to);
|
|
70
55
|
if (i18nConfig.hashMode) {
|
|
71
|
-
locale = await nuxtApp.runWithContext(() => {
|
|
72
|
-
return useCookie("hash-locale", { default: () => locale }).value;
|
|
73
|
-
});
|
|
56
|
+
locale = await nuxtApp.runWithContext(() => useCookie("hash-locale", { default: () => locale }).value);
|
|
74
57
|
}
|
|
75
58
|
if (isNoPrefixStrategy(i18nConfig.strategy)) {
|
|
76
|
-
locale = await nuxtApp.runWithContext(() => {
|
|
77
|
-
|
|
78
|
-
|
|
59
|
+
locale = await nuxtApp.runWithContext(() => useCookie("no-prefix-locale", { default: () => locale }).value);
|
|
60
|
+
}
|
|
61
|
+
const routeName = routeService.getRouteName(to, locale);
|
|
62
|
+
if (!routeName) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (i18nHelper.hasPageTranslation(locale, routeName)) {
|
|
66
|
+
if (isDev) {
|
|
67
|
+
console.log(`[DEBUG] Cache HIT for '${locale}:${routeName}'. Skipping fetch.`);
|
|
68
|
+
}
|
|
69
|
+
return;
|
|
79
70
|
}
|
|
80
|
-
|
|
81
|
-
|
|
71
|
+
const url = `/${apiBaseUrl}/${routeName}/${locale}/data.json`.replace(/\/{2,}/g, "/");
|
|
72
|
+
try {
|
|
82
73
|
const data = await $fetch(url, {
|
|
83
74
|
baseURL: runtimeConfig.app.baseURL,
|
|
84
|
-
params: {
|
|
85
|
-
v: i18nConfig.dateBuild
|
|
86
|
-
}
|
|
75
|
+
params: { v: i18nConfig.dateBuild }
|
|
87
76
|
});
|
|
88
|
-
await i18nHelper.
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
77
|
+
await i18nHelper.loadPageTranslations(locale, routeName, data ?? {});
|
|
78
|
+
} catch (e) {
|
|
79
|
+
if (isDev) {
|
|
80
|
+
console.error(`[i18n] Failed to load translations for ${routeName}/${locale}`, e);
|
|
81
|
+
}
|
|
82
|
+
throw createError({ statusCode: 404, statusMessage: "Page Not Found" });
|
|
94
83
|
}
|
|
95
84
|
}
|
|
96
85
|
router.beforeEach(async (to, from, next) => {
|
|
97
|
-
if (to.path
|
|
98
|
-
if (
|
|
99
|
-
|
|
100
|
-
const fromRouteName = routeService.getRouteName(from, fromLocale);
|
|
101
|
-
previousPageInfo.value = { locale: fromLocale, routeName: fromRouteName };
|
|
102
|
-
console.log(`Saved previous page info for cleanup: ${fromRouteName}`);
|
|
103
|
-
}
|
|
104
|
-
await loadGlobalTranslations(to);
|
|
86
|
+
if (to.path === from.path && !isNoPrefixStrategy(i18nConfig.strategy)) {
|
|
87
|
+
if (next) next();
|
|
88
|
+
return;
|
|
105
89
|
}
|
|
106
|
-
if (
|
|
107
|
-
|
|
90
|
+
if (import.meta.client && enablePreviousPageFallback) {
|
|
91
|
+
const fromLocale = routeService.getCurrentLocale(from);
|
|
92
|
+
const fromRouteName = routeService.getRouteName(from, fromLocale);
|
|
93
|
+
previousPageInfo.value = { locale: fromLocale, routeName: fromRouteName };
|
|
108
94
|
}
|
|
95
|
+
try {
|
|
96
|
+
await loadPageAndGlobalTranslations(to);
|
|
97
|
+
} catch (e) {
|
|
98
|
+
console.error("[i18n] Error loading translations:", e);
|
|
99
|
+
}
|
|
100
|
+
if (next) next();
|
|
109
101
|
});
|
|
110
|
-
await
|
|
102
|
+
await loadPageAndGlobalTranslations(router.currentRoute.value);
|
|
111
103
|
const provideData = {
|
|
112
104
|
i18n: void 0,
|
|
113
105
|
__micro: true,
|
|
@@ -134,9 +126,6 @@ export default defineNuxtPlugin(async (nuxtApp) => {
|
|
|
134
126
|
console.log(`Using fallback translation from previous route: ${prev.routeName} -> ${key}`);
|
|
135
127
|
}
|
|
136
128
|
}
|
|
137
|
-
if (!value) {
|
|
138
|
-
value = i18nHelper.getTranslation(locale, "", key);
|
|
139
|
-
}
|
|
140
129
|
if (!value) {
|
|
141
130
|
if (isDev && import.meta.client) {
|
|
142
131
|
console.warn(`Not found '${key}' key in '${locale}' locale messages for route '${routeName}'.`);
|
|
@@ -243,7 +232,9 @@ export default defineNuxtPlugin(async (nuxtApp) => {
|
|
|
243
232
|
},
|
|
244
233
|
loadPageTranslations: async (locale, routeName, translations) => {
|
|
245
234
|
await i18nHelper.loadPageTranslations(locale, routeName, translations);
|
|
246
|
-
}
|
|
235
|
+
},
|
|
236
|
+
helper: i18nHelper
|
|
237
|
+
// Оставляем helper, он может быть полезен для продвинутых пользователей
|
|
247
238
|
};
|
|
248
239
|
const $provideData = Object.fromEntries(
|
|
249
240
|
Object.entries(provideData).map(([key, value]) => [`$${key}`, value])
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useLocaleHead } from "../composables/useLocaleHead.js";
|
|
2
|
-
import { useRequestURL, useHead, defineNuxtPlugin, useRuntimeConfig, useRoute } from "#imports";
|
|
2
|
+
import { useRequestURL, useHead, defineNuxtPlugin, useRuntimeConfig, useRoute, watch } from "#imports";
|
|
3
3
|
import { isMetaDisabledForRoute } from "../utils/route-utils.js";
|
|
4
4
|
const host = process.env.HOST ?? "localhost";
|
|
5
5
|
const port = process.env.PORT ?? "host";
|
|
@@ -15,11 +15,20 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|
|
15
15
|
const defaultUrl = port === "80" || port === "443" ? `${schema}://${host}` : `${schema}://${host}:${port}`;
|
|
16
16
|
const url = useRequestURL();
|
|
17
17
|
const baseUrl = (i18nConfig.metaBaseUrl || url.origin || defaultUrl).toString();
|
|
18
|
-
const
|
|
18
|
+
const { metaObject, updateMeta } = useLocaleHead({
|
|
19
19
|
addDirAttribute: true,
|
|
20
20
|
identifierAttribute: "id",
|
|
21
21
|
addSeoAttributes: true,
|
|
22
22
|
baseUrl
|
|
23
23
|
});
|
|
24
|
-
useHead(
|
|
24
|
+
useHead(metaObject);
|
|
25
|
+
if (import.meta.server) {
|
|
26
|
+
updateMeta();
|
|
27
|
+
} else if (import.meta.client) {
|
|
28
|
+
watch(
|
|
29
|
+
() => useRoute().fullPath,
|
|
30
|
+
() => updateMeta(),
|
|
31
|
+
{ immediate: true }
|
|
32
|
+
);
|
|
33
|
+
}
|
|
25
34
|
});
|
|
@@ -1,19 +1,27 @@
|
|
|
1
|
-
import { isNoPrefixStrategy
|
|
2
|
-
import { defineNuxtPlugin, useRuntimeConfig, useRouter } from "#imports";
|
|
3
|
-
const
|
|
1
|
+
import { isNoPrefixStrategy } from "nuxt-i18n-micro-core";
|
|
2
|
+
import { defineNuxtPlugin, useRuntimeConfig, useRouter, useNuxtApp } from "#imports";
|
|
3
|
+
const isDev = process.env.NODE_ENV !== "production";
|
|
4
4
|
export default defineNuxtPlugin(async (nuxtApp) => {
|
|
5
5
|
const config = useRuntimeConfig();
|
|
6
6
|
const i18nConfig = config.public.i18nConfig;
|
|
7
7
|
const router = useRouter();
|
|
8
|
-
const
|
|
9
|
-
const
|
|
8
|
+
const { $getLocale, $getRouteName } = useNuxtApp();
|
|
9
|
+
const i18nHelper = nuxtApp.$i18n.helper;
|
|
10
|
+
if (!i18nHelper) {
|
|
11
|
+
if (isDev) {
|
|
12
|
+
console.warn("[i18n] Helper is not available. Skipping hooks plugin.");
|
|
13
|
+
}
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const locale = $getLocale();
|
|
17
|
+
const routeName = $getRouteName();
|
|
10
18
|
await nuxtApp.callHook("i18n:register", (translations, selectedLocale) => {
|
|
11
19
|
i18nHelper.mergeTranslation(selectedLocale ?? locale, routeName, translations, true);
|
|
12
20
|
}, locale);
|
|
13
21
|
router.beforeEach(async (to, from, next) => {
|
|
14
22
|
if (to.path !== from.path || isNoPrefixStrategy(i18nConfig.strategy)) {
|
|
15
|
-
const locale2 =
|
|
16
|
-
const routeName2 =
|
|
23
|
+
const locale2 = $getLocale(to);
|
|
24
|
+
const routeName2 = $getRouteName(to);
|
|
17
25
|
await nuxtApp.callHook("i18n:register", (translations, selectedLocale) => {
|
|
18
26
|
i18nHelper.mergeTranslation(selectedLocale ?? locale2, routeName2, translations, true);
|
|
19
27
|
}, locale2);
|