@i18n-micro/astro 1.3.9 → 1.3.10
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/index.cjs +2 -2
- package/dist/index.mjs +305 -280
- package/dist/utils.d.ts +5 -0
- package/package.json +5 -5
- package/src/utils.ts +14 -11
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const j=require("@i18n-micro/core"),G=require("node:async_hooks"),R=require("node:fs"),$=require("node:path"),M=require("@i18n-micro/utils/parse-path"),V=require("@i18n-micro/utils/accept-language");class v extends j.BaseI18n{constructor(e){const r=e._storage||{translations:new Map};if(super({storage:r,plural:e.plural,missingWarn:e.missingWarn,missingHandler:e.missingHandler,numberFormats:e.numberFormats,datetimeFormats:e.datetimeFormats}),this.initialMessages={},this.storage=r,this._locale=e.locale,this._fallbackLocale=e.fallbackLocale||e.locale,this._currentRoute="index",e.messages){this.initialMessages={...e.messages};for(const[l,c]of Object.entries(e.messages))this.helper.loadTranslations(l,c)}}cloneStorage(e){const r=new Map;for(const[l,c]of e.translations)r.set(l,{...c});return{translations:r}}clone(e){const r=this.cloneStorage(this.storage);return new v({locale:e||this._locale,fallbackLocale:this._fallbackLocale,plural:this.pluralFunc,missingWarn:this.missingWarn,missingHandler:this.missingHandler,numberFormats:this.formatter.getNumberFormats(),datetimeFormats:this.formatter.getDateTimeFormats(),_storage:r})}get locale(){return this._locale}set locale(e){this._locale=e}get fallbackLocale(){return this._fallbackLocale}set fallbackLocale(e){this._fallbackLocale=e}setRoute(e){this._currentRoute=e}getLocale(){return this._locale}getFallbackLocale(){return this._fallbackLocale}getRoute(){return this._currentRoute}getRouteTranslations(e,r){const l=`${e}:${r}`;return this.storage.translations.get(l)??null}addTranslations(e,r,l=!0){super.loadTranslationsCore(e,r,l)}addRouteTranslations(e,r,l,c=!0){super.loadRouteTranslationsCore(e,r,l,c)}mergeTranslations(e,r,l){this.helper.mergeTranslation(e,r,l,!0)}clearCache(){const e={...this.initialMessages};if(super.clearCache(),Object.keys(e).length>0)for(const[r,l]of Object.entries(e))this.helper.loadTranslations(r,l)}}let q=null;const W=new G.AsyncLocalStorage;function _(){const t=W.getStore();return t!==void 0?t:q}function U(t){q=t}function H(t,e){return W.run(t,e)}function J(t){const{locale:e,fallbackLocale:r,translationDir:l,routingStrategy:c}=t;return U(c||null),{name:"@i18n-micro/astro",hooks:{"astro:config:setup":u=>{const{updateConfig:i}=u,o="virtual:i18n-micro/config",s=`\0${o}`,a={defaultLocale:e,fallbackLocale:r||e,locales:t.locales||[],localeCodes:(t.locales||[]).map(n=>n.code),translationDir:l||null,autoDetect:t.autoDetect??!0,redirectToDefault:t.redirectToDefault??!1,localeCookie:t.localeCookie===null?null:t.localeCookie||"i18n-locale",missingWarn:t.missingWarn??!1};i({vite:{plugins:[{name:"vite-plugin-i18n-micro-config",resolveId(n){if(n===o)return s},load(n){if(n===s)return`export const config = ${JSON.stringify(a)}`}}]}})},"astro:config:done":u=>{const{injectTypes:i}=u;i({filename:"i18n-micro-env.d.ts",content:`
|
|
2
2
|
/// <reference types="@i18n-micro/astro/env" />
|
|
3
3
|
|
|
4
4
|
declare module 'virtual:i18n-micro/config' {
|
|
@@ -14,4 +14,4 @@
|
|
|
14
14
|
missingWarn: boolean | null;
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
|
-
`})}}}}function
|
|
17
|
+
`})}}}}function Z(t){return new v(t)}function z(t,e){if(R.existsSync(t))for(const r of R.readdirSync(t)){const l=$.join(t,r);if(R.statSync(l).isDirectory()){z(l,e);continue}r.endsWith(".json")&&e(l)}}function E(t){const{translationDir:e,rootDir:r=process.cwd(),disablePageLocales:l=!1}=t,c=$.resolve(r,e);if(!R.existsSync(c))return console.warn(`[i18n] Translation directory not found: ${c}`),{root:{},routes:{}};const u={root:{},routes:{}};return z(c,i=>{const o=$.relative(c,i).split($.sep).join("/");try{const s=R.readFileSync(i,"utf-8"),a=JSON.parse(s);M.storeLoadedTranslationFile(u,o,a,l)}catch(s){console.error(`[i18n] Failed to load translation file: ${i}`,s)}}),u}function K(t,e){const{root:r,routes:l}=E(e);for(const[c,u]of Object.entries(r))t.addTranslations(c,u,!1);for(const[c,u]of Object.entries(l))for(const[i,o]of Object.entries(u))t.addRouteTranslations(i,c,M.mergeRouteTranslationsWithRoot(r[i],o),!1)}function Q(t){const{i18n:e,defaultLocale:r,locales:l,localeObjects:c,autoDetect:u=!0,redirectToDefault:i=!1,routingStrategy:o}=t,s=o||_();return async(a,n)=>{if(a.locals.locale&&a.locals.i18n)return n();const f=a.url,d=f.pathname;if(!s){const w=e.clone(r),g=d==="/"||d===""?"index":d.split("/").filter(Boolean).join("-");return w.setRoute(g),a.locals.i18n=w,a.locals.locale=r,a.locals.defaultLocale=r,a.locals.locales=c||l.map(L=>({code:L})),a.locals.currentUrl=f,n()}const h={...s,getCurrentPath:()=>d,getRoute:()=>({fullPath:f.pathname+f.search,query:Object.fromEntries(f.searchParams)})},m=d.split("/").filter(Boolean)[0],P=m!==void 0&&l.includes(m);let S;P&&m?S=m:h.getLocaleFromPath?S=h.getLocaleFromPath(d,r,l):S=r;const y=e.clone(S),T=h.getRouteName?h.getRouteName(d,l):"index";return y.setRoute(T),a.locals.i18n=y,a.locals.locale=S,a.locals.defaultLocale=r,a.locals.locales=c||l.map(w=>({code:w})),a.locals.currentUrl=f,a.locals.routingStrategy=h,H(h,()=>n())}}function X(t,e,r,l,c,u="i18n-locale",i){const o=i??_();let s=l;if(o?.getLocaleFromPath)s=o.getLocaleFromPath(t,l,c);else{const n=t.split("/").filter(Boolean)[0];n&&c.includes(n)&&(s=n)}if(u!==null&&s===l&&e.get(u)){const a=e.get(u)?.value;a&&c.includes(a)&&(s=a)}if(s===l)try{const a=V.detectLocaleFromAcceptLanguage(r.get("accept-language")??void 0,c);a&&(s=a)}catch{}return s}function Y(t,e,r){const l=t.map(n=>n.code),c=(n,f=[])=>{const d=n.replace(/^\//,"").replace(/\/$/,"");if(!d)return"index";const h=d.split("/").filter(Boolean),p=h[0];return p&&f.includes(p)&&h.shift(),h.length===0?"index":h.join("-")},u=(n,f="en",d=[])=>{const p=n.split("/").filter(Boolean)[0];return p&&d.includes(p)?p:f},i=(n,f,d=[],h)=>{const p=n.split("/").filter(Boolean),m=p[0];return m&&d.includes(m)&&p.shift(),(f!==h||h===void 0)&&p.unshift(f),`/${p.join("/")}`},o=(n,f,d=[],h)=>{const m=(n.replace(/^\//,"").replace(/\/$/,"")||"").split("/").filter(Boolean),P=m[0];return P&&d.includes(P)&&m.shift(),(f!==h||h===void 0)&&m.unshift(f),`/${m.join("/")}`};return{getCurrentPath:()=>r?r().pathname:typeof window<"u"?window.location.pathname:"/",getRouteName:c,getLocaleFromPath:u,switchLocalePath:i,localizePath:o,removeLocaleFromPath:(n,f=[])=>{const d=n.split("/").filter(Boolean),h=d[0];return h&&f.includes(h)&&d.shift(),`/${d.join("/")}`},resolvePath:(n,f)=>{const d=typeof n=="string"?n:n.path||"/";return o(d,f,l,e)},getRoute:()=>{if(r){const n=r();return{fullPath:n.pathname+n.search,query:Object.fromEntries(n.searchParams)}}if(typeof window<"u"){const n=new URL(window.location.href);return{fullPath:n.pathname+n.search,query:Object.fromEntries(n.searchParams)}}return{fullPath:"/",query:{}}},push:n=>{typeof window<"u"&&(window.location.href=n.path)},replace:n=>{typeof window<"u"&&window.location.replace(n.path)}}}function D(t){return t.iso?.trim()||String(t.code)}function N(t){const e=t.match(/^([A-Za-z]{2,3})(?:[-_](.+))?$/);return e?{language:e[1],region:e[2]}:{language:t}}function ee(t,e={}){const{hreflangBaseLanguage:r=!1}=e;if(!r)return t.map(i=>{const o=String(i.code);return{hreflang:D(i),localeCode:o}});const l=new Map;for(const i of t){const o=String(i.code),s=D(i),{language:a,region:n}=N(s);a&&n&&!l.has(a)&&l.set(a,o),l.set(s,o)}const c=new Set,u=[];for(const i of t){const o=String(i.code),s=D(i),{language:a,region:n}=N(s);a&&n&&l.get(a)===o&&!c.has(a)&&(c.add(a),u.push({hreflang:a,localeCode:o})),c.has(s)||(c.add(s),u.push({hreflang:s,localeCode:o}))}return u}function I(t){const e=t.og?.trim();if(e)return e;const r=t.iso?.trim();if(!r)return null;const l=r.indexOf("_");if(l>0){const u=r.slice(0,l),i=r.slice(l+1);if(u.length>=2&&i.length===2)return`${u.toLowerCase()}_${i.toUpperCase()}`}const c=r.indexOf("-");if(c>0){const u=r.slice(0,c),i=r.slice(c+1);if(u.length>=2&&i.length===2&&/^[A-Za-z]{2}$/.test(i))return`${u.toLowerCase()}_${i.toUpperCase()}`}return null}function A(t,e={}){if(I(t)!==null||e.missingWarn===!1||process.env.NODE_ENV==="production")return;const r=e.tag??"og:locale",l=String(t.code??"unknown"),c=t.iso?`, iso: '${t.iso}'`:"";console.warn(`[i18n] Cannot derive ${r} for locale '${l}'${c}. Set locale.og (e.g. 'en_US') or use iso with a 2-letter region (e.g. 'en-US').`)}function O(t){const e=t.locals.i18n;if(!e)throw new Error("i18n instance not found. Make sure i18n middleware is configured.");return e}function F(t){return t.locals.locale||"en"}function k(t){return t.locals.defaultLocale||"en"}function C(t){return t.locals.locales||[]}function x(t){return t.locals.routingStrategy||null}function te(t){const e=O(t),r=F(t),l=k(t),c=C(t),u=c.map(o=>o.code),i=x(t);return{locale:r,defaultLocale:l,locales:c,t:(o,s,a,n)=>e.t(o,s,a,n),ts:(o,s,a,n)=>e.ts(o,s,a,n),tc:(o,s,a)=>e.tc(o,s,a),tn:e.tn.bind(e),td:e.td.bind(e),tdr:e.tdr.bind(e),has:(o,s)=>e.has(o,s),getRoute:()=>e.getRoute(),getRouteName:o=>{const s=o||t.url.pathname;if(i?.getRouteName)return i.getRouteName(s,u);const a=s.replace(/^\//,"").replace(/\/$/,"");if(!a)return"index";const n=a.split("/").filter(Boolean),f=n[0];return f&&u.includes(f)&&n.shift(),n.length===0?"index":n.join("-")},getLocaleFromPath:o=>{const s=o||t.url.pathname;if(i?.getLocaleFromPath)return i.getLocaleFromPath(s,l,u);const n=s.split("/").filter(Boolean)[0];return n&&u.includes(n)?n:l},switchLocalePath:o=>{if(i?.switchLocalePath)return i.switchLocalePath(t.url.pathname,o,u,l);const s=t.url.pathname.split("/").filter(Boolean),a=s[0];return a&&u.includes(a)&&s.shift(),o!==l&&s.unshift(o),`/${s.join("/")}`},localizePath:(o,s)=>{if(i?.localizePath)return i.localizePath(o,s||r,u,l);const n=(o.replace(/^\//,"").replace(/\/$/,"")||"").split("/").filter(Boolean),f=n[0];return f&&u.includes(f)&&n.shift(),s&&s!==l&&n.unshift(s),`/${n.join("/")}`},getI18n:()=>e,getBasePath:o=>{const n=(o||t.url).pathname.split("/").filter(Boolean),f=n[0];return f&&u.includes(f)&&n.shift(),n.length>0?`/${n.join("/")}`:"/"},addTranslations:(o,s,a=!0)=>{e.addTranslations(o,s,a)},addRouteTranslations:(o,s,a,n=!0)=>{e.addRouteTranslations(o,s,a,n)},mergeTranslations:(o,s,a)=>{e.mergeTranslations(o,s,a)},clearCache:()=>{e.clearCache()}}}function ne(t,e={}){const{baseUrl:r="/",addDirAttribute:l=!0,addSeoAttributes:c=!0,hreflangBaseLanguage:u=!1}=e,i=F(t),o=k(t),a=C(t).filter(g=>!g.disabled),n=a.filter(g=>g.seo!==!1),f=a.find(g=>g.code===i);if(!f)return{htmlAttrs:{},link:[],meta:[]};const d=f.iso||i,h=I(f),p=f.dir||"auto",m={htmlAttrs:{lang:d,...l?{dir:p}:{}},link:[],meta:[]};if(!c)return m;const P=`${r}${t.url.pathname}`;m.link.push({rel:"canonical",href:P});const S=x(t),y=a.map(g=>g.code),T=new Map;for(const g of n){let L=t.url.pathname;if(S?.switchLocalePath)L=S.switchLocalePath(t.url.pathname,g.code,y,o);else{const b=t.url.pathname.split("/").filter(Boolean),B=b[0];B&&y.includes(B)&&b.shift(),g.code!==o&&b.unshift(g.code),L=`/${b.join("/")}`}T.set(String(g.code),`${r}${L}`)}for(const{hreflang:g,localeCode:L}of ee(n,{hreflangBaseLanguage:u})){const b=T.get(L);b&&m.link.push({rel:"alternate",href:b,hreflang:g})}if(a.find(g=>g.code===o)?.seo!==!1){let g=t.url.pathname;if(S?.switchLocalePath)g=S.switchLocalePath(t.url.pathname,o,y,o);else{const L=t.url.pathname.split("/").filter(Boolean),b=L[0];b&&y.includes(b)&&L.shift(),g=`/${L.join("/")}`}m.link.push({rel:"alternate",href:`${r}${g}`,hreflang:"x-default"})}h?m.meta.push({property:"og:locale",content:h}):A(f,{tag:"og:locale"}),m.meta.push({property:"og:url",content:P});for(const g of n){if(g.code===i)continue;const L=I(g);if(!L){A(g,{tag:"og:locale:alternate"});continue}m.meta.push({property:"og:locale:alternate",content:L})}return m}function oe(t,e,r){const l=e.split(".");let c=t;for(let i=0;i<l.length-1;i++){const o=l[i];c[o]||(c[o]={}),c=c[o]}const u=l[l.length-1];u!==void 0&&(c[u]=r)}function ae(t,e){const r=O(t),l=F(t),c=k(t),u=r.getRoute(),i={};if(e&&e.length>0){const o={};for(const s of e){const a=r.t(s,void 0,void 0,u);a!=null&&a!==s&&oe(o,s,a)}Object.keys(o).length>0&&(i[u]=o)}else{const o=r.getRouteTranslations(l,u);o&&(i[u]=o)}return{locale:l,fallbackLocale:c,currentRoute:u,translations:i}}Object.defineProperty(exports,"FormatService",{enumerable:!0,get:()=>j.FormatService});Object.defineProperty(exports,"defaultPlural",{enumerable:!0,get:()=>j.defaultPlural});Object.defineProperty(exports,"interpolate",{enumerable:!0,get:()=>j.interpolate});exports.AstroI18n=v;exports.createAstroRouterAdapter=Y;exports.createI18n=Z;exports.createI18nMiddleware=Q;exports.detectLocale=X;exports.getDefaultLocale=k;exports.getGlobalRoutingStrategy=_;exports.getI18n=O;exports.getI18nProps=ae;exports.getLocale=F;exports.getLocales=C;exports.i18nIntegration=J;exports.loadTranslationsFromDir=E;exports.loadTranslationsIntoI18n=K;exports.runWithRoutingStrategy=H;exports.setGlobalRoutingStrategy=U;exports.useI18n=te;exports.useLocaleHead=ne;
|
package/dist/index.mjs
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
import { BaseI18n as
|
|
2
|
-
import { FormatService as
|
|
3
|
-
import { AsyncLocalStorage as
|
|
4
|
-
import { existsSync as
|
|
5
|
-
import { resolve as
|
|
6
|
-
import { mergeRouteTranslationsWithRoot as
|
|
7
|
-
import { detectLocaleFromAcceptLanguage as
|
|
8
|
-
class
|
|
1
|
+
import { BaseI18n as U } from "@i18n-micro/core";
|
|
2
|
+
import { FormatService as be, defaultPlural as ye, interpolate as we } from "@i18n-micro/core";
|
|
3
|
+
import { AsyncLocalStorage as q } from "node:async_hooks";
|
|
4
|
+
import { existsSync as _, readdirSync as z, statSync as E, readFileSync as H } from "node:fs";
|
|
5
|
+
import { resolve as x, join as V, relative as G, sep as J } from "node:path";
|
|
6
|
+
import { mergeRouteTranslationsWithRoot as Z, storeLoadedTranslationFile as K } from "@i18n-micro/utils/parse-path";
|
|
7
|
+
import { detectLocaleFromAcceptLanguage as Q } from "@i18n-micro/utils/accept-language";
|
|
8
|
+
class v extends U {
|
|
9
9
|
constructor(e) {
|
|
10
|
-
const
|
|
10
|
+
const r = e._storage || {
|
|
11
11
|
translations: /* @__PURE__ */ new Map()
|
|
12
12
|
};
|
|
13
13
|
if (super({
|
|
14
|
-
storage:
|
|
14
|
+
storage: r,
|
|
15
15
|
plural: e.plural,
|
|
16
16
|
missingWarn: e.missingWarn,
|
|
17
17
|
missingHandler: e.missingHandler,
|
|
18
18
|
numberFormats: e.numberFormats,
|
|
19
19
|
datetimeFormats: e.datetimeFormats
|
|
20
|
-
}), this.initialMessages = {}, this.storage =
|
|
20
|
+
}), this.initialMessages = {}, this.storage = r, this._locale = e.locale, this._fallbackLocale = e.fallbackLocale || e.locale, this._currentRoute = "index", e.messages) {
|
|
21
21
|
this.initialMessages = { ...e.messages };
|
|
22
|
-
for (const [
|
|
23
|
-
this.helper.loadTranslations(
|
|
22
|
+
for (const [l, c] of Object.entries(e.messages))
|
|
23
|
+
this.helper.loadTranslations(l, c);
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
cloneStorage(e) {
|
|
27
|
-
const
|
|
28
|
-
for (const [
|
|
29
|
-
|
|
30
|
-
return { translations:
|
|
27
|
+
const r = /* @__PURE__ */ new Map();
|
|
28
|
+
for (const [l, c] of e.translations)
|
|
29
|
+
r.set(l, { ...c });
|
|
30
|
+
return { translations: r };
|
|
31
31
|
}
|
|
32
32
|
clone(e) {
|
|
33
|
-
const
|
|
34
|
-
return new
|
|
33
|
+
const r = this.cloneStorage(this.storage);
|
|
34
|
+
return new v({
|
|
35
35
|
locale: e || this._locale,
|
|
36
36
|
fallbackLocale: this._fallbackLocale,
|
|
37
37
|
plural: this.pluralFunc,
|
|
@@ -39,7 +39,7 @@ class T extends W {
|
|
|
39
39
|
missingHandler: this.missingHandler,
|
|
40
40
|
numberFormats: this.formatter.getNumberFormats(),
|
|
41
41
|
datetimeFormats: this.formatter.getDateTimeFormats(),
|
|
42
|
-
_storage:
|
|
42
|
+
_storage: r
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
45
|
get locale() {
|
|
@@ -66,68 +66,68 @@ class T extends W {
|
|
|
66
66
|
getRoute() {
|
|
67
67
|
return this._currentRoute;
|
|
68
68
|
}
|
|
69
|
-
getRouteTranslations(e,
|
|
70
|
-
const
|
|
71
|
-
return this.storage.translations.get(
|
|
69
|
+
getRouteTranslations(e, r) {
|
|
70
|
+
const l = `${e}:${r}`;
|
|
71
|
+
return this.storage.translations.get(l) ?? null;
|
|
72
72
|
}
|
|
73
|
-
addTranslations(e,
|
|
74
|
-
super.loadTranslationsCore(e,
|
|
73
|
+
addTranslations(e, r, l = !0) {
|
|
74
|
+
super.loadTranslationsCore(e, r, l);
|
|
75
75
|
}
|
|
76
|
-
addRouteTranslations(e,
|
|
77
|
-
super.loadRouteTranslationsCore(e,
|
|
76
|
+
addRouteTranslations(e, r, l, c = !0) {
|
|
77
|
+
super.loadRouteTranslationsCore(e, r, l, c);
|
|
78
78
|
}
|
|
79
|
-
mergeTranslations(e,
|
|
80
|
-
this.helper.mergeTranslation(e,
|
|
79
|
+
mergeTranslations(e, r, l) {
|
|
80
|
+
this.helper.mergeTranslation(e, r, l, !0);
|
|
81
81
|
}
|
|
82
82
|
clearCache() {
|
|
83
83
|
const e = { ...this.initialMessages };
|
|
84
84
|
if (super.clearCache(), Object.keys(e).length > 0)
|
|
85
|
-
for (const [
|
|
86
|
-
this.helper.loadTranslations(
|
|
85
|
+
for (const [r, l] of Object.entries(e))
|
|
86
|
+
this.helper.loadTranslations(r, l);
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
|
-
let
|
|
90
|
-
const
|
|
91
|
-
function
|
|
92
|
-
const t =
|
|
93
|
-
return t !== void 0 ? t :
|
|
89
|
+
let B = null;
|
|
90
|
+
const O = new q();
|
|
91
|
+
function I() {
|
|
92
|
+
const t = O.getStore();
|
|
93
|
+
return t !== void 0 ? t : B;
|
|
94
94
|
}
|
|
95
|
-
function
|
|
96
|
-
|
|
95
|
+
function X(t) {
|
|
96
|
+
B = t;
|
|
97
97
|
}
|
|
98
|
-
function
|
|
99
|
-
return
|
|
98
|
+
function Y(t, e) {
|
|
99
|
+
return O.run(t, e);
|
|
100
100
|
}
|
|
101
|
-
function
|
|
102
|
-
const { locale: e, fallbackLocale:
|
|
103
|
-
return
|
|
101
|
+
function ce(t) {
|
|
102
|
+
const { locale: e, fallbackLocale: r, translationDir: l, routingStrategy: c } = t;
|
|
103
|
+
return X(c || null), {
|
|
104
104
|
name: "@i18n-micro/astro",
|
|
105
105
|
hooks: {
|
|
106
106
|
// 1. Vite setup (virtual module) happens here
|
|
107
|
-
"astro:config:setup": (
|
|
108
|
-
const { updateConfig:
|
|
107
|
+
"astro:config:setup": (u) => {
|
|
108
|
+
const { updateConfig: i } = u, o = "virtual:i18n-micro/config", s = `\0${o}`, a = {
|
|
109
109
|
defaultLocale: e,
|
|
110
|
-
fallbackLocale:
|
|
110
|
+
fallbackLocale: r || e,
|
|
111
111
|
locales: t.locales || [],
|
|
112
112
|
localeCodes: (t.locales || []).map((n) => n.code),
|
|
113
|
-
translationDir:
|
|
113
|
+
translationDir: l || null,
|
|
114
114
|
autoDetect: t.autoDetect ?? !0,
|
|
115
115
|
redirectToDefault: t.redirectToDefault ?? !1,
|
|
116
116
|
localeCookie: t.localeCookie === null ? null : t.localeCookie || "i18n-locale",
|
|
117
117
|
missingWarn: t.missingWarn ?? !1
|
|
118
118
|
};
|
|
119
|
-
|
|
119
|
+
i({
|
|
120
120
|
vite: {
|
|
121
121
|
plugins: [
|
|
122
122
|
{
|
|
123
123
|
name: "vite-plugin-i18n-micro-config",
|
|
124
124
|
resolveId(n) {
|
|
125
|
-
if (n ===
|
|
126
|
-
return
|
|
125
|
+
if (n === o)
|
|
126
|
+
return s;
|
|
127
127
|
},
|
|
128
128
|
load(n) {
|
|
129
|
-
if (n ===
|
|
130
|
-
return `export const config = ${JSON.stringify(
|
|
129
|
+
if (n === s)
|
|
130
|
+
return `export const config = ${JSON.stringify(a)}`;
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
133
|
]
|
|
@@ -135,9 +135,9 @@ function le(t) {
|
|
|
135
135
|
});
|
|
136
136
|
},
|
|
137
137
|
// 2. Type injection happens here (per Astro documentation)
|
|
138
|
-
"astro:config:done": (
|
|
139
|
-
const { injectTypes:
|
|
140
|
-
|
|
138
|
+
"astro:config:done": (u) => {
|
|
139
|
+
const { injectTypes: i } = u;
|
|
140
|
+
i({
|
|
141
141
|
filename: "i18n-micro-env.d.ts",
|
|
142
142
|
content: `
|
|
143
143
|
/// <reference types="@i18n-micro/astro/env" />
|
|
@@ -161,131 +161,131 @@ function le(t) {
|
|
|
161
161
|
}
|
|
162
162
|
};
|
|
163
163
|
}
|
|
164
|
-
function
|
|
165
|
-
return new
|
|
164
|
+
function ue(t) {
|
|
165
|
+
return new v(t);
|
|
166
166
|
}
|
|
167
|
-
function
|
|
168
|
-
if (
|
|
169
|
-
for (const
|
|
170
|
-
const
|
|
171
|
-
if (
|
|
172
|
-
|
|
167
|
+
function N(t, e) {
|
|
168
|
+
if (_(t))
|
|
169
|
+
for (const r of z(t)) {
|
|
170
|
+
const l = V(t, r);
|
|
171
|
+
if (E(l).isDirectory()) {
|
|
172
|
+
N(l, e);
|
|
173
173
|
continue;
|
|
174
174
|
}
|
|
175
|
-
|
|
175
|
+
r.endsWith(".json") && e(l);
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
|
-
function
|
|
179
|
-
const { translationDir: e, rootDir:
|
|
180
|
-
if (!
|
|
181
|
-
return console.warn(`[i18n] Translation directory not found: ${
|
|
182
|
-
const
|
|
183
|
-
return
|
|
184
|
-
const
|
|
178
|
+
function ee(t) {
|
|
179
|
+
const { translationDir: e, rootDir: r = process.cwd(), disablePageLocales: l = !1 } = t, c = x(r, e);
|
|
180
|
+
if (!_(c))
|
|
181
|
+
return console.warn(`[i18n] Translation directory not found: ${c}`), { root: {}, routes: {} };
|
|
182
|
+
const u = { root: {}, routes: {} };
|
|
183
|
+
return N(c, (i) => {
|
|
184
|
+
const o = G(c, i).split(J).join("/");
|
|
185
185
|
try {
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
} catch (
|
|
189
|
-
console.error(`[i18n] Failed to load translation file: ${
|
|
186
|
+
const s = H(i, "utf-8"), a = JSON.parse(s);
|
|
187
|
+
K(u, o, a, l);
|
|
188
|
+
} catch (s) {
|
|
189
|
+
console.error(`[i18n] Failed to load translation file: ${i}`, s);
|
|
190
190
|
}
|
|
191
|
-
}),
|
|
191
|
+
}), u;
|
|
192
192
|
}
|
|
193
|
-
function
|
|
194
|
-
const { root:
|
|
195
|
-
for (const [
|
|
196
|
-
t.addTranslations(
|
|
197
|
-
for (const [
|
|
198
|
-
for (const [
|
|
199
|
-
t.addRouteTranslations(
|
|
193
|
+
function fe(t, e) {
|
|
194
|
+
const { root: r, routes: l } = ee(e);
|
|
195
|
+
for (const [c, u] of Object.entries(r))
|
|
196
|
+
t.addTranslations(c, u, !1);
|
|
197
|
+
for (const [c, u] of Object.entries(l))
|
|
198
|
+
for (const [i, o] of Object.entries(u))
|
|
199
|
+
t.addRouteTranslations(i, c, Z(r[i], o), !1);
|
|
200
200
|
}
|
|
201
|
-
function
|
|
201
|
+
function ge(t) {
|
|
202
202
|
const {
|
|
203
203
|
i18n: e,
|
|
204
204
|
// This is the global singleton with cache
|
|
205
|
-
defaultLocale:
|
|
206
|
-
locales:
|
|
207
|
-
localeObjects:
|
|
208
|
-
autoDetect:
|
|
209
|
-
redirectToDefault:
|
|
210
|
-
routingStrategy:
|
|
211
|
-
} = t,
|
|
212
|
-
return async (
|
|
213
|
-
if (
|
|
205
|
+
defaultLocale: r,
|
|
206
|
+
locales: l,
|
|
207
|
+
localeObjects: c,
|
|
208
|
+
autoDetect: u = !0,
|
|
209
|
+
redirectToDefault: i = !1,
|
|
210
|
+
routingStrategy: o
|
|
211
|
+
} = t, s = o || I();
|
|
212
|
+
return async (a, n) => {
|
|
213
|
+
if (a.locals.locale && a.locals.i18n)
|
|
214
214
|
return n();
|
|
215
|
-
const f =
|
|
216
|
-
if (!
|
|
217
|
-
const
|
|
218
|
-
return
|
|
215
|
+
const f = a.url, h = f.pathname;
|
|
216
|
+
if (!s) {
|
|
217
|
+
const w = e.clone(r), g = h === "/" || h === "" ? "index" : h.split("/").filter(Boolean).join("-");
|
|
218
|
+
return w.setRoute(g), a.locals.i18n = w, a.locals.locale = r, a.locals.defaultLocale = r, a.locals.locales = c || l.map((L) => ({ code: L })), a.locals.currentUrl = f, n();
|
|
219
219
|
}
|
|
220
220
|
const d = {
|
|
221
|
-
...
|
|
221
|
+
...s,
|
|
222
222
|
getCurrentPath: () => h,
|
|
223
223
|
getRoute: () => ({
|
|
224
224
|
fullPath: f.pathname + f.search,
|
|
225
225
|
query: Object.fromEntries(f.searchParams)
|
|
226
226
|
})
|
|
227
|
-
},
|
|
228
|
-
let
|
|
229
|
-
b &&
|
|
230
|
-
const
|
|
231
|
-
return
|
|
227
|
+
}, m = h.split("/").filter(Boolean)[0], b = m !== void 0 && l.includes(m);
|
|
228
|
+
let S;
|
|
229
|
+
b && m ? S = m : d.getLocaleFromPath ? S = d.getLocaleFromPath(h, r, l) : S = r;
|
|
230
|
+
const y = e.clone(S), R = d.getRouteName ? d.getRouteName(h, l) : "index";
|
|
231
|
+
return y.setRoute(R), a.locals.i18n = y, a.locals.locale = S, a.locals.defaultLocale = r, a.locals.locales = c || l.map((w) => ({ code: w })), a.locals.currentUrl = f, a.locals.routingStrategy = d, Y(d, () => n());
|
|
232
232
|
};
|
|
233
233
|
}
|
|
234
|
-
function
|
|
235
|
-
const
|
|
236
|
-
let
|
|
237
|
-
if (
|
|
238
|
-
|
|
234
|
+
function he(t, e, r, l, c, u = "i18n-locale", i) {
|
|
235
|
+
const o = i ?? I();
|
|
236
|
+
let s = l;
|
|
237
|
+
if (o?.getLocaleFromPath)
|
|
238
|
+
s = o.getLocaleFromPath(t, l, c);
|
|
239
239
|
else {
|
|
240
240
|
const n = t.split("/").filter(Boolean)[0];
|
|
241
|
-
n &&
|
|
241
|
+
n && c.includes(n) && (s = n);
|
|
242
242
|
}
|
|
243
|
-
if (
|
|
244
|
-
const
|
|
245
|
-
|
|
243
|
+
if (u !== null && s === l && e.get(u)) {
|
|
244
|
+
const a = e.get(u)?.value;
|
|
245
|
+
a && c.includes(a) && (s = a);
|
|
246
246
|
}
|
|
247
|
-
if (
|
|
247
|
+
if (s === l)
|
|
248
248
|
try {
|
|
249
|
-
const
|
|
250
|
-
|
|
249
|
+
const a = Q(r.get("accept-language") ?? void 0, c);
|
|
250
|
+
a && (s = a);
|
|
251
251
|
} catch {
|
|
252
252
|
}
|
|
253
|
-
return
|
|
253
|
+
return s;
|
|
254
254
|
}
|
|
255
|
-
function
|
|
256
|
-
const
|
|
255
|
+
function de(t, e, r) {
|
|
256
|
+
const l = t.map((n) => n.code), c = (n, f = []) => {
|
|
257
257
|
const h = n.replace(/^\//, "").replace(/\/$/, "");
|
|
258
258
|
if (!h)
|
|
259
259
|
return "index";
|
|
260
|
-
const d = h.split("/").filter(Boolean),
|
|
261
|
-
return
|
|
262
|
-
},
|
|
263
|
-
const
|
|
264
|
-
return
|
|
265
|
-
},
|
|
266
|
-
const
|
|
267
|
-
return
|
|
268
|
-
},
|
|
269
|
-
const
|
|
270
|
-
return b && h.includes(b) &&
|
|
260
|
+
const d = h.split("/").filter(Boolean), p = d[0];
|
|
261
|
+
return p && f.includes(p) && d.shift(), d.length === 0 ? "index" : d.join("-");
|
|
262
|
+
}, u = (n, f = "en", h = []) => {
|
|
263
|
+
const p = n.split("/").filter(Boolean)[0];
|
|
264
|
+
return p && h.includes(p) ? p : f;
|
|
265
|
+
}, i = (n, f, h = [], d) => {
|
|
266
|
+
const p = n.split("/").filter(Boolean), m = p[0];
|
|
267
|
+
return m && h.includes(m) && p.shift(), (f !== d || d === void 0) && p.unshift(f), `/${p.join("/")}`;
|
|
268
|
+
}, o = (n, f, h = [], d) => {
|
|
269
|
+
const m = (n.replace(/^\//, "").replace(/\/$/, "") || "").split("/").filter(Boolean), b = m[0];
|
|
270
|
+
return b && h.includes(b) && m.shift(), (f !== d || d === void 0) && m.unshift(f), `/${m.join("/")}`;
|
|
271
271
|
};
|
|
272
272
|
return {
|
|
273
|
-
getCurrentPath: () =>
|
|
274
|
-
getRouteName:
|
|
275
|
-
getLocaleFromPath:
|
|
276
|
-
switchLocalePath:
|
|
277
|
-
localizePath:
|
|
273
|
+
getCurrentPath: () => r ? r().pathname : typeof window < "u" ? window.location.pathname : "/",
|
|
274
|
+
getRouteName: c,
|
|
275
|
+
getLocaleFromPath: u,
|
|
276
|
+
switchLocalePath: i,
|
|
277
|
+
localizePath: o,
|
|
278
278
|
removeLocaleFromPath: (n, f = []) => {
|
|
279
279
|
const h = n.split("/").filter(Boolean), d = h[0];
|
|
280
280
|
return d && f.includes(d) && h.shift(), `/${h.join("/")}`;
|
|
281
281
|
},
|
|
282
282
|
resolvePath: (n, f) => {
|
|
283
283
|
const h = typeof n == "string" ? n : n.path || "/";
|
|
284
|
-
return
|
|
284
|
+
return o(h, f, l, e);
|
|
285
285
|
},
|
|
286
286
|
getRoute: () => {
|
|
287
|
-
if (
|
|
288
|
-
const n =
|
|
287
|
+
if (r) {
|
|
288
|
+
const n = r();
|
|
289
289
|
return {
|
|
290
290
|
fullPath: n.pathname + n.search,
|
|
291
291
|
query: Object.fromEntries(n.searchParams)
|
|
@@ -312,183 +312,208 @@ function ue(t, e, o) {
|
|
|
312
312
|
}
|
|
313
313
|
};
|
|
314
314
|
}
|
|
315
|
-
function
|
|
315
|
+
function T(t) {
|
|
316
|
+
return t.iso?.trim() || String(t.code);
|
|
317
|
+
}
|
|
318
|
+
function D(t) {
|
|
319
|
+
const e = t.match(/^([A-Za-z]{2,3})(?:[-_](.+))?$/);
|
|
320
|
+
return e ? { language: e[1], region: e[2] } : { language: t };
|
|
321
|
+
}
|
|
322
|
+
function te(t, e = {}) {
|
|
323
|
+
const { hreflangBaseLanguage: r = !1 } = e;
|
|
324
|
+
if (!r)
|
|
325
|
+
return t.map((i) => {
|
|
326
|
+
const o = String(i.code);
|
|
327
|
+
return { hreflang: T(i), localeCode: o };
|
|
328
|
+
});
|
|
329
|
+
const l = /* @__PURE__ */ new Map();
|
|
330
|
+
for (const i of t) {
|
|
331
|
+
const o = String(i.code), s = T(i), { language: a, region: n } = D(s);
|
|
332
|
+
a && n && !l.has(a) && l.set(a, o), l.set(s, o);
|
|
333
|
+
}
|
|
334
|
+
const c = /* @__PURE__ */ new Set(), u = [];
|
|
335
|
+
for (const i of t) {
|
|
336
|
+
const o = String(i.code), s = T(i), { language: a, region: n } = D(s);
|
|
337
|
+
a && n && l.get(a) === o && !c.has(a) && (c.add(a), u.push({ hreflang: a, localeCode: o })), c.has(s) || (c.add(s), u.push({ hreflang: s, localeCode: o }));
|
|
338
|
+
}
|
|
339
|
+
return u;
|
|
340
|
+
}
|
|
341
|
+
function $(t) {
|
|
316
342
|
const e = t.og?.trim();
|
|
317
343
|
if (e) return e;
|
|
318
|
-
const
|
|
319
|
-
if (!
|
|
320
|
-
const
|
|
321
|
-
if (
|
|
322
|
-
const
|
|
323
|
-
if (
|
|
324
|
-
return `${
|
|
344
|
+
const r = t.iso?.trim();
|
|
345
|
+
if (!r) return null;
|
|
346
|
+
const l = r.indexOf("_");
|
|
347
|
+
if (l > 0) {
|
|
348
|
+
const u = r.slice(0, l), i = r.slice(l + 1);
|
|
349
|
+
if (u.length >= 2 && i.length === 2)
|
|
350
|
+
return `${u.toLowerCase()}_${i.toUpperCase()}`;
|
|
325
351
|
}
|
|
326
|
-
const
|
|
327
|
-
if (
|
|
328
|
-
const
|
|
329
|
-
if (
|
|
330
|
-
return `${
|
|
352
|
+
const c = r.indexOf("-");
|
|
353
|
+
if (c > 0) {
|
|
354
|
+
const u = r.slice(0, c), i = r.slice(c + 1);
|
|
355
|
+
if (u.length >= 2 && i.length === 2 && /^[A-Za-z]{2}$/.test(i))
|
|
356
|
+
return `${u.toLowerCase()}_${i.toUpperCase()}`;
|
|
331
357
|
}
|
|
332
358
|
return null;
|
|
333
359
|
}
|
|
334
|
-
function
|
|
335
|
-
if (
|
|
336
|
-
const
|
|
360
|
+
function C(t, e = {}) {
|
|
361
|
+
if ($(t) !== null || e.missingWarn === !1 || process.env.NODE_ENV === "production") return;
|
|
362
|
+
const r = e.tag ?? "og:locale", l = String(t.code ?? "unknown"), c = t.iso ? `, iso: '${t.iso}'` : "";
|
|
337
363
|
console.warn(
|
|
338
|
-
`[i18n] Cannot derive ${
|
|
364
|
+
`[i18n] Cannot derive ${r} for locale '${l}'${c}. Set locale.og (e.g. 'en_US') or use iso with a 2-letter region (e.g. 'en-US').`
|
|
339
365
|
);
|
|
340
366
|
}
|
|
341
|
-
function
|
|
367
|
+
function M(t) {
|
|
342
368
|
const e = t.locals.i18n;
|
|
343
369
|
if (!e)
|
|
344
370
|
throw new Error("i18n instance not found. Make sure i18n middleware is configured.");
|
|
345
371
|
return e;
|
|
346
372
|
}
|
|
347
|
-
function
|
|
373
|
+
function j(t) {
|
|
348
374
|
return t.locals.locale || "en";
|
|
349
375
|
}
|
|
350
|
-
function
|
|
376
|
+
function k(t) {
|
|
351
377
|
return t.locals.defaultLocale || "en";
|
|
352
378
|
}
|
|
353
|
-
function
|
|
379
|
+
function A(t) {
|
|
354
380
|
return t.locals.locales || [];
|
|
355
381
|
}
|
|
356
|
-
function
|
|
382
|
+
function W(t) {
|
|
357
383
|
return t.locals.routingStrategy || null;
|
|
358
384
|
}
|
|
359
|
-
function
|
|
360
|
-
const e =
|
|
385
|
+
function me(t) {
|
|
386
|
+
const e = M(t), r = j(t), l = k(t), c = A(t), u = c.map((o) => o.code), i = W(t);
|
|
361
387
|
return {
|
|
362
388
|
// Current locale
|
|
363
|
-
locale:
|
|
364
|
-
defaultLocale:
|
|
365
|
-
locales:
|
|
389
|
+
locale: r,
|
|
390
|
+
defaultLocale: l,
|
|
391
|
+
locales: c,
|
|
366
392
|
// Translation methods
|
|
367
|
-
t: (
|
|
368
|
-
ts: (
|
|
369
|
-
tc: (
|
|
393
|
+
t: (o, s, a, n) => e.t(o, s, a, n),
|
|
394
|
+
ts: (o, s, a, n) => e.ts(o, s, a, n),
|
|
395
|
+
tc: (o, s, a) => e.tc(o, s, a),
|
|
370
396
|
tn: e.tn.bind(e),
|
|
371
397
|
td: e.td.bind(e),
|
|
372
398
|
tdr: e.tdr.bind(e),
|
|
373
|
-
has: (
|
|
399
|
+
has: (o, s) => e.has(o, s),
|
|
374
400
|
// Route management
|
|
375
401
|
getRoute: () => e.getRoute(),
|
|
376
|
-
getRouteName: (
|
|
377
|
-
const
|
|
378
|
-
if (
|
|
379
|
-
return
|
|
380
|
-
const
|
|
381
|
-
if (!
|
|
382
|
-
const n =
|
|
383
|
-
return f &&
|
|
402
|
+
getRouteName: (o) => {
|
|
403
|
+
const s = o || t.url.pathname;
|
|
404
|
+
if (i?.getRouteName)
|
|
405
|
+
return i.getRouteName(s, u);
|
|
406
|
+
const a = s.replace(/^\//, "").replace(/\/$/, "");
|
|
407
|
+
if (!a) return "index";
|
|
408
|
+
const n = a.split("/").filter(Boolean), f = n[0];
|
|
409
|
+
return f && u.includes(f) && n.shift(), n.length === 0 ? "index" : n.join("-");
|
|
384
410
|
},
|
|
385
|
-
getLocaleFromPath: (
|
|
386
|
-
const
|
|
387
|
-
if (
|
|
388
|
-
return
|
|
389
|
-
const n =
|
|
390
|
-
return n &&
|
|
411
|
+
getLocaleFromPath: (o) => {
|
|
412
|
+
const s = o || t.url.pathname;
|
|
413
|
+
if (i?.getLocaleFromPath)
|
|
414
|
+
return i.getLocaleFromPath(s, l, u);
|
|
415
|
+
const n = s.split("/").filter(Boolean)[0];
|
|
416
|
+
return n && u.includes(n) ? n : l;
|
|
391
417
|
},
|
|
392
418
|
// Path utilities
|
|
393
|
-
switchLocalePath: (
|
|
394
|
-
if (
|
|
395
|
-
return
|
|
396
|
-
const
|
|
397
|
-
return
|
|
419
|
+
switchLocalePath: (o) => {
|
|
420
|
+
if (i?.switchLocalePath)
|
|
421
|
+
return i.switchLocalePath(t.url.pathname, o, u, l);
|
|
422
|
+
const s = t.url.pathname.split("/").filter(Boolean), a = s[0];
|
|
423
|
+
return a && u.includes(a) && s.shift(), o !== l && s.unshift(o), `/${s.join("/")}`;
|
|
398
424
|
},
|
|
399
|
-
localizePath: (
|
|
400
|
-
if (
|
|
401
|
-
return
|
|
402
|
-
const n = (
|
|
403
|
-
return f &&
|
|
425
|
+
localizePath: (o, s) => {
|
|
426
|
+
if (i?.localizePath)
|
|
427
|
+
return i.localizePath(o, s || r, u, l);
|
|
428
|
+
const n = (o.replace(/^\//, "").replace(/\/$/, "") || "").split("/").filter(Boolean), f = n[0];
|
|
429
|
+
return f && u.includes(f) && n.shift(), s && s !== l && n.unshift(s), `/${n.join("/")}`;
|
|
404
430
|
},
|
|
405
431
|
// Get i18n instance
|
|
406
432
|
getI18n: () => e,
|
|
407
433
|
// Get base path without locale (for rewrite)
|
|
408
|
-
getBasePath: (
|
|
409
|
-
const n = (
|
|
410
|
-
return f &&
|
|
434
|
+
getBasePath: (o) => {
|
|
435
|
+
const n = (o || t.url).pathname.split("/").filter(Boolean), f = n[0];
|
|
436
|
+
return f && u.includes(f) && n.shift(), n.length > 0 ? `/${n.join("/")}` : "/";
|
|
411
437
|
},
|
|
412
438
|
// Translation management
|
|
413
|
-
addTranslations: (
|
|
414
|
-
e.addTranslations(
|
|
439
|
+
addTranslations: (o, s, a = !0) => {
|
|
440
|
+
e.addTranslations(o, s, a);
|
|
415
441
|
},
|
|
416
|
-
addRouteTranslations: (
|
|
417
|
-
e.addRouteTranslations(
|
|
442
|
+
addRouteTranslations: (o, s, a, n = !0) => {
|
|
443
|
+
e.addRouteTranslations(o, s, a, n);
|
|
418
444
|
},
|
|
419
|
-
mergeTranslations: (
|
|
420
|
-
e.mergeTranslations(
|
|
445
|
+
mergeTranslations: (o, s, a) => {
|
|
446
|
+
e.mergeTranslations(o, s, a);
|
|
421
447
|
},
|
|
422
448
|
clearCache: () => {
|
|
423
449
|
e.clearCache();
|
|
424
450
|
}
|
|
425
451
|
};
|
|
426
452
|
}
|
|
427
|
-
function
|
|
428
|
-
const { baseUrl:
|
|
429
|
-
if (!
|
|
453
|
+
function pe(t, e = {}) {
|
|
454
|
+
const { baseUrl: r = "/", addDirAttribute: l = !0, addSeoAttributes: c = !0, hreflangBaseLanguage: u = !1 } = e, i = j(t), o = k(t), a = A(t).filter((g) => !g.disabled), n = a.filter((g) => g.seo !== !1), f = a.find((g) => g.code === i);
|
|
455
|
+
if (!f)
|
|
430
456
|
return { htmlAttrs: {}, link: [], meta: [] };
|
|
431
|
-
const
|
|
457
|
+
const h = f.iso || i, d = $(f), p = f.dir || "auto", m = {
|
|
432
458
|
htmlAttrs: {
|
|
433
|
-
lang:
|
|
434
|
-
...
|
|
459
|
+
lang: h,
|
|
460
|
+
...l ? { dir: p } : {}
|
|
435
461
|
},
|
|
436
462
|
link: [],
|
|
437
463
|
meta: []
|
|
438
464
|
};
|
|
439
|
-
if (!
|
|
465
|
+
if (!c)
|
|
440
466
|
return m;
|
|
441
|
-
const
|
|
467
|
+
const b = `${r}${t.url.pathname}`;
|
|
442
468
|
m.link.push({
|
|
443
469
|
rel: "canonical",
|
|
444
|
-
href:
|
|
470
|
+
href: b
|
|
445
471
|
});
|
|
446
|
-
const
|
|
447
|
-
for (const g of
|
|
472
|
+
const S = W(t), y = a.map((g) => g.code), R = /* @__PURE__ */ new Map();
|
|
473
|
+
for (const g of n) {
|
|
448
474
|
let L = t.url.pathname;
|
|
449
|
-
if (
|
|
450
|
-
L =
|
|
475
|
+
if (S?.switchLocalePath)
|
|
476
|
+
L = S.switchLocalePath(t.url.pathname, g.code, y, o);
|
|
451
477
|
else {
|
|
452
|
-
const
|
|
453
|
-
|
|
478
|
+
const P = t.url.pathname.split("/").filter(Boolean), F = P[0];
|
|
479
|
+
F && y.includes(F) && P.shift(), g.code !== o && P.unshift(g.code), L = `/${P.join("/")}`;
|
|
454
480
|
}
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
}), g.iso && g.iso !== g.code && m.link.push({
|
|
481
|
+
R.set(String(g.code), `${r}${L}`);
|
|
482
|
+
}
|
|
483
|
+
for (const { hreflang: g, localeCode: L } of te(n, { hreflangBaseLanguage: u })) {
|
|
484
|
+
const P = R.get(L);
|
|
485
|
+
P && m.link.push({
|
|
461
486
|
rel: "alternate",
|
|
462
|
-
href:
|
|
463
|
-
hreflang: g
|
|
487
|
+
href: P,
|
|
488
|
+
hreflang: g
|
|
464
489
|
});
|
|
465
490
|
}
|
|
466
|
-
if (
|
|
491
|
+
if (a.find((g) => g.code === o)?.seo !== !1) {
|
|
467
492
|
let g = t.url.pathname;
|
|
468
|
-
if (
|
|
469
|
-
g =
|
|
493
|
+
if (S?.switchLocalePath)
|
|
494
|
+
g = S.switchLocalePath(t.url.pathname, o, y, o);
|
|
470
495
|
else {
|
|
471
|
-
const L = t.url.pathname.split("/").filter(Boolean),
|
|
472
|
-
|
|
496
|
+
const L = t.url.pathname.split("/").filter(Boolean), P = L[0];
|
|
497
|
+
P && y.includes(P) && L.shift(), g = `/${L.join("/")}`;
|
|
473
498
|
}
|
|
474
499
|
m.link.push({
|
|
475
500
|
rel: "alternate",
|
|
476
|
-
href: `${
|
|
501
|
+
href: `${r}${g}`,
|
|
477
502
|
hreflang: "x-default"
|
|
478
503
|
});
|
|
479
504
|
}
|
|
480
|
-
|
|
505
|
+
d ? m.meta.push({
|
|
481
506
|
property: "og:locale",
|
|
482
|
-
content:
|
|
483
|
-
}) :
|
|
507
|
+
content: d
|
|
508
|
+
}) : C(f, { tag: "og:locale" }), m.meta.push({
|
|
484
509
|
property: "og:url",
|
|
485
|
-
content:
|
|
510
|
+
content: b
|
|
486
511
|
});
|
|
487
|
-
for (const g of
|
|
488
|
-
if (g.code ===
|
|
489
|
-
const L =
|
|
512
|
+
for (const g of n) {
|
|
513
|
+
if (g.code === i) continue;
|
|
514
|
+
const L = $(g);
|
|
490
515
|
if (!L) {
|
|
491
|
-
|
|
516
|
+
C(g, { tag: "og:locale:alternate" });
|
|
492
517
|
continue;
|
|
493
518
|
}
|
|
494
519
|
m.meta.push({
|
|
@@ -498,56 +523,56 @@ function ge(t, e = {}) {
|
|
|
498
523
|
}
|
|
499
524
|
return m;
|
|
500
525
|
}
|
|
501
|
-
function
|
|
502
|
-
const
|
|
503
|
-
let
|
|
504
|
-
for (let
|
|
505
|
-
const
|
|
506
|
-
|
|
526
|
+
function ne(t, e, r) {
|
|
527
|
+
const l = e.split(".");
|
|
528
|
+
let c = t;
|
|
529
|
+
for (let i = 0; i < l.length - 1; i++) {
|
|
530
|
+
const o = l[i];
|
|
531
|
+
c[o] || (c[o] = {}), c = c[o];
|
|
507
532
|
}
|
|
508
|
-
const
|
|
509
|
-
|
|
533
|
+
const u = l[l.length - 1];
|
|
534
|
+
u !== void 0 && (c[u] = r);
|
|
510
535
|
}
|
|
511
|
-
function
|
|
512
|
-
const
|
|
536
|
+
function Le(t, e) {
|
|
537
|
+
const r = M(t), l = j(t), c = k(t), u = r.getRoute(), i = {};
|
|
513
538
|
if (e && e.length > 0) {
|
|
514
|
-
const
|
|
515
|
-
for (const
|
|
516
|
-
const
|
|
517
|
-
|
|
539
|
+
const o = {};
|
|
540
|
+
for (const s of e) {
|
|
541
|
+
const a = r.t(s, void 0, void 0, u);
|
|
542
|
+
a != null && a !== s && ne(o, s, a);
|
|
518
543
|
}
|
|
519
|
-
Object.keys(
|
|
544
|
+
Object.keys(o).length > 0 && (i[u] = o);
|
|
520
545
|
} else {
|
|
521
|
-
const
|
|
522
|
-
|
|
546
|
+
const o = r.getRouteTranslations(l, u);
|
|
547
|
+
o && (i[u] = o);
|
|
523
548
|
}
|
|
524
549
|
return {
|
|
525
|
-
locale:
|
|
526
|
-
fallbackLocale:
|
|
527
|
-
currentRoute:
|
|
528
|
-
translations:
|
|
550
|
+
locale: l,
|
|
551
|
+
fallbackLocale: c,
|
|
552
|
+
currentRoute: u,
|
|
553
|
+
translations: i
|
|
529
554
|
};
|
|
530
555
|
}
|
|
531
556
|
export {
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
557
|
+
v as AstroI18n,
|
|
558
|
+
be as FormatService,
|
|
559
|
+
de as createAstroRouterAdapter,
|
|
560
|
+
ue as createI18n,
|
|
561
|
+
ge as createI18nMiddleware,
|
|
562
|
+
ye as defaultPlural,
|
|
563
|
+
he as detectLocale,
|
|
564
|
+
k as getDefaultLocale,
|
|
565
|
+
I as getGlobalRoutingStrategy,
|
|
566
|
+
M as getI18n,
|
|
567
|
+
Le as getI18nProps,
|
|
568
|
+
j as getLocale,
|
|
569
|
+
A as getLocales,
|
|
570
|
+
ce as i18nIntegration,
|
|
571
|
+
we as interpolate,
|
|
572
|
+
ee as loadTranslationsFromDir,
|
|
573
|
+
fe as loadTranslationsIntoI18n,
|
|
574
|
+
Y as runWithRoutingStrategy,
|
|
575
|
+
X as setGlobalRoutingStrategy,
|
|
576
|
+
me as useI18n,
|
|
577
|
+
pe as useLocaleHead
|
|
553
578
|
};
|
package/dist/utils.d.ts
CHANGED
|
@@ -59,6 +59,11 @@ export interface LocaleHeadOptions {
|
|
|
59
59
|
baseUrl?: string;
|
|
60
60
|
addDirAttribute?: boolean;
|
|
61
61
|
addSeoAttributes?: boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Also emit bare-language `hreflang` tags derived from `iso` (never from routing `code`).
|
|
64
|
+
* @default false
|
|
65
|
+
*/
|
|
66
|
+
hreflangBaseLanguage?: boolean;
|
|
62
67
|
}
|
|
63
68
|
export interface LocaleHeadResult {
|
|
64
69
|
htmlAttrs: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@i18n-micro/astro",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.10",
|
|
4
4
|
"description": "Astro integration for i18n-micro — translations, routing, and islands.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"astro",
|
|
@@ -77,10 +77,10 @@
|
|
|
77
77
|
"access": "public"
|
|
78
78
|
},
|
|
79
79
|
"dependencies": {
|
|
80
|
-
"@i18n-micro/
|
|
81
|
-
"@i18n-micro/
|
|
82
|
-
"@i18n-micro/utils": "^1.0.
|
|
83
|
-
"@i18n-micro/types": "^1.2.
|
|
80
|
+
"@i18n-micro/node": "^1.2.6",
|
|
81
|
+
"@i18n-micro/core": "^1.3.11",
|
|
82
|
+
"@i18n-micro/utils": "^1.0.13",
|
|
83
|
+
"@i18n-micro/types": "^1.2.10"
|
|
84
84
|
},
|
|
85
85
|
"devDependencies": {
|
|
86
86
|
"astro": "^5.0.0 || ^6.0.0 || ^7.0.0",
|
package/src/utils.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CleanTranslation, Locale, Params, TranslationKey, Translations } from '@i18n-micro/types'
|
|
2
|
+
import { resolveHreflangAlternates } from '@i18n-micro/utils/resolve-hreflang'
|
|
2
3
|
import { resolveOgLocale, warnUnresolvedOgLocale } from '@i18n-micro/utils/resolve-og-locale'
|
|
3
4
|
import type { AstroGlobal } from 'astro'
|
|
4
5
|
import type { AstroI18n } from './composer'
|
|
@@ -187,6 +188,11 @@ export interface LocaleHeadOptions {
|
|
|
187
188
|
baseUrl?: string
|
|
188
189
|
addDirAttribute?: boolean
|
|
189
190
|
addSeoAttributes?: boolean
|
|
191
|
+
/**
|
|
192
|
+
* Also emit bare-language `hreflang` tags derived from `iso` (never from routing `code`).
|
|
193
|
+
* @default false
|
|
194
|
+
*/
|
|
195
|
+
hreflangBaseLanguage?: boolean
|
|
190
196
|
}
|
|
191
197
|
|
|
192
198
|
export interface LocaleHeadResult {
|
|
@@ -206,7 +212,7 @@ export interface LocaleHeadResult {
|
|
|
206
212
|
}
|
|
207
213
|
|
|
208
214
|
export function useLocaleHead(astro: AstroGlobal, options: LocaleHeadOptions = {}): LocaleHeadResult {
|
|
209
|
-
const { baseUrl = '/', addDirAttribute = true, addSeoAttributes = true } = options
|
|
215
|
+
const { baseUrl = '/', addDirAttribute = true, addSeoAttributes = true, hreflangBaseLanguage = false } = options
|
|
210
216
|
|
|
211
217
|
const locale = getLocale(astro)
|
|
212
218
|
const defaultLocale = getDefaultLocale(astro)
|
|
@@ -248,6 +254,7 @@ export function useLocaleHead(astro: AstroGlobal, options: LocaleHeadOptions = {
|
|
|
248
254
|
const allLocaleCodes = locales.map((l) => l.code)
|
|
249
255
|
|
|
250
256
|
// Alternate languages (includes current locale for self-referencing hreflang, per Google guidelines)
|
|
257
|
+
const hrefByCode = new Map<string, string>()
|
|
251
258
|
for (const loc of localesForSeo) {
|
|
252
259
|
let alternatePath = astro.url.pathname
|
|
253
260
|
if (routingStrategy?.switchLocalePath) {
|
|
@@ -264,21 +271,17 @@ export function useLocaleHead(astro: AstroGlobal, options: LocaleHeadOptions = {
|
|
|
264
271
|
}
|
|
265
272
|
alternatePath = `/${segments.join('/')}`
|
|
266
273
|
}
|
|
267
|
-
|
|
274
|
+
hrefByCode.set(String(loc.code), `${baseUrl}${alternatePath}`)
|
|
275
|
+
}
|
|
268
276
|
|
|
277
|
+
for (const { hreflang, localeCode } of resolveHreflangAlternates(localesForSeo, { hreflangBaseLanguage })) {
|
|
278
|
+
const alternateUrl = hrefByCode.get(localeCode)
|
|
279
|
+
if (!alternateUrl) continue
|
|
269
280
|
result.link.push({
|
|
270
281
|
rel: 'alternate',
|
|
271
282
|
href: alternateUrl,
|
|
272
|
-
hreflang
|
|
283
|
+
hreflang,
|
|
273
284
|
})
|
|
274
|
-
|
|
275
|
-
if (loc.iso && loc.iso !== loc.code) {
|
|
276
|
-
result.link.push({
|
|
277
|
-
rel: 'alternate',
|
|
278
|
-
href: alternateUrl,
|
|
279
|
-
hreflang: loc.iso,
|
|
280
|
-
})
|
|
281
|
-
}
|
|
282
285
|
}
|
|
283
286
|
|
|
284
287
|
// x-default hreflang — points to the default locale's URL.
|