@i18n-micro/path-strategy 1.0.3 → 1.1.2

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.
Files changed (35) hide show
  1. package/dist/base-strategy-BuHeTv1K.cjs +2 -0
  2. package/dist/base-strategy-BuHeTv1K.cjs.map +1 -0
  3. package/dist/base-strategy-Cf39XK8k.js +926 -0
  4. package/dist/base-strategy-Cf39XK8k.js.map +1 -0
  5. package/dist/index.cjs +1 -1
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.d.ts +134 -4
  8. package/dist/index.mjs +8 -8
  9. package/dist/index.mjs.map +1 -1
  10. package/dist/no-prefix-strategy.cjs +1 -1
  11. package/dist/no-prefix-strategy.cjs.map +1 -1
  12. package/dist/no-prefix-strategy.d.ts +100 -4
  13. package/dist/no-prefix-strategy.mjs +42 -22
  14. package/dist/no-prefix-strategy.mjs.map +1 -1
  15. package/dist/prefix-and-default-strategy.cjs +1 -1
  16. package/dist/prefix-and-default-strategy.cjs.map +1 -1
  17. package/dist/prefix-and-default-strategy.d.ts +97 -4
  18. package/dist/prefix-and-default-strategy.mjs +101 -84
  19. package/dist/prefix-and-default-strategy.mjs.map +1 -1
  20. package/dist/prefix-except-default-strategy.cjs +1 -1
  21. package/dist/prefix-except-default-strategy.cjs.map +1 -1
  22. package/dist/prefix-except-default-strategy.d.ts +98 -4
  23. package/dist/prefix-except-default-strategy.mjs +248 -177
  24. package/dist/prefix-except-default-strategy.mjs.map +1 -1
  25. package/dist/prefix-strategy.cjs +1 -1
  26. package/dist/prefix-strategy.cjs.map +1 -1
  27. package/dist/prefix-strategy.d.ts +97 -4
  28. package/dist/prefix-strategy.mjs +35 -14
  29. package/dist/prefix-strategy.mjs.map +1 -1
  30. package/dist/types.d.ts +46 -1
  31. package/package.json +2 -2
  32. package/dist/base-strategy-B5mBf3XX.cjs +0 -2
  33. package/dist/base-strategy-B5mBf3XX.cjs.map +0 -1
  34. package/dist/base-strategy-DVqe8ehd.js +0 -790
  35. package/dist/base-strategy-DVqe8ehd.js.map +0 -1
@@ -0,0 +1,926 @@
1
+ const nt = /#/g, lt = /&/g, it = /\//g, ct = /=/g, w = /\+/g, H = /%5e/gi, ht = /%60/gi, ut = /%7b/gi, ft = /%7c/gi, dt = /%7d/gi, pt = /%20/gi;
2
+ function G(o) {
3
+ return encodeURI("" + o).replace(ft, "|");
4
+ }
5
+ function mt(o) {
6
+ return G(o).replace(ut, "{").replace(dt, "}").replace(H, "^");
7
+ }
8
+ function C(o) {
9
+ return G(typeof o == "string" ? o : JSON.stringify(o)).replace(w, "%2B").replace(pt, "+").replace(nt, "%23").replace(lt, "%26").replace(ht, "`").replace(H, "^").replace(it, "%2F");
10
+ }
11
+ function k(o) {
12
+ return C(o).replace(ct, "%3D");
13
+ }
14
+ function A(o = "") {
15
+ try {
16
+ return decodeURIComponent("" + o);
17
+ } catch {
18
+ return "" + o;
19
+ }
20
+ }
21
+ function gt(o) {
22
+ return A(o.replace(w, " "));
23
+ }
24
+ function yt(o) {
25
+ return A(o.replace(w, " "));
26
+ }
27
+ function Pt(o = "") {
28
+ const t = /* @__PURE__ */ Object.create(null);
29
+ o[0] === "?" && (o = o.slice(1));
30
+ for (const e of o.split("&")) {
31
+ const s = e.match(/([^=]+)=?(.*)/) || [];
32
+ if (s.length < 2)
33
+ continue;
34
+ const a = gt(s[1]);
35
+ if (a === "__proto__" || a === "constructor")
36
+ continue;
37
+ const r = yt(s[2] || "");
38
+ t[a] === void 0 ? t[a] = r : Array.isArray(t[a]) ? t[a].push(r) : t[a] = [t[a], r];
39
+ }
40
+ return t;
41
+ }
42
+ function Rt(o, t) {
43
+ return (typeof t == "number" || typeof t == "boolean") && (t = String(t)), t ? Array.isArray(t) ? t.map(
44
+ (e) => `${k(o)}=${C(e)}`
45
+ ).join("&") : `${k(o)}=${C(t)}` : k(o);
46
+ }
47
+ function Lt(o) {
48
+ return Object.keys(o).filter((t) => o[t] !== void 0).map((t) => Rt(t, o[t])).filter(Boolean).join("&");
49
+ }
50
+ const xt = /^[\s\w\0+.-]{2,}:([/\\]{1,2})/, bt = /^[\s\w\0+.-]{2,}:([/\\]{2})?/, Nt = /^([/\\]\s*){2,}[^/\\]/, vt = /^\.?\//;
51
+ function z(o, t = {}) {
52
+ return typeof t == "boolean" && (t = { acceptRelative: t }), t.strict ? xt.test(o) : bt.test(o) || (t.acceptRelative ? Nt.test(o) : !1);
53
+ }
54
+ function zt(o = "", t) {
55
+ return o.endsWith("/");
56
+ }
57
+ function S(o = "", t) {
58
+ return (zt(o) ? o.slice(0, -1) : o) || "/";
59
+ }
60
+ function St(o = "", t) {
61
+ return o.endsWith("/") ? o : o + "/";
62
+ }
63
+ function E(o = "") {
64
+ return o.startsWith("/");
65
+ }
66
+ function Q(o = "") {
67
+ return (E(o) ? o.slice(1) : o) || "/";
68
+ }
69
+ function K(o = "") {
70
+ return E(o) ? o : "/" + o;
71
+ }
72
+ function M(o = "") {
73
+ return o.split("://").map((t) => t.replace(/\/{2,}/g, "/")).join("://");
74
+ }
75
+ function Bt(o, t) {
76
+ const e = j(o), s = { ...Pt(e.search), ...t };
77
+ return e.search = Lt(s), X(e);
78
+ }
79
+ function Wt(o) {
80
+ return !o || o === "/";
81
+ }
82
+ function Ft(o) {
83
+ return o && o !== "/";
84
+ }
85
+ function $(o, ...t) {
86
+ let e = o || "";
87
+ for (const s of t.filter((a) => Ft(a)))
88
+ if (e) {
89
+ const a = s.replace(vt, "");
90
+ e = St(e) + a;
91
+ } else
92
+ e = s;
93
+ return e;
94
+ }
95
+ function $t(o, t) {
96
+ return A(S(o)) === A(S(t));
97
+ }
98
+ function At(o, t) {
99
+ if (!t || t === "#")
100
+ return o;
101
+ const e = j(o);
102
+ return e.hash = t === "" ? "" : "#" + mt(t), X(e);
103
+ }
104
+ const V = /* @__PURE__ */ Symbol.for("ufo:protocolRelative");
105
+ function j(o = "", t) {
106
+ const e = o.match(
107
+ /^[\s\0]*(blob:|data:|javascript:|vbscript:)(.*)/i
108
+ );
109
+ if (e) {
110
+ const [, d, g = ""] = e;
111
+ return {
112
+ protocol: d.toLowerCase(),
113
+ pathname: g,
114
+ href: d + g,
115
+ auth: "",
116
+ host: "",
117
+ search: "",
118
+ hash: ""
119
+ };
120
+ }
121
+ if (!z(o, { acceptRelative: !0 }))
122
+ return _(o);
123
+ const [, s = "", a, r = ""] = o.replace(/\\/g, "/").match(/^[\s\0]*([\w+.-]{2,}:)?\/\/([^/@]+@)?(.*)/) || [];
124
+ let [, n = "", l = ""] = r.match(/([^#/?]*)(.*)?/) || [];
125
+ s === "file:" && (l = l.replace(/\/(?=[A-Za-z]:)/, ""));
126
+ const { pathname: i, search: h, hash: u } = _(l);
127
+ return {
128
+ protocol: s.toLowerCase(),
129
+ auth: a ? a.slice(0, Math.max(0, a.length - 1)) : "",
130
+ host: n,
131
+ pathname: i,
132
+ search: h,
133
+ hash: u,
134
+ [V]: !s
135
+ };
136
+ }
137
+ function _(o = "") {
138
+ const [t = "", e = "", s = ""] = (o.match(/([^#?]*)(\?[^#]*)?(#.*)?/) || []).splice(1);
139
+ return {
140
+ pathname: t,
141
+ search: e,
142
+ hash: s
143
+ };
144
+ }
145
+ function X(o) {
146
+ const t = o.pathname || "", e = o.search ? (o.search.startsWith("?") ? "" : "?") + o.search : "", s = o.hash || "", a = o.auth ? o.auth + "@" : "", r = o.host || "";
147
+ return (o.protocol || o[V] ? (o.protocol || "") + "//" : "") + a + r + t + e + s;
148
+ }
149
+ const _t = /\/([^/]+)$/;
150
+ function Et(o = "", t) {
151
+ const { pathname: e } = j(o), s = e.match(_t);
152
+ return s ? s[1] : void 0;
153
+ }
154
+ function D(o) {
155
+ return (_(o.startsWith("/") ? o : `/${o}`).pathname || "").split("/").filter(Boolean);
156
+ }
157
+ const P = (o) => Wt(o ?? "") ? "/" : K(S(M(o))) || "/";
158
+ function jt(o) {
159
+ const t = M(o || "/");
160
+ return S(t) || "/";
161
+ }
162
+ function y(...o) {
163
+ const t = o.filter((r) => typeof r == "string" && r !== "");
164
+ if (t.length === 0) return "/";
165
+ const [e, ...s] = t, a = $(e, ...s) || "/";
166
+ return z(a) ? a : K(a);
167
+ }
168
+ function J(o) {
169
+ return o && _(o).pathname || "";
170
+ }
171
+ function T(o, t, e) {
172
+ let s = Bt(o, t ?? {});
173
+ if (e && e !== "#") {
174
+ const a = e.startsWith("#") ? e.slice(1) : e;
175
+ s = At(s, a);
176
+ }
177
+ return s;
178
+ }
179
+ function b(o) {
180
+ if (!o) return "";
181
+ let t = "";
182
+ for (let e = 0; e < o.length; e++)
183
+ t += o[e] === "-" ? "/" : o[e];
184
+ return t;
185
+ }
186
+ function Y(o) {
187
+ if (!o) return "";
188
+ const t = o.indexOf("-");
189
+ return t === -1 ? o : $(o.slice(0, t), o.slice(t + 1));
190
+ }
191
+ function Z(o) {
192
+ if (!o) return "";
193
+ const t = o.lastIndexOf("-");
194
+ return t === -1 ? o : $(o.slice(0, t), o.slice(t + 1));
195
+ }
196
+ function qt(o) {
197
+ const t = D(o);
198
+ return t.length > 1 ? t.slice(0, -1).join("-") : "";
199
+ }
200
+ function Ot(o) {
201
+ return Et(o || "/") ?? "";
202
+ }
203
+ function tt(o, t) {
204
+ const e = J(o), s = P(e);
205
+ if (s === "/")
206
+ return { pathWithoutLocale: "/", localeFromPath: null };
207
+ if (!E(s))
208
+ return { pathWithoutLocale: s, localeFromPath: null };
209
+ const a = s.indexOf("/", 1), r = a === -1 ? s.slice(1) : s.slice(1, a);
210
+ if (r && t.includes(r)) {
211
+ const n = 1 + r.length, l = s.slice(n);
212
+ return {
213
+ pathWithoutLocale: P(l || "/"),
214
+ localeFromPath: r
215
+ };
216
+ }
217
+ return { pathWithoutLocale: s, localeFromPath: null };
218
+ }
219
+ function Ut(o, t) {
220
+ const e = J(o);
221
+ if (e === "/" || e === "" || !E(e)) return null;
222
+ const s = e.indexOf("/", 1), a = s === -1 ? e.slice(1) : e.slice(1, s);
223
+ return a && t.includes(a) ? a : null;
224
+ }
225
+ function et(o, t) {
226
+ const e = o.name?.toString();
227
+ if (!e) return null;
228
+ const s = t.localizedRouteNamePrefix || "localized-", a = e.startsWith(s) ? e.slice(s.length) : e, r = [...t.locales].sort((n, l) => l.code.length - n.code.length);
229
+ for (const n of r) {
230
+ const l = `-${n.code}`;
231
+ if (!a.endsWith(l)) continue;
232
+ const i = a.length - n.code.length - 1;
233
+ if (i >= 0 && a[i] === "-")
234
+ return a.slice(0, -l.length);
235
+ }
236
+ return a;
237
+ }
238
+ function kt(o, t, e = "localized-") {
239
+ return `${e}${o}-${t}`;
240
+ }
241
+ function I(o, t) {
242
+ if (o == null) return !1;
243
+ const e = String(o).trim();
244
+ if (e === "" || e === "index") return !0;
245
+ const s = t?.localizedRouteNamePrefix ?? "localized-", a = t?.localeCodes ?? [], r = `${s}index-`;
246
+ if (!e.startsWith(r)) return !1;
247
+ const n = e.slice(r.length);
248
+ return a.length === 0 ? n.length >= 2 : a.includes(n);
249
+ }
250
+ function Ct(o) {
251
+ return o.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
252
+ }
253
+ class wt {
254
+ constructor(t) {
255
+ this.ctx = t;
256
+ }
257
+ /**
258
+ * Substitutes params into path template (:key, :key(), [...key]).
259
+ * Uses one combined regex per key to avoid creating multiple RegExp in a loop.
260
+ */
261
+ resolvePathWithParams(t, e = {}) {
262
+ let s = t;
263
+ for (const a in e) {
264
+ const r = e[a];
265
+ if (r == null || r === "") continue;
266
+ const n = Array.isArray(r) ? r.join("/") : String(r), l = Ct(a), i = new RegExp(`:${l}\\(\\)|:${l}(?![\\w])|\\[\\.\\.\\.${l}\\]`, "g");
267
+ s = s.replace(i, n);
268
+ }
269
+ return s;
270
+ }
271
+ /**
272
+ * Analyzes route: path without locale and base name (normalizer + route-name).
273
+ */
274
+ analyzeRoute(t) {
275
+ const e = this.ctx.locales.map((r) => r.code), { pathWithoutLocale: s } = tt(t.path || "/", e);
276
+ let a = null;
277
+ return t.name && (a = et(t, {
278
+ locales: this.ctx.locales,
279
+ localizedRouteNamePrefix: this.ctx.localizedRouteNamePrefix || "localized-"
280
+ })), { pathWithoutLocale: s, baseRouteName: a };
281
+ }
282
+ /** Public access to route analysis (for strategies). */
283
+ getPathWithoutLocaleAndBaseName(t) {
284
+ return this.analyzeRoute(t);
285
+ }
286
+ /**
287
+ * Lookup keys for config (same order for resolveCustomPath, getPathForUnlocalizedRoute, getAllowedLocalesForRoute).
288
+ */
289
+ getLookupKeys(t, e) {
290
+ const s = [];
291
+ s.push(t);
292
+ const a = Q(t);
293
+ if (a !== t && s.push(a), (t === "/" || a === "") && s.push(""), e) {
294
+ s.push(`/${e}`), s.push(e);
295
+ const r = b(e);
296
+ r && r !== e && s.push(r);
297
+ const n = Y(e);
298
+ n && s.push(n);
299
+ const l = Z(e);
300
+ l && s.push(l);
301
+ }
302
+ return s;
303
+ }
304
+ /**
305
+ * Resolves custom path for targetLocale from globalLocaleRoutes.
306
+ */
307
+ resolveCustomPath(t, e) {
308
+ const s = this.ctx.globalLocaleRoutes;
309
+ if (!s || Object.keys(s).length === 0) return null;
310
+ const { pathWithoutLocale: a, baseRouteName: r } = this.analyzeRoute(t), n = this.getLookupKeys(a, r);
311
+ for (const l of n) {
312
+ const i = s[l];
313
+ if (i && typeof i == "object" && !Array.isArray(i)) {
314
+ const h = i[e];
315
+ if (typeof h == "string")
316
+ return this.resolvePathWithParams(h, t.params ?? {});
317
+ }
318
+ }
319
+ return null;
320
+ }
321
+ /**
322
+ * Unlocalized route (globalLocaleRoutes[key] === false) — returns path without locale.
323
+ */
324
+ getPathForUnlocalizedRoute(t) {
325
+ const e = this.ctx.globalLocaleRoutes;
326
+ if (!e) return null;
327
+ const { pathWithoutLocale: s, baseRouteName: a } = this.analyzeRoute(t), r = this.getLookupKeys(s, a);
328
+ for (const n of r)
329
+ if (e[n] === !1) {
330
+ if (a && (n === a || n === `/${a}`)) {
331
+ const l = b(a);
332
+ return l ? y("/", l) : `/${a}`;
333
+ }
334
+ return s;
335
+ }
336
+ return null;
337
+ }
338
+ /**
339
+ * Unlocalized by name (when no route object available).
340
+ */
341
+ getPathForUnlocalizedRouteByName(t) {
342
+ const e = this.ctx.globalLocaleRoutes;
343
+ if (!e) return null;
344
+ const s = [t, `/${t}`, Q(t)];
345
+ for (const a of s)
346
+ if (e[a] === !1) {
347
+ const r = b(a.startsWith("/") ? a.slice(1) : a);
348
+ return r ? y("/", r) : a.startsWith("/") ? a : `/${a}`;
349
+ }
350
+ return null;
351
+ }
352
+ /**
353
+ * Allowed locales for route (routeLocales).
354
+ */
355
+ getAllowedLocalesForRoute(t) {
356
+ const e = this.ctx.routeLocales;
357
+ if (!e || Object.keys(e).length === 0)
358
+ return this.ctx.locales.map((n) => n.code);
359
+ const { pathWithoutLocale: s, baseRouteName: a } = this.analyzeRoute(t);
360
+ let r = this.getLookupKeys(s, a);
361
+ a && this.ctx.routesLocaleLinks?.[a] && (r = [this.ctx.routesLocaleLinks[a], ...r]);
362
+ for (const n of r) {
363
+ const l = e[n];
364
+ if (Array.isArray(l) && l.length > 0)
365
+ return l.filter((i) => this.ctx.locales.some((h) => h.code === i));
366
+ }
367
+ return this.ctx.locales.map((n) => n.code);
368
+ }
369
+ /**
370
+ * Parent path for nested route (parent key -> targetLocale path).
371
+ */
372
+ getParentPathForNested(t, e) {
373
+ if (t.length <= 1) return "/";
374
+ const s = t.length > 1 ? t.slice(0, -1).join("-") : "", a = this.ctx.globalLocaleRoutes;
375
+ if (s && a?.[s] && typeof a[s] == "object") {
376
+ const r = a[s];
377
+ if (r[e])
378
+ return P(r[e]);
379
+ }
380
+ return y("/", ...t.slice(0, -1));
381
+ }
382
+ }
383
+ class Qt {
384
+ constructor(t) {
385
+ this.ctx = t, this.resolver = new wt(t);
386
+ }
387
+ setRouter(t) {
388
+ this.ctx.router = t;
389
+ }
390
+ getDefaultLocale() {
391
+ return this.ctx.defaultLocale;
392
+ }
393
+ getLocales() {
394
+ return this.ctx.locales;
395
+ }
396
+ getStrategy() {
397
+ return this.ctx.strategy;
398
+ }
399
+ getLocalizedRouteNamePrefix() {
400
+ return this.ctx.localizedRouteNamePrefix || "localized-";
401
+ }
402
+ getGlobalLocaleRoutes() {
403
+ return this.ctx.globalLocaleRoutes;
404
+ }
405
+ getRouteLocales() {
406
+ return this.ctx.routeLocales;
407
+ }
408
+ getRoutesLocaleLinks() {
409
+ return this.ctx.routesLocaleLinks;
410
+ }
411
+ getNoPrefixRedirect() {
412
+ return this.ctx.noPrefixRedirect;
413
+ }
414
+ /**
415
+ * Returns base route name without locale prefix/suffix.
416
+ * @param route - Route object
417
+ * @param locale - Optional locale to strip suffix for (if not provided, tries all locales)
418
+ */
419
+ getRouteBaseName(t, e) {
420
+ const s = e ? [{ code: e }] : this.ctx.locales;
421
+ return et(t, {
422
+ locales: s,
423
+ localizedRouteNamePrefix: this.getLocalizedRouteNamePrefix()
424
+ });
425
+ }
426
+ /** Alias for internal use - strips localization prefix/suffix for specific locale. */
427
+ getBaseRouteName(t, e) {
428
+ return this.getRouteBaseName(t, e);
429
+ }
430
+ /** Resolves target path for a locale, checking globalLocaleRoutes first. */
431
+ resolvePathForLocale(t, e) {
432
+ const s = {
433
+ path: t,
434
+ name: null,
435
+ fullPath: t,
436
+ params: {}
437
+ }, a = this.resolver.resolveCustomPath(s, e);
438
+ return P(a || t);
439
+ }
440
+ buildLocalizedName(t, e) {
441
+ return kt(t, e, this.getLocalizedRouteNamePrefix());
442
+ }
443
+ getLocaleObject(t) {
444
+ return this.ctx.locales.find((e) => e.code === t);
445
+ }
446
+ applyBaseUrl(t, e) {
447
+ if (typeof e == "string") {
448
+ if (z(e)) return e;
449
+ } else if (e.path && z(e.path))
450
+ return e;
451
+ const s = this.getLocaleObject(t);
452
+ if (!s?.baseUrl)
453
+ return e;
454
+ const a = S(s.baseUrl);
455
+ if (typeof e == "string") {
456
+ const l = P(e.startsWith("/") ? e : `/${e}`);
457
+ return y(a, l);
458
+ }
459
+ const r = P(e.path || ""), n = y(a, r);
460
+ return z(n) ? n : {
461
+ ...e,
462
+ path: n,
463
+ fullPath: n
464
+ };
465
+ }
466
+ /**
467
+ * Merges target route (strategy result) with query and hash from source route.
468
+ * Returns normalized RouteLike object.
469
+ */
470
+ preserveQueryAndHash(t, e) {
471
+ if (!e || !e.query && !e.hash)
472
+ return t;
473
+ const s = typeof t == "string" ? { path: t } : { ...t };
474
+ e.query && (s.query = { ...e.query, ...s.query }), !s.hash && e.hash && (s.hash = e.hash);
475
+ const a = s.path ?? "";
476
+ return s.fullPath = T(a, s.query, s.hash), s;
477
+ }
478
+ resolvePathWithParams(t, e = {}) {
479
+ return this.resolver.resolvePathWithParams(t, e);
480
+ }
481
+ getPathWithoutLocaleAndBaseName(t) {
482
+ return this.resolver.getPathWithoutLocaleAndBaseName(t);
483
+ }
484
+ /** Look up custom path segment for targetLocale in globalLocaleRoutes. */
485
+ getCustomPathSegment(t, e) {
486
+ return this.resolver.resolveCustomPath(t, e);
487
+ }
488
+ getAllowedLocalesForRoute(t) {
489
+ return this.resolver.getAllowedLocalesForRoute(t);
490
+ }
491
+ getCanonicalPath(t, e) {
492
+ return null;
493
+ }
494
+ getPathForUnlocalizedRouteByName(t) {
495
+ return this.resolver.getPathForUnlocalizedRouteByName(t);
496
+ }
497
+ /**
498
+ * Try to resolve route by localized name. Returns RouteLike with query/hash from sourceRoute to preserve them.
499
+ */
500
+ tryResolveByLocalizedName(t, e, s) {
501
+ const a = this.getLocalizedRouteNamePrefix(), r = `${a}${t}-${e}`, n = `${a}${t}`;
502
+ let l;
503
+ if (this.ctx.router.hasRoute(r))
504
+ l = r;
505
+ else if (this.ctx.router.hasRoute(n))
506
+ l = n;
507
+ else
508
+ return this.debugLog("tryResolveByLocalizedName", {
509
+ routeName: t,
510
+ targetLocale: e,
511
+ tried: [r, n],
512
+ found: !1
513
+ }), null;
514
+ this.debugLog("tryResolveByLocalizedName", { routeName: t, targetLocale: e, localizedName: l, found: !0 });
515
+ const i = { ...s?.params };
516
+ l === n && (i.locale = e);
517
+ let h;
518
+ try {
519
+ h = this.ctx.router.resolve({
520
+ name: l,
521
+ params: i,
522
+ query: s?.query,
523
+ hash: s?.hash
524
+ });
525
+ } catch {
526
+ return this.debugLog("tryResolveByLocalizedName resolve error", { localizedName: l, params: i }), null;
527
+ }
528
+ return this.debugLog("tryResolveByLocalizedName resolved", { localizedName: l, path: h?.path, fullPath: h?.fullPath }), h?.path ? {
529
+ name: l,
530
+ path: h.path,
531
+ fullPath: h.fullPath,
532
+ params: h.params,
533
+ query: h.query ?? s?.query,
534
+ hash: h.hash ?? s?.hash
535
+ } : null;
536
+ }
537
+ /**
538
+ * Try to resolve route by localized name with params. Returns RouteLike to preserve query/hash.
539
+ */
540
+ tryResolveByLocalizedNameWithParams(t, e, s, a) {
541
+ const r = this.getLocalizedRouteNamePrefix(), n = `${r}${t}-${e}`, l = `${r}${t}`;
542
+ let i;
543
+ if (this.ctx.router.hasRoute(n))
544
+ i = n;
545
+ else if (this.ctx.router.hasRoute(l))
546
+ i = l;
547
+ else
548
+ return this.debugLog("tryResolveByLocalizedNameWithParams", {
549
+ routeName: t,
550
+ targetLocale: e,
551
+ params: s,
552
+ tried: [n, l],
553
+ found: !1
554
+ }), null;
555
+ this.debugLog("tryResolveByLocalizedNameWithParams", { routeName: t, targetLocale: e, params: s, localizedName: i, found: !0 });
556
+ const h = { ...s };
557
+ i === l && (h.locale = e);
558
+ let u;
559
+ try {
560
+ u = this.ctx.router.resolve({
561
+ name: i,
562
+ params: h,
563
+ query: a?.query,
564
+ hash: a?.hash
565
+ });
566
+ } catch {
567
+ return this.debugLog("tryResolveByLocalizedNameWithParams resolve error", { localizedName: i, resolveParams: h }), null;
568
+ }
569
+ return this.debugLog("tryResolveByLocalizedNameWithParams resolved", { path: u?.path, fullPath: u?.fullPath }), !u?.path || u.path === "/" ? null : {
570
+ name: i,
571
+ path: u.path,
572
+ fullPath: u.fullPath,
573
+ params: u.params,
574
+ query: u.query ?? a?.query,
575
+ hash: u.hash ?? a?.hash
576
+ };
577
+ }
578
+ getPathForUnlocalizedRoute(t) {
579
+ return this.resolver.getPathForUnlocalizedRoute(t);
580
+ }
581
+ /**
582
+ * Builds localized path from baseName + params when router does not have the route.
583
+ * Tries two conventions:
584
+ * 1) Hyphen form (Nuxt test-[id].vue → /test-:id): when single param key equals last baseName segment (e.g. test-id + id → test-:id).
585
+ * 2) Slash form (kebab→slash): path segments from baseName, last N replaced by :paramKey (e.g. test-id → /test/:id).
586
+ */
587
+ buildPathFromBaseNameAndParams(t, e, s) {
588
+ const a = Object.keys(e).filter((u) => e[u] !== void 0 && e[u] !== null && e[u] !== "");
589
+ if (a.length === 0) return null;
590
+ let r;
591
+ const n = a[0];
592
+ if (a.length === 1 && n !== void 0 && t.endsWith(`-${n}`))
593
+ r = y("/", `${t.slice(0, t.length - n.length - 1)}-:${n}`);
594
+ else {
595
+ const u = b(t), d = u ? u.split("/").filter(Boolean) : [t], g = Math.min(a.length, d.length), R = d.slice(0, d.length - g).concat(a.slice(0, g).map((B) => `:${B}`));
596
+ r = y("/", ...R);
597
+ }
598
+ const l = this.resolvePathWithParams(r, e), i = this.buildLocalizedPath(l, s, !1), h = this.applyBaseUrl(s, i);
599
+ return typeof h == "string" ? h : h.path ?? i;
600
+ }
601
+ getPathWithoutLocale(t) {
602
+ return tt(
603
+ t,
604
+ this.ctx.locales.map((e) => e.code)
605
+ );
606
+ }
607
+ getLocaleFromPath(t) {
608
+ return Ut(
609
+ t,
610
+ this.ctx.locales.map((e) => e.code)
611
+ );
612
+ }
613
+ /**
614
+ * Checks if the current path should return 404.
615
+ * Returns error message if 404 should be returned, null otherwise.
616
+ * Base implementation checks unlocalized routes and routeLocales restrictions.
617
+ */
618
+ shouldReturn404(t) {
619
+ const { pathWithoutLocale: e, localeFromPath: s } = this.getPathWithoutLocale(t);
620
+ if (s === null) return null;
621
+ const a = e === "/" ? "/" : e.replace(/^\//, ""), r = this.ctx.globalLocaleRoutes;
622
+ if (r && (r[e] === !1 || r[a] === !1))
623
+ return "Unlocalized route cannot have locale prefix";
624
+ const n = this.ctx.routeLocales;
625
+ if (n && Object.keys(n).length > 0) {
626
+ const l = n[e] ?? n[a];
627
+ if (Array.isArray(l) && l.length > 0) {
628
+ const i = this.ctx.locales.map((u) => u.code), h = l.filter((u) => i.includes(u));
629
+ if (h.length > 0 && !h.includes(s))
630
+ return "Locale not allowed for this route";
631
+ }
632
+ }
633
+ return null;
634
+ }
635
+ /**
636
+ * Builds SEO attributes (canonical + hreflangs) from current route.
637
+ * Respects routeLocales: only allowed locales for this route get an hreflang entry.
638
+ * routesLocaleLinks is used when resolving the route key for routeLocales lookup.
639
+ */
640
+ getSeoAttributes(t) {
641
+ const e = this.resolveLocaleFromPath(t.path) ?? this.ctx.defaultLocale, s = this.getCanonicalPath(t, e) ?? t.path, a = this.buildFullUrl(e, s), r = this.getAllowedLocalesForRoute(t), l = this.ctx.locales.filter((i) => r.includes(i.code)).map((i) => {
642
+ const h = this.localeRoute(i.code, t, t), d = (h.path ?? h.fullPath ?? "") || "/";
643
+ return {
644
+ rel: "alternate",
645
+ hreflang: i.code,
646
+ href: this.buildFullUrl(i.code, d)
647
+ };
648
+ });
649
+ return { canonical: a, hreflangs: l };
650
+ }
651
+ /**
652
+ * Builds full URL (path + optional baseUrl for locale).
653
+ */
654
+ buildFullUrl(t, e) {
655
+ const s = this.applyBaseUrl(t, e);
656
+ return typeof s == "string" ? s : s.path ?? e;
657
+ }
658
+ /** When router knows neither targetName nor baseName — what to return (strategy may override). */
659
+ getSwitchLocaleFallbackWhenNoRoute(t, e) {
660
+ return { ...t, name: e };
661
+ }
662
+ /**
663
+ * Default: baseName → buildLocalizedRouteName → hasRoute → applyBaseUrl; fallback to baseName.
664
+ */
665
+ switchLocaleRoute(t, e, s, a) {
666
+ const r = this.getBaseRouteName(s, t);
667
+ if (!r) return s;
668
+ const n = this.buildLocalizedRouteName(r, e), l = `${this.getLocalizedRouteNamePrefix()}${r}`;
669
+ let i, h = !1;
670
+ if (this.ctx.router.hasRoute(n))
671
+ i = n;
672
+ else if (this.ctx.router.hasRoute(l))
673
+ i = l, h = !0;
674
+ else if (this.ctx.router.hasRoute(r))
675
+ i = r;
676
+ else
677
+ return this.getSwitchLocaleFallbackWhenNoRoute(s, n);
678
+ const u = a.i18nRouteParams?.[e] || {}, d = { ...s.params || {}, ...u };
679
+ h ? d.locale = e : delete d.locale;
680
+ const g = {
681
+ name: i,
682
+ params: d,
683
+ query: s.query,
684
+ hash: s.hash
685
+ };
686
+ return this.applyBaseUrl(e, g);
687
+ }
688
+ /**
689
+ * Template Method: BaseStrategy knows "how" (normalize → delegate to strategy).
690
+ * Always returns RouteLike with path and fullPath (never a string).
691
+ */
692
+ localeRoute(t, e, s) {
693
+ const a = this.normalizeRouteInput(e, s), r = this.resolveLocaleRoute(t, a, s);
694
+ this.debugLog("localeRoute raw", {
695
+ rawPath: typeof r == "string" ? r : r.path,
696
+ rawFullPath: typeof r == "string" ? r : r.fullPath
697
+ });
698
+ const n = this.ensureRouteLike(r, a.kind === "route" ? a.sourceRoute : void 0);
699
+ return this.debugLog("localeRoute after ensureRouteLike", { path: n.path, fullPath: n.fullPath }), n;
700
+ }
701
+ /** Normalizes resolveLocaleRoute result into RouteLike (path and fullPath always set). */
702
+ ensureRouteLike(t, e) {
703
+ if (typeof t == "string") {
704
+ const r = t, n = e?.query || e?.hash ? T(r, e?.query, e?.hash) : r;
705
+ return {
706
+ path: r,
707
+ fullPath: n,
708
+ ...e?.query && { query: e.query },
709
+ ...e?.hash && { hash: e.hash }
710
+ };
711
+ }
712
+ let s = t.fullPath ?? t.path ?? "", a = t.path ?? s.split("?")[0]?.split("#")[0] ?? s;
713
+ if (!a && !s) {
714
+ const r = t.name?.toString() ?? e?.name?.toString() ?? "";
715
+ I(r, {
716
+ localizedRouteNamePrefix: this.getLocalizedRouteNamePrefix(),
717
+ localeCodes: this.ctx.locales.map((n) => n.code)
718
+ }) && (a = "/", s = "/");
719
+ }
720
+ return { ...t, path: a, fullPath: s };
721
+ }
722
+ /**
723
+ * Normalizes localeRoute input into a single structure (path string or route with resolved).
724
+ */
725
+ normalizeRouteInput(t, e) {
726
+ if (typeof t == "string")
727
+ return { kind: "path", path: t };
728
+ const s = t, a = s.name?.toString() ?? null;
729
+ let r;
730
+ try {
731
+ r = this.ctx.router.resolve(t), this.debugLog("normalizeRouteInput router.resolve ok", { inputName: a, resolvedPath: r.path, resolvedName: r.name });
732
+ } catch {
733
+ r = {
734
+ name: a,
735
+ path: s.path ?? "/",
736
+ fullPath: s.fullPath ?? s.path ?? "/",
737
+ params: s.params ?? {},
738
+ query: s.query ?? {},
739
+ hash: s.hash ?? ""
740
+ }, this.debugLog("normalizeRouteInput router.resolve catch fallback", { inputName: a, resolvedPath: r.path });
741
+ }
742
+ return { kind: "route", inputName: a, sourceRoute: s, resolved: r };
743
+ }
744
+ /** Logging when ctx.debug (for localeRoute debugging). Disabled by default. */
745
+ debugLog(...t) {
746
+ }
747
+ /**
748
+ * Default resolution: uses buildLocalizedPath and buildLocalizedRouteName.
749
+ * Strategies with different logic (e.g. prefix-except-default) override this method.
750
+ */
751
+ resolveLocaleRoute(t, e, s) {
752
+ if (e.kind === "path") {
753
+ const c = this.resolvePathForLocale(e.path, t), f = this.buildLocalizedPath(c, t, !1), p = this.applyBaseUrl(t, f);
754
+ return this.debugLog("branch=path", { targetLocale: t, path: e.path, finalPath: f, out: typeof p == "string" ? p : p.path }), p;
755
+ }
756
+ const { inputName: a, sourceRoute: r, resolved: n } = e, l = r.params && Object.keys(r.params ?? {}).length > 0, i = this.getRouteBaseName(n) ?? a ?? n.name?.toString() ?? null, h = n.name?.toString();
757
+ if (this.debugLog("input", {
758
+ targetLocale: t,
759
+ inputName: a,
760
+ resolvedPath: n.path,
761
+ resolvedName: n.name,
762
+ params: r.params,
763
+ hasParams: l,
764
+ baseName: i
765
+ }), a) {
766
+ const c = this.getPathForUnlocalizedRouteByName(a);
767
+ if (c !== null)
768
+ return this.debugLog("branch=unlocalizedByName", { inputName: a, unlocalizedByName: c }), this.preserveQueryAndHash(c, r);
769
+ }
770
+ if (a && l) {
771
+ const c = this.tryResolveByLocalizedNameWithParams(a, t, r.params ?? {}, r);
772
+ if (c !== null)
773
+ return this.debugLog("branch=routeWithParams", { inputName: a, path: c.path, fullPath: c.fullPath }), this.preserveQueryAndHash(this.applyBaseUrl(t, c), r);
774
+ }
775
+ if (a && !l) {
776
+ let c = this.tryResolveByLocalizedName(a, t, r);
777
+ const f = this.getLocalizedRouteNamePrefix();
778
+ if (c === null && i != null && i !== a && a.startsWith(f) && (c = this.tryResolveByLocalizedName(i, t, r)), c !== null)
779
+ return this.debugLog("branch=routeByLocalizedName", { inputName: a, path: c.path, fullPath: c.fullPath }), this.preserveQueryAndHash(this.applyBaseUrl(t, c), r);
780
+ }
781
+ const u = this.getPathForUnlocalizedRoute(n);
782
+ if (u !== null) {
783
+ const c = this.buildLocalizedPath(u, t, !1);
784
+ return this.debugLog("branch=unlocalizedPath", { unlocalizedPath: u, path: c }), this.preserveQueryAndHash(this.applyBaseUrl(t, c), r);
785
+ }
786
+ const d = this.getCustomPathSegment(n, t);
787
+ if (d !== null) {
788
+ const c = n.name?.toString() ?? a ?? "", f = c ? Y(c) : "", p = c ? Z(c) : "", m = this.ctx.globalLocaleRoutes, N = f.includes("/") && m?.[f], x = p.includes("/") && m?.[p], st = N || x, at = x ? p : f;
789
+ let F;
790
+ if (st) {
791
+ const U = D(at), v = U.length > 1 ? U.slice(0, -1).join("-") : "", O = v && m?.[v] && typeof m[v] == "object" && !Array.isArray(m[v]) ? m[v] : null, ot = O?.[t] ? P(O[t]) : y("/", ...U.slice(0, -1)), rt = d.startsWith("/") ? d.slice(1) : d;
792
+ F = y(ot, rt);
793
+ } else
794
+ F = P(d);
795
+ const q = this.buildLocalizedPath(F, t, !0);
796
+ return this.debugLog("branch=customSegment", { customSegment: d, pathWithoutLocale: F, finalPath: q }), this.preserveQueryAndHash(this.applyBaseUrl(t, q), r);
797
+ }
798
+ const g = i ?? a;
799
+ if (this.debugLog("before effectiveBaseName check", { baseName: i, inputName: a, effectiveBaseName: g, resolvedName: n.name?.toString() }), !g)
800
+ return this.debugLog("branch=noBaseName", { return: "src" }), r;
801
+ if (!l && n.path && n.path !== "/" && n.name) {
802
+ const { pathWithoutLocale: c, baseRouteName: f } = this.getPathWithoutLocaleAndBaseName(n);
803
+ if (c && c !== "/") {
804
+ const p = f && c === f ? y("/", b(f)) : c, m = this.buildLocalizedPath(p, t, !1);
805
+ return this.debugLog("branch=pathFromResolved", { pathWithoutLocale: c, baseRouteName: f, pathToUse: p, finalPath: m }), this.preserveQueryAndHash(this.applyBaseUrl(t, m), r);
806
+ }
807
+ }
808
+ const R = h === a ? g : a ?? g;
809
+ this.debugLog("fallback build", { resolvedNameStr: h, inputName: a, baseNameForPath: R, targetLocale: t, hasParams: l });
810
+ const B = this.buildLocalizedRouteName(R, t), L = {
811
+ ...r,
812
+ name: B,
813
+ params: { ...r.params }
814
+ };
815
+ if (l) {
816
+ let c = null;
817
+ try {
818
+ const f = this.ctx.router.resolve({ name: R, params: r.params });
819
+ if (f?.path) {
820
+ const p = f.path === "/" ? "/" : (() => {
821
+ const { pathWithoutLocale: x } = this.getPathWithoutLocale(f.path);
822
+ return x && x !== "/" ? x : f.path;
823
+ })(), m = this.buildLocalizedPath(p, t, !1), N = this.applyBaseUrl(t, m);
824
+ c = typeof N == "string" ? N : N.path ?? m;
825
+ }
826
+ } catch {
827
+ c = this.buildPathFromBaseNameAndParams(R, r.params ?? {}, t);
828
+ }
829
+ c && (L.path = c, L.fullPath = c);
830
+ } else {
831
+ const c = I(R) ? "/" : y("/", b(R)), f = this.buildLocalizedPath(c, t, !1), p = this.applyBaseUrl(t, f), m = typeof p == "string" ? p : p.path ?? f;
832
+ this.debugLog("fallback !hasParams", { pathWithoutLocale: c, finalPath: f, pathStr: m }), L.path = m, L.fullPath = m;
833
+ }
834
+ L.path && delete L.name;
835
+ const W = this.preserveQueryAndHash(this.applyBaseUrl(t, L), r);
836
+ return this.debugLog("branch=fallbackNewRoute return", {
837
+ baseName: i,
838
+ targetName: B,
839
+ hasParams: l,
840
+ newRoutePath: L.path,
841
+ outPath: typeof W == "string" ? W : W.path
842
+ }), W;
843
+ }
844
+ /**
845
+ * Extracts locale from URL path by checking the first path segment.
846
+ */
847
+ extractLocaleFromPath(t) {
848
+ if (!t) return null;
849
+ const s = t.split("?")[0]?.split("#")[0];
850
+ if (!s || s === "/") return null;
851
+ const a = s.split("/").filter(Boolean);
852
+ if (a.length === 0) return null;
853
+ const r = a[0];
854
+ return r && this.ctx.locales.map((l) => l.code).includes(r) ? r : null;
855
+ }
856
+ /**
857
+ * Determines current locale from route, considering hashMode, noPrefix, prefix_and_default at /, etc.
858
+ */
859
+ getCurrentLocale(t, e) {
860
+ const s = this.ctx.strategy;
861
+ if (this.ctx.hashMode) {
862
+ const l = e?.();
863
+ return l || this.ctx.defaultLocale;
864
+ }
865
+ if (s === "no_prefix") {
866
+ const l = e?.();
867
+ return l || this.ctx.defaultLocale;
868
+ }
869
+ const a = t.path || t.fullPath || "";
870
+ if (s === "prefix_and_default" && (a === "/" || a === "")) {
871
+ const l = e?.();
872
+ if (l) return l;
873
+ }
874
+ if (t.params?.locale)
875
+ return String(t.params.locale);
876
+ const r = this.extractLocaleFromPath(a);
877
+ if (r)
878
+ return r;
879
+ if (s === "prefix_except_default")
880
+ return this.ctx.defaultLocale;
881
+ const n = e?.();
882
+ return n || this.ctx.defaultLocale;
883
+ }
884
+ /**
885
+ * Returns the route name for plugin translation loading.
886
+ * If disablePageLocales is true, returns 'general'.
887
+ */
888
+ getPluginRouteName(t, e) {
889
+ if (this.ctx.disablePageLocales)
890
+ return "general";
891
+ const s = this.getRouteBaseName(t);
892
+ return s || (t.name ?? "").toString().replace(this.getLocalizedRouteNamePrefix(), "").replace(new RegExp(`-${e}$`), "");
893
+ }
894
+ /**
895
+ * Returns displayName of the current locale, or null if not found.
896
+ */
897
+ getCurrentLocaleName(t) {
898
+ const e = this.getCurrentLocale(t);
899
+ return this.ctx.locales.find((a) => a.code === e)?.displayName ?? null;
900
+ }
901
+ }
902
+ export {
903
+ Qt as B,
904
+ wt as R,
905
+ jt as a,
906
+ Z as b,
907
+ M as c,
908
+ I as d,
909
+ Y as e,
910
+ D as f,
911
+ J as g,
912
+ K as h,
913
+ $t as i,
914
+ y as j,
915
+ T as k,
916
+ Ot as l,
917
+ kt as m,
918
+ P as n,
919
+ Ut as o,
920
+ qt as p,
921
+ tt as q,
922
+ et as r,
923
+ b as t,
924
+ Q as w
925
+ };
926
+ //# sourceMappingURL=base-strategy-Cf39XK8k.js.map