@i18n-micro/astro 1.3.6 → 1.3.7

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 CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const j=require("@i18n-micro/core"),T=require("node:fs"),R=require("node:path"),F=require("@i18n-micro/utils/parse-path"),N=require("@i18n-micro/utils/accept-language");class v extends j.BaseI18n{constructor(e){const l=e._storage||{translations:new Map};if(super({storage:l,plural:e.plural,missingWarn:e.missingWarn,missingHandler:e.missingHandler}),this.initialMessages={},this.storage=l,this._locale=e.locale,this._fallbackLocale=e.fallbackLocale||e.locale,this._currentRoute="index",e.messages){this.initialMessages={...e.messages};for(const[r,c]of Object.entries(e.messages))this.helper.loadTranslations(r,c)}}cloneStorage(e){const l=new Map;for(const[r,c]of e.translations)l.set(r,{...c});return{translations:l}}clone(e){const l=this.cloneStorage(this.storage);return new v({locale:e||this._locale,fallbackLocale:this._fallbackLocale,plural:this.pluralFunc,missingWarn:this.missingWarn,missingHandler:this.missingHandler,_storage:l})}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,l){const r=`${e}:${l}`;return this.storage.translations.get(r)??null}addTranslations(e,l,r=!0){super.loadTranslationsCore(e,l,r)}addRouteTranslations(e,l,r,c=!0){super.loadRouteTranslationsCore(e,l,r,c)}mergeTranslations(e,l,r){this.helper.mergeTranslation(e,l,r,!0)}clearCache(){const e={...this.initialMessages};if(super.clearCache(),Object.keys(e).length>0)for(const[l,r]of Object.entries(e))this.helper.loadTranslations(l,r)}}let O=null;function _(){return O}function q(a){const{locale:e,fallbackLocale:l,translationDir:r,routingStrategy:c}=a;return O=c||null,{name:"@i18n-micro/astro",hooks:{"astro:config:setup":i=>{const{updateConfig:u}=i,t="virtual:i18n-micro/config",o=`\0${t}`,s={defaultLocale:e,fallbackLocale:l||e,locales:a.locales||[],localeCodes:(a.locales||[]).map(n=>n.code),translationDir:r||null,autoDetect:a.autoDetect??!0,redirectToDefault:a.redirectToDefault??!1,localeCookie:a.localeCookie===null?null:a.localeCookie||"i18n-locale",missingWarn:a.missingWarn??!1};u({vite:{plugins:[{name:"vite-plugin-i18n-micro-config",resolveId(n){if(n===t)return o},load(n){if(n===o)return`export const config = ${JSON.stringify(s)}`}}]}})},"astro:config:done":i=>{const{injectTypes:u}=i;u({filename:"i18n-micro-env.d.ts",content:`
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const R=require("@i18n-micro/core"),w=require("node:fs"),T=require("node:path"),C=require("@i18n-micro/utils/parse-path"),W=require("@i18n-micro/utils/accept-language");class j extends R.BaseI18n{constructor(e){const a=e._storage||{translations:new Map};if(super({storage:a,plural:e.plural,missingWarn:e.missingWarn,missingHandler:e.missingHandler}),this.initialMessages={},this.storage=a,this._locale=e.locale,this._fallbackLocale=e.fallbackLocale||e.locale,this._currentRoute="index",e.messages){this.initialMessages={...e.messages};for(const[r,i]of Object.entries(e.messages))this.helper.loadTranslations(r,i)}}cloneStorage(e){const a=new Map;for(const[r,i]of e.translations)a.set(r,{...i});return{translations:a}}clone(e){const a=this.cloneStorage(this.storage);return new j({locale:e||this._locale,fallbackLocale:this._fallbackLocale,plural:this.pluralFunc,missingWarn:this.missingWarn,missingHandler:this.missingHandler,_storage:a})}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,a){const r=`${e}:${a}`;return this.storage.translations.get(r)??null}addTranslations(e,a,r=!0){super.loadTranslationsCore(e,a,r)}addRouteTranslations(e,a,r,i=!0){super.loadRouteTranslationsCore(e,a,r,i)}mergeTranslations(e,a,r){this.helper.mergeTranslation(e,a,r,!0)}clearCache(){const e={...this.initialMessages};if(super.clearCache(),Object.keys(e).length>0)for(const[a,r]of Object.entries(e))this.helper.loadTranslations(a,r)}}let B=null;function N(){return B}function U(t){const{locale:e,fallbackLocale:a,translationDir:r,routingStrategy:i}=t;return B=i||null,{name:"@i18n-micro/astro",hooks:{"astro:config:setup":c=>{const{updateConfig:u}=c,o="virtual:i18n-micro/config",l=`\0${o}`,s={defaultLocale:e,fallbackLocale:a||e,locales:t.locales||[],localeCodes:(t.locales||[]).map(n=>n.code),translationDir:r||null,autoDetect:t.autoDetect??!0,redirectToDefault:t.redirectToDefault??!1,localeCookie:t.localeCookie===null?null:t.localeCookie||"i18n-locale",missingWarn:t.missingWarn??!1};u({vite:{plugins:[{name:"vite-plugin-i18n-micro-config",resolveId(n){if(n===o)return l},load(n){if(n===l)return`export const config = ${JSON.stringify(s)}`}}]}})},"astro:config:done":c=>{const{injectTypes:u}=c;u({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 A(a){return new v(a)}function B(a,e){if(T.existsSync(a))for(const l of T.readdirSync(a)){const r=R.join(a,l);if(T.statSync(r).isDirectory()){B(r,e);continue}l.endsWith(".json")&&e(r)}}function C(a){const{translationDir:e,rootDir:l=process.cwd(),disablePageLocales:r=!1}=a,c=R.resolve(l,e);if(!T.existsSync(c))return console.warn(`[i18n] Translation directory not found: ${c}`),{root:{},routes:{}};const i={root:{},routes:{}};return B(c,u=>{const t=R.relative(c,u).split(R.sep).join("/");try{const o=T.readFileSync(u,"utf-8"),s=JSON.parse(o);F.storeLoadedTranslationFile(i,t,s,r)}catch(o){console.error(`[i18n] Failed to load translation file: ${u}`,o)}}),i}function W(a,e){const{root:l,routes:r}=C(e);for(const[c,i]of Object.entries(l))a.addTranslations(c,i,!1);for(const[c,i]of Object.entries(r))for(const[u,t]of Object.entries(i))a.addRouteTranslations(u,c,F.mergeRouteTranslationsWithRoot(l[u],t),!1)}function H(a){const{i18n:e,defaultLocale:l,locales:r,localeObjects:c,autoDetect:i=!0,redirectToDefault:u=!1,routingStrategy:t}=a,o=t||_();return async(s,n)=>{if(s.locals.locale&&s.locals.i18n)return n();const f=s.url,h=f.pathname;if(!o){const P=e.clone(l),S=h==="/"||h===""?"index":h.split("/").filter(Boolean).join("-");return P.setRoute(S),s.locals.i18n=P,s.locals.locale=l,s.locals.defaultLocale=l,s.locals.locales=c||r.map(w=>({code:w})),s.locals.currentUrl=f,n()}const g={...o,getCurrentPath:()=>h,getRoute:()=>({fullPath:f.pathname+f.search,query:Object.fromEntries(f.searchParams)})},m=h.split("/").filter(Boolean)[0],L=m!==void 0&&r.includes(m);let y;L&&m?y=m:g.getLocaleFromPath?y=g.getLocaleFromPath(h,l,r):y=l;const d=e.clone(y),b=g.getRouteName?g.getRouteName(h,r):"index";return d.setRoute(b),s.locals.i18n=d,s.locals.locale=y,s.locals.defaultLocale=l,s.locals.locales=c||r.map(P=>({code:P})),s.locals.currentUrl=f,s.locals.routingStrategy=g,n()}}function U(a,e,l,r,c,i="i18n-locale"){const u=_();let t=r;if(u?.getLocaleFromPath)t=u.getLocaleFromPath(a,r,c);else{const s=a.split("/").filter(Boolean)[0];s&&c.includes(s)&&(t=s)}if(i!==null&&t===r&&e.get(i)){const o=e.get(i)?.value;o&&c.includes(o)&&(t=o)}if(t===r)try{const o=N.detectLocaleFromAcceptLanguage(l.get("accept-language")??void 0,c);o&&(t=o)}catch{}return t}function z(a,e,l){const r=a.map(n=>n.code),c=(n,f=[])=>{const h=n.replace(/^\//,"").replace(/\/$/,"");if(!h)return"index";const g=h.split("/").filter(Boolean),p=g[0];return p&&f.includes(p)&&g.shift(),g.length===0?"index":g.join("-")},i=(n,f="en",h=[])=>{const p=n.split("/").filter(Boolean)[0];return p&&h.includes(p)?p:f},u=(n,f,h=[],g)=>{const p=n.split("/").filter(Boolean),m=p[0];return m&&h.includes(m)&&p.shift(),(f!==g||g===void 0)&&p.unshift(f),`/${p.join("/")}`},t=(n,f,h=[],g)=>{const m=(n.replace(/^\//,"").replace(/\/$/,"")||"").split("/").filter(Boolean),L=m[0];return L&&h.includes(L)&&m.shift(),(f!==g||g===void 0)&&m.unshift(f),`/${m.join("/")}`};return{getCurrentPath:()=>l?l().pathname:typeof window<"u"?window.location.pathname:"/",getRouteName:c,getLocaleFromPath:i,switchLocalePath:u,localizePath:t,removeLocaleFromPath:(n,f=[])=>{const h=n.split("/").filter(Boolean),g=h[0];return g&&f.includes(g)&&h.shift(),`/${h.join("/")}`},resolvePath:(n,f)=>{const h=typeof n=="string"?n:n.path||"/";return t(h,f,r,e)},getRoute:()=>{if(l){const n=l();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(a){const e=a.locals.i18n;if(!e)throw new Error("i18n instance not found. Make sure i18n middleware is configured.");return e}function k(a){return a.locals.locale||"en"}function I(a){return a.locals.defaultLocale||"en"}function $(a){return a.locals.locales||[]}function M(a){return a.locals.routingStrategy||null}function E(a){const e=D(a),l=k(a),r=I(a),c=$(a),i=c.map(t=>t.code),u=M(a);return{locale:l,defaultLocale:r,locales:c,t:(t,o,s,n)=>e.t(t,o,s,n),ts:(t,o,s,n)=>e.ts(t,o,s,n),tc:(t,o,s)=>e.tc(t,o,s),tn:(t,o)=>e.tn(t,o),td:(t,o)=>e.td(t,o),tdr:(t,o)=>e.tdr(t,o),has:(t,o)=>e.has(t,o),getRoute:()=>e.getRoute(),getRouteName:t=>{const o=t||a.url.pathname;if(u?.getRouteName)return u.getRouteName(o,i);const s=o.replace(/^\//,"").replace(/\/$/,"");if(!s)return"index";const n=s.split("/").filter(Boolean),f=n[0];return f&&i.includes(f)&&n.shift(),n.length===0?"index":n.join("-")},getLocaleFromPath:t=>{const o=t||a.url.pathname;if(u?.getLocaleFromPath)return u.getLocaleFromPath(o,r,i);const n=o.split("/").filter(Boolean)[0];return n&&i.includes(n)?n:r},switchLocalePath:t=>{if(u?.switchLocalePath)return u.switchLocalePath(a.url.pathname,t,i,r);const o=a.url.pathname.split("/").filter(Boolean),s=o[0];return s&&i.includes(s)&&o.shift(),t!==r&&o.unshift(t),`/${o.join("/")}`},localizePath:(t,o)=>{if(u?.localizePath)return u.localizePath(t,o||l,i,r);const n=(t.replace(/^\//,"").replace(/\/$/,"")||"").split("/").filter(Boolean),f=n[0];return f&&i.includes(f)&&n.shift(),o&&o!==r&&n.unshift(o),`/${n.join("/")}`},getI18n:()=>e,getBasePath:t=>{const n=(t||a.url).pathname.split("/").filter(Boolean),f=n[0];return f&&i.includes(f)&&n.shift(),n.length>0?`/${n.join("/")}`:"/"},addTranslations:(t,o,s=!0)=>{e.addTranslations(t,o,s)},addRouteTranslations:(t,o,s,n=!0)=>{e.addRouteTranslations(t,o,s,n)},mergeTranslations:(t,o,s)=>{e.mergeTranslations(t,o,s)},clearCache:()=>{e.clearCache()}}}function x(a,e={}){const{baseUrl:l="/",addDirAttribute:r=!0,addSeoAttributes:c=!0}=e,i=k(a),u=I(a),o=$(a).filter(d=>!d.disabled),s=o.filter(d=>d.seo!==!1),n=o.find(d=>d.code===i);if(!n)return{htmlAttrs:{},link:[],meta:[]};const f=n.iso||i,h=n.dir||"auto",g={htmlAttrs:{lang:f,...r?{dir:h}:{}},link:[],meta:[]};if(!c)return g;const p=`${l}${a.url.pathname}`;g.link.push({rel:"canonical",href:p});const m=M(a),L=o.map(d=>d.code);for(const d of s){let b=a.url.pathname;if(m?.switchLocalePath)b=m.switchLocalePath(a.url.pathname,d.code,L,u);else{const S=a.url.pathname.split("/").filter(Boolean),w=S[0];w&&L.includes(w)&&S.shift(),d.code!==u&&S.unshift(d.code),b=`/${S.join("/")}`}const P=`${l}${b}`;g.link.push({rel:"alternate",href:P,hreflang:d.code}),d.iso&&d.iso!==d.code&&g.link.push({rel:"alternate",href:P,hreflang:d.iso})}if(o.find(d=>d.code===u)?.seo!==!1){let d=a.url.pathname;if(m?.switchLocalePath)d=m.switchLocalePath(a.url.pathname,u,L,u);else{const b=a.url.pathname.split("/").filter(Boolean),P=b[0];P&&L.includes(P)&&b.shift(),d=`/${b.join("/")}`}g.link.push({rel:"alternate",href:`${l}${d}`,hreflang:"x-default"})}g.meta.push({property:"og:locale",content:f}),g.meta.push({property:"og:url",content:p});for(const d of s)d.code!==i&&g.meta.push({property:"og:locale:alternate",content:d.og||d.iso||d.code});return g}function J(a,e,l){const r=e.split(".");let c=a;for(let u=0;u<r.length-1;u++){const t=r[u];c[t]||(c[t]={}),c=c[t]}const i=r[r.length-1];i!==void 0&&(c[i]=l)}function V(a,e){const l=D(a),r=k(a),c=I(a),i=l.getRoute(),u={};if(e&&e.length>0){const t={};for(const o of e){const s=l.t(o,void 0,void 0,i);s!=null&&s!==o&&J(t,o,s)}Object.keys(t).length>0&&(u[i]=t)}else{const t=l.getRouteTranslations(r,i);t&&(u[i]=t)}return{locale:r,fallbackLocale:c,currentRoute:i,translations:u}}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=z;exports.createI18n=A;exports.createI18nMiddleware=H;exports.detectLocale=U;exports.getDefaultLocale=I;exports.getI18n=D;exports.getI18nProps=V;exports.getLocale=k;exports.getLocales=$;exports.i18nIntegration=q;exports.loadTranslationsFromDir=C;exports.loadTranslationsIntoI18n=W;exports.useI18n=E;exports.useLocaleHead=x;
17
+ `})}}}}function H(t){return new j(t)}function A(t,e){if(w.existsSync(t))for(const a of w.readdirSync(t)){const r=T.join(t,a);if(w.statSync(r).isDirectory()){A(r,e);continue}a.endsWith(".json")&&e(r)}}function M(t){const{translationDir:e,rootDir:a=process.cwd(),disablePageLocales:r=!1}=t,i=T.resolve(a,e);if(!w.existsSync(i))return console.warn(`[i18n] Translation directory not found: ${i}`),{root:{},routes:{}};const c={root:{},routes:{}};return A(i,u=>{const o=T.relative(i,u).split(T.sep).join("/");try{const l=w.readFileSync(u,"utf-8"),s=JSON.parse(l);C.storeLoadedTranslationFile(c,o,s,r)}catch(l){console.error(`[i18n] Failed to load translation file: ${u}`,l)}}),c}function E(t,e){const{root:a,routes:r}=M(e);for(const[i,c]of Object.entries(a))t.addTranslations(i,c,!1);for(const[i,c]of Object.entries(r))for(const[u,o]of Object.entries(c))t.addRouteTranslations(u,i,C.mergeRouteTranslationsWithRoot(a[u],o),!1)}function z(t){const{i18n:e,defaultLocale:a,locales:r,localeObjects:i,autoDetect:c=!0,redirectToDefault:u=!1,routingStrategy:o}=t,l=o||N();return async(s,n)=>{if(s.locals.locale&&s.locals.i18n)return n();const f=s.url,d=f.pathname;if(!l){const L=e.clone(a),y=d==="/"||d===""?"index":d.split("/").filter(Boolean).join("-");return L.setRoute(y),s.locals.i18n=L,s.locals.locale=a,s.locals.defaultLocale=a,s.locals.locales=i||r.map(S=>({code:S})),s.locals.currentUrl=f,n()}const m={...l,getCurrentPath:()=>d,getRoute:()=>({fullPath:f.pathname+f.search,query:Object.fromEntries(f.searchParams)})},p=d.split("/").filter(Boolean)[0],b=p!==void 0&&r.includes(p);let P;b&&p?P=p:m.getLocaleFromPath?P=m.getLocaleFromPath(d,a,r):P=a;const k=e.clone(P),g=m.getRouteName?m.getRouteName(d,r):"index";return k.setRoute(g),s.locals.i18n=k,s.locals.locale=P,s.locals.defaultLocale=a,s.locals.locales=i||r.map(L=>({code:L})),s.locals.currentUrl=f,s.locals.routingStrategy=m,n()}}function x(t,e,a,r,i,c="i18n-locale"){const u=N();let o=r;if(u?.getLocaleFromPath)o=u.getLocaleFromPath(t,r,i);else{const s=t.split("/").filter(Boolean)[0];s&&i.includes(s)&&(o=s)}if(c!==null&&o===r&&e.get(c)){const l=e.get(c)?.value;l&&i.includes(l)&&(o=l)}if(o===r)try{const l=W.detectLocaleFromAcceptLanguage(a.get("accept-language")??void 0,i);l&&(o=l)}catch{}return o}function V(t,e,a){const r=t.map(n=>n.code),i=(n,f=[])=>{const d=n.replace(/^\//,"").replace(/\/$/,"");if(!d)return"index";const m=d.split("/").filter(Boolean),h=m[0];return h&&f.includes(h)&&m.shift(),m.length===0?"index":m.join("-")},c=(n,f="en",d=[])=>{const h=n.split("/").filter(Boolean)[0];return h&&d.includes(h)?h:f},u=(n,f,d=[],m)=>{const h=n.split("/").filter(Boolean),p=h[0];return p&&d.includes(p)&&h.shift(),(f!==m||m===void 0)&&h.unshift(f),`/${h.join("/")}`},o=(n,f,d=[],m)=>{const p=(n.replace(/^\//,"").replace(/\/$/,"")||"").split("/").filter(Boolean),b=p[0];return b&&d.includes(b)&&p.shift(),(f!==m||m===void 0)&&p.unshift(f),`/${p.join("/")}`};return{getCurrentPath:()=>a?a().pathname:typeof window<"u"?window.location.pathname:"/",getRouteName:i,getLocaleFromPath:c,switchLocalePath:u,localizePath:o,removeLocaleFromPath:(n,f=[])=>{const d=n.split("/").filter(Boolean),m=d[0];return m&&f.includes(m)&&d.shift(),`/${d.join("/")}`},resolvePath:(n,f)=>{const d=typeof n=="string"?n:n.path||"/";return o(d,f,r,e)},getRoute:()=>{if(a){const n=a();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){const e=t.og?.trim();if(e)return e;const a=t.iso?.trim();if(!a)return null;const r=a.indexOf("_");if(r>0){const c=a.slice(0,r),u=a.slice(r+1);if(c.length>=2&&u.length===2)return`${c.toLowerCase()}_${u.toUpperCase()}`}const i=a.indexOf("-");if(i>0){const c=a.slice(0,i),u=a.slice(i+1);if(c.length>=2&&u.length===2&&/^[A-Za-z]{2}$/.test(u))return`${c.toLowerCase()}_${u.toUpperCase()}`}return null}function F(t,e={}){if(D(t)!==null||e.missingWarn===!1||process.env.NODE_ENV==="production")return;const a=e.tag??"og:locale",r=String(t.code??"unknown"),i=t.iso?`, iso: '${t.iso}'`:"";console.warn(`[i18n] Cannot derive ${a} for locale '${r}'${i}. Set locale.og (e.g. 'en_US') or use iso with a 2-letter region (e.g. 'en-US').`)}function I(t){const e=t.locals.i18n;if(!e)throw new Error("i18n instance not found. Make sure i18n middleware is configured.");return e}function $(t){return t.locals.locale||"en"}function v(t){return t.locals.defaultLocale||"en"}function O(t){return t.locals.locales||[]}function q(t){return t.locals.routingStrategy||null}function J(t){const e=I(t),a=$(t),r=v(t),i=O(t),c=i.map(o=>o.code),u=q(t);return{locale:a,defaultLocale:r,locales:i,t:(o,l,s,n)=>e.t(o,l,s,n),ts:(o,l,s,n)=>e.ts(o,l,s,n),tc:(o,l,s)=>e.tc(o,l,s),tn:(o,l)=>e.tn(o,l),td:(o,l)=>e.td(o,l),tdr:(o,l)=>e.tdr(o,l),has:(o,l)=>e.has(o,l),getRoute:()=>e.getRoute(),getRouteName:o=>{const l=o||t.url.pathname;if(u?.getRouteName)return u.getRouteName(l,c);const s=l.replace(/^\//,"").replace(/\/$/,"");if(!s)return"index";const n=s.split("/").filter(Boolean),f=n[0];return f&&c.includes(f)&&n.shift(),n.length===0?"index":n.join("-")},getLocaleFromPath:o=>{const l=o||t.url.pathname;if(u?.getLocaleFromPath)return u.getLocaleFromPath(l,r,c);const n=l.split("/").filter(Boolean)[0];return n&&c.includes(n)?n:r},switchLocalePath:o=>{if(u?.switchLocalePath)return u.switchLocalePath(t.url.pathname,o,c,r);const l=t.url.pathname.split("/").filter(Boolean),s=l[0];return s&&c.includes(s)&&l.shift(),o!==r&&l.unshift(o),`/${l.join("/")}`},localizePath:(o,l)=>{if(u?.localizePath)return u.localizePath(o,l||a,c,r);const n=(o.replace(/^\//,"").replace(/\/$/,"")||"").split("/").filter(Boolean),f=n[0];return f&&c.includes(f)&&n.shift(),l&&l!==r&&n.unshift(l),`/${n.join("/")}`},getI18n:()=>e,getBasePath:o=>{const n=(o||t.url).pathname.split("/").filter(Boolean),f=n[0];return f&&c.includes(f)&&n.shift(),n.length>0?`/${n.join("/")}`:"/"},addTranslations:(o,l,s=!0)=>{e.addTranslations(o,l,s)},addRouteTranslations:(o,l,s,n=!0)=>{e.addRouteTranslations(o,l,s,n)},mergeTranslations:(o,l,s)=>{e.mergeTranslations(o,l,s)},clearCache:()=>{e.clearCache()}}}function G(t,e={}){const{baseUrl:a="/",addDirAttribute:r=!0,addSeoAttributes:i=!0}=e,c=$(t),u=v(t),l=O(t).filter(g=>!g.disabled),s=l.filter(g=>g.seo!==!1),n=l.find(g=>g.code===c);if(!n)return{htmlAttrs:{},link:[],meta:[]};const f=n.iso||c,d=D(n),m=n.dir||"auto",h={htmlAttrs:{lang:f,...r?{dir:m}:{}},link:[],meta:[]};if(!i)return h;const p=`${a}${t.url.pathname}`;h.link.push({rel:"canonical",href:p});const b=q(t),P=l.map(g=>g.code);for(const g of s){let L=t.url.pathname;if(b?.switchLocalePath)L=b.switchLocalePath(t.url.pathname,g.code,P,u);else{const S=t.url.pathname.split("/").filter(Boolean),_=S[0];_&&P.includes(_)&&S.shift(),g.code!==u&&S.unshift(g.code),L=`/${S.join("/")}`}const y=`${a}${L}`;h.link.push({rel:"alternate",href:y,hreflang:g.code}),g.iso&&g.iso!==g.code&&h.link.push({rel:"alternate",href:y,hreflang:g.iso})}if(l.find(g=>g.code===u)?.seo!==!1){let g=t.url.pathname;if(b?.switchLocalePath)g=b.switchLocalePath(t.url.pathname,u,P,u);else{const L=t.url.pathname.split("/").filter(Boolean),y=L[0];y&&P.includes(y)&&L.shift(),g=`/${L.join("/")}`}h.link.push({rel:"alternate",href:`${a}${g}`,hreflang:"x-default"})}d?h.meta.push({property:"og:locale",content:d}):F(n,{tag:"og:locale"}),h.meta.push({property:"og:url",content:p});for(const g of s){if(g.code===c)continue;const L=D(g);if(!L){F(g,{tag:"og:locale:alternate"});continue}h.meta.push({property:"og:locale:alternate",content:L})}return h}function K(t,e,a){const r=e.split(".");let i=t;for(let u=0;u<r.length-1;u++){const o=r[u];i[o]||(i[o]={}),i=i[o]}const c=r[r.length-1];c!==void 0&&(i[c]=a)}function Z(t,e){const a=I(t),r=$(t),i=v(t),c=a.getRoute(),u={};if(e&&e.length>0){const o={};for(const l of e){const s=a.t(l,void 0,void 0,c);s!=null&&s!==l&&K(o,l,s)}Object.keys(o).length>0&&(u[c]=o)}else{const o=a.getRouteTranslations(r,c);o&&(u[c]=o)}return{locale:r,fallbackLocale:i,currentRoute:c,translations:u}}Object.defineProperty(exports,"FormatService",{enumerable:!0,get:()=>R.FormatService});Object.defineProperty(exports,"defaultPlural",{enumerable:!0,get:()=>R.defaultPlural});Object.defineProperty(exports,"interpolate",{enumerable:!0,get:()=>R.interpolate});exports.AstroI18n=j;exports.createAstroRouterAdapter=V;exports.createI18n=H;exports.createI18nMiddleware=z;exports.detectLocale=x;exports.getDefaultLocale=v;exports.getI18n=I;exports.getI18nProps=Z;exports.getLocale=$;exports.getLocales=O;exports.i18nIntegration=U;exports.loadTranslationsFromDir=M;exports.loadTranslationsIntoI18n=E;exports.useI18n=J;exports.useLocaleHead=G;
package/dist/index.mjs CHANGED
@@ -1,40 +1,40 @@
1
- import { BaseI18n as O } from "@i18n-micro/core";
2
- import { FormatService as ie, defaultPlural as ce, interpolate as ue } from "@i18n-micro/core";
3
- import { existsSync as k, readdirSync as _, statSync as C, readFileSync as N } from "node:fs";
4
- import { resolve as M, join as W, relative as A, sep as q } from "node:path";
5
- import { mergeRouteTranslationsWithRoot as H, storeLoadedTranslationFile as U } from "@i18n-micro/utils/parse-path";
6
- import { detectLocaleFromAcceptLanguage as z } from "@i18n-micro/utils/accept-language";
7
- class R extends O {
1
+ import { BaseI18n as N } from "@i18n-micro/core";
2
+ import { FormatService as fe, defaultPlural as ge, interpolate as he } from "@i18n-micro/core";
3
+ import { existsSync as D, readdirSync as M, statSync as W, readFileSync as A } from "node:fs";
4
+ import { resolve as U, join as q, relative as E, sep as H } from "node:path";
5
+ import { mergeRouteTranslationsWithRoot as x, storeLoadedTranslationFile as z } from "@i18n-micro/utils/parse-path";
6
+ import { detectLocaleFromAcceptLanguage as V } from "@i18n-micro/utils/accept-language";
7
+ class T extends N {
8
8
  constructor(e) {
9
- const l = e._storage || {
9
+ const a = e._storage || {
10
10
  translations: /* @__PURE__ */ new Map()
11
11
  };
12
12
  if (super({
13
- storage: l,
13
+ storage: a,
14
14
  plural: e.plural,
15
15
  missingWarn: e.missingWarn,
16
16
  missingHandler: e.missingHandler
17
- }), this.initialMessages = {}, this.storage = l, this._locale = e.locale, this._fallbackLocale = e.fallbackLocale || e.locale, this._currentRoute = "index", e.messages) {
17
+ }), this.initialMessages = {}, this.storage = a, this._locale = e.locale, this._fallbackLocale = e.fallbackLocale || e.locale, this._currentRoute = "index", e.messages) {
18
18
  this.initialMessages = { ...e.messages };
19
19
  for (const [r, i] of Object.entries(e.messages))
20
20
  this.helper.loadTranslations(r, i);
21
21
  }
22
22
  }
23
23
  cloneStorage(e) {
24
- const l = /* @__PURE__ */ new Map();
24
+ const a = /* @__PURE__ */ new Map();
25
25
  for (const [r, i] of e.translations)
26
- l.set(r, { ...i });
27
- return { translations: l };
26
+ a.set(r, { ...i });
27
+ return { translations: a };
28
28
  }
29
29
  clone(e) {
30
- const l = this.cloneStorage(this.storage);
31
- return new R({
30
+ const a = this.cloneStorage(this.storage);
31
+ return new T({
32
32
  locale: e || this._locale,
33
33
  fallbackLocale: this._fallbackLocale,
34
34
  plural: this.pluralFunc,
35
35
  missingWarn: this.missingWarn,
36
36
  missingHandler: this.missingHandler,
37
- _storage: l
37
+ _storage: a
38
38
  });
39
39
  }
40
40
  get locale() {
@@ -61,47 +61,47 @@ class R extends O {
61
61
  getRoute() {
62
62
  return this._currentRoute;
63
63
  }
64
- getRouteTranslations(e, l) {
65
- const r = `${e}:${l}`;
64
+ getRouteTranslations(e, a) {
65
+ const r = `${e}:${a}`;
66
66
  return this.storage.translations.get(r) ?? null;
67
67
  }
68
- addTranslations(e, l, r = !0) {
69
- super.loadTranslationsCore(e, l, r);
68
+ addTranslations(e, a, r = !0) {
69
+ super.loadTranslationsCore(e, a, r);
70
70
  }
71
- addRouteTranslations(e, l, r, i = !0) {
72
- super.loadRouteTranslationsCore(e, l, r, i);
71
+ addRouteTranslations(e, a, r, i = !0) {
72
+ super.loadRouteTranslationsCore(e, a, r, i);
73
73
  }
74
- mergeTranslations(e, l, r) {
75
- this.helper.mergeTranslation(e, l, r, !0);
74
+ mergeTranslations(e, a, r) {
75
+ this.helper.mergeTranslation(e, a, r, !0);
76
76
  }
77
77
  clearCache() {
78
78
  const e = { ...this.initialMessages };
79
79
  if (super.clearCache(), Object.keys(e).length > 0)
80
- for (const [l, r] of Object.entries(e))
81
- this.helper.loadTranslations(l, r);
80
+ for (const [a, r] of Object.entries(e))
81
+ this.helper.loadTranslations(a, r);
82
82
  }
83
83
  }
84
- let v = null;
85
- function $() {
86
- return v;
84
+ let _ = null;
85
+ function F() {
86
+ return _;
87
87
  }
88
- function X(o) {
89
- const { locale: e, fallbackLocale: l, translationDir: r, routingStrategy: i } = o;
90
- return v = i || null, {
88
+ function ee(t) {
89
+ const { locale: e, fallbackLocale: a, translationDir: r, routingStrategy: i } = t;
90
+ return _ = i || null, {
91
91
  name: "@i18n-micro/astro",
92
92
  hooks: {
93
93
  // 1. Vite setup (virtual module) happens here
94
94
  "astro:config:setup": (c) => {
95
- const { updateConfig: u } = c, t = "virtual:i18n-micro/config", a = `\0${t}`, s = {
95
+ const { updateConfig: u } = c, o = "virtual:i18n-micro/config", l = `\0${o}`, s = {
96
96
  defaultLocale: e,
97
- fallbackLocale: l || e,
98
- locales: o.locales || [],
99
- localeCodes: (o.locales || []).map((n) => n.code),
97
+ fallbackLocale: a || e,
98
+ locales: t.locales || [],
99
+ localeCodes: (t.locales || []).map((n) => n.code),
100
100
  translationDir: r || null,
101
- autoDetect: o.autoDetect ?? !0,
102
- redirectToDefault: o.redirectToDefault ?? !1,
103
- localeCookie: o.localeCookie === null ? null : o.localeCookie || "i18n-locale",
104
- missingWarn: o.missingWarn ?? !1
101
+ autoDetect: t.autoDetect ?? !0,
102
+ redirectToDefault: t.redirectToDefault ?? !1,
103
+ localeCookie: t.localeCookie === null ? null : t.localeCookie || "i18n-locale",
104
+ missingWarn: t.missingWarn ?? !1
105
105
  };
106
106
  u({
107
107
  vite: {
@@ -109,11 +109,11 @@ function X(o) {
109
109
  {
110
110
  name: "vite-plugin-i18n-micro-config",
111
111
  resolveId(n) {
112
- if (n === t)
113
- return a;
112
+ if (n === o)
113
+ return l;
114
114
  },
115
115
  load(n) {
116
- if (n === a)
116
+ if (n === l)
117
117
  return `export const config = ${JSON.stringify(s)}`;
118
118
  }
119
119
  }
@@ -148,131 +148,131 @@ function X(o) {
148
148
  }
149
149
  };
150
150
  }
151
- function Y(o) {
152
- return new R(o);
151
+ function te(t) {
152
+ return new T(t);
153
153
  }
154
- function D(o, e) {
155
- if (k(o))
156
- for (const l of _(o)) {
157
- const r = W(o, l);
158
- if (C(r).isDirectory()) {
159
- D(r, e);
154
+ function O(t, e) {
155
+ if (D(t))
156
+ for (const a of M(t)) {
157
+ const r = q(t, a);
158
+ if (W(r).isDirectory()) {
159
+ O(r, e);
160
160
  continue;
161
161
  }
162
- l.endsWith(".json") && e(r);
162
+ a.endsWith(".json") && e(r);
163
163
  }
164
164
  }
165
- function E(o) {
166
- const { translationDir: e, rootDir: l = process.cwd(), disablePageLocales: r = !1 } = o, i = M(l, e);
167
- if (!k(i))
165
+ function J(t) {
166
+ const { translationDir: e, rootDir: a = process.cwd(), disablePageLocales: r = !1 } = t, i = U(a, e);
167
+ if (!D(i))
168
168
  return console.warn(`[i18n] Translation directory not found: ${i}`), { root: {}, routes: {} };
169
169
  const c = { root: {}, routes: {} };
170
- return D(i, (u) => {
171
- const t = A(i, u).split(q).join("/");
170
+ return O(i, (u) => {
171
+ const o = E(i, u).split(H).join("/");
172
172
  try {
173
- const a = N(u, "utf-8"), s = JSON.parse(a);
174
- U(c, t, s, r);
175
- } catch (a) {
176
- console.error(`[i18n] Failed to load translation file: ${u}`, a);
173
+ const l = A(u, "utf-8"), s = JSON.parse(l);
174
+ z(c, o, s, r);
175
+ } catch (l) {
176
+ console.error(`[i18n] Failed to load translation file: ${u}`, l);
177
177
  }
178
178
  }), c;
179
179
  }
180
- function Z(o, e) {
181
- const { root: l, routes: r } = E(e);
182
- for (const [i, c] of Object.entries(l))
183
- o.addTranslations(i, c, !1);
180
+ function ne(t, e) {
181
+ const { root: a, routes: r } = J(e);
182
+ for (const [i, c] of Object.entries(a))
183
+ t.addTranslations(i, c, !1);
184
184
  for (const [i, c] of Object.entries(r))
185
- for (const [u, t] of Object.entries(c))
186
- o.addRouteTranslations(u, i, H(l[u], t), !1);
185
+ for (const [u, o] of Object.entries(c))
186
+ t.addRouteTranslations(u, i, x(a[u], o), !1);
187
187
  }
188
- function ee(o) {
188
+ function oe(t) {
189
189
  const {
190
190
  i18n: e,
191
191
  // This is the global singleton with cache
192
- defaultLocale: l,
192
+ defaultLocale: a,
193
193
  locales: r,
194
194
  localeObjects: i,
195
195
  autoDetect: c = !0,
196
196
  redirectToDefault: u = !1,
197
- routingStrategy: t
198
- } = o, a = t || $();
197
+ routingStrategy: o
198
+ } = t, l = o || F();
199
199
  return async (s, n) => {
200
200
  if (s.locals.locale && s.locals.i18n)
201
201
  return n();
202
- const f = s.url, d = f.pathname;
203
- if (!a) {
204
- const L = e.clone(l), S = d === "/" || d === "" ? "index" : d.split("/").filter(Boolean).join("-");
205
- return L.setRoute(S), s.locals.i18n = L, s.locals.locale = l, s.locals.defaultLocale = l, s.locals.locales = i || r.map((w) => ({ code: w })), s.locals.currentUrl = f, n();
202
+ const f = s.url, h = f.pathname;
203
+ if (!l) {
204
+ const L = e.clone(a), S = h === "/" || h === "" ? "index" : h.split("/").filter(Boolean).join("-");
205
+ return L.setRoute(S), s.locals.i18n = L, s.locals.locale = a, s.locals.defaultLocale = a, s.locals.locales = i || r.map((y) => ({ code: y })), s.locals.currentUrl = f, n();
206
206
  }
207
- const g = {
208
- ...a,
209
- getCurrentPath: () => d,
207
+ const m = {
208
+ ...l,
209
+ getCurrentPath: () => h,
210
210
  getRoute: () => ({
211
211
  fullPath: f.pathname + f.search,
212
212
  query: Object.fromEntries(f.searchParams)
213
213
  })
214
- }, m = d.split("/").filter(Boolean)[0], P = m !== void 0 && r.includes(m);
215
- let y;
216
- P && m ? y = m : g.getLocaleFromPath ? y = g.getLocaleFromPath(d, l, r) : y = l;
217
- const h = e.clone(y), b = g.getRouteName ? g.getRouteName(d, r) : "index";
218
- return h.setRoute(b), s.locals.i18n = h, s.locals.locale = y, s.locals.defaultLocale = l, s.locals.locales = i || r.map((L) => ({ code: L })), s.locals.currentUrl = f, s.locals.routingStrategy = g, n();
214
+ }, p = h.split("/").filter(Boolean)[0], b = p !== void 0 && r.includes(p);
215
+ let P;
216
+ b && p ? P = p : m.getLocaleFromPath ? P = m.getLocaleFromPath(h, a, r) : P = a;
217
+ const w = e.clone(P), g = m.getRouteName ? m.getRouteName(h, r) : "index";
218
+ return w.setRoute(g), s.locals.i18n = w, s.locals.locale = P, s.locals.defaultLocale = a, s.locals.locales = i || r.map((L) => ({ code: L })), s.locals.currentUrl = f, s.locals.routingStrategy = m, n();
219
219
  };
220
220
  }
221
- function te(o, e, l, r, i, c = "i18n-locale") {
222
- const u = $();
223
- let t = r;
221
+ function ae(t, e, a, r, i, c = "i18n-locale") {
222
+ const u = F();
223
+ let o = r;
224
224
  if (u?.getLocaleFromPath)
225
- t = u.getLocaleFromPath(o, r, i);
225
+ o = u.getLocaleFromPath(t, r, i);
226
226
  else {
227
- const s = o.split("/").filter(Boolean)[0];
228
- s && i.includes(s) && (t = s);
227
+ const s = t.split("/").filter(Boolean)[0];
228
+ s && i.includes(s) && (o = s);
229
229
  }
230
- if (c !== null && t === r && e.get(c)) {
231
- const a = e.get(c)?.value;
232
- a && i.includes(a) && (t = a);
230
+ if (c !== null && o === r && e.get(c)) {
231
+ const l = e.get(c)?.value;
232
+ l && i.includes(l) && (o = l);
233
233
  }
234
- if (t === r)
234
+ if (o === r)
235
235
  try {
236
- const a = z(l.get("accept-language") ?? void 0, i);
237
- a && (t = a);
236
+ const l = V(a.get("accept-language") ?? void 0, i);
237
+ l && (o = l);
238
238
  } catch {
239
239
  }
240
- return t;
240
+ return o;
241
241
  }
242
- function ne(o, e, l) {
243
- const r = o.map((n) => n.code), i = (n, f = []) => {
244
- const d = n.replace(/^\//, "").replace(/\/$/, "");
245
- if (!d)
242
+ function le(t, e, a) {
243
+ const r = t.map((n) => n.code), i = (n, f = []) => {
244
+ const h = n.replace(/^\//, "").replace(/\/$/, "");
245
+ if (!h)
246
246
  return "index";
247
- const g = d.split("/").filter(Boolean), p = g[0];
248
- return p && f.includes(p) && g.shift(), g.length === 0 ? "index" : g.join("-");
249
- }, c = (n, f = "en", d = []) => {
250
- const p = n.split("/").filter(Boolean)[0];
251
- return p && d.includes(p) ? p : f;
252
- }, u = (n, f, d = [], g) => {
253
- const p = n.split("/").filter(Boolean), m = p[0];
254
- return m && d.includes(m) && p.shift(), (f !== g || g === void 0) && p.unshift(f), `/${p.join("/")}`;
255
- }, t = (n, f, d = [], g) => {
256
- const m = (n.replace(/^\//, "").replace(/\/$/, "") || "").split("/").filter(Boolean), P = m[0];
257
- return P && d.includes(P) && m.shift(), (f !== g || g === void 0) && m.unshift(f), `/${m.join("/")}`;
247
+ const m = h.split("/").filter(Boolean), d = m[0];
248
+ return d && f.includes(d) && m.shift(), m.length === 0 ? "index" : m.join("-");
249
+ }, c = (n, f = "en", h = []) => {
250
+ const d = n.split("/").filter(Boolean)[0];
251
+ return d && h.includes(d) ? d : f;
252
+ }, u = (n, f, h = [], m) => {
253
+ const d = n.split("/").filter(Boolean), p = d[0];
254
+ return p && h.includes(p) && d.shift(), (f !== m || m === void 0) && d.unshift(f), `/${d.join("/")}`;
255
+ }, o = (n, f, h = [], m) => {
256
+ const p = (n.replace(/^\//, "").replace(/\/$/, "") || "").split("/").filter(Boolean), b = p[0];
257
+ return b && h.includes(b) && p.shift(), (f !== m || m === void 0) && p.unshift(f), `/${p.join("/")}`;
258
258
  };
259
259
  return {
260
- getCurrentPath: () => l ? l().pathname : typeof window < "u" ? window.location.pathname : "/",
260
+ getCurrentPath: () => a ? a().pathname : typeof window < "u" ? window.location.pathname : "/",
261
261
  getRouteName: i,
262
262
  getLocaleFromPath: c,
263
263
  switchLocalePath: u,
264
- localizePath: t,
264
+ localizePath: o,
265
265
  removeLocaleFromPath: (n, f = []) => {
266
- const d = n.split("/").filter(Boolean), g = d[0];
267
- return g && f.includes(g) && d.shift(), `/${d.join("/")}`;
266
+ const h = n.split("/").filter(Boolean), m = h[0];
267
+ return m && f.includes(m) && h.shift(), `/${h.join("/")}`;
268
268
  },
269
269
  resolvePath: (n, f) => {
270
- const d = typeof n == "string" ? n : n.path || "/";
271
- return t(d, f, r, e);
270
+ const h = typeof n == "string" ? n : n.path || "/";
271
+ return o(h, f, r, e);
272
272
  },
273
273
  getRoute: () => {
274
- if (l) {
275
- const n = l();
274
+ if (a) {
275
+ const n = a();
276
276
  return {
277
277
  fullPath: n.pathname + n.search,
278
278
  query: Object.fromEntries(n.searchParams)
@@ -299,181 +299,214 @@ function ne(o, e, l) {
299
299
  }
300
300
  };
301
301
  }
302
- function F(o) {
303
- const e = o.locals.i18n;
302
+ function R(t) {
303
+ const e = t.og?.trim();
304
+ if (e) return e;
305
+ const a = t.iso?.trim();
306
+ if (!a) return null;
307
+ const r = a.indexOf("_");
308
+ if (r > 0) {
309
+ const c = a.slice(0, r), u = a.slice(r + 1);
310
+ if (c.length >= 2 && u.length === 2)
311
+ return `${c.toLowerCase()}_${u.toUpperCase()}`;
312
+ }
313
+ const i = a.indexOf("-");
314
+ if (i > 0) {
315
+ const c = a.slice(0, i), u = a.slice(i + 1);
316
+ if (c.length >= 2 && u.length === 2 && /^[A-Za-z]{2}$/.test(u))
317
+ return `${c.toLowerCase()}_${u.toUpperCase()}`;
318
+ }
319
+ return null;
320
+ }
321
+ function k(t, e = {}) {
322
+ if (R(t) !== null || e.missingWarn === !1 || process.env.NODE_ENV === "production") return;
323
+ const a = e.tag ?? "og:locale", r = String(t.code ?? "unknown"), i = t.iso ? `, iso: '${t.iso}'` : "";
324
+ console.warn(
325
+ `[i18n] Cannot derive ${a} for locale '${r}'${i}. Set locale.og (e.g. 'en_US') or use iso with a 2-letter region (e.g. 'en-US').`
326
+ );
327
+ }
328
+ function C(t) {
329
+ const e = t.locals.i18n;
304
330
  if (!e)
305
331
  throw new Error("i18n instance not found. Make sure i18n middleware is configured.");
306
332
  return e;
307
333
  }
308
- function T(o) {
309
- return o.locals.locale || "en";
334
+ function $(t) {
335
+ return t.locals.locale || "en";
310
336
  }
311
- function j(o) {
312
- return o.locals.defaultLocale || "en";
337
+ function v(t) {
338
+ return t.locals.defaultLocale || "en";
313
339
  }
314
- function B(o) {
315
- return o.locals.locales || [];
340
+ function B(t) {
341
+ return t.locals.locales || [];
316
342
  }
317
- function I(o) {
318
- return o.locals.routingStrategy || null;
343
+ function I(t) {
344
+ return t.locals.routingStrategy || null;
319
345
  }
320
- function oe(o) {
321
- const e = F(o), l = T(o), r = j(o), i = B(o), c = i.map((t) => t.code), u = I(o);
346
+ function re(t) {
347
+ const e = C(t), a = $(t), r = v(t), i = B(t), c = i.map((o) => o.code), u = I(t);
322
348
  return {
323
349
  // Current locale
324
- locale: l,
350
+ locale: a,
325
351
  defaultLocale: r,
326
352
  locales: i,
327
353
  // Translation methods
328
- t: (t, a, s, n) => e.t(t, a, s, n),
329
- ts: (t, a, s, n) => e.ts(t, a, s, n),
330
- tc: (t, a, s) => e.tc(t, a, s),
331
- tn: (t, a) => e.tn(t, a),
332
- td: (t, a) => e.td(t, a),
333
- tdr: (t, a) => e.tdr(t, a),
334
- has: (t, a) => e.has(t, a),
354
+ t: (o, l, s, n) => e.t(o, l, s, n),
355
+ ts: (o, l, s, n) => e.ts(o, l, s, n),
356
+ tc: (o, l, s) => e.tc(o, l, s),
357
+ tn: (o, l) => e.tn(o, l),
358
+ td: (o, l) => e.td(o, l),
359
+ tdr: (o, l) => e.tdr(o, l),
360
+ has: (o, l) => e.has(o, l),
335
361
  // Route management
336
362
  getRoute: () => e.getRoute(),
337
- getRouteName: (t) => {
338
- const a = t || o.url.pathname;
363
+ getRouteName: (o) => {
364
+ const l = o || t.url.pathname;
339
365
  if (u?.getRouteName)
340
- return u.getRouteName(a, c);
341
- const s = a.replace(/^\//, "").replace(/\/$/, "");
366
+ return u.getRouteName(l, c);
367
+ const s = l.replace(/^\//, "").replace(/\/$/, "");
342
368
  if (!s) return "index";
343
369
  const n = s.split("/").filter(Boolean), f = n[0];
344
370
  return f && c.includes(f) && n.shift(), n.length === 0 ? "index" : n.join("-");
345
371
  },
346
- getLocaleFromPath: (t) => {
347
- const a = t || o.url.pathname;
372
+ getLocaleFromPath: (o) => {
373
+ const l = o || t.url.pathname;
348
374
  if (u?.getLocaleFromPath)
349
- return u.getLocaleFromPath(a, r, c);
350
- const n = a.split("/").filter(Boolean)[0];
375
+ return u.getLocaleFromPath(l, r, c);
376
+ const n = l.split("/").filter(Boolean)[0];
351
377
  return n && c.includes(n) ? n : r;
352
378
  },
353
379
  // Path utilities
354
- switchLocalePath: (t) => {
380
+ switchLocalePath: (o) => {
355
381
  if (u?.switchLocalePath)
356
- return u.switchLocalePath(o.url.pathname, t, c, r);
357
- const a = o.url.pathname.split("/").filter(Boolean), s = a[0];
358
- return s && c.includes(s) && a.shift(), t !== r && a.unshift(t), `/${a.join("/")}`;
382
+ return u.switchLocalePath(t.url.pathname, o, c, r);
383
+ const l = t.url.pathname.split("/").filter(Boolean), s = l[0];
384
+ return s && c.includes(s) && l.shift(), o !== r && l.unshift(o), `/${l.join("/")}`;
359
385
  },
360
- localizePath: (t, a) => {
386
+ localizePath: (o, l) => {
361
387
  if (u?.localizePath)
362
- return u.localizePath(t, a || l, c, r);
363
- const n = (t.replace(/^\//, "").replace(/\/$/, "") || "").split("/").filter(Boolean), f = n[0];
364
- return f && c.includes(f) && n.shift(), a && a !== r && n.unshift(a), `/${n.join("/")}`;
388
+ return u.localizePath(o, l || a, c, r);
389
+ const n = (o.replace(/^\//, "").replace(/\/$/, "") || "").split("/").filter(Boolean), f = n[0];
390
+ return f && c.includes(f) && n.shift(), l && l !== r && n.unshift(l), `/${n.join("/")}`;
365
391
  },
366
392
  // Get i18n instance
367
393
  getI18n: () => e,
368
394
  // Get base path without locale (for rewrite)
369
- getBasePath: (t) => {
370
- const n = (t || o.url).pathname.split("/").filter(Boolean), f = n[0];
395
+ getBasePath: (o) => {
396
+ const n = (o || t.url).pathname.split("/").filter(Boolean), f = n[0];
371
397
  return f && c.includes(f) && n.shift(), n.length > 0 ? `/${n.join("/")}` : "/";
372
398
  },
373
399
  // Translation management
374
- addTranslations: (t, a, s = !0) => {
375
- e.addTranslations(t, a, s);
400
+ addTranslations: (o, l, s = !0) => {
401
+ e.addTranslations(o, l, s);
376
402
  },
377
- addRouteTranslations: (t, a, s, n = !0) => {
378
- e.addRouteTranslations(t, a, s, n);
403
+ addRouteTranslations: (o, l, s, n = !0) => {
404
+ e.addRouteTranslations(o, l, s, n);
379
405
  },
380
- mergeTranslations: (t, a, s) => {
381
- e.mergeTranslations(t, a, s);
406
+ mergeTranslations: (o, l, s) => {
407
+ e.mergeTranslations(o, l, s);
382
408
  },
383
409
  clearCache: () => {
384
410
  e.clearCache();
385
411
  }
386
412
  };
387
413
  }
388
- function ae(o, e = {}) {
389
- const { baseUrl: l = "/", addDirAttribute: r = !0, addSeoAttributes: i = !0 } = e, c = T(o), u = j(o), a = B(o).filter((h) => !h.disabled), s = a.filter((h) => h.seo !== !1), n = a.find((h) => h.code === c);
414
+ function se(t, e = {}) {
415
+ const { baseUrl: a = "/", addDirAttribute: r = !0, addSeoAttributes: i = !0 } = e, c = $(t), u = v(t), l = B(t).filter((g) => !g.disabled), s = l.filter((g) => g.seo !== !1), n = l.find((g) => g.code === c);
390
416
  if (!n)
391
417
  return { htmlAttrs: {}, link: [], meta: [] };
392
- const f = n.iso || c, d = n.dir || "auto", g = {
418
+ const f = n.iso || c, h = R(n), m = n.dir || "auto", d = {
393
419
  htmlAttrs: {
394
420
  lang: f,
395
- ...r ? { dir: d } : {}
421
+ ...r ? { dir: m } : {}
396
422
  },
397
423
  link: [],
398
424
  meta: []
399
425
  };
400
426
  if (!i)
401
- return g;
402
- const p = `${l}${o.url.pathname}`;
403
- g.link.push({
427
+ return d;
428
+ const p = `${a}${t.url.pathname}`;
429
+ d.link.push({
404
430
  rel: "canonical",
405
431
  href: p
406
432
  });
407
- const m = I(o), P = a.map((h) => h.code);
408
- for (const h of s) {
409
- let b = o.url.pathname;
410
- if (m?.switchLocalePath)
411
- b = m.switchLocalePath(o.url.pathname, h.code, P, u);
433
+ const b = I(t), P = l.map((g) => g.code);
434
+ for (const g of s) {
435
+ let L = t.url.pathname;
436
+ if (b?.switchLocalePath)
437
+ L = b.switchLocalePath(t.url.pathname, g.code, P, u);
412
438
  else {
413
- const S = o.url.pathname.split("/").filter(Boolean), w = S[0];
414
- w && P.includes(w) && S.shift(), h.code !== u && S.unshift(h.code), b = `/${S.join("/")}`;
439
+ const y = t.url.pathname.split("/").filter(Boolean), j = y[0];
440
+ j && P.includes(j) && y.shift(), g.code !== u && y.unshift(g.code), L = `/${y.join("/")}`;
415
441
  }
416
- const L = `${l}${b}`;
417
- g.link.push({
442
+ const S = `${a}${L}`;
443
+ d.link.push({
418
444
  rel: "alternate",
419
- href: L,
420
- hreflang: h.code
421
- }), h.iso && h.iso !== h.code && g.link.push({
445
+ href: S,
446
+ hreflang: g.code
447
+ }), g.iso && g.iso !== g.code && d.link.push({
422
448
  rel: "alternate",
423
- href: L,
424
- hreflang: h.iso
449
+ href: S,
450
+ hreflang: g.iso
425
451
  });
426
452
  }
427
- if (a.find((h) => h.code === u)?.seo !== !1) {
428
- let h = o.url.pathname;
429
- if (m?.switchLocalePath)
430
- h = m.switchLocalePath(o.url.pathname, u, P, u);
453
+ if (l.find((g) => g.code === u)?.seo !== !1) {
454
+ let g = t.url.pathname;
455
+ if (b?.switchLocalePath)
456
+ g = b.switchLocalePath(t.url.pathname, u, P, u);
431
457
  else {
432
- const b = o.url.pathname.split("/").filter(Boolean), L = b[0];
433
- L && P.includes(L) && b.shift(), h = `/${b.join("/")}`;
458
+ const L = t.url.pathname.split("/").filter(Boolean), S = L[0];
459
+ S && P.includes(S) && L.shift(), g = `/${L.join("/")}`;
434
460
  }
435
- g.link.push({
461
+ d.link.push({
436
462
  rel: "alternate",
437
- href: `${l}${h}`,
463
+ href: `${a}${g}`,
438
464
  hreflang: "x-default"
439
465
  });
440
466
  }
441
- g.meta.push({
467
+ h ? d.meta.push({
442
468
  property: "og:locale",
443
- content: f
444
- }), g.meta.push({
469
+ content: h
470
+ }) : k(n, { tag: "og:locale" }), d.meta.push({
445
471
  property: "og:url",
446
472
  content: p
447
473
  });
448
- for (const h of s)
449
- h.code !== c && g.meta.push({
474
+ for (const g of s) {
475
+ if (g.code === c) continue;
476
+ const L = R(g);
477
+ if (!L) {
478
+ k(g, { tag: "og:locale:alternate" });
479
+ continue;
480
+ }
481
+ d.meta.push({
450
482
  property: "og:locale:alternate",
451
- content: h.og || h.iso || h.code
483
+ content: L
452
484
  });
453
- return g;
485
+ }
486
+ return d;
454
487
  }
455
- function x(o, e, l) {
488
+ function G(t, e, a) {
456
489
  const r = e.split(".");
457
- let i = o;
490
+ let i = t;
458
491
  for (let u = 0; u < r.length - 1; u++) {
459
- const t = r[u];
460
- i[t] || (i[t] = {}), i = i[t];
492
+ const o = r[u];
493
+ i[o] || (i[o] = {}), i = i[o];
461
494
  }
462
495
  const c = r[r.length - 1];
463
- c !== void 0 && (i[c] = l);
496
+ c !== void 0 && (i[c] = a);
464
497
  }
465
- function le(o, e) {
466
- const l = F(o), r = T(o), i = j(o), c = l.getRoute(), u = {};
498
+ function ie(t, e) {
499
+ const a = C(t), r = $(t), i = v(t), c = a.getRoute(), u = {};
467
500
  if (e && e.length > 0) {
468
- const t = {};
469
- for (const a of e) {
470
- const s = l.t(a, void 0, void 0, c);
471
- s != null && s !== a && x(t, a, s);
501
+ const o = {};
502
+ for (const l of e) {
503
+ const s = a.t(l, void 0, void 0, c);
504
+ s != null && s !== l && G(o, l, s);
472
505
  }
473
- Object.keys(t).length > 0 && (u[c] = t);
506
+ Object.keys(o).length > 0 && (u[c] = o);
474
507
  } else {
475
- const t = l.getRouteTranslations(r, c);
476
- t && (u[c] = t);
508
+ const o = a.getRouteTranslations(r, c);
509
+ o && (u[c] = o);
477
510
  }
478
511
  return {
479
512
  locale: r,
@@ -483,22 +516,22 @@ function le(o, e) {
483
516
  };
484
517
  }
485
518
  export {
486
- R as AstroI18n,
487
- ie as FormatService,
488
- ne as createAstroRouterAdapter,
489
- Y as createI18n,
490
- ee as createI18nMiddleware,
491
- ce as defaultPlural,
492
- te as detectLocale,
493
- j as getDefaultLocale,
494
- F as getI18n,
495
- le as getI18nProps,
496
- T as getLocale,
519
+ T as AstroI18n,
520
+ fe as FormatService,
521
+ le as createAstroRouterAdapter,
522
+ te as createI18n,
523
+ oe as createI18nMiddleware,
524
+ ge as defaultPlural,
525
+ ae as detectLocale,
526
+ v as getDefaultLocale,
527
+ C as getI18n,
528
+ ie as getI18nProps,
529
+ $ as getLocale,
497
530
  B as getLocales,
498
- X as i18nIntegration,
499
- ue as interpolate,
500
- E as loadTranslationsFromDir,
501
- Z as loadTranslationsIntoI18n,
502
- oe as useI18n,
503
- ae as useLocaleHead
531
+ ee as i18nIntegration,
532
+ he as interpolate,
533
+ J as loadTranslationsFromDir,
534
+ ne as loadTranslationsIntoI18n,
535
+ re as useI18n,
536
+ se as useLocaleHead
504
537
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@i18n-micro/astro",
3
- "version": "1.3.6",
3
+ "version": "1.3.7",
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/utils": "1.0.1",
81
80
  "@i18n-micro/core": "1.3.2",
82
- "@i18n-micro/node": "1.2.3",
83
- "@i18n-micro/types": "1.2.4"
81
+ "@i18n-micro/types": "1.2.5",
82
+ "@i18n-micro/utils": "1.0.2",
83
+ "@i18n-micro/node": "1.2.3"
84
84
  },
85
85
  "devDependencies": {
86
86
  "@types/jest": "^29.5.14",
package/src/utils.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { CleanTranslation, Locale, Params, TranslationKey, Translations } from '@i18n-micro/types'
2
+ import { resolveOgLocale, warnUnresolvedOgLocale } from '@i18n-micro/utils/resolve-og-locale'
2
3
  import type { AstroGlobal } from 'astro'
3
4
  import type { AstroI18n } from './composer'
4
5
  import type { I18nRoutingStrategy } from './router/types'
@@ -225,6 +226,7 @@ export function useLocaleHead(astro: AstroGlobal, options: LocaleHeadOptions = {
225
226
  }
226
227
 
227
228
  const currentIso = currentLocaleObj.iso || locale
229
+ const currentOg = resolveOgLocale(currentLocaleObj)
228
230
  const currentDir = currentLocaleObj.dir || 'auto'
229
231
 
230
232
  const result: LocaleHeadResult = {
@@ -309,10 +311,14 @@ export function useLocaleHead(astro: AstroGlobal, options: LocaleHeadOptions = {
309
311
  }
310
312
 
311
313
  // Open Graph locale
312
- result.meta.push({
313
- property: 'og:locale',
314
- content: currentIso,
315
- })
314
+ if (currentOg) {
315
+ result.meta.push({
316
+ property: 'og:locale',
317
+ content: currentOg,
318
+ })
319
+ } else {
320
+ warnUnresolvedOgLocale(currentLocaleObj, { tag: 'og:locale' })
321
+ }
316
322
 
317
323
  result.meta.push({
318
324
  property: 'og:url',
@@ -322,9 +328,14 @@ export function useLocaleHead(astro: AstroGlobal, options: LocaleHeadOptions = {
322
328
  // Alternate OG locales
323
329
  for (const loc of localesForSeo) {
324
330
  if (loc.code === locale) continue
331
+ const ogAlt = resolveOgLocale(loc)
332
+ if (!ogAlt) {
333
+ warnUnresolvedOgLocale(loc, { tag: 'og:locale:alternate' })
334
+ continue
335
+ }
325
336
  result.meta.push({
326
337
  property: 'og:locale:alternate',
327
- content: loc.og || loc.iso || loc.code,
338
+ content: ogAlt,
328
339
  })
329
340
  }
330
341