nuxt-i18n-micro 1.100.0 → 1.101.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 +2 -2
- package/dist/client/404.html +2 -2
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/3c2f5e13-457a-416f-af4d-c74141ba3650.json +1 -0
- package/dist/client/index.html +2 -2
- package/dist/module.json +1 -1
- package/dist/module.mjs +102 -75
- package/dist/runtime/composables/useLocaleHead.js +2 -1
- package/dist/runtime/plugins/06.redirect.js +3 -6
- package/dist/runtime/utils/route-utils.d.ts +22 -0
- package/dist/runtime/utils/route-utils.js +19 -0
- package/package.json +3 -3
- package/dist/client/_nuxt/builds/meta/23d9342b-133b-4d2e-909f-71dd66a693ec.json +0 -1
package/dist/client/200.html
CHANGED
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
<link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/T7szCJDf.js">
|
|
9
9
|
<link rel="prefetch" as="style" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/error-500.DGwSTbEi.css">
|
|
10
10
|
<link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/DTIY11lm.js">
|
|
11
|
-
<script type="module" src="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/s7GTWWQo.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},
|
|
12
|
-
<script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__NUXT_DEVTOOLS_I18N_BASE__/",buildId:"
|
|
11
|
+
<script type="module" src="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/s7GTWWQo.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},1759936060690,false]</script>
|
|
12
|
+
<script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__NUXT_DEVTOOLS_I18N_BASE__/",buildId:"3c2f5e13-457a-416f-af4d-c74141ba3650",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
|
package/dist/client/404.html
CHANGED
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
<link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/T7szCJDf.js">
|
|
9
9
|
<link rel="prefetch" as="style" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/error-500.DGwSTbEi.css">
|
|
10
10
|
<link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/DTIY11lm.js">
|
|
11
|
-
<script type="module" src="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/s7GTWWQo.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},
|
|
12
|
-
<script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__NUXT_DEVTOOLS_I18N_BASE__/",buildId:"
|
|
11
|
+
<script type="module" src="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/s7GTWWQo.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},1759936060690,false]</script>
|
|
12
|
+
<script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__NUXT_DEVTOOLS_I18N_BASE__/",buildId:"3c2f5e13-457a-416f-af4d-c74141ba3650",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"id":"
|
|
1
|
+
{"id":"3c2f5e13-457a-416f-af4d-c74141ba3650","timestamp":1759936052722}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"id":"3c2f5e13-457a-416f-af4d-c74141ba3650","timestamp":1759936052722,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":[]}
|
package/dist/client/index.html
CHANGED
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
<link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/T7szCJDf.js">
|
|
9
9
|
<link rel="prefetch" as="style" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/error-500.DGwSTbEi.css">
|
|
10
10
|
<link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/DTIY11lm.js">
|
|
11
|
-
<script type="module" src="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/s7GTWWQo.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},
|
|
12
|
-
<script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__NUXT_DEVTOOLS_I18N_BASE__/",buildId:"
|
|
11
|
+
<script type="module" src="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/s7GTWWQo.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},1759936060691,false]</script>
|
|
12
|
+
<script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__NUXT_DEVTOOLS_I18N_BASE__/",buildId:"3c2f5e13-457a-416f-af4d-c74141ba3650",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -110,92 +110,119 @@ function setupDevToolsUI(options, resolve2) {
|
|
|
110
110
|
});
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
function
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
if (
|
|
140
|
-
if (trimmed[i] === "}") braceCount--;
|
|
141
|
-
if (braceCount === 0) break;
|
|
113
|
+
function extractScriptContent(content) {
|
|
114
|
+
const scriptMatch = content.match(/<script[^>]*>([\s\S]*?)<\/script>/);
|
|
115
|
+
return scriptMatch ? scriptMatch[1] : null;
|
|
116
|
+
}
|
|
117
|
+
function removeTypeScriptTypes(scriptContent) {
|
|
118
|
+
return scriptContent.replace(/\((\w+):[^)]*\)/g, "($1)");
|
|
119
|
+
}
|
|
120
|
+
function findDefineI18nRouteConfig(scriptContent) {
|
|
121
|
+
try {
|
|
122
|
+
const defineStart = scriptContent.indexOf("$defineI18nRoute(");
|
|
123
|
+
if (defineStart === -1) {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
const openParen = scriptContent.indexOf("(", defineStart);
|
|
127
|
+
if (openParen === -1) {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
let braceCount = 0;
|
|
131
|
+
let parenCount = 1;
|
|
132
|
+
let i = openParen + 1;
|
|
133
|
+
for (; i < scriptContent.length; i++) {
|
|
134
|
+
if (scriptContent[i] === "{") braceCount++;
|
|
135
|
+
if (scriptContent[i] === "}") braceCount--;
|
|
136
|
+
if (scriptContent[i] === "(") parenCount++;
|
|
137
|
+
if (scriptContent[i] === ")") {
|
|
138
|
+
parenCount--;
|
|
139
|
+
if (parenCount === 0 && braceCount === 0) break;
|
|
142
140
|
}
|
|
143
|
-
localesStr = trimmed.substring(0, i + 1);
|
|
144
141
|
}
|
|
145
|
-
|
|
146
|
-
|
|
142
|
+
if (i >= scriptContent.length) {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
const configStr = scriptContent.substring(openParen + 1, i);
|
|
147
146
|
try {
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
147
|
+
const cleanConfigStr = removeTypeScriptTypes(configStr);
|
|
148
|
+
try {
|
|
149
|
+
const configObject = Function('"use strict";return (' + cleanConfigStr + ")")();
|
|
150
|
+
try {
|
|
151
|
+
const serialized = JSON.stringify(configObject);
|
|
152
|
+
return JSON.parse(serialized);
|
|
153
|
+
} catch {
|
|
154
|
+
return configObject;
|
|
153
155
|
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
}
|
|
156
|
+
} catch {
|
|
157
|
+
const scriptWithoutImports = scriptContent.split("\n").filter((line) => !line.trim().startsWith("import ")).join("\n");
|
|
158
|
+
const cleanScript = removeTypeScriptTypes(scriptWithoutImports);
|
|
159
|
+
const safeScript = `
|
|
160
|
+
// Mock $defineI18nRoute to prevent errors
|
|
161
|
+
const $defineI18nRoute = () => {}
|
|
162
|
+
const defineI18nRoute = () => {}
|
|
163
|
+
|
|
164
|
+
// Mock process.env for conditional logic
|
|
165
|
+
const process = { env: { NODE_ENV: 'development' } }
|
|
166
|
+
|
|
167
|
+
// Execute the script content without imports and TypeScript types
|
|
168
|
+
${cleanScript}
|
|
169
|
+
|
|
170
|
+
// Return the config object
|
|
171
|
+
return (${cleanConfigStr})
|
|
172
|
+
`;
|
|
173
|
+
const configObject = Function('"use strict";' + safeScript)();
|
|
174
|
+
try {
|
|
175
|
+
const serialized = JSON.stringify(configObject);
|
|
176
|
+
return JSON.parse(serialized);
|
|
177
|
+
} catch {
|
|
178
|
+
return configObject;
|
|
170
179
|
}
|
|
171
180
|
}
|
|
172
|
-
} catch
|
|
173
|
-
|
|
181
|
+
} catch {
|
|
182
|
+
return null;
|
|
174
183
|
}
|
|
184
|
+
} catch {
|
|
185
|
+
return null;
|
|
175
186
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
187
|
+
}
|
|
188
|
+
function extractDefineI18nRouteData(content, _filePath) {
|
|
189
|
+
try {
|
|
190
|
+
const scriptContent = extractScriptContent(content);
|
|
191
|
+
if (!scriptContent) {
|
|
192
|
+
return { locales: null, localeRoutes: null };
|
|
193
|
+
}
|
|
194
|
+
const configObject = findDefineI18nRouteConfig(scriptContent);
|
|
195
|
+
if (!configObject) {
|
|
196
|
+
return { locales: null, localeRoutes: null };
|
|
197
|
+
}
|
|
198
|
+
let locales = null;
|
|
199
|
+
if (configObject.locales) {
|
|
200
|
+
if (Array.isArray(configObject.locales)) {
|
|
201
|
+
locales = configObject.locales.map((item) => {
|
|
202
|
+
if (typeof item === "string") {
|
|
203
|
+
return item;
|
|
204
|
+
} else if (typeof item === "object" && item !== null && item.code) {
|
|
205
|
+
return item.code;
|
|
206
|
+
}
|
|
207
|
+
return null;
|
|
208
|
+
}).filter((item) => item !== null);
|
|
209
|
+
} else if (typeof configObject.locales === "object") {
|
|
210
|
+
locales = Object.keys(configObject.locales).filter(
|
|
211
|
+
(key) => key !== "meta" && key !== "path" && key !== "title" && key !== "description"
|
|
212
|
+
);
|
|
186
213
|
}
|
|
187
|
-
} catch (error) {
|
|
188
|
-
console.error("Failed to parse localeRoutes:", error, "in file:", filePath);
|
|
189
214
|
}
|
|
215
|
+
let localeRoutes = null;
|
|
216
|
+
if (configObject.localeRoutes && typeof configObject.localeRoutes === "object") {
|
|
217
|
+
const isValid = Object.values(configObject.localeRoutes).every((value) => typeof value === "string");
|
|
218
|
+
if (isValid) {
|
|
219
|
+
localeRoutes = configObject.localeRoutes;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return { locales, localeRoutes };
|
|
223
|
+
} catch {
|
|
224
|
+
return { locales: null, localeRoutes: null };
|
|
190
225
|
}
|
|
191
|
-
return { locales, localeRoutes };
|
|
192
|
-
}
|
|
193
|
-
function validateDefineI18nRouteConfig(obj) {
|
|
194
|
-
if (typeof obj !== "object") return false;
|
|
195
|
-
for (const routeKey in obj.localeRoutes) {
|
|
196
|
-
if (typeof obj.localeRoutes[routeKey] !== "string") return false;
|
|
197
|
-
}
|
|
198
|
-
return true;
|
|
199
226
|
}
|
|
200
227
|
const normalizePath = (routePath) => {
|
|
201
228
|
if (!routePath) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { joinURL, parseURL, withQuery } from "ufo";
|
|
2
2
|
import { isPrefixExceptDefaultStrategy, isNoPrefixStrategy } from "nuxt-i18n-micro-core";
|
|
3
3
|
import { unref, useRoute, useRuntimeConfig, watch, onUnmounted, ref, useNuxtApp } from "#imports";
|
|
4
|
+
import { findAllowedLocalesForRoute } from "../utils/route-utils.js";
|
|
4
5
|
export const useLocaleHead = async ({ addDirAttribute = true, identifierAttribute = "id", addSeoAttributes = true, baseUrl = "/" } = {}) => {
|
|
5
6
|
const metaObject = ref({
|
|
6
7
|
htmlAttrs: {},
|
|
@@ -28,7 +29,7 @@ export const useLocaleHead = async ({ addDirAttribute = true, identifierAttribut
|
|
|
28
29
|
const routeName = (route.name ?? "").toString();
|
|
29
30
|
const currentLocale = unref($getLocales().find((loc) => loc.code === locale));
|
|
30
31
|
if (!currentLocale) return;
|
|
31
|
-
const currentRouteLocales =
|
|
32
|
+
const currentRouteLocales = findAllowedLocalesForRoute(route, routeLocales);
|
|
32
33
|
const locales = currentRouteLocales ? allLocales.filter((loc) => currentRouteLocales.includes(loc.code)) : allLocales;
|
|
33
34
|
const currentIso = currentLocale.iso || locale;
|
|
34
35
|
const currentDir = currentLocale.dir || "auto";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { isNoPrefixStrategy, isPrefixStrategy } from "nuxt-i18n-micro-core";
|
|
2
2
|
import { defineNuxtPlugin, useRuntimeConfig, useRoute, useRouter, navigateTo, createError } from "#imports";
|
|
3
|
+
import { findAllowedLocalesForRoute } from "../utils/route-utils.js";
|
|
3
4
|
export default defineNuxtPlugin(async (nuxtApp) => {
|
|
4
5
|
const config = useRuntimeConfig();
|
|
5
6
|
const i18nConfig = config.public.i18nConfig;
|
|
@@ -7,15 +8,11 @@ export default defineNuxtPlugin(async (nuxtApp) => {
|
|
|
7
8
|
const route = useRoute();
|
|
8
9
|
const router = useRouter();
|
|
9
10
|
const checkRouteLocales = (to) => {
|
|
10
|
-
const
|
|
11
|
-
const routeName = to.name?.toString();
|
|
12
|
-
const normalizedRouteName = routeName?.replace("localized-", "");
|
|
13
|
-
const normalizedRoutePath = normalizedRouteName ? `/${normalizedRouteName}` : void 0;
|
|
14
|
-
const allowedLocales = routeName && routeLocales?.[routeName] || normalizedRouteName && routeLocales?.[normalizedRouteName] || normalizedRoutePath && routeLocales?.[normalizedRoutePath] || routeLocales?.[routePath];
|
|
11
|
+
const allowedLocales = findAllowedLocalesForRoute(to, routeLocales);
|
|
15
12
|
if (!allowedLocales || allowedLocales.length === 0) {
|
|
16
13
|
return;
|
|
17
14
|
}
|
|
18
|
-
const pathSegments =
|
|
15
|
+
const pathSegments = to.path.split("/").filter(Boolean);
|
|
19
16
|
const firstSegment = pathSegments[0];
|
|
20
17
|
const allLocales = i18nConfig.locales?.map((l) => l.code) || [];
|
|
21
18
|
if (firstSegment && allLocales.includes(firstSegment) && !allowedLocales.includes(firstSegment)) {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { RouteLocationNormalizedLoaded } from 'vue-router';
|
|
2
|
+
/**
|
|
3
|
+
* Extracts the base route pattern from a matched route path
|
|
4
|
+
* Converts Vue Router dynamic route patterns to file-based route patterns
|
|
5
|
+
*
|
|
6
|
+
* @param matchedPath - The matched route path from route.matched[0].path
|
|
7
|
+
* @returns The base route pattern (e.g., "/test/[param]")
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* extractBaseRoutePattern('/:locale(es)/test/:param()') // Returns '/test/[param]'
|
|
11
|
+
* extractBaseRoutePattern('/:locale(en)/static') // Returns '/static'
|
|
12
|
+
* extractBaseRoutePattern('/:locale(fr)/about/:id') // Returns '/about/[id]'
|
|
13
|
+
*/
|
|
14
|
+
export declare function extractBaseRoutePattern(matchedPath: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Finds allowed locales for a route using various matching strategies
|
|
17
|
+
*
|
|
18
|
+
* @param route - The route object
|
|
19
|
+
* @param routeLocales - The routeLocales configuration object
|
|
20
|
+
* @returns Array of allowed locale codes or null if no restrictions
|
|
21
|
+
*/
|
|
22
|
+
export declare function findAllowedLocalesForRoute(route: RouteLocationNormalizedLoaded, routeLocales: Record<string, string[]> | undefined): string[] | null;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export function extractBaseRoutePattern(matchedPath) {
|
|
2
|
+
return matchedPath.replace(/\/:locale\([^)]+\)/g, "").replace(/\/:([^()]+)\(\)/g, "/[$1]").replace(/\/:([^()]+)/g, "/[$1]");
|
|
3
|
+
}
|
|
4
|
+
export function findAllowedLocalesForRoute(route, routeLocales) {
|
|
5
|
+
const routePath = route.path;
|
|
6
|
+
const routeName = route.name?.toString();
|
|
7
|
+
const normalizedRouteName = routeName?.replace("localized-", "");
|
|
8
|
+
const normalizedRoutePath = normalizedRouteName ? `/${normalizedRouteName}` : void 0;
|
|
9
|
+
let allowedLocales = routeName && routeLocales?.[routeName] || normalizedRouteName && routeLocales?.[normalizedRouteName] || normalizedRoutePath && routeLocales?.[normalizedRoutePath] || routeLocales?.[routePath];
|
|
10
|
+
if (!allowedLocales && route.matched && route.matched.length > 0) {
|
|
11
|
+
const matchedRoute = route.matched[0];
|
|
12
|
+
const matchedPath = matchedRoute.path;
|
|
13
|
+
const baseRoutePattern = extractBaseRoutePattern(matchedPath);
|
|
14
|
+
if (routeLocales?.[baseRoutePattern]) {
|
|
15
|
+
allowedLocales = routeLocales[baseRoutePattern];
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return allowedLocales || null;
|
|
19
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-i18n-micro",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.101.0",
|
|
4
4
|
"description": "Nuxt I18n Micro is a lightweight, high-performance internationalization module for Nuxt, designed to handle multi-language support with minimal overhead, fast build times, and efficient runtime performance.",
|
|
5
5
|
"repository": "s00d/nuxt-i18n-micro",
|
|
6
6
|
"license": "MIT",
|
|
@@ -62,8 +62,8 @@
|
|
|
62
62
|
"sirv": "^2.0.4",
|
|
63
63
|
"ufo": "^1.5.4",
|
|
64
64
|
"nuxt-i18n-micro-core": "1.0.18",
|
|
65
|
-
"nuxt-i18n-micro-
|
|
66
|
-
"nuxt-i18n-micro-
|
|
65
|
+
"nuxt-i18n-micro-types": "1.0.9",
|
|
66
|
+
"nuxt-i18n-micro-test-utils": "1.0.6"
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
69
|
"@nuxt/devtools": "^2.6.3",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"id":"23d9342b-133b-4d2e-909f-71dd66a693ec","timestamp":1759906439920,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":[]}
|