nuxt-i18n-micro 3.24.3 → 3.26.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 +19 -20
- 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/24f3c578-f02b-41bc-953a-c7ff7b504d56.json +1 -0
- package/dist/client/index.html +1 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +2 -0
- package/dist/runtime/composables/useLocaleHead.js +28 -28
- package/dist/runtime/middleware/i18n-redirect.global.js +5 -0
- package/dist/runtime/plugins/02.meta.js +12 -1
- package/dist/runtime/plugins/06.redirect.js +35 -37
- package/package.json +13 -12
- package/dist/client/_nuxt/builds/meta/225477ec-bfda-48f4-aca0-4fc5d067bae9.json +0 -1
package/README.md
CHANGED
|
@@ -22,41 +22,40 @@ The `Nuxt I18n Micro` module was created to address critical performance issues
|
|
|
22
22
|
|
|
23
23
|
### Performance Comparison
|
|
24
24
|
|
|
25
|
-
To showcase the efficiency of `Nuxt I18n Micro`, we ran the same fixture suite
|
|
25
|
+
To showcase the efficiency of `Nuxt I18n Micro`, we ran the same fixture suite via `pnpm test:performance` (`pnpm -C scripts cli performance`) against **`@nuxtjs/i18n@10.6.0`** on the same hardware. We also include a **plain-nuxt** baseline (no i18n module) to measure the real overhead.
|
|
26
26
|
|
|
27
27
|
#### Build Time and Resource Consumption
|
|
28
28
|
|
|
29
|
-
> **Note:** The `plain-nuxt` baseline is a minimal implementation created solely for benchmarking purposes. It loads data directly from JSON files without any i18n logic.
|
|
29
|
+
> **Note:** The `plain-nuxt` baseline is a minimal implementation created solely for benchmarking purposes. It loads data directly from JSON files without any i18n logic. Latest run: `@nuxtjs/i18n@10.6.0`, mean of 3 consecutive runs per fixture, default CLI profile (~16.8k index leaves).
|
|
30
30
|
|
|
31
31
|
| Project | Build Time | Code Bundle | Max Memory | Max CPU |
|
|
32
32
|
|---------|------------|-------------|------------|---------|
|
|
33
|
-
| **plain-nuxt** (baseline) |
|
|
34
|
-
| **i18n-micro** |
|
|
35
|
-
| **@nuxtjs/i18n v10.6** |
|
|
33
|
+
| **plain-nuxt** (baseline) | 5.32s | 1.53 MB | 810 MB | 207% |
|
|
34
|
+
| **i18n-micro** | 5.34s | 1.74 MB | 1,065 MB | 204% |
|
|
35
|
+
| **@nuxtjs/i18n v10.6** | 8.34s | 2.16 MB | 1,821 MB | 204% |
|
|
36
36
|
|
|
37
|
-
> **Code Bundle** =
|
|
38
|
-
> i18n-micro stores translations as lazy-loaded JSON files, keeping the code bundle minimal.
|
|
37
|
+
> **Code Bundle** = JS/CSS only (excludes classified translation payloads, including `@nuxtjs/i18n` `chunks/raw/*`). Older tables that showed ~15 MB “code” for v10.6 were counting message chunks as app code.
|
|
39
38
|
|
|
40
|
-
- **i18n-micro vs baseline**:
|
|
41
|
-
- **@nuxtjs/i18n v10.6 vs baseline**: +
|
|
39
|
+
- **i18n-micro vs baseline**: ≈ same build time, +0.21 MB code, +255 MB peak RSS
|
|
40
|
+
- **@nuxtjs/i18n v10.6 vs baseline**: +3.02s build, +0.63 MB code, +1,011 MB peak RSS
|
|
42
41
|
|
|
43
42
|
#### Stress Test Results (Requests per Second)
|
|
44
43
|
|
|
45
|
-
| Project | Avg Response | RPS (Artillery) |
|
|
46
|
-
|
|
47
|
-
| **plain-nuxt** |
|
|
48
|
-
| **i18n-micro** |
|
|
49
|
-
| **@nuxtjs/i18n v10.6** |
|
|
44
|
+
| Project | Avg Response (Artillery) | RPS (Artillery) | RPS (Autocannon) | Avg Latency (AC) |
|
|
45
|
+
|---------|--------------------------|-----------------|------------------|------------------|
|
|
46
|
+
| **plain-nuxt** | 1,194 ms | 109 | 65 | 152 ms |
|
|
47
|
+
| **i18n-micro** | 483 ms | 275 | 162 | 62 ms |
|
|
48
|
+
| **@nuxtjs/i18n v10.6** | 956 ms | 143 | 72 | 139 ms |
|
|
50
49
|
|
|
51
50
|
#### Comparison: `@nuxtjs/i18n` v10.6 vs i18n-micro
|
|
52
51
|
|
|
53
|
-
- **Code Bundle**:
|
|
54
|
-
- **Build Time**:
|
|
55
|
-
- **Max Memory (build)**:
|
|
56
|
-
- **Average Response Time**:
|
|
57
|
-
- **Requests Per Second**:
|
|
52
|
+
- **Code Bundle**: 0.42 MB smaller (1.74 MB vs 2.16 MB)
|
|
53
|
+
- **Build Time**: 3.00s faster (5.34s vs 8.34s)
|
|
54
|
+
- **Max Memory (build)**: 756 MB less (1,065 MB vs 1,821 MB)
|
|
55
|
+
- **Average Response Time (Artillery)**: 473 ms faster (483 ms vs 956 ms)
|
|
56
|
+
- **Requests Per Second (Artillery)**: 132 more (275 vs 143)
|
|
58
57
|
|
|
59
|
-
|
|
58
|
+
Micro leads on build cost and especially under load. See the [full benchmark report](https://s00d.github.io/nuxt-i18n-micro/guide/performance-results) for methodology and charts.
|
|
60
59
|
|
|
61
60
|
## Key Features
|
|
62
61
|
|
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"><script type="importmap">{"imports":{"#entry":"/__nuxt-i18n-micro/_nuxt/Bwak6g3b.js"}}</script><link rel="stylesheet" href="/__nuxt-i18n-micro/_nuxt/entry.CJGrD2VA.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/Bwak6g3b.js"><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/DBXvRcU1.js"><script type="module" src="/__nuxt-i18n-micro/_nuxt/Bwak6g3b.js" crossorigin></script><link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-500.BcWSpGYy.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/p3h4sA5-.js"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/DbtvxgAm.js"></head><body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"
|
|
1
|
+
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><script type="importmap">{"imports":{"#entry":"/__nuxt-i18n-micro/_nuxt/Bwak6g3b.js"}}</script><link rel="stylesheet" href="/__nuxt-i18n-micro/_nuxt/entry.CJGrD2VA.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/Bwak6g3b.js"><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/DBXvRcU1.js"><script type="module" src="/__nuxt-i18n-micro/_nuxt/Bwak6g3b.js" crossorigin></script><link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-500.BcWSpGYy.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/p3h4sA5-.js"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/DbtvxgAm.js"></head><body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"24f3c578-f02b-41bc-953a-c7ff7b504d56",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1785527485918,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"><script type="importmap">{"imports":{"#entry":"/__nuxt-i18n-micro/_nuxt/Bwak6g3b.js"}}</script><link rel="stylesheet" href="/__nuxt-i18n-micro/_nuxt/entry.CJGrD2VA.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/Bwak6g3b.js"><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/DBXvRcU1.js"><script type="module" src="/__nuxt-i18n-micro/_nuxt/Bwak6g3b.js" crossorigin></script><link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-500.BcWSpGYy.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/p3h4sA5-.js"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/DbtvxgAm.js"></head><body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"
|
|
1
|
+
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><script type="importmap">{"imports":{"#entry":"/__nuxt-i18n-micro/_nuxt/Bwak6g3b.js"}}</script><link rel="stylesheet" href="/__nuxt-i18n-micro/_nuxt/entry.CJGrD2VA.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/Bwak6g3b.js"><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/DBXvRcU1.js"><script type="module" src="/__nuxt-i18n-micro/_nuxt/Bwak6g3b.js" crossorigin></script><link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-500.BcWSpGYy.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/p3h4sA5-.js"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/DbtvxgAm.js"></head><body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"24f3c578-f02b-41bc-953a-c7ff7b504d56",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1785527485918,false]</script></body></html>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"id":"
|
|
1
|
+
{"id":"24f3c578-f02b-41bc-953a-c7ff7b504d56","timestamp":1785527483273}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"id":"24f3c578-f02b-41bc-953a-c7ff7b504d56","timestamp":1785527483273,"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"><script type="importmap">{"imports":{"#entry":"/__nuxt-i18n-micro/_nuxt/Bwak6g3b.js"}}</script><link rel="stylesheet" href="/__nuxt-i18n-micro/_nuxt/entry.CJGrD2VA.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/Bwak6g3b.js"><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/DBXvRcU1.js"><script type="module" src="/__nuxt-i18n-micro/_nuxt/Bwak6g3b.js" crossorigin></script><link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-500.BcWSpGYy.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/p3h4sA5-.js"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/DbtvxgAm.js"></head><body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"
|
|
1
|
+
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><script type="importmap">{"imports":{"#entry":"/__nuxt-i18n-micro/_nuxt/Bwak6g3b.js"}}</script><link rel="stylesheet" href="/__nuxt-i18n-micro/_nuxt/entry.CJGrD2VA.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/Bwak6g3b.js"><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/DBXvRcU1.js"><script type="module" src="/__nuxt-i18n-micro/_nuxt/Bwak6g3b.js" crossorigin></script><link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-500.BcWSpGYy.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/p3h4sA5-.js"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/DbtvxgAm.js"></head><body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"24f3c578-f02b-41bc-953a-c7ff7b504d56",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1785527485918,false]</script></body></html>
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -509,6 +509,7 @@ function buildFullConfig(params) {
|
|
|
509
509
|
metaBaseUrl: options.metaBaseUrl || void 0,
|
|
510
510
|
metaTrustForwardedHost: options.metaTrustForwardedHost ?? true,
|
|
511
511
|
metaTrustForwardedProto: options.metaTrustForwardedProto ?? true,
|
|
512
|
+
hreflangBaseLanguage: options.hreflangBaseLanguage ?? false,
|
|
512
513
|
defaultLocale,
|
|
513
514
|
fallbackLocale: options.fallbackLocale ?? void 0,
|
|
514
515
|
localeCookie: options.localeCookie ?? null,
|
|
@@ -675,6 +676,7 @@ const module$1 = defineNuxtModule({
|
|
|
675
676
|
missingWarn: true,
|
|
676
677
|
metaTrustForwardedHost: true,
|
|
677
678
|
metaTrustForwardedProto: true,
|
|
679
|
+
hreflangBaseLanguage: false,
|
|
678
680
|
httpCacheDuration: 31536e3
|
|
679
681
|
},
|
|
680
682
|
async setup(options, nuxt) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isNoPrefixStrategy } from "@i18n-micro/core";
|
|
2
|
+
import { resolveHreflangAlternates } from "@i18n-micro/utils/resolve-hreflang";
|
|
2
3
|
import { findAllowedLocalesForRoute } from "@i18n-micro/utils/route";
|
|
3
4
|
import { resolveOgLocale, warnUnresolvedOgLocale } from "@i18n-micro/utils/resolve-og-locale";
|
|
4
5
|
import { joinURL, parseURL, withQuery } from "ufo";
|
|
@@ -121,36 +122,35 @@ export const useLocaleHead = ({
|
|
|
121
122
|
const defaultLocale = i18nConfig.defaultLocale || "en";
|
|
122
123
|
const defaultLocaleObj = allLocales.find((loc) => loc.code === defaultLocale);
|
|
123
124
|
const whitelist = canonicalQueryWhitelist ?? [];
|
|
124
|
-
const alternateLinks = isNoPrefixStrategy(strategy) ? [] :
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
136
|
-
const links = [
|
|
137
|
-
{
|
|
138
|
-
[identifierAttribute]: `i18n-alternate-${loc.code}`,
|
|
139
|
-
rel: "alternate",
|
|
140
|
-
href,
|
|
141
|
-
hreflang: unref(loc.code)
|
|
125
|
+
const alternateLinks = isNoPrefixStrategy(strategy) ? [] : (() => {
|
|
126
|
+
const hrefByCode = /* @__PURE__ */ new Map();
|
|
127
|
+
for (const loc of localesForSeo) {
|
|
128
|
+
const switchedPath = switchLocalePath(loc.code);
|
|
129
|
+
if (!switchedPath) continue;
|
|
130
|
+
let href;
|
|
131
|
+
if (switchedPath.startsWith("http://") || switchedPath.startsWith("https://")) {
|
|
132
|
+
href = filterLocalizedHref(switchedPath, whitelist);
|
|
133
|
+
} else {
|
|
134
|
+
const filteredPath = filterLocalizedHref(switchedPath, whitelist);
|
|
135
|
+
href = joinURL(unref(baseUrl), filteredPath.startsWith("/") ? filteredPath : `/${filteredPath}`);
|
|
142
136
|
}
|
|
143
|
-
|
|
144
|
-
if (loc.iso && loc.iso !== loc.code) {
|
|
145
|
-
links.push({
|
|
146
|
-
[identifierAttribute]: `i18n-alternate-${loc.iso}`,
|
|
147
|
-
rel: "alternate",
|
|
148
|
-
href,
|
|
149
|
-
hreflang: unref(loc.iso)
|
|
150
|
-
});
|
|
137
|
+
hrefByCode.set(String(loc.code), href);
|
|
151
138
|
}
|
|
152
|
-
return
|
|
153
|
-
|
|
139
|
+
return resolveHreflangAlternates(localesForSeo, {
|
|
140
|
+
hreflangBaseLanguage: i18nConfig.hreflangBaseLanguage ?? false
|
|
141
|
+
}).flatMap(({ hreflang, localeCode }) => {
|
|
142
|
+
const href = hrefByCode.get(localeCode);
|
|
143
|
+
if (!href) return [];
|
|
144
|
+
return [
|
|
145
|
+
{
|
|
146
|
+
[identifierAttribute]: `i18n-alternate-${hreflang}`,
|
|
147
|
+
rel: "alternate",
|
|
148
|
+
href,
|
|
149
|
+
hreflang
|
|
150
|
+
}
|
|
151
|
+
];
|
|
152
|
+
});
|
|
153
|
+
})();
|
|
154
154
|
let xDefaultLink = null;
|
|
155
155
|
if (!isNoPrefixStrategy(strategy) && defaultLocaleObj?.seo !== false) {
|
|
156
156
|
const defaultSwitchedPath = switchLocalePath(defaultLocale);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getEnabledLocaleCodes } from "@i18n-micro/utils/active-locales";
|
|
2
|
+
import { shouldAttemptLocaleRedirect } from "@i18n-micro/utils/auto-detect-path";
|
|
2
3
|
import { defineNuxtRouteMiddleware, navigateTo, useNuxtApp } from "#imports";
|
|
3
4
|
import { useI18nLocale } from "../composables/useI18nLocale.js";
|
|
4
5
|
function redirectTo(path, to) {
|
|
@@ -23,6 +24,10 @@ export default defineNuxtRouteMiddleware((to, from) => {
|
|
|
23
24
|
const pathSegments = path.replace(/^\//, "").split("/").filter(Boolean);
|
|
24
25
|
const firstSegment = pathSegments[0];
|
|
25
26
|
const hasLocalePrefix = Boolean(firstSegment && validLocales.includes(firstSegment));
|
|
27
|
+
const allowPreferenceRedirect = shouldAttemptLocaleRedirect(path, { autoDetectPath, hasLocalePrefix });
|
|
28
|
+
if (!hasLocalePrefix && !allowPreferenceRedirect) {
|
|
29
|
+
preferredLocale = defaultLocale;
|
|
30
|
+
}
|
|
26
31
|
if (autoDetectPath === "*" && !hasLocalePrefix) {
|
|
27
32
|
preferredLocale = defaultLocale;
|
|
28
33
|
}
|
|
@@ -6,6 +6,16 @@ import { getI18nConfig } from "#build/i18n.strategy.mjs";
|
|
|
6
6
|
import { defineNuxtPlugin, useHead, useRequestURL, useRoute, useState } from "#imports";
|
|
7
7
|
import { useI18nHead } from "../composables/useI18nHead.js";
|
|
8
8
|
import { useLocaleHead } from "../composables/useLocaleHead.js";
|
|
9
|
+
function readSiteConfigUrl(nuxtApp) {
|
|
10
|
+
const stack = nuxtApp.$nuxtSiteConfig;
|
|
11
|
+
if (!stack || typeof stack.get !== "function") return void 0;
|
|
12
|
+
try {
|
|
13
|
+
const url = stack.get({ resolveRefs: true })?.url;
|
|
14
|
+
return typeof url === "string" && url.trim() ? url : void 0;
|
|
15
|
+
} catch {
|
|
16
|
+
return void 0;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
9
19
|
export default defineNuxtPlugin((nuxtApp) => {
|
|
10
20
|
const route = useRoute();
|
|
11
21
|
const i18nRouteParams = useState("i18n-route-params", () => ({}));
|
|
@@ -22,7 +32,8 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|
|
22
32
|
xForwardedHost: i18nConfig.metaTrustForwardedHost !== false,
|
|
23
33
|
xForwardedProto: i18nConfig.metaTrustForwardedProto !== false
|
|
24
34
|
});
|
|
25
|
-
const
|
|
35
|
+
const siteUrl = readSiteConfigUrl(nuxtApp);
|
|
36
|
+
const baseUrl = (i18nConfig.metaBaseUrl || siteUrl || url.origin).replace(/\/+$/, "");
|
|
26
37
|
const { metaObject, updateMeta } = useLocaleHead({
|
|
27
38
|
addDirAttribute: true,
|
|
28
39
|
identifierAttribute: "id",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isInternalPath } from "@i18n-micro/route-strategy";
|
|
2
2
|
import { getEnabledLocaleCodes } from "@i18n-micro/utils/active-locales";
|
|
3
3
|
import { withoutAppBaseURL } from "@i18n-micro/utils/app-path";
|
|
4
|
+
import { shouldAttemptLocaleRedirect } from "@i18n-micro/utils/auto-detect-path";
|
|
4
5
|
import { getLocaleCookieName, getLocaleCookieOptions } from "@i18n-micro/utils/cookie";
|
|
5
6
|
import { resolvePreferredLocale } from "@i18n-micro/utils/resolve-locale";
|
|
6
7
|
import { getCookie, getHeader, getRequestURL, setCookie } from "h3";
|
|
@@ -65,45 +66,42 @@ export default defineNuxtPlugin({
|
|
|
65
66
|
setCookie(event, cookieName, currentLocale, cookieOpts);
|
|
66
67
|
}
|
|
67
68
|
if (i18nConfig.redirects !== false) {
|
|
68
|
-
const
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
} else {
|
|
93
|
-
targetPath = rest ? `/${preferredLocale}/${rest}` : `/${preferredLocale}`;
|
|
94
|
-
}
|
|
95
|
-
if (cookieName) {
|
|
96
|
-
const { watch: _w2, ...cookieOpts2 } = getLocaleCookieOptions();
|
|
97
|
-
setCookie(event, cookieName, preferredLocale, cookieOpts2);
|
|
98
|
-
}
|
|
99
|
-
if (DEBUG) console.error("[i18n-redirect] REDIRECT autoDetectPath *", { path, targetPath, preferredLocale });
|
|
100
|
-
return performRedirect(targetPath + (url.search || "") + (url.hash || ""));
|
|
69
|
+
const allowPreferenceRedirect = shouldAttemptLocaleRedirect(path, { autoDetectPath, hasLocalePrefix });
|
|
70
|
+
const localeState = autoDetectPath !== "*" ? useState("i18n-locale", () => null) : null;
|
|
71
|
+
let preferredLocale = resolvePreferredLocale({
|
|
72
|
+
defaultLocale,
|
|
73
|
+
validLocales,
|
|
74
|
+
autoDetectLanguage: i18nConfig.autoDetectLanguage,
|
|
75
|
+
stateLocale: localeState?.value ?? null,
|
|
76
|
+
cookieLocale: cookieName ? getCookie(event, cookieName) : null,
|
|
77
|
+
acceptLanguageHeader: getHeader(event, "accept-language"),
|
|
78
|
+
ignoreStateLocale: autoDetectPath === "*"
|
|
79
|
+
});
|
|
80
|
+
if (!hasLocalePrefix && !allowPreferenceRedirect) {
|
|
81
|
+
preferredLocale = defaultLocale;
|
|
82
|
+
}
|
|
83
|
+
if (autoDetectPath === "*" && !hasLocalePrefix) {
|
|
84
|
+
preferredLocale = defaultLocale;
|
|
85
|
+
}
|
|
86
|
+
if (autoDetectPath === "*" && hasLocalePrefix && firstSegment !== preferredLocale) {
|
|
87
|
+
const rest = pathSegments.slice(1).join("/");
|
|
88
|
+
let targetPath;
|
|
89
|
+
if (preferredLocale === defaultLocale && i18nConfig.strategy === "prefix_except_default") {
|
|
90
|
+
targetPath = rest ? `/${rest}` : "/";
|
|
91
|
+
} else {
|
|
92
|
+
targetPath = rest ? `/${preferredLocale}/${rest}` : `/${preferredLocale}`;
|
|
101
93
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
return performRedirect(redirectPath + (url.search || "") + (url.hash || ""));
|
|
94
|
+
if (cookieName) {
|
|
95
|
+
const { watch: _w2, ...cookieOpts2 } = getLocaleCookieOptions();
|
|
96
|
+
setCookie(event, cookieName, preferredLocale, cookieOpts2);
|
|
106
97
|
}
|
|
98
|
+
if (DEBUG) console.error("[i18n-redirect] REDIRECT autoDetectPath *", { path, targetPath, preferredLocale });
|
|
99
|
+
return performRedirect(targetPath + (url.search || "") + (url.hash || ""));
|
|
100
|
+
}
|
|
101
|
+
const redirectPath = i18nStrategy.getClientRedirect(path, preferredLocale);
|
|
102
|
+
if (redirectPath) {
|
|
103
|
+
if (DEBUG) console.error("[i18n-redirect] REDIRECT", { path, redirectPath, preferredLocale });
|
|
104
|
+
return performRedirect(redirectPath + (url.search || "") + (url.hash || ""));
|
|
107
105
|
}
|
|
108
106
|
}
|
|
109
107
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-i18n-micro",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.26.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
|
"keywords": [
|
|
6
6
|
"i18n",
|
|
@@ -80,14 +80,14 @@
|
|
|
80
80
|
"h3": "^1.15.11",
|
|
81
81
|
"sirv": "^2.0.3",
|
|
82
82
|
"ufo": "^1.5.4",
|
|
83
|
-
"unplugin": "^1.16.1",
|
|
84
|
-
"@i18n-micro/
|
|
85
|
-
"@i18n-micro/
|
|
86
|
-
"@i18n-micro/
|
|
87
|
-
"@i18n-micro/
|
|
88
|
-
"@i18n-micro/types": "^1.2.
|
|
89
|
-
"@i18n-micro/
|
|
90
|
-
"@i18n-micro/
|
|
83
|
+
"unplugin": "^1.16.1 || ^2.0.0 || ^3.3.0",
|
|
84
|
+
"@i18n-micro/path-strategy": "^1.3.9",
|
|
85
|
+
"@i18n-micro/test-utils": "^1.2.8",
|
|
86
|
+
"@i18n-micro/core": "^1.3.11",
|
|
87
|
+
"@i18n-micro/hmr": "^1.0.6",
|
|
88
|
+
"@i18n-micro/types": "^1.2.10",
|
|
89
|
+
"@i18n-micro/utils": "^1.0.13",
|
|
90
|
+
"@i18n-micro/route-strategy": "^1.1.14"
|
|
91
91
|
},
|
|
92
92
|
"devDependencies": {
|
|
93
93
|
"@nuxt/devtools": "^3.3.1",
|
|
@@ -112,7 +112,7 @@
|
|
|
112
112
|
"vue-tsc": "^2.0.21"
|
|
113
113
|
},
|
|
114
114
|
"peerDependencies": {
|
|
115
|
-
"vue-router": "^4.6.3"
|
|
115
|
+
"vue-router": "^4.6.3 || ^5.0.0"
|
|
116
116
|
},
|
|
117
117
|
"optionalDependencies": {
|
|
118
118
|
"@rollup/rollup-linux-x64-gnu": "^4.28.1",
|
|
@@ -130,8 +130,9 @@
|
|
|
130
130
|
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
|
|
131
131
|
"dev:generate": "nuxi generate playground",
|
|
132
132
|
"release": "pnpm run release:check && pnpm run release:patch",
|
|
133
|
-
"release:check": "pnpm run format && pnpm run lint && pnpm run typecheck && pnpm run test:types && pnpm run
|
|
133
|
+
"release:check": "pnpm run format && pnpm run lint && pnpm run typecheck && pnpm run test:types && pnpm run check:versions -- --npm && pnpm run release:source && pnpm run compare:published && pnpm run test",
|
|
134
134
|
"release:auth": "pnpm -C scripts cli ensure-npm-auth",
|
|
135
|
+
"release:source": "pnpm -C scripts cli ensure-release-source",
|
|
135
136
|
"release:patch": "pnpm run release:auth && pnpm run prepack && pnpm -C scripts cli release --bump patch && pnpm publish -r && git push --follow-tags",
|
|
136
137
|
"release:minor": "pnpm run release:auth && pnpm run prepack && pnpm -C scripts cli release --bump minor && pnpm publish -r && git push --follow-tags",
|
|
137
138
|
"release:major": "pnpm run release:auth && pnpm run prepack && pnpm -C scripts cli release --bump major && pnpm publish -r && git push --follow-tags",
|
|
@@ -144,7 +145,7 @@
|
|
|
144
145
|
"test:integration": "vitest run --config vitest.integration.config.ts",
|
|
145
146
|
"test:e2e": "vitest run --config vitest.e2e.config.ts",
|
|
146
147
|
"test:packages": "vitest run --config vitest.packages.config.ts",
|
|
147
|
-
"test:performance": "
|
|
148
|
+
"test:performance": "pnpm -C scripts cli performance",
|
|
148
149
|
"test:strategies": "vitest run --config vitest.integration.config.ts test/strategies-",
|
|
149
150
|
"test:watch": "vitest watch --config vitest.unit.config.ts",
|
|
150
151
|
"test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"id":"225477ec-bfda-48f4-aca0-4fc5d067bae9","timestamp":1785480459001,"prerendered":[]}
|