@fluenti/nuxt 0.2.0 → 0.3.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/detectors-BnmzZTww.cjs +2 -0
- package/dist/detectors-BnmzZTww.cjs.map +1 -0
- package/dist/detectors-CAqp_VCN.js +100 -0
- package/dist/detectors-CAqp_VCN.js.map +1 -0
- package/dist/devtools.d.ts +31 -0
- package/dist/devtools.d.ts.map +1 -0
- package/dist/isr-validation.d.ts +14 -0
- package/dist/isr-validation.d.ts.map +1 -0
- package/dist/locale-head-BuSO-fCZ.js +88 -0
- package/dist/locale-head-BuSO-fCZ.js.map +1 -0
- package/dist/locale-head-D1NAUQc8.cjs +2 -0
- package/dist/locale-head-D1NAUQc8.cjs.map +1 -0
- package/dist/module.cjs +1 -1
- package/dist/module.cjs.map +1 -1
- package/dist/module.d.ts +18 -0
- package/dist/module.d.ts.map +1 -0
- package/dist/module.js +231 -46
- package/dist/module.js.map +1 -1
- package/dist/page-extend-BrPO2RhM.js +36 -0
- package/dist/page-extend-BrPO2RhM.js.map +1 -0
- package/dist/page-extend-tRXsujtK.cjs +2 -0
- package/dist/page-extend-tRXsujtK.cjs.map +1 -0
- package/dist/page-meta-transform.d.ts +17 -0
- package/dist/page-meta-transform.d.ts.map +1 -0
- package/dist/runtime/client.cjs +1 -1
- package/dist/runtime/client.cjs.map +1 -1
- package/dist/runtime/client.js +2 -2
- package/dist/runtime/components/NuxtLinkLocale.cjs +1 -1
- package/dist/runtime/components/NuxtLinkLocale.cjs.map +1 -1
- package/dist/runtime/composables.cjs +1 -1
- package/dist/runtime/composables.cjs.map +1 -1
- package/dist/runtime/composables.d.ts +46 -0
- package/dist/runtime/composables.d.ts.map +1 -1
- package/dist/runtime/composables.js +55 -13
- package/dist/runtime/composables.js.map +1 -1
- package/dist/runtime/define-i18n-route.cjs +2 -0
- package/dist/runtime/define-i18n-route.cjs.map +1 -0
- package/dist/runtime/define-i18n-route.d.ts +27 -0
- package/dist/runtime/define-i18n-route.d.ts.map +1 -0
- package/dist/runtime/define-i18n-route.js +6 -0
- package/dist/runtime/define-i18n-route.js.map +1 -0
- package/dist/runtime/detectors/cookie.d.ts.map +1 -1
- package/dist/runtime/detectors/domain.cjs +2 -0
- package/dist/runtime/detectors/domain.cjs.map +1 -0
- package/dist/runtime/detectors/domain.d.ts +9 -0
- package/dist/runtime/detectors/domain.d.ts.map +1 -0
- package/dist/runtime/detectors/domain.js +15 -0
- package/dist/runtime/detectors/domain.js.map +1 -0
- package/dist/runtime/detectors/header.d.ts.map +1 -1
- package/dist/runtime/detectors/index.d.ts +1 -1
- package/dist/runtime/detectors/index.d.ts.map +1 -1
- package/dist/runtime/detectors/query.d.ts.map +1 -1
- package/dist/runtime/index.cjs +1 -1
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +5 -5
- package/dist/runtime/locale-head.d.ts +3 -0
- package/dist/runtime/locale-head.d.ts.map +1 -1
- package/dist/runtime/middleware/locale-redirect.cjs +1 -1
- package/dist/runtime/middleware/locale-redirect.cjs.map +1 -1
- package/dist/runtime/middleware/locale-redirect.js +1 -1
- package/dist/runtime/page-extend.d.ts +21 -5
- package/dist/runtime/page-extend.d.ts.map +1 -1
- package/dist/runtime/plugin.cjs +1 -1
- package/dist/runtime/plugin.cjs.map +1 -1
- package/dist/runtime/plugin.d.ts.map +1 -1
- package/dist/runtime/plugin.js +55 -23
- package/dist/runtime/plugin.js.map +1 -1
- package/dist/runtime/server/locale-redirect.cjs +2 -0
- package/dist/runtime/server/locale-redirect.cjs.map +1 -0
- package/dist/runtime/server/locale-redirect.d.ts +12 -0
- package/dist/runtime/server/locale-redirect.d.ts.map +1 -0
- package/dist/runtime/server/locale-redirect.js +51 -0
- package/dist/runtime/server/locale-redirect.js.map +1 -0
- package/dist/runtime/standalone-composables.cjs +2 -0
- package/dist/runtime/standalone-composables.cjs.map +1 -0
- package/dist/runtime/standalone-composables.d.ts +6 -0
- package/dist/runtime/standalone-composables.d.ts.map +1 -1
- package/dist/runtime/standalone-composables.js +34 -0
- package/dist/runtime/standalone-composables.js.map +1 -0
- package/dist/sitemap.d.ts +24 -0
- package/dist/sitemap.d.ts.map +1 -0
- package/dist/types.d.ts +210 -13
- package/dist/types.d.ts.map +1 -1
- package/llms-full.txt +411 -0
- package/llms-migration.txt +201 -0
- package/llms.txt +103 -0
- package/package.json +5 -4
- package/dist/detectors-CFJvuwzi.cjs +0 -2
- package/dist/detectors-CFJvuwzi.cjs.map +0 -1
- package/dist/detectors-DhkfHBHr.js +0 -84
- package/dist/detectors-DhkfHBHr.js.map +0 -1
- package/dist/locale-head-BfsESdd7.cjs +0 -2
- package/dist/locale-head-BfsESdd7.cjs.map +0 -1
- package/dist/locale-head-CqUlvy3O.js +0 -38
- package/dist/locale-head-CqUlvy3O.js.map +0 -1
- package/dist/page-extend-DJ7wpuVj.js +0 -25
- package/dist/page-extend-DJ7wpuVj.js.map +0 -1
- package/dist/page-extend-OvV-ZhFB.cjs +0 -2
- package/dist/page-extend-OvV-ZhFB.cjs.map +0 -1
package/dist/module.js
CHANGED
|
@@ -1,67 +1,214 @@
|
|
|
1
|
-
import { t as e } from "./page-extend-
|
|
1
|
+
import { t as e } from "./page-extend-BrPO2RhM.js";
|
|
2
2
|
import { n as t, r as n, t as r } from "./path-utils-BcvXLCGi.js";
|
|
3
|
-
import { t as i } from "./locale-head-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { t as i } from "./locale-head-BuSO-fCZ.js";
|
|
4
|
+
import { useLocaleHead as a, useLocalePath as o, useLocaleRoute as s, useSwitchLocalePath as c } from "./runtime/standalone-composables.js";
|
|
5
|
+
import { defineI18nRoute as l } from "./runtime/define-i18n-route.js";
|
|
6
|
+
import { addComponent as u, addImports as d, addPlugin as f, addRouteMiddleware as p, addServerHandler as m, createResolver as h, defineNuxtModule as g } from "@nuxt/kit";
|
|
7
|
+
import { resolveLocaleCodes as _, resolveLocaleCodes as v } from "@fluenti/core/internal";
|
|
8
|
+
import y from "@fluenti/vue/vite-plugin";
|
|
6
9
|
//#region \0rolldown/runtime.js
|
|
7
|
-
var
|
|
10
|
+
var b = /* @__PURE__ */ ((e) => typeof require < "u" ? require : typeof Proxy < "u" ? new Proxy(e, { get: (e, t) => (typeof require < "u" ? require : e)[t] }) : e)(function(e) {
|
|
8
11
|
if (typeof require < "u") return require.apply(this, arguments);
|
|
9
12
|
throw Error("Calling `require` for \"" + e + "\" in an environment that doesn't expose the `require` function. See https://rolldown.rs/in-depth/bundling-cjs#require-external-modules for more details.");
|
|
10
13
|
});
|
|
11
14
|
//#endregion
|
|
12
|
-
//#region src/
|
|
13
|
-
function
|
|
14
|
-
|
|
15
|
+
//#region src/types.ts
|
|
16
|
+
function x(e) {
|
|
17
|
+
let t = {};
|
|
18
|
+
for (let n of e) typeof n == "string" ? t[n] = { code: n } : t[n.code] = n;
|
|
19
|
+
return t;
|
|
15
20
|
}
|
|
16
|
-
function
|
|
17
|
-
|
|
21
|
+
function S(e, t) {
|
|
22
|
+
if (t?.length) return t;
|
|
23
|
+
let n = [];
|
|
24
|
+
for (let t of e) typeof t != "string" && t.domain && n.push({
|
|
25
|
+
domain: t.domain,
|
|
26
|
+
locale: t.code
|
|
27
|
+
});
|
|
28
|
+
return n;
|
|
18
29
|
}
|
|
19
|
-
|
|
20
|
-
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region src/isr-validation.ts
|
|
32
|
+
function C(e, t, n) {
|
|
33
|
+
let r = [];
|
|
34
|
+
if (!e?.enabled) return r;
|
|
35
|
+
let i = n.filter((e) => e === "cookie" || e === "header");
|
|
36
|
+
return i.length > 0 && r.push({
|
|
37
|
+
level: "warn",
|
|
38
|
+
message: `[@fluenti/nuxt] ISR is enabled but detectOrder includes non-path detectors (${i.join(", ")}). ISR caches by URL path, so cookie/header-based detection may serve the wrong locale from cache. Consider using detectOrder: ['path'] with ISR.`
|
|
39
|
+
}), t === "no_prefix" && r.push({
|
|
40
|
+
level: "warn",
|
|
41
|
+
message: "[@fluenti/nuxt] ISR is enabled with strategy: 'no_prefix'. All locales share the same URL path, so ISR will cache only one locale per URL. Use 'prefix' or 'prefix_except_default' strategy with ISR."
|
|
42
|
+
}), r;
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region src/devtools.ts
|
|
46
|
+
function w(e, t, n, r) {
|
|
47
|
+
try {
|
|
48
|
+
e.hook("devtools:customTabs", (e) => {
|
|
49
|
+
e.push({
|
|
50
|
+
name: "fluenti",
|
|
51
|
+
title: "Fluenti i18n",
|
|
52
|
+
icon: "i-carbon-translate",
|
|
53
|
+
view: {
|
|
54
|
+
type: "client-component",
|
|
55
|
+
componentName: "FluentiDevToolsPanel"
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
} catch {}
|
|
60
|
+
e.hook("nitro:config", (e) => {
|
|
61
|
+
let i = e.runtimeConfig;
|
|
62
|
+
if (i) {
|
|
63
|
+
let e = (i.public ??= {}).fluenti ?? {};
|
|
64
|
+
e.devtools = {
|
|
65
|
+
enabled: !0,
|
|
66
|
+
locales: t,
|
|
67
|
+
defaultLocale: n,
|
|
68
|
+
strategy: r
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region src/page-meta-transform.ts
|
|
75
|
+
function T() {
|
|
76
|
+
return {
|
|
77
|
+
name: "fluenti:page-meta-transform",
|
|
78
|
+
enforce: "pre",
|
|
79
|
+
transform(e, t) {
|
|
80
|
+
if (!t.includes("/pages/") && !t.includes("\\pages\\") || !e.includes("defineI18nRoute") && !e.includes("i18n")) return null;
|
|
81
|
+
let n = e;
|
|
82
|
+
return /defineI18nRoute\s*\(([^)]+)\)/g.test(n) && (n = n.replace(/defineI18nRoute\s*\(([^)]+)\)/g, (e, t) => `definePageMeta({ i18nRoute: ${t.trim()} })`)), n.includes("definePageMeta") && n.includes("i18n:") && (n = n.replace(/(definePageMeta\s*\(\s*\{[^}]*)\bi18n\s*:/g, "$1i18nRoute:")), n === e ? null : {
|
|
83
|
+
code: n,
|
|
84
|
+
map: null
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
//#endregion
|
|
90
|
+
//#region src/sitemap.ts
|
|
91
|
+
function E(e, t, n, r, i) {
|
|
92
|
+
let a = [], o = i ?? "";
|
|
93
|
+
for (let i of e) {
|
|
94
|
+
let e = i.startsWith("/") ? i : `/${i}`;
|
|
95
|
+
for (let i of t) {
|
|
96
|
+
let s = D(e, i, n, r), c = t.map((t) => ({
|
|
97
|
+
hreflang: t,
|
|
98
|
+
href: `${o}${D(e, t, n, r)}`
|
|
99
|
+
}));
|
|
100
|
+
c.push({
|
|
101
|
+
hreflang: "x-default",
|
|
102
|
+
href: `${o}${D(e, n, n, r)}`
|
|
103
|
+
}), a.push({
|
|
104
|
+
loc: `${o}${s}`,
|
|
105
|
+
alternatives: c
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return a;
|
|
110
|
+
}
|
|
111
|
+
function D(e, t, n, r) {
|
|
112
|
+
return r === "no_prefix" || r === "prefix_except_default" && t === n ? e : `/${t}${e === "/" ? "" : e}`;
|
|
113
|
+
}
|
|
114
|
+
function O(e, t, n, r) {
|
|
115
|
+
return (i) => {
|
|
116
|
+
if (n === "no_prefix") return i;
|
|
117
|
+
let a = [];
|
|
118
|
+
for (let o of i) {
|
|
119
|
+
let i = o.loc.replace(/^https?:\/\/[^/]+/, "");
|
|
120
|
+
for (let o of e) {
|
|
121
|
+
let s = D(i, o, t, n), c = e.map((e) => ({
|
|
122
|
+
hreflang: e,
|
|
123
|
+
href: `${r ?? ""}${D(i, e, t, n)}`
|
|
124
|
+
}));
|
|
125
|
+
c.push({
|
|
126
|
+
hreflang: "x-default",
|
|
127
|
+
href: `${r ?? ""}${D(i, t, t, n)}`
|
|
128
|
+
}), a.push({
|
|
129
|
+
loc: `${r ?? ""}${s}`,
|
|
130
|
+
alternatives: c
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return a;
|
|
135
|
+
};
|
|
21
136
|
}
|
|
22
137
|
//#endregion
|
|
23
138
|
//#region src/module.ts
|
|
24
|
-
var
|
|
139
|
+
var k = "@fluenti/nuxt", A = "fluenti";
|
|
140
|
+
function j(e, t) {
|
|
141
|
+
if (typeof e == "object") try {
|
|
142
|
+
let { DEFAULT_FLUENTI_CONFIG: t } = b("@fluenti/core/config");
|
|
143
|
+
return {
|
|
144
|
+
...t,
|
|
145
|
+
...e
|
|
146
|
+
};
|
|
147
|
+
} catch {
|
|
148
|
+
return e;
|
|
149
|
+
}
|
|
150
|
+
try {
|
|
151
|
+
let { loadConfigSync: n } = b("@fluenti/core/config");
|
|
152
|
+
return n(typeof e == "string" ? e : void 0, t);
|
|
153
|
+
} catch {
|
|
154
|
+
return {
|
|
155
|
+
sourceLocale: "en",
|
|
156
|
+
locales: ["en"],
|
|
157
|
+
catalogDir: "./locales",
|
|
158
|
+
format: "po",
|
|
159
|
+
include: ["./src/**/*.{vue,tsx,jsx,ts,js}"],
|
|
160
|
+
compileOutDir: "./src/locales/compiled"
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
var M = g({
|
|
25
165
|
meta: {
|
|
26
|
-
name:
|
|
27
|
-
configKey:
|
|
166
|
+
name: k,
|
|
167
|
+
configKey: A,
|
|
28
168
|
compatibility: { nuxt: ">=3.0.0" }
|
|
29
169
|
},
|
|
30
|
-
defaults: {
|
|
31
|
-
locales: [],
|
|
32
|
-
defaultLocale: "en",
|
|
33
|
-
strategy: "prefix_except_default"
|
|
34
|
-
},
|
|
170
|
+
defaults: { strategy: "prefix_except_default" },
|
|
35
171
|
setup(t, n) {
|
|
36
|
-
let { resolve: r } =
|
|
172
|
+
let { resolve: r } = h(import.meta.url), i = n.options.rootDir ?? process.cwd(), a = j(t.config, i);
|
|
173
|
+
t.locales && (a.locales = t.locales), t.defaultLocale && (a.defaultLocale = t.defaultLocale), t.sourceLocale && (a.sourceLocale = t.sourceLocale), t.catalogDir && (a.catalogDir = t.catalogDir);
|
|
174
|
+
let o = v(a.locales), s = x(a.locales), c = a.defaultLocale ?? a.sourceLocale, l = t.strategy === "domains" ? S(a.locales, t.domains) : void 0, g = t.detectOrder ?? (t.strategy === "domains" ? [
|
|
175
|
+
"domain",
|
|
176
|
+
"cookie",
|
|
177
|
+
"header"
|
|
178
|
+
] : [
|
|
37
179
|
"path",
|
|
38
180
|
"cookie",
|
|
39
181
|
"header"
|
|
40
|
-
];
|
|
41
|
-
|
|
42
|
-
locales:
|
|
43
|
-
defaultLocale:
|
|
182
|
+
]);
|
|
183
|
+
n.options.runtimeConfig.public.fluenti = {
|
|
184
|
+
locales: o,
|
|
185
|
+
defaultLocale: c,
|
|
44
186
|
strategy: t.strategy ?? "prefix_except_default",
|
|
45
187
|
detectBrowserLanguage: t.detectBrowserLanguage,
|
|
46
|
-
detectOrder:
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
188
|
+
detectOrder: g,
|
|
189
|
+
queryParamKey: t.queryParamKey ?? "locale",
|
|
190
|
+
injectGlobalProperties: t.injectGlobalProperties !== !1,
|
|
191
|
+
...l ? { domains: l } : {},
|
|
192
|
+
localeProperties: s
|
|
193
|
+
}, t.autoVitePlugin !== !1 && (n.options.vite = n.options.vite || {}, n.options.vite.plugins = n.options.vite.plugins || [], n.options.vite.plugins.push(...y({ config: a }))), n.options.vite = n.options.vite || {}, n.options.vite.plugins = n.options.vite.plugins || [], n.options.vite.plugins.push(T()), f({
|
|
52
194
|
src: r("./runtime/plugin"),
|
|
53
195
|
mode: "all"
|
|
54
|
-
})
|
|
196
|
+
});
|
|
197
|
+
let _ = t.strategy ?? "prefix_except_default";
|
|
198
|
+
_ !== "no_prefix" && _ !== "domains" && t.extendRoutes !== !1 && n.hook("pages:extend", (n) => {
|
|
55
199
|
e(n, {
|
|
56
|
-
locales:
|
|
57
|
-
defaultLocale:
|
|
58
|
-
strategy:
|
|
200
|
+
locales: o,
|
|
201
|
+
defaultLocale: c,
|
|
202
|
+
strategy: _,
|
|
203
|
+
...t.routeNameTemplate ? { routeNameTemplate: t.routeNameTemplate } : {},
|
|
204
|
+
...t.routeOverrides ? { routeOverrides: t.routeOverrides } : {},
|
|
205
|
+
...t.routeMode ? { routeMode: t.routeMode } : {}
|
|
59
206
|
});
|
|
60
|
-
}),
|
|
207
|
+
}), _ === "prefix" && p({
|
|
61
208
|
name: "fluenti-locale-redirect",
|
|
62
209
|
path: r("./runtime/middleware/locale-redirect"),
|
|
63
|
-
global: !
|
|
64
|
-
}),
|
|
210
|
+
global: t.globalMiddleware !== !1
|
|
211
|
+
}), t.autoImports !== !1 && d([
|
|
65
212
|
{
|
|
66
213
|
name: "useLocalePath",
|
|
67
214
|
from: r("./runtime/composables")
|
|
@@ -70,24 +217,58 @@ var g = "@fluenti/nuxt", _ = "fluenti", v = u({
|
|
|
70
217
|
name: "useSwitchLocalePath",
|
|
71
218
|
from: r("./runtime/composables")
|
|
72
219
|
},
|
|
220
|
+
{
|
|
221
|
+
name: "useLocaleRoute",
|
|
222
|
+
from: r("./runtime/composables")
|
|
223
|
+
},
|
|
73
224
|
{
|
|
74
225
|
name: "useLocaleHead",
|
|
75
226
|
from: r("./runtime/composables")
|
|
76
227
|
},
|
|
228
|
+
{
|
|
229
|
+
name: "useI18nScoped",
|
|
230
|
+
from: r("./runtime/composables")
|
|
231
|
+
},
|
|
77
232
|
{
|
|
78
233
|
name: "useI18n",
|
|
79
234
|
from: "@fluenti/vue"
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
name: "defineI18nRoute",
|
|
238
|
+
from: r("./runtime/define-i18n-route")
|
|
80
239
|
}
|
|
81
|
-
])
|
|
82
|
-
|
|
240
|
+
]);
|
|
241
|
+
let b = t.componentPrefix ?? "";
|
|
242
|
+
if (t.registerNuxtLinkLocale !== !1 && u({
|
|
243
|
+
name: `${b}NuxtLinkLocale`,
|
|
83
244
|
filePath: r("./runtime/components/NuxtLinkLocale")
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
|
|
245
|
+
}), u({
|
|
246
|
+
name: `${b}Trans`,
|
|
247
|
+
filePath: "@fluenti/vue",
|
|
248
|
+
export: "Trans"
|
|
249
|
+
}), u({
|
|
250
|
+
name: `${b}Plural`,
|
|
251
|
+
filePath: "@fluenti/vue",
|
|
252
|
+
export: "Plural"
|
|
253
|
+
}), u({
|
|
254
|
+
name: `${b}Select`,
|
|
255
|
+
filePath: "@fluenti/vue",
|
|
256
|
+
export: "Select"
|
|
257
|
+
}), u({
|
|
258
|
+
name: `${b}DateTime`,
|
|
259
|
+
filePath: "@fluenti/vue",
|
|
260
|
+
export: "DateTime"
|
|
261
|
+
}), u({
|
|
262
|
+
name: `${b}NumberFormat`,
|
|
263
|
+
filePath: "@fluenti/vue",
|
|
264
|
+
export: "NumberFormat"
|
|
265
|
+
}), _ !== "no_prefix" && _ !== "domains") {
|
|
87
266
|
let e = n.options, r = e.nitro ??= {}, i = r.prerender ??= {};
|
|
88
|
-
|
|
267
|
+
i.crawlLinks = i.crawlLinks ?? !0, _ === "prefix" && (i.routes = (i.routes ?? ["/"]).map((e) => e === "/" ? `/${c}` : e));
|
|
268
|
+
for (let e of C(t.isr, _, g)) console.warn(e.message);
|
|
269
|
+
if (t.isr?.enabled) {
|
|
89
270
|
let n = e.routeRules ??= {}, r = t.isr.ttl ?? 3600;
|
|
90
|
-
for (let e of
|
|
271
|
+
for (let e of o) e === c && _ === "prefix_except_default" ? n["/**"] = {
|
|
91
272
|
...n["/**"],
|
|
92
273
|
isr: r
|
|
93
274
|
} : n[`/${e}/**`] = {
|
|
@@ -96,9 +277,13 @@ var g = "@fluenti/nuxt", _ = "fluenti", v = u({
|
|
|
96
277
|
};
|
|
97
278
|
}
|
|
98
279
|
}
|
|
280
|
+
n.options.dev && w(n, o, c, _), (_ === "prefix" || _ === "prefix_and_default") && m({
|
|
281
|
+
handler: r("./runtime/server/locale-redirect"),
|
|
282
|
+
middleware: !0
|
|
283
|
+
});
|
|
99
284
|
}
|
|
100
285
|
});
|
|
101
286
|
//#endregion
|
|
102
|
-
export {
|
|
287
|
+
export { A as CONFIG_KEY, k as MODULE_NAME, i as buildLocaleHead, O as createSitemapHook, M as default, l as defineI18nRoute, e as extendPages, r as extractLocaleFromPath, E as generateSitemapUrls, t as localePath, S as resolveDomainConfigs, _ as resolveLocaleCodes, x as resolveLocaleProperties, n as switchLocalePath, a as useLocaleHead, o as useLocalePath, s as useLocaleRoute, c as useSwitchLocalePath };
|
|
103
288
|
|
|
104
289
|
//# sourceMappingURL=module.js.map
|
package/dist/module.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.js","names":[],"sources":["../src/runtime/standalone-composables.ts","../src/module.ts"],"sourcesContent":["import { computed } from 'vue'\nimport type { ComputedRef, Ref } from 'vue'\nimport { localePath, switchLocalePath } from './path-utils'\nimport type { FluentNuxtRuntimeConfig } from '../types'\nimport type { LocaleHeadMeta, LocaleHeadOptions } from './locale-head'\nimport { buildLocaleHead } from './locale-head'\n\n/**\n * Standalone composable for locale-prefixed paths (no Nuxt dependency).\n * Accepts explicit locale ref and config instead of reading from Nuxt context.\n */\nexport function useLocalePath(\n locale: Ref<string>,\n config: FluentNuxtRuntimeConfig,\n): (path: string, targetLocale?: string) => string {\n return (path: string, targetLocale?: string) => {\n return localePath(\n path,\n targetLocale ?? locale.value,\n config.defaultLocale,\n config.strategy,\n )\n }\n}\n\n/**\n * Standalone composable for switch-locale paths (no Nuxt dependency).\n * Accepts explicit current path ref and config.\n */\nexport function useSwitchLocalePath(\n currentPath: Ref<string>,\n config: FluentNuxtRuntimeConfig,\n): (locale: string) => string {\n return (newLocale: string) => {\n return switchLocalePath(\n currentPath.value,\n newLocale,\n config.locales,\n config.defaultLocale,\n config.strategy,\n )\n }\n}\n\n/**\n * Standalone composable for locale-aware head metadata (no Nuxt dependency).\n * Accepts explicit locale, path, and config refs.\n */\nexport function useLocaleHead(\n locale: Ref<string>,\n currentPath: Ref<string>,\n config: FluentNuxtRuntimeConfig,\n options?: LocaleHeadOptions,\n): ComputedRef<LocaleHeadMeta> {\n return computed(() => {\n return buildLocaleHead(locale.value, currentPath.value, config, options)\n })\n}\n","import { defineNuxtModule, addPlugin, addImports, addComponent, addRouteMiddleware, createResolver } from '@nuxt/kit'\nimport type { FluentNuxtOptions } from './types'\nimport { extendPages } from './runtime/page-extend'\n\nexport type { FluentNuxtOptions, Strategy, FluentNuxtRuntimeConfig, DetectBrowserLanguageOptions, LocaleDetectContext, LocaleDetectorFn, BuiltinDetector, ISROptions } from './types'\nexport { localePath, extractLocaleFromPath, switchLocalePath } from './runtime/path-utils'\nexport { extendPages } from './runtime/page-extend'\nexport type { PageRoute } from './runtime/page-extend'\nexport { buildLocaleHead } from './runtime/locale-head'\nexport type { LocaleHeadMeta, LocaleHeadOptions } from './runtime/locale-head'\nexport { useLocalePath, useSwitchLocalePath, useLocaleHead } from './runtime/standalone-composables'\n\nexport const MODULE_NAME = '@fluenti/nuxt'\nexport const CONFIG_KEY = 'fluenti'\n\nexport default defineNuxtModule<FluentNuxtOptions>({\n meta: {\n name: MODULE_NAME,\n configKey: CONFIG_KEY,\n compatibility: { nuxt: '>=3.0.0' },\n },\n defaults: {\n locales: [],\n defaultLocale: 'en',\n strategy: 'prefix_except_default',\n },\n setup(options, nuxt) {\n const { resolve } = createResolver(import.meta.url)\n\n // --- Inject runtime config ---\n const detectOrder = options.detectOrder ?? ['path', 'cookie', 'header']\n nuxt.options.runtimeConfig.public['fluenti'] = {\n locales: options.locales,\n defaultLocale: options.defaultLocale,\n strategy: options.strategy ?? 'prefix_except_default',\n detectBrowserLanguage: options.detectBrowserLanguage,\n detectOrder,\n }\n\n // --- Auto-register @fluenti/vite-plugin ---\n if (options.autoVitePlugin !== false) {\n try {\n const vitePlugin = require('@fluenti/vite-plugin')\n const plugin = vitePlugin.default ?? vitePlugin\n nuxt.options.vite = nuxt.options.vite || {}\n nuxt.options.vite.plugins = nuxt.options.vite.plugins || []\n ;(nuxt.options.vite.plugins as unknown[]).push(\n plugin({ framework: 'vue' }),\n )\n } catch {\n // @fluenti/vite-plugin is an optional peer dependency\n }\n }\n\n // --- Register runtime plugin ---\n addPlugin({\n src: resolve('./runtime/plugin'),\n mode: 'all',\n })\n\n // --- Extend routes with locale prefixes ---\n if (options.strategy !== 'no_prefix') {\n nuxt.hook('pages:extend', (pages) => {\n extendPages(pages, {\n locales: options.locales,\n defaultLocale: options.defaultLocale,\n strategy: options.strategy ?? 'prefix_except_default',\n })\n })\n }\n\n // --- Register locale redirect middleware ---\n if (options.strategy === 'prefix') {\n addRouteMiddleware({\n name: 'fluenti-locale-redirect',\n path: resolve('./runtime/middleware/locale-redirect'),\n global: true,\n })\n }\n\n // --- Auto-import composables ---\n addImports([\n { name: 'useLocalePath', from: resolve('./runtime/composables') },\n { name: 'useSwitchLocalePath', from: resolve('./runtime/composables') },\n { name: 'useLocaleHead', from: resolve('./runtime/composables') },\n { name: 'useI18n', from: '@fluenti/vue' },\n ])\n\n // --- Register NuxtLinkLocale component ---\n const prefix = options.componentPrefix ?? ''\n addComponent({\n name: `${prefix}NuxtLinkLocale`,\n filePath: resolve('./runtime/components/NuxtLinkLocale'),\n })\n\n // --- SSG / ISR: configure nitro prerender and route rules ---\n const strategy = options.strategy ?? 'prefix_except_default'\n if (strategy !== 'no_prefix') {\n const nuxtOpts = nuxt.options as unknown as Record<string, unknown>\n\n // Enable link crawling so locale-prefixed routes are discovered during prerender\n const nitroOpts = (nuxtOpts['nitro'] ?? (nuxtOpts['nitro'] = {})) as Record<string, unknown>\n const prerender = (nitroOpts['prerender'] ?? (nitroOpts['prerender'] = {})) as Record<string, unknown>\n prerender['crawlLinks'] = prerender['crawlLinks'] ?? true\n\n // For 'prefix' strategy, / has no matching route (all routes are\n // locale-prefixed). Replace the default / initial route with\n // /<defaultLocale> so the prerenderer starts from a valid route.\n if (strategy === 'prefix') {\n const routes = (prerender['routes'] ?? ['/']) as string[]\n prerender['routes'] = routes.map((r) =>\n r === '/' ? `/${options.defaultLocale}` : r,\n )\n }\n\n // ISR: generate routeRules for each locale pattern\n if (options.isr?.enabled) {\n const routeRules = (nuxtOpts['routeRules'] ?? (nuxtOpts['routeRules'] = {})) as Record<string, Record<string, unknown>>\n const ttl = options.isr.ttl ?? 3600\n for (const locale of options.locales) {\n if (locale === options.defaultLocale && strategy === 'prefix_except_default') {\n routeRules['/**'] = { ...routeRules['/**'], isr: ttl }\n } else {\n routeRules[`/${locale}/**`] = { ...routeRules[`/${locale}/**`], isr: ttl }\n }\n }\n }\n }\n },\n})\n"],"mappings":";;;;;;;;;;;;AAWA,SAAgB,EACd,GACA,GACiD;AACjD,SAAQ,GAAc,MACb,EACL,GACA,KAAgB,EAAO,OACvB,EAAO,eACP,EAAO,SACR;;AAQL,SAAgB,EACd,GACA,GAC4B;AAC5B,SAAQ,MACC,EACL,EAAY,OACZ,GACA,EAAO,SACP,EAAO,eACP,EAAO,SACR;;AAQL,SAAgB,EACd,GACA,GACA,GACA,GAC6B;AAC7B,QAAO,QACE,EAAgB,EAAO,OAAO,EAAY,OAAO,GAAQ,EAAQ,CACxE;;;;AC5CJ,IAAa,IAAc,iBACd,IAAa,WAE1B,IAAe,EAAoC;CACjD,MAAM;EACJ,MAAM;EACN,WAAW;EACX,eAAe,EAAE,MAAM,WAAW;EACnC;CACD,UAAU;EACR,SAAS,EAAE;EACX,eAAe;EACf,UAAU;EACX;CACD,MAAM,GAAS,GAAM;EACnB,IAAM,EAAE,eAAY,EAAe,OAAO,KAAK,IAAI,EAG7C,IAAc,EAAQ,eAAe;GAAC;GAAQ;GAAU;GAAS;AAUvE,MATA,EAAK,QAAQ,cAAc,OAAO,UAAa;GAC7C,SAAS,EAAQ;GACjB,eAAe,EAAQ;GACvB,UAAU,EAAQ,YAAY;GAC9B,uBAAuB,EAAQ;GAC/B;GACD,EAGG,EAAQ,mBAAmB,GAC7B,KAAI;GACF,IAAM,IAAA,EAAqB,uBAAuB,EAC5C,IAAS,EAAW,WAAW;AAGnC,GAFF,EAAK,QAAQ,OAAO,EAAK,QAAQ,QAAQ,EAAE,EAC3C,EAAK,QAAQ,KAAK,UAAU,EAAK,QAAQ,KAAK,WAAW,EAAE,EACzD,EAAK,QAAQ,KAAK,QAAsB,KACxC,EAAO,EAAE,WAAW,OAAO,CAAC,CAC7B;UACK;AAyCV,EAnCA,EAAU;GACR,KAAK,EAAQ,mBAAmB;GAChC,MAAM;GACP,CAAC,EAGE,EAAQ,aAAa,eACvB,EAAK,KAAK,iBAAiB,MAAU;AACnC,KAAY,GAAO;IACjB,SAAS,EAAQ;IACjB,eAAe,EAAQ;IACvB,UAAU,EAAQ,YAAY;IAC/B,CAAC;IACF,EAIA,EAAQ,aAAa,YACvB,EAAmB;GACjB,MAAM;GACN,MAAM,EAAQ,uCAAuC;GACrD,QAAQ;GACT,CAAC,EAIJ,EAAW;GACT;IAAE,MAAM;IAAiB,MAAM,EAAQ,wBAAwB;IAAE;GACjE;IAAE,MAAM;IAAuB,MAAM,EAAQ,wBAAwB;IAAE;GACvE;IAAE,MAAM;IAAiB,MAAM,EAAQ,wBAAwB;IAAE;GACjE;IAAE,MAAM;IAAW,MAAM;IAAgB;GAC1C,CAAC,EAIF,EAAa;GACX,MAAM,GAFO,EAAQ,mBAAmB,GAExB;GAChB,UAAU,EAAQ,sCAAsC;GACzD,CAAC;EAGF,IAAM,IAAW,EAAQ,YAAY;AACrC,MAAI,MAAa,aAAa;GAC5B,IAAM,IAAW,EAAK,SAGhB,IAAa,AAAsB,EAAS,UAAW,EAAE,EACzD,IAAa,AAA2B,EAAU,cAAe,EAAE;AAczE,OAbA,EAAU,aAAgB,EAAU,cAAiB,IAKjD,MAAa,aAEf,EAAU,UADM,EAAU,UAAa,CAAC,IAAI,EACf,KAAK,MAChC,MAAM,MAAM,IAAI,EAAQ,kBAAkB,EAC3C,GAIC,EAAQ,KAAK,SAAS;IACxB,IAAM,IAAc,AAA2B,EAAS,eAAgB,EAAE,EACpE,IAAM,EAAQ,IAAI,OAAO;AAC/B,SAAK,IAAM,KAAU,EAAQ,QAC3B,CAAI,MAAW,EAAQ,iBAAiB,MAAa,0BACnD,EAAW,SAAS;KAAE,GAAG,EAAW;KAAQ,KAAK;KAAK,GAEtD,EAAW,IAAI,EAAO,QAAQ;KAAE,GAAG,EAAW,IAAI,EAAO;KAAO,KAAK;KAAK;;;;CAMrF,CAAC"}
|
|
1
|
+
{"version":3,"file":"module.js","names":[],"sources":["../src/types.ts","../src/isr-validation.ts","../src/devtools.ts","../src/page-meta-transform.ts","../src/sitemap.ts","../src/module.ts"],"sourcesContent":["import type { FluentiBuildConfig } from '@fluenti/core/internal'\nimport { resolveLocaleCodes } from '@fluenti/core/internal'\n// Re-export core types for backwards compatibility\nexport type { LocaleObject, LocaleDefinition } from '@fluenti/core'\nexport { resolveLocaleCodes }\n\n// Import core types needed locally\nimport type { LocaleDefinition, LocaleObject } from '@fluenti/core'\n\n/** Routing strategy for locale-prefixed URLs */\nexport type Strategy = 'prefix' | 'prefix_except_default' | 'prefix_and_default' | 'no_prefix' | 'domains'\n\n/** Browser language detection options */\nexport interface DetectBrowserLanguageOptions {\n /** Use a cookie to persist the detected locale */\n useCookie?: boolean\n /** Cookie key name (default: 'fluenti_locale') */\n cookieKey?: string\n /** Fallback locale when detection fails */\n fallbackLocale?: string\n}\n\n/** Built-in detector names */\nexport type BuiltinDetector = 'path' | 'cookie' | 'header' | 'query' | 'domain'\n\n/**\n * Context passed to locale detectors and the `fluenti:detect-locale` hook.\n *\n * Detectors inspect the context and call `setLocale()` to claim a locale.\n * Once a locale is set, subsequent detectors are skipped.\n */\nexport interface LocaleDetectContext {\n /** The request path (e.g. '/ja/about') */\n path: string\n /** Available locale codes */\n locales: string[]\n /** Default locale */\n defaultLocale: string\n /** Routing strategy */\n strategy: Strategy\n /** detectBrowserLanguage config */\n detectBrowserLanguage?: DetectBrowserLanguageOptions\n /** The detected locale so far (null if not yet detected) */\n detectedLocale: string | null\n /** Set the locale and stop the detection chain */\n setLocale: (locale: string) => void\n /** Whether we are running on the server */\n isServer: boolean\n /** The request hostname (available when `strategy: 'domains'`) */\n host?: string\n /** Pre-read cookie value (hoisted before await in plugin) */\n cookieValue?: string | null\n /** Pre-read Accept-Language header (hoisted before await in plugin) */\n acceptLanguage?: string\n}\n\n/**\n * A locale detector function.\n *\n * Can be sync or async. Call `ctx.setLocale(locale)` to claim a locale.\n */\nexport type LocaleDetectorFn = (ctx: LocaleDetectContext) => void | Promise<void>\n\n/**\n * Per-page locale configuration.\n *\n * Restricts which locales a page supports. Routes will only be generated\n * for the specified locales.\n *\n * @example\n * ```ts\n * // In a page component's <script setup>\n * defineI18nRoute({ locales: ['en', 'ja'] }) // only en and ja for this page\n * defineI18nRoute(false) // disable i18n for this page\n * ```\n */\nexport type I18nRouteConfig = { locales: string[] } | false\n\n/** Domain-to-locale mapping for the `'domains'` strategy */\nexport interface DomainConfig {\n /** Domain hostname (e.g. 'example.jp', 'ja.example.com') */\n domain: string\n /** Locale code for this domain */\n locale: string\n /** Whether this is the default domain (used for x-default hreflang) */\n defaultForLocale?: boolean\n}\n\n/** @fluenti/nuxt module options (set in nuxt.config.ts under `fluenti` key) */\nexport interface FluentNuxtOptions {\n /** fluenti.config.ts path or inline config */\n config?: string | FluentiBuildConfig\n\n // ---- Core overrides (take precedence over fluenti.config.ts) ----\n\n /** Override locales from fluenti.config.ts */\n locales?: FluentiBuildConfig['locales']\n /** Override defaultLocale from fluenti.config.ts */\n defaultLocale?: string\n /** Override sourceLocale from fluenti.config.ts */\n sourceLocale?: string\n /** Override catalogDir from fluenti.config.ts */\n catalogDir?: string\n\n // ---- Nuxt-specific: routing, detection, components ----\n\n /** URL routing strategy */\n strategy?: Strategy\n /** Browser language detection settings */\n detectBrowserLanguage?: DetectBrowserLanguageOptions\n /**\n * Ordered list of locale detectors.\n *\n * Each entry is either a built-in detector name ('path', 'cookie', 'header', 'query', 'domain')\n * or a file path to a custom detector module (e.g. '~/detectors/jwt-detector').\n *\n * Detectors run in order; the first one to call `ctx.setLocale()` wins.\n *\n * @default ['path', 'cookie', 'header']\n */\n detectOrder?: Array<BuiltinDetector | string>\n /**\n * Query parameter name for locale detection (e.g. `?lang=ja`).\n *\n * @default 'locale'\n */\n queryParamKey?: string\n /**\n * Prefix for globally registered i18n components (Trans, Plural, Select, DateTime, NumberFormat).\n *\n * Use this to avoid naming conflicts with other libraries.\n *\n * @example 'I18n' // → I18nTrans, I18nPlural, I18nSelect, I18nDateTime, I18nNumberFormat\n * @default '' (no prefix)\n */\n componentPrefix?: string\n /**\n * Automatically register `@fluenti/vite-plugin` in the Vite config.\n *\n * Set to `false` to disable if you configure the Vite plugin manually.\n *\n * @default true\n */\n autoVitePlugin?: boolean\n /**\n * Whether to auto-import composables (useLocalePath, useSwitchLocalePath, useLocaleHead, useI18n).\n *\n * Set to `false` to disable all auto-imports. Useful when migrating from `@nuxtjs/i18n`\n * or when you want explicit imports to avoid naming collisions.\n *\n * @default true\n */\n autoImports?: boolean\n /**\n * Whether to extend routes with locale-prefixed variants.\n *\n * Set to `false` to handle locale routing yourself (e.g., via a custom\n * `pages:extend` hook or Nuxt Layers). When `false`, the module will NOT\n * create locale-suffixed route clones and will NOT remove unprefixed routes.\n *\n * @default true\n */\n extendRoutes?: boolean\n /**\n * Route generation mode for locale variants.\n *\n * - `'all'` (default): All pages get locale route variants unless explicitly\n * opted out via `definePageMeta({ i18n: false })`.\n * - `'opt-in'`: Only pages that explicitly declare `definePageMeta({ i18n: { locales: [...] } })`\n * get locale route variants. Pages without an `i18n` meta field are left untouched.\n *\n * Use `'opt-in'` for large projects where only a subset of pages need i18n routing.\n *\n * @default 'all'\n */\n routeMode?: 'all' | 'opt-in'\n /**\n * Template for generating locale-specific route names.\n *\n * Receives the original route name and locale code, returns the desired name.\n * Only used when `extendRoutes` is not `false`.\n *\n * @default (name, locale) => `${name}___${locale}`\n * @example (name, locale) => `${locale}:${name}`\n */\n routeNameTemplate?: (name: string, locale: string) => string\n /**\n * Custom route paths per locale.\n *\n * Allows different URL slugs for different locales (e.g. `/about` in English\n * becomes `/について` in Japanese).\n *\n * Keys are the original route paths; values are locale-to-path mappings.\n *\n * @example\n * ```ts\n * routeOverrides: {\n * '/about': { ja: '/について', 'zh-CN': '/关于' },\n * '/contact': { ja: '/お問い合わせ' },\n * }\n * ```\n */\n routeOverrides?: Record<string, Record<string, string>>\n /**\n * Whether the locale redirect middleware should be registered globally.\n *\n * Set to `false` to register it as a named middleware instead, so you can\n * apply it only to specific pages via `definePageMeta({ middleware: ['fluenti-locale-redirect'] })`.\n *\n * Only relevant when `strategy` is `'prefix'`.\n *\n * @default true\n */\n globalMiddleware?: boolean\n /**\n * Whether to register the `NuxtLinkLocale` component globally.\n *\n * Set to `false` to disable registration. You can still import it manually\n * from `@fluenti/nuxt/runtime/components/NuxtLinkLocale`.\n *\n * @default true\n */\n registerNuxtLinkLocale?: boolean\n /**\n * Domain-to-locale mappings for the `'domains'` strategy.\n *\n * Each entry maps a domain hostname to a locale. Required when `strategy` is `'domains'`.\n *\n * Can also be specified inline in locale objects via `{ code: 'ja', domain: 'example.jp' }`.\n *\n * @example\n * ```ts\n * domains: [\n * { domain: 'example.com', locale: 'en', defaultForLocale: true },\n * { domain: 'example.jp', locale: 'ja' },\n * ]\n * ```\n */\n domains?: DomainConfig[]\n /**\n * Incremental Static Regeneration (ISR) settings.\n *\n * When enabled, the module automatically generates `routeRules` with\n * ISR caching for all locale route patterns.\n */\n isr?: ISROptions\n /** Enable @fluenti/vue-i18n-compat bridge mode */\n compat?: boolean\n /**\n * Whether to inject `$localePath` onto `app.config.globalProperties`.\n *\n * Set to `false` if another plugin (e.g. `@nuxtjs/i18n`) already provides `$localePath`,\n * or when using composition API exclusively.\n *\n * @default true\n */\n injectGlobalProperties?: boolean\n /**\n * Callback fired when a translation key is missing from the catalog.\n *\n * Useful for logging, error tracking, or providing dynamic fallbacks.\n */\n onMissingTranslation?: (locale: string, id: string) => string | undefined\n /**\n * Structured error handler for i18n errors.\n */\n onError?: I18nErrorHandler\n /**\n * Generate fallback text when a translation is missing or errors.\n */\n getMessageFallback?: MessageFallbackHandler\n}\n\n/** Structured i18n error types */\nexport type I18nErrorCode = 'MISSING_MESSAGE' | 'MISSING_LOCALE' | 'FORMAT_ERROR' | 'LOAD_ERROR'\n\n/** Structured error passed to the onError callback */\nexport interface I18nError {\n /** Error classification */\n code: I18nErrorCode\n /** Human-readable error message */\n message: string\n /** The message key that caused the error */\n key?: string\n /** The locale that caused the error */\n locale?: string\n /** The original error (if wrapping a lower-level error) */\n cause?: unknown\n}\n\n/** Callback for structured i18n error handling */\nexport type I18nErrorHandler = (error: I18nError) => void\n\n/**\n * Callback to generate fallback text when a translation is missing or errors.\n *\n * Return a string to use as the fallback, or `undefined` for default behavior\n * (which shows the message key).\n */\nexport type MessageFallbackHandler = (error: I18nError) => string | undefined\n\n/** ISR configuration */\nexport interface ISROptions {\n /** Enable ISR route rules generation */\n enabled: boolean\n /** Cache TTL in seconds (default: 3600 — 1 hour) */\n ttl?: number\n}\n\n/** Runtime config injected into Nuxt's public runtimeConfig */\nexport interface FluentNuxtRuntimeConfig {\n locales: string[]\n defaultLocale: string\n strategy: Strategy\n detectBrowserLanguage?: DetectBrowserLanguageOptions\n /** Ordered list of detector names/paths */\n detectOrder: Array<string>\n /** Query parameter name for locale detection */\n queryParamKey: string\n /** Whether to inject $localePath onto globalProperties */\n injectGlobalProperties: boolean\n /** Domain-to-locale mappings (when strategy is 'domains') */\n domains?: DomainConfig[]\n /** Locale metadata (iso tags, dir, names) — keyed by locale code */\n localeProperties?: Record<string, LocaleObject>\n}\n\n// ---- Utility helpers ----\n\n/** Build a locale properties map from LocaleDefinition[] */\nexport function resolveLocaleProperties(locales: LocaleDefinition[]): Record<string, LocaleObject> {\n const map: Record<string, LocaleObject> = {}\n for (const l of locales) {\n if (typeof l === 'string') {\n map[l] = { code: l }\n } else {\n map[l.code] = l\n }\n }\n return map\n}\n\n/** Build domain configs from locale objects that have a `domain` field */\nexport function resolveDomainConfigs(\n locales: LocaleDefinition[],\n explicit?: DomainConfig[],\n): DomainConfig[] {\n if (explicit?.length) return explicit\n const configs: DomainConfig[] = []\n for (const l of locales) {\n if (typeof l !== 'string' && l.domain) {\n configs.push({ domain: l.domain, locale: l.code })\n }\n }\n return configs\n}\n","import type { FluentNuxtOptions, Strategy } from './types'\n\nexport interface ISRWarning {\n level: 'warn' | 'error'\n message: string\n}\n\n/**\n * Validate ISR configuration against locale detection settings.\n *\n * ISR caches responses by URL path. If locale detection relies on\n * non-path signals (cookies, headers), the cached response may serve\n * the wrong locale to subsequent visitors.\n */\nexport function validateISRConfig(\n isr: FluentNuxtOptions['isr'],\n strategy: Strategy,\n detectOrder: string[],\n): ISRWarning[] {\n const warnings: ISRWarning[] = []\n if (!isr?.enabled) return warnings\n\n const nonPathDetectors = detectOrder.filter(\n (d) => d === 'cookie' || d === 'header',\n )\n if (nonPathDetectors.length > 0) {\n warnings.push({\n level: 'warn',\n message:\n `[@fluenti/nuxt] ISR is enabled but detectOrder includes non-path ` +\n `detectors (${nonPathDetectors.join(', ')}). ISR caches by URL path, ` +\n `so cookie/header-based detection may serve the wrong locale from ` +\n `cache. Consider using detectOrder: ['path'] with ISR.`,\n })\n }\n\n if (strategy === 'no_prefix') {\n warnings.push({\n level: 'warn',\n message:\n `[@fluenti/nuxt] ISR is enabled with strategy: 'no_prefix'. All ` +\n `locales share the same URL path, so ISR will cache only one locale ` +\n `per URL. Use 'prefix' or 'prefix_except_default' strategy with ISR.`,\n })\n }\n\n return warnings\n}\n","import type { Nuxt } from '@nuxt/schema'\n\n/**\n * DevTools state exposed to the custom tab.\n * Serialized to JSON and sent to the DevTools panel.\n */\nexport interface DevToolsI18nState {\n currentLocale: string\n availableLocales: string[]\n defaultLocale: string\n strategy: string\n detectedBy: string\n messageCount: number\n loadedLocales: string[]\n missingKeys: string[]\n}\n\n/**\n * Register a Nuxt DevTools custom tab for Fluenti.\n *\n * Shows: current locale, available locales, detection chain result,\n * loaded message count, and missing translation keys.\n */\nexport function setupDevTools(nuxt: Nuxt, localeCodes: string[], defaultLocale: string, strategy: string): void {\n try {\n // Attempt to use @nuxt/devtools-kit if available\n // @ts-expect-error — devtools:customTabs hook is provided by @nuxt/devtools\n nuxt.hook('devtools:customTabs', (tabs: unknown[]) => {\n tabs.push({\n name: 'fluenti',\n title: 'Fluenti i18n',\n icon: 'i-carbon-translate',\n view: {\n type: 'client-component',\n componentName: 'FluentiDevToolsPanel',\n },\n })\n })\n } catch {\n // DevTools not available — silently skip\n }\n\n // Inject DevTools client component via virtual module\n // @ts-expect-error — nitro:config hook is provided by Nitro\n nuxt.hook('nitro:config', (nitroConfig: Record<string, unknown>) => {\n const publicConfig = nitroConfig['runtimeConfig'] as Record<string, unknown> | undefined\n if (publicConfig) {\n const pub = (publicConfig['public'] ?? (publicConfig['public'] = {})) as Record<string, unknown>\n const fluentiConfig = (pub['fluenti'] ?? {}) as Record<string, unknown>\n fluentiConfig['devtools'] = {\n enabled: true,\n locales: localeCodes,\n defaultLocale,\n strategy,\n }\n }\n })\n}\n\n/**\n * Client-side DevTools panel component source.\n *\n * This is injected as a virtual module and rendered inside the\n * Nuxt DevTools panel. It reads the Fluenti runtime state and\n * displays it in a simple, readable format.\n */\nexport const DEVTOOLS_PANEL_COMPONENT = `\n<template>\n <div style=\"padding: 16px; font-family: system-ui, sans-serif;\">\n <h2 style=\"margin: 0 0 16px; font-size: 18px;\">🌐 Fluenti i18n</h2>\n\n <div style=\"display: grid; grid-template-columns: 140px 1fr; gap: 8px 16px; font-size: 14px;\">\n <span style=\"color: #888;\">Current locale:</span>\n <strong>{{ state.currentLocale }}</strong>\n\n <span style=\"color: #888;\">Default locale:</span>\n <span>{{ state.defaultLocale }}</span>\n\n <span style=\"color: #888;\">Strategy:</span>\n <span>{{ state.strategy }}</span>\n\n <span style=\"color: #888;\">Available:</span>\n <span>{{ state.availableLocales.join(', ') }}</span>\n\n <span style=\"color: #888;\">Loaded:</span>\n <span>{{ state.loadedLocales.join(', ') || 'none' }}</span>\n\n <span style=\"color: #888;\">Messages:</span>\n <span>{{ state.messageCount }}</span>\n\n <span style=\"color: #888;\">Missing keys:</span>\n <span :style=\"{ color: state.missingKeys.length > 0 ? '#e53e3e' : '#38a169' }\">\n {{ state.missingKeys.length > 0 ? state.missingKeys.length + ' missing' : 'All translated ✓' }}\n </span>\n </div>\n\n <div v-if=\"state.missingKeys.length > 0\" style=\"margin-top: 16px;\">\n <h3 style=\"margin: 0 0 8px; font-size: 14px; color: #e53e3e;\">Missing translations:</h3>\n <ul style=\"margin: 0; padding: 0 0 0 20px; font-size: 13px; font-family: monospace;\">\n <li v-for=\"key in state.missingKeys\" :key=\"key\" style=\"margin: 2px 0;\">{{ key }}</li>\n </ul>\n </div>\n </div>\n</template>\n\n<script setup>\nimport { ref, onMounted } from 'vue'\n\nconst state = ref({\n currentLocale: '',\n defaultLocale: '',\n strategy: '',\n availableLocales: [],\n loadedLocales: [],\n messageCount: 0,\n missingKeys: [],\n})\n\nonMounted(() => {\n try {\n const nuxtApp = window.__NUXT_DEVTOOLS_VIEW__?.nuxtApp ?? useNuxtApp()\n const config = nuxtApp.$config?.public?.fluenti ?? {}\n const fluentiLocale = nuxtApp.$fluentiLocale ?? ref('')\n\n state.value = {\n currentLocale: fluentiLocale.value || config.defaultLocale || '',\n defaultLocale: config.defaultLocale || '',\n strategy: config.strategy || '',\n availableLocales: config.locales || [],\n loadedLocales: [],\n messageCount: 0,\n missingKeys: [],\n }\n } catch (e) {\n // DevTools context not available\n }\n})\n</script>\n`\n","import type { Plugin } from 'vite'\n\n/**\n * Vite plugin that transforms `definePageMeta({ i18n: ... })` into\n * the internal `i18nRoute` format used by the page extension system.\n *\n * This allows users to use native Nuxt `definePageMeta` with an `i18n` key\n * instead of the separate `defineI18nRoute()` macro.\n *\n * Supports:\n * - `definePageMeta({ i18n: { locales: ['en', 'ja'] } })`\n * - `definePageMeta({ i18n: false })`\n *\n * The transform also rewrites `defineI18nRoute(...)` to\n * `definePageMeta({ i18nRoute: ... })` for backwards compatibility.\n */\nexport function createPageMetaTransform(): Plugin {\n return {\n name: 'fluenti:page-meta-transform',\n enforce: 'pre',\n\n transform(code, id) {\n // Only transform Vue SFC script blocks and TS/JS files in pages/\n if (!id.includes('/pages/') && !id.includes('\\\\pages\\\\')) return null\n if (!code.includes('defineI18nRoute') && !code.includes('i18n')) return null\n\n let transformed = code\n\n // Transform: defineI18nRoute({ locales: [...] })\n // → definePageMeta({ i18nRoute: { locales: [...] } })\n // Transform: defineI18nRoute(false)\n // → definePageMeta({ i18nRoute: false })\n const defineI18nRouteRegex = /defineI18nRoute\\s*\\(([^)]+)\\)/g\n if (defineI18nRouteRegex.test(transformed)) {\n transformed = transformed.replace(\n /defineI18nRoute\\s*\\(([^)]+)\\)/g,\n (_match, arg: string) => `definePageMeta({ i18nRoute: ${arg.trim()} })`,\n )\n }\n\n // Support native: definePageMeta({ i18n: { locales: [...] } })\n // Rewrite `i18n:` key to `i18nRoute:` so page-extend can read it\n if (transformed.includes('definePageMeta') && transformed.includes('i18n:')) {\n // Simple regex for { i18n: ... } within definePageMeta\n // This handles the common case; complex nested objects may need\n // AST-based transformation in the future.\n transformed = transformed.replace(\n /(definePageMeta\\s*\\(\\s*\\{[^}]*)\\bi18n\\s*:/g,\n '$1i18nRoute:',\n )\n }\n\n if (transformed === code) return null\n\n return {\n code: transformed,\n map: null,\n }\n },\n }\n}\n","import type { Strategy } from './types'\n\nexport interface SitemapUrl {\n loc: string\n alternatives?: Array<{ hreflang: string; href: string }>\n}\n\n/**\n * Generate multi-locale sitemap URLs from a list of base paths.\n *\n * For each base path, produces a URL entry with hreflang alternatives\n * pointing to every locale variant. Compatible with `@nuxtjs/sitemap`'s\n * `sources` hook format.\n */\nexport function generateSitemapUrls(\n paths: string[],\n locales: string[],\n defaultLocale: string,\n strategy: Strategy,\n baseUrl?: string,\n): SitemapUrl[] {\n const urls: SitemapUrl[] = []\n const base = baseUrl ?? ''\n\n for (const rawPath of paths) {\n const path = rawPath.startsWith('/') ? rawPath : `/${rawPath}`\n\n for (const locale of locales) {\n const localizedPath = buildLocalePath(path, locale, defaultLocale, strategy)\n\n const alternatives = locales.map((altLocale) => ({\n hreflang: altLocale,\n href: `${base}${buildLocalePath(path, altLocale, defaultLocale, strategy)}`,\n }))\n\n // Add x-default pointing to default locale\n alternatives.push({\n hreflang: 'x-default',\n href: `${base}${buildLocalePath(path, defaultLocale, defaultLocale, strategy)}`,\n })\n\n urls.push({\n loc: `${base}${localizedPath}`,\n alternatives,\n })\n }\n }\n\n return urls\n}\n\nfunction buildLocalePath(\n path: string,\n locale: string,\n defaultLocale: string,\n strategy: Strategy,\n): string {\n if (strategy === 'no_prefix') return path\n\n if (strategy === 'prefix_except_default' && locale === defaultLocale) {\n return path\n }\n\n const cleanPath = path === '/' ? '' : path\n return `/${locale}${cleanPath}`\n}\n\n/**\n * Hook handler for `@nuxtjs/sitemap`'s `sitemap:generate` hook.\n *\n * Transforms single-locale URLs into multi-locale entries with hreflang.\n * Register this in your nuxt.config.ts or let the module auto-register it.\n */\nexport function createSitemapHook(\n locales: string[],\n defaultLocale: string,\n strategy: Strategy,\n baseUrl?: string,\n) {\n return (urls: SitemapUrl[]) => {\n if (strategy === 'no_prefix') return urls\n\n const expanded: SitemapUrl[] = []\n\n for (const url of urls) {\n const loc = url.loc.replace(/^https?:\\/\\/[^/]+/, '')\n\n for (const locale of locales) {\n const localizedPath = buildLocalePath(loc, locale, defaultLocale, strategy)\n const alternatives = locales.map((altLocale) => ({\n hreflang: altLocale,\n href: `${baseUrl ?? ''}${buildLocalePath(loc, altLocale, defaultLocale, strategy)}`,\n }))\n alternatives.push({\n hreflang: 'x-default',\n href: `${baseUrl ?? ''}${buildLocalePath(loc, defaultLocale, defaultLocale, strategy)}`,\n })\n\n expanded.push({\n loc: `${baseUrl ?? ''}${localizedPath}`,\n alternatives,\n })\n }\n }\n\n return expanded\n }\n}\n","import { defineNuxtModule, addPlugin, addImports, addComponent, addRouteMiddleware, addServerHandler, createResolver } from '@nuxt/kit'\nimport type { FluentNuxtOptions } from './types'\nimport { resolveLocaleProperties, resolveDomainConfigs } from './types'\nimport { resolveLocaleCodes } from '@fluenti/core/internal'\nimport type { FluentiBuildConfig } from '@fluenti/core/internal'\nimport fluentiVue from '@fluenti/vue/vite-plugin'\nimport { extendPages } from './runtime/page-extend'\nimport { validateISRConfig } from './isr-validation'\nimport { setupDevTools } from './devtools'\nimport { createPageMetaTransform } from './page-meta-transform'\n\nexport type { FluentNuxtOptions, Strategy, FluentNuxtRuntimeConfig, DetectBrowserLanguageOptions, LocaleDetectContext, LocaleDetectorFn, BuiltinDetector, ISROptions, LocaleObject, LocaleDefinition, DomainConfig, I18nRouteConfig, I18nError, I18nErrorCode, I18nErrorHandler, MessageFallbackHandler } from './types'\nexport { generateSitemapUrls, createSitemapHook } from './sitemap'\nexport type { SitemapUrl } from './sitemap'\nexport { resolveLocaleProperties, resolveDomainConfigs } from './types'\nexport { resolveLocaleCodes } from '@fluenti/core/internal'\nexport { localePath, extractLocaleFromPath, switchLocalePath } from './runtime/path-utils'\nexport { extendPages } from './runtime/page-extend'\nexport type { PageRoute, RouteNameTemplate, ExtendPagesOptions } from './runtime/page-extend'\nexport { buildLocaleHead } from './runtime/locale-head'\nexport type { LocaleHeadMeta, LocaleHeadOptions } from './runtime/locale-head'\nexport { useLocalePath, useSwitchLocalePath, useLocaleRoute, useLocaleHead } from './runtime/standalone-composables'\nexport { defineI18nRoute } from './runtime/define-i18n-route'\n\nexport const MODULE_NAME = '@fluenti/nuxt'\nexport const CONFIG_KEY = 'fluenti'\n\n/**\n * Resolve the FluentiBuildConfig from the module options.\n */\nfunction resolveFluentiBuildConfig(configOption: string | FluentiBuildConfig | undefined, rootDir: string): FluentiBuildConfig {\n if (typeof configOption === 'object') {\n // Inline config — merge with defaults\n try {\n const { DEFAULT_FLUENTI_CONFIG } = require('@fluenti/core/config') as {\n DEFAULT_FLUENTI_CONFIG: FluentiBuildConfig\n }\n return { ...DEFAULT_FLUENTI_CONFIG, ...configOption }\n } catch {\n return configOption as FluentiBuildConfig\n }\n }\n\n // string → specified path; undefined → auto-discover\n try {\n const { loadConfigSync } = require('@fluenti/core/config') as {\n loadConfigSync: (configPath?: string, cwd?: string) => FluentiBuildConfig\n }\n return loadConfigSync(\n typeof configOption === 'string' ? configOption : undefined,\n rootDir,\n )\n } catch {\n // @fluenti/core not available — return minimal defaults\n return {\n sourceLocale: 'en',\n locales: ['en'],\n catalogDir: './locales',\n format: 'po',\n include: ['./src/**/*.{vue,tsx,jsx,ts,js}'],\n compileOutDir: './src/locales/compiled',\n }\n }\n}\n\nexport default defineNuxtModule<FluentNuxtOptions>({\n meta: {\n name: MODULE_NAME,\n configKey: CONFIG_KEY,\n compatibility: { nuxt: '>=3.0.0' },\n },\n defaults: {\n strategy: 'prefix_except_default',\n },\n setup(options, nuxt) {\n const { resolve } = createResolver(import.meta.url)\n\n // --- Resolve FluentiBuildConfig from options.config, then overlay module-level options ---\n const rootDir = nuxt.options.rootDir ?? process.cwd()\n const fluentiConfig = resolveFluentiBuildConfig(options.config, rootDir)\n\n // Module-level options (e.g. nuxt.config.ts `fluenti.locales`) override the\n // resolved fluenti.config.ts values — this ensures Nuxt-specific config takes\n // precedence even when config file loading fails (e.g. CJS/jiti issues).\n if (options.locales) fluentiConfig.locales = options.locales\n if (options.defaultLocale) fluentiConfig.defaultLocale = options.defaultLocale\n if (options.sourceLocale) fluentiConfig.sourceLocale = options.sourceLocale\n if (options.catalogDir) fluentiConfig.catalogDir = options.catalogDir\n\n // --- Resolve locale codes and metadata ---\n const localeCodes = resolveLocaleCodes(fluentiConfig.locales)\n const localeProperties = resolveLocaleProperties(fluentiConfig.locales)\n const defaultLocale = fluentiConfig.defaultLocale ?? fluentiConfig.sourceLocale\n const domainConfigs = options.strategy === 'domains'\n ? resolveDomainConfigs(fluentiConfig.locales, options.domains)\n : undefined\n\n // --- Inject runtime config ---\n const detectOrder = options.detectOrder ?? (\n options.strategy === 'domains'\n ? ['domain', 'cookie', 'header']\n : ['path', 'cookie', 'header']\n )\n nuxt.options.runtimeConfig.public['fluenti'] = {\n locales: localeCodes,\n defaultLocale,\n strategy: options.strategy ?? 'prefix_except_default',\n detectBrowserLanguage: options.detectBrowserLanguage,\n detectOrder,\n queryParamKey: options.queryParamKey ?? 'locale',\n injectGlobalProperties: options.injectGlobalProperties !== false,\n ...(domainConfigs ? { domains: domainConfigs } : {}),\n localeProperties,\n }\n\n // --- Auto-register @fluenti/vue vite plugin (includes v-t transform + scope transform) ---\n if (options.autoVitePlugin !== false) {\n nuxt.options.vite = nuxt.options.vite || {}\n nuxt.options.vite.plugins = nuxt.options.vite.plugins || []\n ;(nuxt.options.vite.plugins as unknown[]).push(\n ...fluentiVue({ config: fluentiConfig }),\n )\n }\n\n // --- Register definePageMeta({ i18n }) transform ---\n nuxt.options.vite = nuxt.options.vite || {}\n nuxt.options.vite.plugins = nuxt.options.vite.plugins || []\n ;(nuxt.options.vite.plugins as unknown[]).push(createPageMetaTransform())\n\n // --- Register runtime plugin ---\n addPlugin({\n src: resolve('./runtime/plugin'),\n mode: 'all',\n })\n\n // --- Extend routes with locale prefixes ---\n const strategy = options.strategy ?? 'prefix_except_default'\n if (strategy !== 'no_prefix' && strategy !== 'domains' && options.extendRoutes !== false) {\n nuxt.hook('pages:extend', (pages) => {\n extendPages(pages, {\n locales: localeCodes,\n defaultLocale,\n strategy,\n ...(options.routeNameTemplate ? { routeNameTemplate: options.routeNameTemplate } : {}),\n ...(options.routeOverrides ? { routeOverrides: options.routeOverrides } : {}),\n ...(options.routeMode ? { routeMode: options.routeMode } : {}),\n })\n })\n }\n\n // --- Register locale redirect middleware ---\n if (strategy === 'prefix') {\n addRouteMiddleware({\n name: 'fluenti-locale-redirect',\n path: resolve('./runtime/middleware/locale-redirect'),\n global: options.globalMiddleware !== false,\n })\n }\n\n // --- Auto-import composables ---\n if (options.autoImports !== false) {\n addImports([\n { name: 'useLocalePath', from: resolve('./runtime/composables') },\n { name: 'useSwitchLocalePath', from: resolve('./runtime/composables') },\n { name: 'useLocaleRoute', from: resolve('./runtime/composables') },\n { name: 'useLocaleHead', from: resolve('./runtime/composables') },\n { name: 'useI18nScoped', from: resolve('./runtime/composables') },\n { name: 'useI18n', from: '@fluenti/vue' },\n { name: 'defineI18nRoute', from: resolve('./runtime/define-i18n-route') },\n ])\n }\n\n // --- Register components (including DateTime + NumberFormat) ---\n const prefix = options.componentPrefix ?? ''\n if (options.registerNuxtLinkLocale !== false) {\n addComponent({\n name: `${prefix}NuxtLinkLocale`,\n filePath: resolve('./runtime/components/NuxtLinkLocale'),\n })\n }\n\n // Auto-import DateTime and NumberFormat from @fluenti/vue\n addComponent({ name: `${prefix}Trans`, filePath: '@fluenti/vue', export: 'Trans' })\n addComponent({ name: `${prefix}Plural`, filePath: '@fluenti/vue', export: 'Plural' })\n addComponent({ name: `${prefix}Select`, filePath: '@fluenti/vue', export: 'Select' })\n addComponent({ name: `${prefix}DateTime`, filePath: '@fluenti/vue', export: 'DateTime' })\n addComponent({ name: `${prefix}NumberFormat`, filePath: '@fluenti/vue', export: 'NumberFormat' })\n\n // --- SSG / ISR: configure nitro prerender and route rules ---\n if (strategy !== 'no_prefix' && strategy !== 'domains') {\n const nuxtOpts = nuxt.options as unknown as Record<string, unknown>\n\n // Enable link crawling so locale-prefixed routes are discovered during prerender\n const nitroOpts = (nuxtOpts['nitro'] ?? (nuxtOpts['nitro'] = {})) as Record<string, unknown>\n const prerender = (nitroOpts['prerender'] ?? (nitroOpts['prerender'] = {})) as Record<string, unknown>\n prerender['crawlLinks'] = prerender['crawlLinks'] ?? true\n\n // For 'prefix' strategy, / has no matching route (all routes are\n // locale-prefixed). Replace the default / initial route with\n // /<defaultLocale> so the prerenderer starts from a valid route.\n if (strategy === 'prefix') {\n const routes = (prerender['routes'] ?? ['/']) as string[]\n prerender['routes'] = routes.map((r) =>\n r === '/' ? `/${defaultLocale}` : r,\n )\n }\n\n // ISR: validate configuration and generate routeRules\n for (const w of validateISRConfig(options.isr, strategy, detectOrder)) {\n console.warn(w.message)\n }\n if (options.isr?.enabled) {\n const routeRules = (nuxtOpts['routeRules'] ?? (nuxtOpts['routeRules'] = {})) as Record<string, Record<string, unknown>>\n const ttl = options.isr.ttl ?? 3600\n for (const locale of localeCodes) {\n if (locale === defaultLocale && strategy === 'prefix_except_default') {\n routeRules['/**'] = { ...routeRules['/**'], isr: ttl }\n } else {\n routeRules[`/${locale}/**`] = { ...routeRules[`/${locale}/**`], isr: ttl }\n }\n }\n }\n }\n\n // --- Nuxt DevTools integration ---\n if (nuxt.options.dev) {\n setupDevTools(nuxt, localeCodes, defaultLocale, strategy)\n }\n\n // --- Nitro server handler for locale redirect (T2-10) ---\n if (strategy === 'prefix' || strategy === 'prefix_and_default') {\n addServerHandler({\n handler: resolve('./runtime/server/locale-redirect'),\n middleware: true,\n })\n }\n },\n})\n"],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
//#region src/runtime/page-extend.ts
|
|
2
|
+
var e = (e, t) => `${e}___${t}`;
|
|
3
|
+
function t(t, r) {
|
|
4
|
+
let { locales: i, defaultLocale: a, strategy: o, routeOverrides: s } = r, c = r.routeMode ?? "all";
|
|
5
|
+
if (o === "no_prefix" || o === "domains") return;
|
|
6
|
+
let l = r.routeNameTemplate ?? e, u = [...t], d = (e, t) => {
|
|
7
|
+
let n = e.meta?.i18nRoute;
|
|
8
|
+
return c === "opt-in" && n === void 0 || n === !1 ? !1 : n && n.locales ? n.locales.includes(t) : !0;
|
|
9
|
+
};
|
|
10
|
+
for (let e of i) if (!(o === "prefix_except_default" && e === a)) for (let r of u) {
|
|
11
|
+
if (!d(r, e)) continue;
|
|
12
|
+
let i = n(r, e, l, s);
|
|
13
|
+
t.push(i);
|
|
14
|
+
}
|
|
15
|
+
if (o === "prefix" && t.splice(0, u.length), o === "prefix_except_default") for (let e = t.length - 1; e >= 0; e--) {
|
|
16
|
+
let n = t[e];
|
|
17
|
+
u.includes(n) && !d(n, a) && t.splice(e, 1);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function n(e, t, n, r) {
|
|
21
|
+
let i = r?.[e.path]?.[t] ?? e.path, a = {
|
|
22
|
+
...e,
|
|
23
|
+
path: `/${t}${i === "/" ? "" : i}`
|
|
24
|
+
};
|
|
25
|
+
return e.name && (a.name = n(e.name, t)), e.children && (a.children = e.children.map((e) => {
|
|
26
|
+
let i = r?.[e.path]?.[t], a = {
|
|
27
|
+
...e,
|
|
28
|
+
...i ? { path: i } : {}
|
|
29
|
+
};
|
|
30
|
+
return e.name && (a.name = n(e.name, t)), a;
|
|
31
|
+
})), a;
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
export { t };
|
|
35
|
+
|
|
36
|
+
//# sourceMappingURL=page-extend-BrPO2RhM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-extend-BrPO2RhM.js","names":[],"sources":["../src/runtime/page-extend.ts"],"sourcesContent":["import type { Strategy } from '../types'\n\n/** Page route definition used for route extension */\nexport interface PageRoute {\n path: string\n name?: string\n children?: PageRoute[]\n meta?: Record<string, unknown>\n}\n\n/** Route name template: (originalName, locale) => newName */\nexport type RouteNameTemplate = (name: string, locale: string) => string\n\nconst DEFAULT_ROUTE_NAME_TEMPLATE: RouteNameTemplate = (name, locale) =>\n `${name}___${locale}`\n\nexport interface ExtendPagesOptions {\n locales: string[]\n defaultLocale: string\n strategy: Strategy\n routeNameTemplate?: RouteNameTemplate\n /**\n * Custom route paths per locale.\n * Keys are original route paths; values map locale → custom path.\n */\n routeOverrides?: Record<string, Record<string, string>>\n /**\n * Route generation mode.\n * - `'all'` (default): All pages get locale variants unless opted out via `i18nRoute: false`.\n * - `'opt-in'`: Only pages with explicit `i18nRoute` meta get locale variants.\n */\n routeMode?: 'all' | 'opt-in'\n}\n\n/**\n * Extend page routes with locale-prefixed variants.\n * Mutates the pages array in place (Nuxt convention).\n *\n * This is a build-time utility used in the module's `pages:extend` hook.\n */\nexport function extendPages(\n pages: PageRoute[],\n options: ExtendPagesOptions,\n): void {\n const { locales, defaultLocale, strategy, routeOverrides } = options\n const routeMode = options.routeMode ?? 'all'\n if (strategy === 'no_prefix' || strategy === 'domains') return\n\n const nameTemplate = options.routeNameTemplate ?? DEFAULT_ROUTE_NAME_TEMPLATE\n const originalPages = [...pages]\n\n // Filter out pages that have i18nRoute === false in their meta\n const isPageEnabled = (page: PageRoute, locale: string): boolean => {\n const i18nRoute = page.meta?.['i18nRoute'] as { locales?: string[] } | false | undefined\n\n // opt-in mode: pages without any i18nRoute meta are not extended\n if (routeMode === 'opt-in' && i18nRoute === undefined) return false\n\n if (i18nRoute === false) return false\n if (i18nRoute && i18nRoute.locales) {\n return i18nRoute.locales.includes(locale)\n }\n return true\n }\n\n for (const locale of locales) {\n // For prefix_except_default, skip creating prefixed routes for the default locale\n if (strategy === 'prefix_except_default' && locale === defaultLocale) continue\n\n for (const page of originalPages) {\n if (!isPageEnabled(page, locale)) continue\n const prefixedPage = prefixPage(page, locale, nameTemplate, routeOverrides)\n pages.push(prefixedPage)\n }\n }\n\n // For prefix strategy, remove the original unprefixed routes\n // (every locale including default must have a prefix)\n if (strategy === 'prefix') {\n // Remove all original pages (they'll only exist as prefixed versions)\n pages.splice(0, originalPages.length)\n }\n\n // For prefix_except_default, filter out pages disabled for the default locale\n if (strategy === 'prefix_except_default') {\n for (let i = pages.length - 1; i >= 0; i--) {\n const page = pages[i]!\n // Only check original (unprefixed) pages\n if (originalPages.includes(page) && !isPageEnabled(page, defaultLocale)) {\n pages.splice(i, 1)\n }\n }\n }\n}\n\nfunction prefixPage(\n page: PageRoute,\n locale: string,\n nameTemplate: RouteNameTemplate,\n routeOverrides?: Record<string, Record<string, string>>,\n): PageRoute {\n // Check if there's a custom path for this locale\n const overridePath = routeOverrides?.[page.path]?.[locale]\n const basePath = overridePath ?? page.path\n\n const prefixed: PageRoute = {\n ...page,\n path: `/${locale}${basePath === '/' ? '' : basePath}`,\n }\n if (page.name) {\n prefixed.name = nameTemplate(page.name, locale)\n }\n\n if (page.children) {\n prefixed.children = page.children.map((child) => {\n const childOverride = routeOverrides?.[child.path]?.[locale]\n const prefixedChild: PageRoute = {\n ...child,\n ...(childOverride ? { path: childOverride } : {}),\n }\n if (child.name) {\n prefixedChild.name = nameTemplate(child.name, locale)\n }\n return prefixedChild\n })\n }\n\n return prefixed\n}\n"],"mappings":";AAaA,IAAM,KAAkD,GAAM,MAC5D,GAAG,EAAK,KAAK;AA0Bf,SAAgB,EACd,GACA,GACM;CACN,IAAM,EAAE,YAAS,kBAAe,aAAU,sBAAmB,GACvD,IAAY,EAAQ,aAAa;AACvC,KAAI,MAAa,eAAe,MAAa,UAAW;CAExD,IAAM,IAAe,EAAQ,qBAAqB,GAC5C,IAAgB,CAAC,GAAG,EAAM,EAG1B,KAAiB,GAAiB,MAA4B;EAClE,IAAM,IAAY,EAAK,MAAO;AAS9B,SANI,MAAc,YAAY,MAAc,KAAA,KAExC,MAAc,KAAc,KAC5B,KAAa,EAAU,UAClB,EAAU,QAAQ,SAAS,EAAO,GAEpC;;AAGT,MAAK,IAAM,KAAU,EAEf,aAAa,2BAA2B,MAAW,GAEvD,MAAK,IAAM,KAAQ,GAAe;AAChC,MAAI,CAAC,EAAc,GAAM,EAAO,CAAE;EAClC,IAAM,IAAe,EAAW,GAAM,GAAQ,GAAc,EAAe;AAC3E,IAAM,KAAK,EAAa;;AAY5B,KANI,MAAa,YAEf,EAAM,OAAO,GAAG,EAAc,OAAO,EAInC,MAAa,wBACf,MAAK,IAAI,IAAI,EAAM,SAAS,GAAG,KAAK,GAAG,KAAK;EAC1C,IAAM,IAAO,EAAM;AAEnB,EAAI,EAAc,SAAS,EAAK,IAAI,CAAC,EAAc,GAAM,EAAc,IACrE,EAAM,OAAO,GAAG,EAAE;;;AAM1B,SAAS,EACP,GACA,GACA,GACA,GACW;CAGX,IAAM,IADe,IAAiB,EAAK,QAAQ,MAClB,EAAK,MAEhC,IAAsB;EAC1B,GAAG;EACH,MAAM,IAAI,IAAS,MAAa,MAAM,KAAK;EAC5C;AAmBD,QAlBI,EAAK,SACP,EAAS,OAAO,EAAa,EAAK,MAAM,EAAO,GAG7C,EAAK,aACP,EAAS,WAAW,EAAK,SAAS,KAAK,MAAU;EAC/C,IAAM,IAAgB,IAAiB,EAAM,QAAQ,IAC/C,IAA2B;GAC/B,GAAG;GACH,GAAI,IAAgB,EAAE,MAAM,GAAe,GAAG,EAAE;GACjD;AAID,SAHI,EAAM,SACR,EAAc,OAAO,EAAa,EAAM,MAAM,EAAO,GAEhD;GACP,GAGG"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var e=(e,t)=>`${e}___${t}`;function t(t,r){let{locales:i,defaultLocale:a,strategy:o,routeOverrides:s}=r,c=r.routeMode??`all`;if(o===`no_prefix`||o===`domains`)return;let l=r.routeNameTemplate??e,u=[...t],d=(e,t)=>{let n=e.meta?.i18nRoute;return c===`opt-in`&&n===void 0||n===!1?!1:n&&n.locales?n.locales.includes(t):!0};for(let e of i)if(!(o===`prefix_except_default`&&e===a))for(let r of u){if(!d(r,e))continue;let i=n(r,e,l,s);t.push(i)}if(o===`prefix`&&t.splice(0,u.length),o===`prefix_except_default`)for(let e=t.length-1;e>=0;e--){let n=t[e];u.includes(n)&&!d(n,a)&&t.splice(e,1)}}function n(e,t,n,r){let i=r?.[e.path]?.[t]??e.path,a={...e,path:`/${t}${i===`/`?``:i}`};return e.name&&(a.name=n(e.name,t)),e.children&&(a.children=e.children.map(e=>{let i=r?.[e.path]?.[t],a={...e,...i?{path:i}:{}};return e.name&&(a.name=n(e.name,t)),a})),a}Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return t}});
|
|
2
|
+
//# sourceMappingURL=page-extend-tRXsujtK.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-extend-tRXsujtK.cjs","names":[],"sources":["../src/runtime/page-extend.ts"],"sourcesContent":["import type { Strategy } from '../types'\n\n/** Page route definition used for route extension */\nexport interface PageRoute {\n path: string\n name?: string\n children?: PageRoute[]\n meta?: Record<string, unknown>\n}\n\n/** Route name template: (originalName, locale) => newName */\nexport type RouteNameTemplate = (name: string, locale: string) => string\n\nconst DEFAULT_ROUTE_NAME_TEMPLATE: RouteNameTemplate = (name, locale) =>\n `${name}___${locale}`\n\nexport interface ExtendPagesOptions {\n locales: string[]\n defaultLocale: string\n strategy: Strategy\n routeNameTemplate?: RouteNameTemplate\n /**\n * Custom route paths per locale.\n * Keys are original route paths; values map locale → custom path.\n */\n routeOverrides?: Record<string, Record<string, string>>\n /**\n * Route generation mode.\n * - `'all'` (default): All pages get locale variants unless opted out via `i18nRoute: false`.\n * - `'opt-in'`: Only pages with explicit `i18nRoute` meta get locale variants.\n */\n routeMode?: 'all' | 'opt-in'\n}\n\n/**\n * Extend page routes with locale-prefixed variants.\n * Mutates the pages array in place (Nuxt convention).\n *\n * This is a build-time utility used in the module's `pages:extend` hook.\n */\nexport function extendPages(\n pages: PageRoute[],\n options: ExtendPagesOptions,\n): void {\n const { locales, defaultLocale, strategy, routeOverrides } = options\n const routeMode = options.routeMode ?? 'all'\n if (strategy === 'no_prefix' || strategy === 'domains') return\n\n const nameTemplate = options.routeNameTemplate ?? DEFAULT_ROUTE_NAME_TEMPLATE\n const originalPages = [...pages]\n\n // Filter out pages that have i18nRoute === false in their meta\n const isPageEnabled = (page: PageRoute, locale: string): boolean => {\n const i18nRoute = page.meta?.['i18nRoute'] as { locales?: string[] } | false | undefined\n\n // opt-in mode: pages without any i18nRoute meta are not extended\n if (routeMode === 'opt-in' && i18nRoute === undefined) return false\n\n if (i18nRoute === false) return false\n if (i18nRoute && i18nRoute.locales) {\n return i18nRoute.locales.includes(locale)\n }\n return true\n }\n\n for (const locale of locales) {\n // For prefix_except_default, skip creating prefixed routes for the default locale\n if (strategy === 'prefix_except_default' && locale === defaultLocale) continue\n\n for (const page of originalPages) {\n if (!isPageEnabled(page, locale)) continue\n const prefixedPage = prefixPage(page, locale, nameTemplate, routeOverrides)\n pages.push(prefixedPage)\n }\n }\n\n // For prefix strategy, remove the original unprefixed routes\n // (every locale including default must have a prefix)\n if (strategy === 'prefix') {\n // Remove all original pages (they'll only exist as prefixed versions)\n pages.splice(0, originalPages.length)\n }\n\n // For prefix_except_default, filter out pages disabled for the default locale\n if (strategy === 'prefix_except_default') {\n for (let i = pages.length - 1; i >= 0; i--) {\n const page = pages[i]!\n // Only check original (unprefixed) pages\n if (originalPages.includes(page) && !isPageEnabled(page, defaultLocale)) {\n pages.splice(i, 1)\n }\n }\n }\n}\n\nfunction prefixPage(\n page: PageRoute,\n locale: string,\n nameTemplate: RouteNameTemplate,\n routeOverrides?: Record<string, Record<string, string>>,\n): PageRoute {\n // Check if there's a custom path for this locale\n const overridePath = routeOverrides?.[page.path]?.[locale]\n const basePath = overridePath ?? page.path\n\n const prefixed: PageRoute = {\n ...page,\n path: `/${locale}${basePath === '/' ? '' : basePath}`,\n }\n if (page.name) {\n prefixed.name = nameTemplate(page.name, locale)\n }\n\n if (page.children) {\n prefixed.children = page.children.map((child) => {\n const childOverride = routeOverrides?.[child.path]?.[locale]\n const prefixedChild: PageRoute = {\n ...child,\n ...(childOverride ? { path: childOverride } : {}),\n }\n if (child.name) {\n prefixedChild.name = nameTemplate(child.name, locale)\n }\n return prefixedChild\n })\n }\n\n return prefixed\n}\n"],"mappings":"AAaA,IAAM,GAAkD,EAAM,IAC5D,GAAG,EAAK,KAAK,IA0Bf,SAAgB,EACd,EACA,EACM,CACN,GAAM,CAAE,UAAS,gBAAe,WAAU,kBAAmB,EACvD,EAAY,EAAQ,WAAa,MACvC,GAAI,IAAa,aAAe,IAAa,UAAW,OAExD,IAAM,EAAe,EAAQ,mBAAqB,EAC5C,EAAgB,CAAC,GAAG,EAAM,CAG1B,GAAiB,EAAiB,IAA4B,CAClE,IAAM,EAAY,EAAK,MAAO,UAS9B,OANI,IAAc,UAAY,IAAc,IAAA,IAExC,IAAc,GAAc,GAC5B,GAAa,EAAU,QAClB,EAAU,QAAQ,SAAS,EAAO,CAEpC,IAGT,IAAK,IAAM,KAAU,EAEf,SAAa,yBAA2B,IAAW,GAEvD,IAAK,IAAM,KAAQ,EAAe,CAChC,GAAI,CAAC,EAAc,EAAM,EAAO,CAAE,SAClC,IAAM,EAAe,EAAW,EAAM,EAAQ,EAAc,EAAe,CAC3E,EAAM,KAAK,EAAa,CAY5B,GANI,IAAa,UAEf,EAAM,OAAO,EAAG,EAAc,OAAO,CAInC,IAAa,wBACf,IAAK,IAAI,EAAI,EAAM,OAAS,EAAG,GAAK,EAAG,IAAK,CAC1C,IAAM,EAAO,EAAM,GAEf,EAAc,SAAS,EAAK,EAAI,CAAC,EAAc,EAAM,EAAc,EACrE,EAAM,OAAO,EAAG,EAAE,EAM1B,SAAS,EACP,EACA,EACA,EACA,EACW,CAGX,IAAM,EADe,IAAiB,EAAK,QAAQ,IAClB,EAAK,KAEhC,EAAsB,CAC1B,GAAG,EACH,KAAM,IAAI,IAAS,IAAa,IAAM,GAAK,IAC5C,CAmBD,OAlBI,EAAK,OACP,EAAS,KAAO,EAAa,EAAK,KAAM,EAAO,EAG7C,EAAK,WACP,EAAS,SAAW,EAAK,SAAS,IAAK,GAAU,CAC/C,IAAM,EAAgB,IAAiB,EAAM,QAAQ,GAC/C,EAA2B,CAC/B,GAAG,EACH,GAAI,EAAgB,CAAE,KAAM,EAAe,CAAG,EAAE,CACjD,CAID,OAHI,EAAM,OACR,EAAc,KAAO,EAAa,EAAM,KAAM,EAAO,EAEhD,GACP,EAGG"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Plugin } from 'vite';
|
|
2
|
+
/**
|
|
3
|
+
* Vite plugin that transforms `definePageMeta({ i18n: ... })` into
|
|
4
|
+
* the internal `i18nRoute` format used by the page extension system.
|
|
5
|
+
*
|
|
6
|
+
* This allows users to use native Nuxt `definePageMeta` with an `i18n` key
|
|
7
|
+
* instead of the separate `defineI18nRoute()` macro.
|
|
8
|
+
*
|
|
9
|
+
* Supports:
|
|
10
|
+
* - `definePageMeta({ i18n: { locales: ['en', 'ja'] } })`
|
|
11
|
+
* - `definePageMeta({ i18n: false })`
|
|
12
|
+
*
|
|
13
|
+
* The transform also rewrites `defineI18nRoute(...)` to
|
|
14
|
+
* `definePageMeta({ i18nRoute: ... })` for backwards compatibility.
|
|
15
|
+
*/
|
|
16
|
+
export declare function createPageMetaTransform(): Plugin;
|
|
17
|
+
//# sourceMappingURL=page-meta-transform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-meta-transform.d.ts","sourceRoot":"","sources":["../src/page-meta-transform.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAElC;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CA4ChD"}
|
package/dist/runtime/client.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../page-extend-
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../page-extend-tRXsujtK.cjs`),t=require(`../path-utils-BQIsp_or.cjs`),n=require(`../locale-head-D1NAUQc8.cjs`);require(`../module.cjs`);let r=require(`vue`);function i(e,n){return(r,i)=>t.n(r,i??e.value,n.defaultLocale,n.strategy)}function a(e,n){return r=>t.r(e.value,r,n.locales,n.defaultLocale,n.strategy)}function o(e,t,i,a){return(0,r.computed)(()=>n.t(e.value,t.value,i,a))}exports.buildLocaleHead=n.t,exports.extendPages=e.t,exports.extractLocaleFromPath=t.t,exports.localePath=t.n,exports.switchLocalePath=t.r,exports.useLocaleHead=o,exports.useLocalePath=i,exports.useSwitchLocalePath=a;
|
|
2
2
|
//# sourceMappingURL=client.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.cjs","names":[],"sources":["../../src/runtime/client.ts"],"sourcesContent":["// Browser-safe exports — no Nuxt auto-imports (#imports) dependency.\n// Use this entry point in non-Nuxt environments (e.g. plain Vue SPA).\n\nimport { computed } from 'vue'\nimport type { ComputedRef, Ref } from 'vue'\nimport { localePath, switchLocalePath } from './path-utils'\nimport { buildLocaleHead } from './locale-head'\nimport type { LocaleHeadMeta, LocaleHeadOptions } from './locale-head'\nimport type { FluentNuxtRuntimeConfig } from '../types'\n\n// Path utilities (pure functions, framework-agnostic)\nexport { localePath, extractLocaleFromPath, switchLocalePath } from './path-utils'\n\n// Page route extension (build-time utility)\nexport { extendPages } from './page-extend'\nexport type { PageRoute } from './page-extend'\n\n// Locale head (pure function)\nexport { buildLocaleHead } from './locale-head'\nexport type { LocaleHeadMeta, LocaleHeadOptions } from './locale-head'\n\n// Re-export types\nexport type { FluentNuxtRuntimeConfig } from '../types'\n\n/**\n * Browser-safe composable for locale-prefixed paths.\n * Accepts explicit locale and config instead of using Nuxt auto-imports.\n */\nexport function useLocalePath(\n locale: Ref<string>,\n config: FluentNuxtRuntimeConfig,\n): (path: string, targetLocale?: string) => string {\n return (path: string, targetLocale?: string) => {\n return localePath(\n path,\n targetLocale ?? locale.value,\n config.defaultLocale,\n config.strategy,\n )\n }\n}\n\n/**\n * Browser-safe composable for switching locale paths.\n * Accepts explicit currentPath and config instead of using Nuxt auto-imports.\n */\nexport function useSwitchLocalePath(\n currentPath: Ref<string> | ComputedRef<string>,\n config: FluentNuxtRuntimeConfig,\n): (locale: string) => string {\n return (newLocale: string) => {\n return switchLocalePath(\n currentPath.value,\n newLocale,\n config.locales,\n config.defaultLocale,\n config.strategy,\n )\n }\n}\n\n/**\n * Browser-safe composable for locale head metadata.\n * Accepts explicit locale, currentPath, and config instead of using Nuxt auto-imports.\n */\nexport function useLocaleHead(\n locale: Ref<string>,\n currentPath: Ref<string> | ComputedRef<string>,\n config: FluentNuxtRuntimeConfig,\n options?: LocaleHeadOptions,\n): ComputedRef<LocaleHeadMeta> {\n return computed(() => {\n return buildLocaleHead(locale.value, currentPath.value, config, options)\n })\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.cjs","names":[],"sources":["../../src/runtime/client.ts"],"sourcesContent":["// Browser-safe exports — no Nuxt auto-imports (#imports) dependency.\n// Use this entry point in non-Nuxt environments (e.g. plain Vue SPA).\n\nimport { computed } from 'vue'\nimport type { ComputedRef, Ref } from 'vue'\nimport { localePath, switchLocalePath } from './path-utils'\nimport { buildLocaleHead } from './locale-head'\nimport type { LocaleHeadMeta, LocaleHeadOptions } from './locale-head'\nimport type { FluentNuxtRuntimeConfig } from '../types'\n\n// Path utilities (pure functions, framework-agnostic)\nexport { localePath, extractLocaleFromPath, switchLocalePath } from './path-utils'\n\n// Page route extension (build-time utility)\nexport { extendPages } from './page-extend'\nexport type { PageRoute } from './page-extend'\n\n// Locale head (pure function)\nexport { buildLocaleHead } from './locale-head'\nexport type { LocaleHeadMeta, LocaleHeadOptions } from './locale-head'\n\n// Re-export types\nexport type { FluentNuxtRuntimeConfig } from '../types'\n\n/**\n * Browser-safe composable for locale-prefixed paths.\n * Accepts explicit locale and config instead of using Nuxt auto-imports.\n */\nexport function useLocalePath(\n locale: Ref<string>,\n config: FluentNuxtRuntimeConfig,\n): (path: string, targetLocale?: string) => string {\n return (path: string, targetLocale?: string) => {\n return localePath(\n path,\n targetLocale ?? locale.value,\n config.defaultLocale,\n config.strategy,\n )\n }\n}\n\n/**\n * Browser-safe composable for switching locale paths.\n * Accepts explicit currentPath and config instead of using Nuxt auto-imports.\n */\nexport function useSwitchLocalePath(\n currentPath: Ref<string> | ComputedRef<string>,\n config: FluentNuxtRuntimeConfig,\n): (locale: string) => string {\n return (newLocale: string) => {\n return switchLocalePath(\n currentPath.value,\n newLocale,\n config.locales,\n config.defaultLocale,\n config.strategy,\n )\n }\n}\n\n/**\n * Browser-safe composable for locale head metadata.\n * Accepts explicit locale, currentPath, and config instead of using Nuxt auto-imports.\n */\nexport function useLocaleHead(\n locale: Ref<string>,\n currentPath: Ref<string> | ComputedRef<string>,\n config: FluentNuxtRuntimeConfig,\n options?: LocaleHeadOptions,\n): ComputedRef<LocaleHeadMeta> {\n return computed(() => {\n return buildLocaleHead(locale.value, currentPath.value, config, options)\n })\n}\n"],"mappings":"iPA4BA,SAAgB,EACd,EACA,EACiD,CACjD,OAAQ,EAAc,IACb,EAAA,EACL,EACA,GAAgB,EAAO,MACvB,EAAO,cACP,EAAO,SACR,CAQL,SAAgB,EACd,EACA,EAC4B,CAC5B,MAAQ,IACC,EAAA,EACL,EAAY,MACZ,EACA,EAAO,QACP,EAAO,cACP,EAAO,SACR,CAQL,SAAgB,EACd,EACA,EACA,EACA,EAC6B,CAC7B,OAAA,EAAA,EAAA,cACS,EAAA,EAAgB,EAAO,MAAO,EAAY,MAAO,EAAQ,EAAQ,CACxE"}
|
package/dist/runtime/client.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { t as e } from "../page-extend-
|
|
1
|
+
import { t as e } from "../page-extend-BrPO2RhM.js";
|
|
2
2
|
import { n as t, r as n, t as r } from "../path-utils-BcvXLCGi.js";
|
|
3
|
-
import { t as i } from "../locale-head-
|
|
3
|
+
import { t as i } from "../locale-head-BuSO-fCZ.js";
|
|
4
4
|
import { computed as a } from "vue";
|
|
5
5
|
//#region src/runtime/client.ts
|
|
6
6
|
function o(e, n) {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require(`../composables.cjs`);let t=require(`vue`),n=require(`#components`);var r=(0,t.defineComponent)({name:`NuxtLinkLocale`,props:{to:{type:[String,Object],required:!0},locale:{type:String,default:void 0}},setup(r,{slots:i,attrs:a}){let o=e.useLocalePath(),s=(0,t.computed)(()=>o(typeof r.to==`string`?r.to:r.to.path??`/`,r.locale));return()=>(0,t.h)(n.NuxtLink,{...a,to:s.value},i)}});exports.NuxtLinkLocale=r,exports.default=r;
|
|
1
|
+
Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}}),require(`../../module.cjs`);const e=require(`../composables.cjs`);let t=require(`vue`),n=require(`#components`);var r=(0,t.defineComponent)({name:`NuxtLinkLocale`,props:{to:{type:[String,Object],required:!0},locale:{type:String,default:void 0}},setup(r,{slots:i,attrs:a}){let o=e.useLocalePath(),s=(0,t.computed)(()=>o(typeof r.to==`string`?r.to:r.to.path??`/`,r.locale));return()=>(0,t.h)(n.NuxtLink,{...a,to:s.value},i)}});exports.NuxtLinkLocale=r,exports.default=r;
|
|
2
2
|
//# sourceMappingURL=NuxtLinkLocale.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NuxtLinkLocale.cjs","names":[],"sources":["../../../src/runtime/components/NuxtLinkLocale.ts"],"sourcesContent":["import { defineComponent, computed, h, type PropType } from 'vue'\nimport { NuxtLink } from '#components'\nimport { useLocalePath } from '../composables'\n\n/**\n * Locale-aware wrapper around NuxtLink.\n *\n * Automatically prefixes the `to` prop with the current locale\n * based on the routing strategy. Uses the real NuxtLink component\n * for client-side navigation and prefetching.\n *\n * @example\n * ```vue\n * <NuxtLinkLocale to=\"/about\">About</NuxtLinkLocale>\n * <NuxtLinkLocale to=\"/about\" locale=\"ja\">About (Japanese)</NuxtLinkLocale>\n * ```\n */\nconst NuxtLinkLocale = defineComponent({\n name: 'NuxtLinkLocale',\n props: {\n to: {\n type: [String, Object] as PropType<string | { path?: string }>,\n required: true,\n },\n locale: {\n type: String as PropType<string | undefined>,\n default: undefined,\n },\n },\n setup(props, { slots, attrs }) {\n const getLocalePath = useLocalePath()\n\n const localizedTo = computed(() => {\n const path = typeof props.to === 'string' ? props.to : props.to.path ?? '/'\n return getLocalePath(path, props.locale)\n })\n\n return () => h(\n NuxtLink,\n { ...attrs, to: localizedTo.value },\n slots,\n )\n },\n})\n\nexport { NuxtLinkLocale }\nexport default NuxtLinkLocale\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"NuxtLinkLocale.cjs","names":[],"sources":["../../../src/runtime/components/NuxtLinkLocale.ts"],"sourcesContent":["import { defineComponent, computed, h, type PropType } from 'vue'\nimport { NuxtLink } from '#components'\nimport { useLocalePath } from '../composables'\n\n/**\n * Locale-aware wrapper around NuxtLink.\n *\n * Automatically prefixes the `to` prop with the current locale\n * based on the routing strategy. Uses the real NuxtLink component\n * for client-side navigation and prefetching.\n *\n * @example\n * ```vue\n * <NuxtLinkLocale to=\"/about\">About</NuxtLinkLocale>\n * <NuxtLinkLocale to=\"/about\" locale=\"ja\">About (Japanese)</NuxtLinkLocale>\n * ```\n */\nconst NuxtLinkLocale = defineComponent({\n name: 'NuxtLinkLocale',\n props: {\n to: {\n type: [String, Object] as PropType<string | { path?: string }>,\n required: true,\n },\n locale: {\n type: String as PropType<string | undefined>,\n default: undefined,\n },\n },\n setup(props, { slots, attrs }) {\n const getLocalePath = useLocalePath()\n\n const localizedTo = computed(() => {\n const path = typeof props.to === 'string' ? props.to : props.to.path ?? '/'\n return getLocalePath(path, props.locale)\n })\n\n return () => h(\n NuxtLink,\n { ...attrs, to: localizedTo.value },\n slots,\n )\n },\n})\n\nexport { NuxtLinkLocale }\nexport default NuxtLinkLocale\n"],"mappings":"+MAiBA,IAAM,GAAA,EAAA,EAAA,iBAAiC,CACrC,KAAM,iBACN,MAAO,CACL,GAAI,CACF,KAAM,CAAC,OAAQ,OAAO,CACtB,SAAU,GACX,CACD,OAAQ,CACN,KAAM,OACN,QAAS,IAAA,GACV,CACF,CACD,MAAM,EAAO,CAAE,QAAO,SAAS,CAC7B,IAAM,EAAgB,EAAA,eAAe,CAE/B,GAAA,EAAA,EAAA,cAEG,EADM,OAAO,EAAM,IAAO,SAAW,EAAM,GAAK,EAAM,GAAG,MAAQ,IAC7C,EAAM,OAAO,CACxC,CAEF,WAAA,EAAA,EAAA,GACE,EAAA,SACA,CAAE,GAAG,EAAO,GAAI,EAAY,MAAO,CACnC,EACD,EAEJ,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../path-utils-BQIsp_or.cjs`),t=require(`../locale-head-
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../path-utils-BQIsp_or.cjs`),t=require(`../locale-head-D1NAUQc8.cjs`);require(`../module.cjs`);let n=require(`vue`),r=require(`#imports`),i=require(`@fluenti/vue`);function a(){return(0,r.useRuntimeConfig)().public.fluenti}function o(){let{locale:t}=(0,i.useI18n)(),n=a();return(r,i)=>e.n(r,i??t.value,n.defaultLocale,n.strategy)}function s(){let t=(0,r.useRoute)(),n=a();return r=>e.r(t.path,r,n.locales,n.defaultLocale,n.strategy)}function c(){let{locale:t}=(0,i.useI18n)(),n=(0,r.useRouter)(),o=a();return(r,i)=>{let a=i??t.value;if(typeof r==`string`){let t=e.n(r,a,o.defaultLocale,o.strategy);return n.resolve(t)}if(`path`in r&&r.path){let t=e.n(r.path,a,o.defaultLocale,o.strategy);return n.resolve({...r,path:t})}return n.resolve(r)}}function l(e){let t=(0,i.useI18n)();return{...t,t(n,r){if(typeof n==`string`)return t.t(`${e}.${n}`,r);if(n&&typeof n==`object`&&`id`in n){let i=n;return t.t({...i,id:`${e}.${i.id}`},r)}return t.t(n,r)},te(n,r){return t.te(`${e}.${n}`,r)},tm(n,r){return t.tm(`${e}.${n}`,r)},namespace:e}}function u(e){let{locale:o}=(0,i.useI18n)(),s=(0,r.useRoute)(),c=a();return(0,n.computed)(()=>t.t(o.value,s.path,c,e))}exports.useI18nScoped=l,exports.useLocaleHead=u,exports.useLocalePath=o,exports.useLocaleRoute=c,exports.useSwitchLocalePath=s;
|
|
2
2
|
//# sourceMappingURL=composables.cjs.map
|