nuxt-i18n-micro 1.102.0 → 2.0.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/9577efa7-2d15-4fca-9d0d-3cd305cdd931.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 +77 -25
- 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":"9577efa7-2d15-4fca-9d0d-3cd305cdd931","timestamp":1761831387055}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"id":"9577efa7-2d15-4fca-9d0d-3cd305cdd931","timestamp":1761831387055,"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},1761831392702,false]</script>
|
|
12
|
+
<script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__NUXT_DEVTOOLS_I18N_BASE__/",buildId:"9577efa7-2d15-4fca-9d0d-3cd305cdd931",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) {
|
|
@@ -685,6 +691,7 @@ const module = defineNuxtModule({
|
|
|
685
691
|
disablePageLocales: false,
|
|
686
692
|
disableWatcher: false,
|
|
687
693
|
disableUpdater: false,
|
|
694
|
+
// experimental kept in runtimeConfig only to avoid type drift here
|
|
688
695
|
noPrefixRedirect: false,
|
|
689
696
|
includeDefaultLocaleRoute: void 0,
|
|
690
697
|
fallbackLocale: void 0,
|
|
@@ -768,9 +775,6 @@ const module = defineNuxtModule({
|
|
|
768
775
|
localeCookie: options.localeCookie ?? "user-locale",
|
|
769
776
|
autoDetectPath: options.autoDetectPath ?? "/",
|
|
770
777
|
strategy: options.strategy ?? "prefix_except_default",
|
|
771
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
772
|
-
// @ts-ignore
|
|
773
|
-
routesLocaleLinks: options.routesLocaleLinks ?? {},
|
|
774
778
|
dateBuild: Date.now(),
|
|
775
779
|
hashMode: nuxt.options?.router?.options?.hashMode ?? false,
|
|
776
780
|
apiBaseUrl,
|
|
@@ -785,7 +789,10 @@ const module = defineNuxtModule({
|
|
|
785
789
|
// @ts-ignore
|
|
786
790
|
routeDisableMeta,
|
|
787
791
|
experimental: {
|
|
788
|
-
i18nPreviousPageFallback: options.experimental?.i18nPreviousPageFallback ?? false
|
|
792
|
+
i18nPreviousPageFallback: options.experimental?.i18nPreviousPageFallback ?? false,
|
|
793
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
794
|
+
// @ts-ignore
|
|
795
|
+
hmr: options.experimental?.hmr ?? true
|
|
789
796
|
}
|
|
790
797
|
};
|
|
791
798
|
if (typeof options.customRegexMatcher !== "undefined") {
|
|
@@ -802,7 +809,10 @@ const module = defineNuxtModule({
|
|
|
802
809
|
// @ts-ignore
|
|
803
810
|
fallbackLocale: options.fallbackLocale ?? void 0,
|
|
804
811
|
translationDir: options.translationDir ?? "locales",
|
|
805
|
-
customRegexMatcher: options.customRegexMatcher
|
|
812
|
+
customRegexMatcher: options.customRegexMatcher,
|
|
813
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
814
|
+
// @ts-ignore
|
|
815
|
+
routesLocaleLinks: options.routesLocaleLinks ?? {}
|
|
806
816
|
};
|
|
807
817
|
addImportsDir(resolver.resolve("./runtime/composables"));
|
|
808
818
|
if (process.env && process.env.TEST) {
|
|
@@ -862,12 +872,66 @@ const module = defineNuxtModule({
|
|
|
862
872
|
pathPrefix: false,
|
|
863
873
|
extensions: ["vue"]
|
|
864
874
|
});
|
|
875
|
+
if (nuxt.options.dev && (options.experimental?.hmr ?? true)) {
|
|
876
|
+
const translationsDir = join(nuxt.options.rootDir, options.translationDir || "locales");
|
|
877
|
+
const files = await globby(["**/*.json"], { cwd: translationsDir, absolute: true });
|
|
878
|
+
const tpl = addTemplate({
|
|
879
|
+
filename: "i18n-hmr-plugin.mjs",
|
|
880
|
+
write: true,
|
|
881
|
+
getContents: () => generateHmrPlugin(files.map((f) => f.replace(/\\/g, "/")))
|
|
882
|
+
});
|
|
883
|
+
addPlugin({
|
|
884
|
+
src: tpl.dst,
|
|
885
|
+
mode: "client",
|
|
886
|
+
name: "i18n-hmr-plugin",
|
|
887
|
+
order: 10
|
|
888
|
+
});
|
|
889
|
+
}
|
|
865
890
|
if (options.types) {
|
|
866
891
|
addTypeTemplate({
|
|
867
892
|
filename: "types/i18n-plugin.d.ts",
|
|
868
893
|
getContents: () => generateI18nTypes()
|
|
869
894
|
});
|
|
870
895
|
}
|
|
896
|
+
function generateHmrPlugin(files) {
|
|
897
|
+
const accepts = files.map((file) => {
|
|
898
|
+
const isPage = /\/pages\//.test(file);
|
|
899
|
+
let pageName = "";
|
|
900
|
+
let locale = "";
|
|
901
|
+
if (isPage) {
|
|
902
|
+
const m = /\/pages\/([^/]+)\/([^/]+)\.json$/.exec(file);
|
|
903
|
+
pageName = m?.[1] || "";
|
|
904
|
+
locale = m?.[2] || "";
|
|
905
|
+
} else {
|
|
906
|
+
const m = /\/([^/]+)\.json$/.exec(file);
|
|
907
|
+
locale = m?.[1] || "";
|
|
908
|
+
}
|
|
909
|
+
return `
|
|
910
|
+
if (import.meta.hot) {
|
|
911
|
+
import.meta.hot.accept('${file}', async (mod) => {
|
|
912
|
+
const nuxtApp = useNuxtApp()
|
|
913
|
+
const data = (mod && typeof mod === 'object' && Object.prototype.hasOwnProperty.call(mod, 'default'))
|
|
914
|
+
? mod.default
|
|
915
|
+
: mod
|
|
916
|
+
try {
|
|
917
|
+
${isPage ? `await nuxtApp.$loadPageTranslations('${locale}', '${pageName}', data)` : `await nuxtApp.$loadTranslations('${locale}', data)`}
|
|
918
|
+
console.log('[i18n HMR] Translations reloaded:', '${isPage ? "page" : "global"}', '${locale}'${isPage ? `, '${pageName}'` : ""})
|
|
919
|
+
}
|
|
920
|
+
catch (e) {
|
|
921
|
+
console.warn('[i18n HMR] Failed to reload translations for', '${file}', e)
|
|
922
|
+
}
|
|
923
|
+
})
|
|
924
|
+
}
|
|
925
|
+
`.trim();
|
|
926
|
+
}).join("\n");
|
|
927
|
+
return `
|
|
928
|
+
import { defineNuxtPlugin, useNuxtApp } from '#imports'
|
|
929
|
+
|
|
930
|
+
export default defineNuxtPlugin(() => {
|
|
931
|
+
${accepts}
|
|
932
|
+
})
|
|
933
|
+
`.trim();
|
|
934
|
+
}
|
|
871
935
|
nuxt.hook("pages:resolved", (pages) => {
|
|
872
936
|
const prerenderRoutes = [];
|
|
873
937
|
const routeRules = nuxt.options.routeRules || {};
|
|
@@ -1024,24 +1088,12 @@ const module = defineNuxtModule({
|
|
|
1024
1088
|
}
|
|
1025
1089
|
}
|
|
1026
1090
|
});
|
|
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
|
-
}
|
|
1091
|
+
nuxt.hook("nitro:config", (nitroConfig) => {
|
|
1092
|
+
if (nuxt.options.dev && (options.experimental?.hmr ?? true) && !options.disableUpdater) {
|
|
1093
|
+
nitroConfig.plugins = nitroConfig.plugins || [];
|
|
1094
|
+
nitroConfig.plugins.push(resolver.resolve("./runtime/server/plugins/watcher.dev"));
|
|
1095
|
+
}
|
|
1096
|
+
});
|
|
1045
1097
|
nuxt.hook("prerender:routes", async (prerenderRoutes) => {
|
|
1046
1098
|
if (isNoPrefixStrategy(options.strategy)) {
|
|
1047
1099
|
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);
|