@i18n-micro/astro 1.3.5 → 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 w=require("@i18n-micro/core"),j=require("node:fs"),T=require("node:path"),D=require("@i18n-micro/utils/parse-path"),M=require("@i18n-micro/utils/accept-language");class v extends w.BaseI18n{constructor(e){const o=e._storage||{translations:new Map};if(super({storage:o,plural:e.plural,missingWarn:e.missingWarn,missingHandler:e.missingHandler}),this.initialMessages={},this.storage=o,this._locale=e.locale,this._fallbackLocale=e.fallbackLocale||e.locale,this._currentRoute="index",e.messages){this.initialMessages={...e.messages};for(const[n,s]of Object.entries(e.messages))this.helper.loadTranslations(n,s)}}cloneStorage(e){const o=new Map;for(const[n,s]of e.translations)o.set(n,{...s});return{translations:o}}clone(e){const o=this.cloneStorage(this.storage);return new v({locale:e||this._locale,fallbackLocale:this._fallbackLocale,plural:this.pluralFunc,missingWarn:this.missingWarn,missingHandler:this.missingHandler,_storage:o})}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,o){const n=`${e}:${o}`;return this.storage.translations.get(n)??null}addTranslations(e,o,n=!0){super.loadTranslationsCore(e,o,n)}addRouteTranslations(e,o,n,s=!0){super.loadRouteTranslationsCore(e,o,n,s)}mergeTranslations(e,o,n){this.helper.mergeTranslation(e,o,n,!0)}clearCache(){const e={...this.initialMessages};if(super.clearCache(),Object.keys(e).length>0)for(const[o,n]of Object.entries(e))this.helper.loadTranslations(o,n)}}let B=null;function O(){return B}function q(t){const{locale:e,fallbackLocale:o,translationDir:n,routingStrategy:s}=t;return B=s||null,{name:"@i18n-micro/astro",hooks:{"astro:config:setup":c=>{const{updateConfig:u}=c,a="virtual:i18n-micro/config",r=`\0${a}`,i={defaultLocale:e,fallbackLocale:o||e,locales:t.locales||[],localeCodes:(t.locales||[]).map(l=>l.code),translationDir:n||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(l){if(l===a)return r},load(l){if(l===r)return`export const config = ${JSON.stringify(i)}`}}]}})},"astro:config:done":c=>{const{injectTypes:u}=c;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(t){return new v(t)}function _(t,e){if(j.existsSync(t))for(const o of j.readdirSync(t)){const n=T.join(t,o);if(j.statSync(n).isDirectory()){_(n,e);continue}o.endsWith(".json")&&e(n)}}function N(t){const{translationDir:e,rootDir:o=process.cwd(),disablePageLocales:n=!1}=t,s=T.resolve(o,e);if(!j.existsSync(s))return console.warn(`[i18n] Translation directory not found: ${s}`),{root:{},routes:{}};const c={root:{},routes:{}};return _(s,u=>{const a=T.relative(s,u).split(T.sep).join("/");try{const r=j.readFileSync(u,"utf-8"),i=JSON.parse(r);D.storeLoadedTranslationFile(c,a,i,n)}catch(r){console.error(`[i18n] Failed to load translation file: ${u}`,r)}}),c}function W(t,e){const{root:o,routes:n}=N(e);for(const[s,c]of Object.entries(o))t.addTranslations(s,c,!1);for(const[s,c]of Object.entries(n))for(const[u,a]of Object.entries(c))t.addRouteTranslations(u,s,D.mergeRouteTranslationsWithRoot(o[u],a),!1)}function H(t){const{i18n:e,defaultLocale:o,locales:n,localeObjects:s,autoDetect:c=!0,redirectToDefault:u=!1,routingStrategy:a}=t,r=a||O();return async(i,l)=>{if(i.locals.locale&&i.locals.i18n)return l();const f=i.url,d=f.pathname;if(!r){const P=e.clone(o),S=d==="/"||d===""?"index":d.split("/").filter(Boolean).join("-");return P.setRoute(S),i.locals.i18n=P,i.locals.locale=o,i.locals.defaultLocale=o,i.locals.locales=s||n.map(R=>({code:R})),i.locals.currentUrl=f,l()}const g={...r,getCurrentPath:()=>d,getRoute:()=>({fullPath:f.pathname+f.search,query:Object.fromEntries(f.searchParams)})},m=d.split("/").filter(Boolean)[0],L=m!==void 0&&n.includes(m);let y;L&&m?y=m:g.getLocaleFromPath?y=g.getLocaleFromPath(d,o,n):y=o;const h=e.clone(y),b=g.getRouteName?g.getRouteName(d,n):"index";return h.setRoute(b),i.locals.i18n=h,i.locals.locale=y,i.locals.defaultLocale=o,i.locals.locales=s||n.map(P=>({code:P})),i.locals.currentUrl=f,i.locals.routingStrategy=g,l()}}function z(t,e,o,n,s,c="i18n-locale"){const u=O();let a=n;if(u?.getLocaleFromPath)a=u.getLocaleFromPath(t,n,s);else{const i=t.split("/").filter(Boolean)[0];i&&s.includes(i)&&(a=i)}if(c!==null&&a===n&&e.get(c)){const r=e.get(c)?.value;r&&s.includes(r)&&(a=r)}if(a===n)try{const r=M.detectLocaleFromAcceptLanguage(o.get("accept-language")??void 0,s);r&&(a=r)}catch{}return a}function U(t,e,o){const n=t.map(l=>l.code),s=(l,f=[])=>{const d=l.replace(/^\//,"").replace(/\/$/,"");if(!d)return"index";const g=d.split("/").filter(Boolean),p=g[0];return p&&f.includes(p)&&g.shift(),g.length===0?"index":g.join("-")},c=(l,f="en",d=[])=>{const p=l.split("/").filter(Boolean)[0];return p&&d.includes(p)?p:f},u=(l,f,d=[],g)=>{const p=l.split("/").filter(Boolean),m=p[0];return m&&d.includes(m)&&p.shift(),(f!==g||g===void 0)&&p.unshift(f),`/${p.join("/")}`},a=(l,f,d=[],g)=>{const m=(l.replace(/^\//,"").replace(/\/$/,"")||"").split("/").filter(Boolean),L=m[0];return L&&d.includes(L)&&m.shift(),(f!==g||g===void 0)&&m.unshift(f),`/${m.join("/")}`};return{getCurrentPath:()=>o?o().pathname:typeof window<"u"?window.location.pathname:"/",getRouteName:s,getLocaleFromPath:c,switchLocalePath:u,localizePath:a,removeLocaleFromPath:(l,f=[])=>{const d=l.split("/").filter(Boolean),g=d[0];return g&&f.includes(g)&&d.shift(),`/${d.join("/")}`},resolvePath:(l,f)=>{const d=typeof l=="string"?l:l.path||"/";return a(d,f,n,e)},getRoute:()=>{if(o){const l=o();return{fullPath:l.pathname+l.search,query:Object.fromEntries(l.searchParams)}}if(typeof window<"u"){const l=new URL(window.location.href);return{fullPath:l.pathname+l.search,query:Object.fromEntries(l.searchParams)}}return{fullPath:"/",query:{}}},push:l=>{typeof window<"u"&&(window.location.href=l.path)},replace:l=>{typeof window<"u"&&window.location.replace(l.path)}}}function x(t,e=[]){const o=t.replace(/^\//,"").replace(/\/$/,"");if(!o)return"index";const n=o.split("/").filter(Boolean),s=n[0];return s&&e.includes(s)&&n.shift(),n.length===0?"index":n.join("-")}function E(t,e="en",o=[]){const s=t.split("/").filter(Boolean)[0];return s&&o.includes(s)?s:e}function J(t,e,o=[],n){const s=t.split("/").filter(Boolean),c=s[0];return c&&o.includes(c)&&s.shift(),(e!==n||n===void 0)&&s.unshift(e),`/${s.join("/")}`}function V(t,e,o=[],n){const c=(t.replace(/^\//,"").replace(/\/$/,"")||"").split("/").filter(Boolean),u=c[0];return u&&o.includes(u)&&c.shift(),(e!==n||n===void 0)&&c.unshift(e),`/${c.join("/")}`}function G(t,e=[]){const o=t.split("/").filter(Boolean),n=o[0];return n&&e.includes(n)&&o.shift(),`/${o.join("/")}`}function F(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 k(t){return t.locals.defaultLocale||"en"}function I(t){return t.locals.locales||[]}function C(t){return t.locals.routingStrategy||null}function K(t){const e=F(t),o=$(t),n=k(t),s=I(t),c=s.map(a=>a.code),u=C(t);return{locale:o,defaultLocale:n,locales:s,t:(a,r,i,l)=>e.t(a,r,i,l),ts:(a,r,i,l)=>e.ts(a,r,i,l),tc:(a,r,i)=>e.tc(a,r,i),tn:(a,r)=>e.tn(a,r),td:(a,r)=>e.td(a,r),tdr:(a,r)=>e.tdr(a,r),has:(a,r)=>e.has(a,r),getRoute:()=>e.getRoute(),getRouteName:a=>{const r=a||t.url.pathname;if(u?.getRouteName)return u.getRouteName(r,c);const i=r.replace(/^\//,"").replace(/\/$/,"");if(!i)return"index";const l=i.split("/").filter(Boolean),f=l[0];return f&&c.includes(f)&&l.shift(),l.length===0?"index":l.join("-")},getLocaleFromPath:a=>{const r=a||t.url.pathname;if(u?.getLocaleFromPath)return u.getLocaleFromPath(r,n,c);const l=r.split("/").filter(Boolean)[0];return l&&c.includes(l)?l:n},switchLocalePath:a=>{if(u?.switchLocalePath)return u.switchLocalePath(t.url.pathname,a,c,n);const r=t.url.pathname.split("/").filter(Boolean),i=r[0];return i&&c.includes(i)&&r.shift(),a!==n&&r.unshift(a),`/${r.join("/")}`},localizePath:(a,r)=>{if(u?.localizePath)return u.localizePath(a,r||o,c,n);const l=(a.replace(/^\//,"").replace(/\/$/,"")||"").split("/").filter(Boolean),f=l[0];return f&&c.includes(f)&&l.shift(),r&&r!==n&&l.unshift(r),`/${l.join("/")}`},getI18n:()=>e,getBasePath:a=>{const l=(a||t.url).pathname.split("/").filter(Boolean),f=l[0];return f&&c.includes(f)&&l.shift(),l.length>0?`/${l.join("/")}`:"/"},addTranslations:(a,r,i=!0)=>{e.addTranslations(a,r,i)},addRouteTranslations:(a,r,i,l=!0)=>{e.addRouteTranslations(a,r,i,l)},mergeTranslations:(a,r,i)=>{e.mergeTranslations(a,r,i)},clearCache:()=>{e.clearCache()}}}function Q(t,e={}){const{baseUrl:o="/",addDirAttribute:n=!0,addSeoAttributes:s=!0}=e,c=$(t),u=k(t),r=I(t).filter(h=>!h.disabled),i=r.filter(h=>h.seo!==!1),l=r.find(h=>h.code===c);if(!l)return{htmlAttrs:{},link:[],meta:[]};const f=l.iso||c,d=l.dir||"auto",g={htmlAttrs:{lang:f,...n?{dir:d}:{}},link:[],meta:[]};if(!s)return g;const p=`${o}${t.url.pathname}`;g.link.push({rel:"canonical",href:p});const m=C(t),L=r.map(h=>h.code);for(const h of i){let b=t.url.pathname;if(m?.switchLocalePath)b=m.switchLocalePath(t.url.pathname,h.code,L,u);else{const S=t.url.pathname.split("/").filter(Boolean),R=S[0];R&&L.includes(R)&&S.shift(),h.code!==u&&S.unshift(h.code),b=`/${S.join("/")}`}const P=`${o}${b}`;g.link.push({rel:"alternate",href:P,hreflang:h.code}),h.iso&&h.iso!==h.code&&g.link.push({rel:"alternate",href:P,hreflang:h.iso})}if(r.find(h=>h.code===u)?.seo!==!1){let h=t.url.pathname;if(m?.switchLocalePath)h=m.switchLocalePath(t.url.pathname,u,L,u);else{const b=t.url.pathname.split("/").filter(Boolean),P=b[0];P&&L.includes(P)&&b.shift(),h=`/${b.join("/")}`}g.link.push({rel:"alternate",href:`${o}${h}`,hreflang:"x-default"})}g.meta.push({property:"og:locale",content:f}),g.meta.push({property:"og:url",content:p});for(const h of i)h.code!==c&&g.meta.push({property:"og:locale:alternate",content:h.og||h.iso||h.code});return g}function X(t,e,o){const n=e.split(".");let s=t;for(let u=0;u<n.length-1;u++){const a=n[u];s[a]||(s[a]={}),s=s[a]}const c=n[n.length-1];c!==void 0&&(s[c]=o)}function Y(t,e){const o=F(t),n=$(t),s=k(t),c=o.getRoute(),u={};if(e&&e.length>0){const a={};for(const r of e){const i=o.t(r,void 0,void 0,c);i!=null&&i!==r&&X(a,r,i)}Object.keys(a).length>0&&(u[c]=a)}else{const a=o.getRouteTranslations(n,c);a&&(u[c]=a)}return{locale:n,fallbackLocale:s,currentRoute:c,translations:u}}Object.defineProperty(exports,"FormatService",{enumerable:!0,get:()=>w.FormatService});Object.defineProperty(exports,"defaultPlural",{enumerable:!0,get:()=>w.defaultPlural});Object.defineProperty(exports,"interpolate",{enumerable:!0,get:()=>w.interpolate});exports.AstroI18n=v;exports.createAstroRouterAdapter=U;exports.createI18n=A;exports.createI18nMiddleware=H;exports.detectLocale=z;exports.getDefaultLocale=k;exports.getI18n=F;exports.getI18nProps=Y;exports.getLocale=$;exports.getLocaleFromPath=E;exports.getLocales=I;exports.getRouteName=x;exports.i18nIntegration=q;exports.loadTranslationsFromDir=N;exports.loadTranslationsIntoI18n=W;exports.localizePath=V;exports.removeLocaleFromPath=G;exports.switchLocalePath=J;exports.useI18n=K;exports.useLocaleHead=Q;
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.d.cts CHANGED
@@ -1,14 +1,13 @@
1
1
  export { defaultPlural, FormatService, interpolate } from '@i18n-micro/core';
2
- export type { CleanTranslation, Getter, Locale, LocaleCode, Params, PluralFunc, Translations, } from '@i18n-micro/types';
2
+ export type { CleanTranslation, Getter, Locale, LocaleCode, Params, PluralFunc, Translations } from '@i18n-micro/types';
3
3
  export { AstroI18n, type AstroI18nOptions } from './composer';
4
4
  export type { I18nIntegrationOptions } from './integration';
5
5
  export { createI18n, i18nIntegration } from './integration';
6
6
  export type { LoadedTranslations, LoadTranslationsOptions } from './load-translations';
7
- export { loadTranslationsFromDir, loadTranslationsIntoI18n, } from './load-translations';
7
+ export { loadTranslationsFromDir, loadTranslationsIntoI18n } from './load-translations';
8
8
  export type { I18nMiddlewareOptions } from './middleware';
9
9
  export { createI18nMiddleware, detectLocale } from './middleware';
10
10
  export { createAstroRouterAdapter } from './router/adapter';
11
11
  export type { I18nRoutingStrategy } from './router/types';
12
- export { getLocaleFromPath, getRouteName, localizePath, removeLocaleFromPath, switchLocalePath, } from './routing';
13
12
  export type { I18nClientProps, LocaleHeadOptions, LocaleHeadResult } from './utils';
14
- export { getDefaultLocale, getI18n, getI18nProps, getLocale, getLocales, useI18n, useLocaleHead, } from './utils';
13
+ export { getDefaultLocale, getI18n, getI18nProps, getLocale, getLocales, useI18n, useLocaleHead } from './utils';
package/dist/index.d.ts CHANGED
@@ -1,14 +1,13 @@
1
1
  export { defaultPlural, FormatService, interpolate } from '@i18n-micro/core';
2
- export type { CleanTranslation, Getter, Locale, LocaleCode, Params, PluralFunc, Translations, } from '@i18n-micro/types';
2
+ export type { CleanTranslation, Getter, Locale, LocaleCode, Params, PluralFunc, Translations } from '@i18n-micro/types';
3
3
  export { AstroI18n, type AstroI18nOptions } from './composer';
4
4
  export type { I18nIntegrationOptions } from './integration';
5
5
  export { createI18n, i18nIntegration } from './integration';
6
6
  export type { LoadedTranslations, LoadTranslationsOptions } from './load-translations';
7
- export { loadTranslationsFromDir, loadTranslationsIntoI18n, } from './load-translations';
7
+ export { loadTranslationsFromDir, loadTranslationsIntoI18n } from './load-translations';
8
8
  export type { I18nMiddlewareOptions } from './middleware';
9
9
  export { createI18nMiddleware, detectLocale } from './middleware';
10
10
  export { createAstroRouterAdapter } from './router/adapter';
11
11
  export type { I18nRoutingStrategy } from './router/types';
12
- export { getLocaleFromPath, getRouteName, localizePath, removeLocaleFromPath, switchLocalePath, } from './routing';
13
12
  export type { I18nClientProps, LocaleHeadOptions, LocaleHeadResult } from './utils';
14
- export { getDefaultLocale, getI18n, getI18nProps, getLocale, getLocales, useI18n, useLocaleHead, } from './utils';
13
+ export { getDefaultLocale, getI18n, getI18nProps, getLocale, getLocales, useI18n, useLocaleHead } from './utils';
package/dist/index.mjs CHANGED
@@ -1,40 +1,40 @@
1
- import { BaseI18n as O } from "@i18n-micro/core";
2
- import { FormatService as he, defaultPlural as de, interpolate as me } from "@i18n-micro/core";
3
- import { existsSync as v, 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 x } from "@i18n-micro/utils/parse-path";
6
- import { detectLocaleFromAcceptLanguage as z } from "@i18n-micro/utils/accept-language";
7
- class j 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 o = e._storage || {
9
+ const a = e._storage || {
10
10
  translations: /* @__PURE__ */ new Map()
11
11
  };
12
12
  if (super({
13
- storage: o,
13
+ storage: a,
14
14
  plural: e.plural,
15
15
  missingWarn: e.missingWarn,
16
16
  missingHandler: e.missingHandler
17
- }), this.initialMessages = {}, this.storage = o, 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
- for (const [n, r] of Object.entries(e.messages))
20
- this.helper.loadTranslations(n, r);
19
+ for (const [r, i] of Object.entries(e.messages))
20
+ this.helper.loadTranslations(r, i);
21
21
  }
22
22
  }
23
23
  cloneStorage(e) {
24
- const o = /* @__PURE__ */ new Map();
25
- for (const [n, r] of e.translations)
26
- o.set(n, { ...r });
27
- return { translations: o };
24
+ const a = /* @__PURE__ */ new Map();
25
+ for (const [r, i] of e.translations)
26
+ a.set(r, { ...i });
27
+ return { translations: a };
28
28
  }
29
29
  clone(e) {
30
- const o = this.cloneStorage(this.storage);
31
- return new j({
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: o
37
+ _storage: a
38
38
  });
39
39
  }
40
40
  get locale() {
@@ -61,43 +61,43 @@ class j extends O {
61
61
  getRoute() {
62
62
  return this._currentRoute;
63
63
  }
64
- getRouteTranslations(e, o) {
65
- const n = `${e}:${o}`;
66
- return this.storage.translations.get(n) ?? null;
64
+ getRouteTranslations(e, a) {
65
+ const r = `${e}:${a}`;
66
+ return this.storage.translations.get(r) ?? null;
67
67
  }
68
- addTranslations(e, o, n = !0) {
69
- super.loadTranslationsCore(e, o, n);
68
+ addTranslations(e, a, r = !0) {
69
+ super.loadTranslationsCore(e, a, r);
70
70
  }
71
- addRouteTranslations(e, o, n, r = !0) {
72
- super.loadRouteTranslationsCore(e, o, n, r);
71
+ addRouteTranslations(e, a, r, i = !0) {
72
+ super.loadRouteTranslationsCore(e, a, r, i);
73
73
  }
74
- mergeTranslations(e, o, n) {
75
- this.helper.mergeTranslation(e, o, n, !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 [o, n] of Object.entries(e))
81
- this.helper.loadTranslations(o, n);
80
+ for (const [a, r] of Object.entries(e))
81
+ this.helper.loadTranslations(a, r);
82
82
  }
83
83
  }
84
- let $ = null;
85
- function k() {
86
- return $;
84
+ let _ = null;
85
+ function F() {
86
+ return _;
87
87
  }
88
- function X(t) {
89
- const { locale: e, fallbackLocale: o, translationDir: n, routingStrategy: r } = t;
90
- return $ = r || 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, a = "virtual:i18n-micro/config", s = `\0${a}`, i = {
95
+ const { updateConfig: u } = c, o = "virtual:i18n-micro/config", l = `\0${o}`, s = {
96
96
  defaultLocale: e,
97
- fallbackLocale: o || e,
97
+ fallbackLocale: a || e,
98
98
  locales: t.locales || [],
99
- localeCodes: (t.locales || []).map((l) => l.code),
100
- translationDir: n || null,
99
+ localeCodes: (t.locales || []).map((n) => n.code),
100
+ translationDir: r || null,
101
101
  autoDetect: t.autoDetect ?? !0,
102
102
  redirectToDefault: t.redirectToDefault ?? !1,
103
103
  localeCookie: t.localeCookie === null ? null : t.localeCookie || "i18n-locale",
@@ -108,13 +108,13 @@ function X(t) {
108
108
  plugins: [
109
109
  {
110
110
  name: "vite-plugin-i18n-micro-config",
111
- resolveId(l) {
112
- if (l === a)
113
- return s;
111
+ resolveId(n) {
112
+ if (n === o)
113
+ return l;
114
114
  },
115
- load(l) {
116
- if (l === s)
117
- return `export const config = ${JSON.stringify(i)}`;
115
+ load(n) {
116
+ if (n === l)
117
+ return `export const config = ${JSON.stringify(s)}`;
118
118
  }
119
119
  }
120
120
  ]
@@ -148,141 +148,141 @@ function X(t) {
148
148
  }
149
149
  };
150
150
  }
151
- function Y(t) {
152
- return new j(t);
151
+ function te(t) {
152
+ return new T(t);
153
153
  }
154
- function D(t, e) {
155
- if (v(t))
156
- for (const o of _(t)) {
157
- const n = W(t, o);
158
- if (C(n).isDirectory()) {
159
- D(n, 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
- o.endsWith(".json") && e(n);
162
+ a.endsWith(".json") && e(r);
163
163
  }
164
164
  }
165
- function U(t) {
166
- const { translationDir: e, rootDir: o = process.cwd(), disablePageLocales: n = !1 } = t, r = M(o, e);
167
- if (!v(r))
168
- return console.warn(`[i18n] Translation directory not found: ${r}`), { root: {}, routes: {} };
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
+ return console.warn(`[i18n] Translation directory not found: ${i}`), { root: {}, routes: {} };
169
169
  const c = { root: {}, routes: {} };
170
- return D(r, (u) => {
171
- const a = A(r, u).split(q).join("/");
170
+ return O(i, (u) => {
171
+ const o = E(i, u).split(H).join("/");
172
172
  try {
173
- const s = N(u, "utf-8"), i = JSON.parse(s);
174
- x(c, a, i, n);
175
- } catch (s) {
176
- console.error(`[i18n] Failed to load translation file: ${u}`, s);
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(t, e) {
181
- const { root: o, routes: n } = U(e);
182
- for (const [r, c] of Object.entries(o))
183
- t.addTranslations(r, c, !1);
184
- for (const [r, c] of Object.entries(n))
185
- for (const [u, a] of Object.entries(c))
186
- t.addRouteTranslations(u, r, H(o[u], a), !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
+ for (const [i, c] of Object.entries(r))
185
+ for (const [u, o] of Object.entries(c))
186
+ t.addRouteTranslations(u, i, x(a[u], o), !1);
187
187
  }
188
- function ee(t) {
188
+ function oe(t) {
189
189
  const {
190
190
  i18n: e,
191
191
  // This is the global singleton with cache
192
- defaultLocale: o,
193
- locales: n,
194
- localeObjects: r,
192
+ defaultLocale: a,
193
+ locales: r,
194
+ localeObjects: i,
195
195
  autoDetect: c = !0,
196
196
  redirectToDefault: u = !1,
197
- routingStrategy: a
198
- } = t, s = a || k();
199
- return async (i, l) => {
200
- if (i.locals.locale && i.locals.i18n)
201
- return l();
202
- const f = i.url, d = f.pathname;
203
- if (!s) {
204
- const P = e.clone(o), y = d === "/" || d === "" ? "index" : d.split("/").filter(Boolean).join("-");
205
- return P.setRoute(y), i.locals.i18n = P, i.locals.locale = o, i.locals.defaultLocale = o, i.locals.locales = r || n.map((R) => ({ code: R })), i.locals.currentUrl = f, l();
197
+ routingStrategy: o
198
+ } = t, l = o || F();
199
+ return async (s, n) => {
200
+ if (s.locals.locale && s.locals.i18n)
201
+ return 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
- ...s,
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], L = m !== void 0 && n.includes(m);
215
- let b;
216
- L && m ? b = m : g.getLocaleFromPath ? b = g.getLocaleFromPath(d, o, n) : b = o;
217
- const h = e.clone(b), S = g.getRouteName ? g.getRouteName(d, n) : "index";
218
- return h.setRoute(S), i.locals.i18n = h, i.locals.locale = b, i.locals.defaultLocale = o, i.locals.locales = r || n.map((P) => ({ code: P })), i.locals.currentUrl = f, i.locals.routingStrategy = g, l();
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(t, e, o, n, r, c = "i18n-locale") {
222
- const u = k();
223
- let a = n;
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
- a = u.getLocaleFromPath(t, n, r);
225
+ o = u.getLocaleFromPath(t, r, i);
226
226
  else {
227
- const i = t.split("/").filter(Boolean)[0];
228
- i && r.includes(i) && (a = i);
227
+ const s = t.split("/").filter(Boolean)[0];
228
+ s && i.includes(s) && (o = s);
229
229
  }
230
- if (c !== null && a === n && e.get(c)) {
231
- const s = e.get(c)?.value;
232
- s && r.includes(s) && (a = s);
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 (a === n)
234
+ if (o === r)
235
235
  try {
236
- const s = z(o.get("accept-language") ?? void 0, r);
237
- s && (a = s);
236
+ const l = V(a.get("accept-language") ?? void 0, i);
237
+ l && (o = l);
238
238
  } catch {
239
239
  }
240
- return a;
240
+ return o;
241
241
  }
242
- function ne(t, e, o) {
243
- const n = t.map((l) => l.code), r = (l, f = []) => {
244
- const d = l.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 = (l, f = "en", d = []) => {
250
- const p = l.split("/").filter(Boolean)[0];
251
- return p && d.includes(p) ? p : f;
252
- }, u = (l, f, d = [], g) => {
253
- const p = l.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
- }, a = (l, f, d = [], g) => {
256
- const m = (l.replace(/^\//, "").replace(/\/$/, "") || "").split("/").filter(Boolean), L = m[0];
257
- return L && d.includes(L) && 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: () => o ? o().pathname : typeof window < "u" ? window.location.pathname : "/",
261
- getRouteName: r,
260
+ getCurrentPath: () => a ? a().pathname : typeof window < "u" ? window.location.pathname : "/",
261
+ getRouteName: i,
262
262
  getLocaleFromPath: c,
263
263
  switchLocalePath: u,
264
- localizePath: a,
265
- removeLocaleFromPath: (l, f = []) => {
266
- const d = l.split("/").filter(Boolean), g = d[0];
267
- return g && f.includes(g) && d.shift(), `/${d.join("/")}`;
264
+ localizePath: o,
265
+ removeLocaleFromPath: (n, f = []) => {
266
+ const h = n.split("/").filter(Boolean), m = h[0];
267
+ return m && f.includes(m) && h.shift(), `/${h.join("/")}`;
268
268
  },
269
- resolvePath: (l, f) => {
270
- const d = typeof l == "string" ? l : l.path || "/";
271
- return a(d, f, n, e);
269
+ resolvePath: (n, f) => {
270
+ const h = typeof n == "string" ? n : n.path || "/";
271
+ return o(h, f, r, e);
272
272
  },
273
273
  getRoute: () => {
274
- if (o) {
275
- const l = o();
274
+ if (a) {
275
+ const n = a();
276
276
  return {
277
- fullPath: l.pathname + l.search,
278
- query: Object.fromEntries(l.searchParams)
277
+ fullPath: n.pathname + n.search,
278
+ query: Object.fromEntries(n.searchParams)
279
279
  };
280
280
  }
281
281
  if (typeof window < "u") {
282
- const l = new URL(window.location.href);
282
+ const n = new URL(window.location.href);
283
283
  return {
284
- fullPath: l.pathname + l.search,
285
- query: Object.fromEntries(l.searchParams)
284
+ fullPath: n.pathname + n.search,
285
+ query: Object.fromEntries(n.searchParams)
286
286
  };
287
287
  }
288
288
  return {
@@ -291,242 +291,247 @@ function ne(t, e, o) {
291
291
  };
292
292
  },
293
293
  // Optional: client-side navigation for islands
294
- push: (l) => {
295
- typeof window < "u" && (window.location.href = l.path);
294
+ push: (n) => {
295
+ typeof window < "u" && (window.location.href = n.path);
296
296
  },
297
- replace: (l) => {
298
- typeof window < "u" && window.location.replace(l.path);
297
+ replace: (n) => {
298
+ typeof window < "u" && window.location.replace(n.path);
299
299
  }
300
300
  };
301
301
  }
302
- function oe(t, e = []) {
303
- const o = t.replace(/^\//, "").replace(/\/$/, "");
304
- if (!o)
305
- return "index";
306
- const n = o.split("/").filter(Boolean), r = n[0];
307
- return r && e.includes(r) && n.shift(), n.length === 0 ? "index" : n.join("-");
308
- }
309
- function ae(t, e = "en", o = []) {
310
- const r = t.split("/").filter(Boolean)[0];
311
- return r && o.includes(r) ? r : e;
312
- }
313
- function le(t, e, o = [], n) {
314
- const r = t.split("/").filter(Boolean), c = r[0];
315
- return c && o.includes(c) && r.shift(), (e !== n || n === void 0) && r.unshift(e), `/${r.join("/")}`;
316
- }
317
- function se(t, e, o = [], n) {
318
- const c = (t.replace(/^\//, "").replace(/\/$/, "") || "").split("/").filter(Boolean), u = c[0];
319
- return u && o.includes(u) && c.shift(), (e !== n || n === void 0) && c.unshift(e), `/${c.join("/")}`;
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
320
  }
321
- function re(t, e = []) {
322
- const o = t.split("/").filter(Boolean), n = o[0];
323
- return n && e.includes(n) && o.shift(), `/${o.join("/")}`;
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
+ );
324
327
  }
325
- function B(t) {
328
+ function C(t) {
326
329
  const e = t.locals.i18n;
327
330
  if (!e)
328
331
  throw new Error("i18n instance not found. Make sure i18n middleware is configured.");
329
332
  return e;
330
333
  }
331
- function w(t) {
334
+ function $(t) {
332
335
  return t.locals.locale || "en";
333
336
  }
334
- function T(t) {
337
+ function v(t) {
335
338
  return t.locals.defaultLocale || "en";
336
339
  }
337
- function F(t) {
340
+ function B(t) {
338
341
  return t.locals.locales || [];
339
342
  }
340
343
  function I(t) {
341
344
  return t.locals.routingStrategy || null;
342
345
  }
343
- function ie(t) {
344
- const e = B(t), o = w(t), n = T(t), r = F(t), c = r.map((a) => a.code), u = I(t);
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);
345
348
  return {
346
349
  // Current locale
347
- locale: o,
348
- defaultLocale: n,
349
- locales: r,
350
+ locale: a,
351
+ defaultLocale: r,
352
+ locales: i,
350
353
  // Translation methods
351
- t: (a, s, i, l) => e.t(a, s, i, l),
352
- ts: (a, s, i, l) => e.ts(a, s, i, l),
353
- tc: (a, s, i) => e.tc(a, s, i),
354
- tn: (a, s) => e.tn(a, s),
355
- td: (a, s) => e.td(a, s),
356
- tdr: (a, s) => e.tdr(a, s),
357
- has: (a, s) => e.has(a, s),
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),
358
361
  // Route management
359
362
  getRoute: () => e.getRoute(),
360
- getRouteName: (a) => {
361
- const s = a || t.url.pathname;
363
+ getRouteName: (o) => {
364
+ const l = o || t.url.pathname;
362
365
  if (u?.getRouteName)
363
- return u.getRouteName(s, c);
364
- const i = s.replace(/^\//, "").replace(/\/$/, "");
365
- if (!i) return "index";
366
- const l = i.split("/").filter(Boolean), f = l[0];
367
- return f && c.includes(f) && l.shift(), l.length === 0 ? "index" : l.join("-");
366
+ return u.getRouteName(l, c);
367
+ const s = l.replace(/^\//, "").replace(/\/$/, "");
368
+ if (!s) return "index";
369
+ const n = s.split("/").filter(Boolean), f = n[0];
370
+ return f && c.includes(f) && n.shift(), n.length === 0 ? "index" : n.join("-");
368
371
  },
369
- getLocaleFromPath: (a) => {
370
- const s = a || t.url.pathname;
372
+ getLocaleFromPath: (o) => {
373
+ const l = o || t.url.pathname;
371
374
  if (u?.getLocaleFromPath)
372
- return u.getLocaleFromPath(s, n, c);
373
- const l = s.split("/").filter(Boolean)[0];
374
- return l && c.includes(l) ? l : n;
375
+ return u.getLocaleFromPath(l, r, c);
376
+ const n = l.split("/").filter(Boolean)[0];
377
+ return n && c.includes(n) ? n : r;
375
378
  },
376
379
  // Path utilities
377
- switchLocalePath: (a) => {
380
+ switchLocalePath: (o) => {
378
381
  if (u?.switchLocalePath)
379
- return u.switchLocalePath(t.url.pathname, a, c, n);
380
- const s = t.url.pathname.split("/").filter(Boolean), i = s[0];
381
- return i && c.includes(i) && s.shift(), a !== n && s.unshift(a), `/${s.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("/")}`;
382
385
  },
383
- localizePath: (a, s) => {
386
+ localizePath: (o, l) => {
384
387
  if (u?.localizePath)
385
- return u.localizePath(a, s || o, c, n);
386
- const l = (a.replace(/^\//, "").replace(/\/$/, "") || "").split("/").filter(Boolean), f = l[0];
387
- return f && c.includes(f) && l.shift(), s && s !== n && l.unshift(s), `/${l.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("/")}`;
388
391
  },
389
392
  // Get i18n instance
390
393
  getI18n: () => e,
391
394
  // Get base path without locale (for rewrite)
392
- getBasePath: (a) => {
393
- const l = (a || t.url).pathname.split("/").filter(Boolean), f = l[0];
394
- return f && c.includes(f) && l.shift(), l.length > 0 ? `/${l.join("/")}` : "/";
395
+ getBasePath: (o) => {
396
+ const n = (o || t.url).pathname.split("/").filter(Boolean), f = n[0];
397
+ return f && c.includes(f) && n.shift(), n.length > 0 ? `/${n.join("/")}` : "/";
395
398
  },
396
399
  // Translation management
397
- addTranslations: (a, s, i = !0) => {
398
- e.addTranslations(a, s, i);
400
+ addTranslations: (o, l, s = !0) => {
401
+ e.addTranslations(o, l, s);
399
402
  },
400
- addRouteTranslations: (a, s, i, l = !0) => {
401
- e.addRouteTranslations(a, s, i, l);
403
+ addRouteTranslations: (o, l, s, n = !0) => {
404
+ e.addRouteTranslations(o, l, s, n);
402
405
  },
403
- mergeTranslations: (a, s, i) => {
404
- e.mergeTranslations(a, s, i);
406
+ mergeTranslations: (o, l, s) => {
407
+ e.mergeTranslations(o, l, s);
405
408
  },
406
409
  clearCache: () => {
407
410
  e.clearCache();
408
411
  }
409
412
  };
410
413
  }
411
- function ce(t, e = {}) {
412
- const { baseUrl: o = "/", addDirAttribute: n = !0, addSeoAttributes: r = !0 } = e, c = w(t), u = T(t), s = F(t).filter((h) => !h.disabled), i = s.filter((h) => h.seo !== !1), l = s.find((h) => h.code === c);
413
- if (!l)
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);
416
+ if (!n)
414
417
  return { htmlAttrs: {}, link: [], meta: [] };
415
- const f = l.iso || c, d = l.dir || "auto", g = {
418
+ const f = n.iso || c, h = R(n), m = n.dir || "auto", d = {
416
419
  htmlAttrs: {
417
420
  lang: f,
418
- ...n ? { dir: d } : {}
421
+ ...r ? { dir: m } : {}
419
422
  },
420
423
  link: [],
421
424
  meta: []
422
425
  };
423
- if (!r)
424
- return g;
425
- const p = `${o}${t.url.pathname}`;
426
- g.link.push({
426
+ if (!i)
427
+ return d;
428
+ const p = `${a}${t.url.pathname}`;
429
+ d.link.push({
427
430
  rel: "canonical",
428
431
  href: p
429
432
  });
430
- const m = I(t), L = s.map((h) => h.code);
431
- for (const h of i) {
432
- let S = t.url.pathname;
433
- if (m?.switchLocalePath)
434
- S = m.switchLocalePath(t.url.pathname, h.code, L, 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);
435
438
  else {
436
- const y = t.url.pathname.split("/").filter(Boolean), R = y[0];
437
- R && L.includes(R) && y.shift(), h.code !== u && y.unshift(h.code), S = `/${y.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("/")}`;
438
441
  }
439
- const P = `${o}${S}`;
440
- g.link.push({
442
+ const S = `${a}${L}`;
443
+ d.link.push({
441
444
  rel: "alternate",
442
- href: P,
443
- hreflang: h.code
444
- }), 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({
445
448
  rel: "alternate",
446
- href: P,
447
- hreflang: h.iso
449
+ href: S,
450
+ hreflang: g.iso
448
451
  });
449
452
  }
450
- if (s.find((h) => h.code === u)?.seo !== !1) {
451
- let h = t.url.pathname;
452
- if (m?.switchLocalePath)
453
- h = m.switchLocalePath(t.url.pathname, u, L, 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);
454
457
  else {
455
- const S = t.url.pathname.split("/").filter(Boolean), P = S[0];
456
- P && L.includes(P) && S.shift(), h = `/${S.join("/")}`;
458
+ const L = t.url.pathname.split("/").filter(Boolean), S = L[0];
459
+ S && P.includes(S) && L.shift(), g = `/${L.join("/")}`;
457
460
  }
458
- g.link.push({
461
+ d.link.push({
459
462
  rel: "alternate",
460
- href: `${o}${h}`,
463
+ href: `${a}${g}`,
461
464
  hreflang: "x-default"
462
465
  });
463
466
  }
464
- g.meta.push({
467
+ h ? d.meta.push({
465
468
  property: "og:locale",
466
- content: f
467
- }), g.meta.push({
469
+ content: h
470
+ }) : k(n, { tag: "og:locale" }), d.meta.push({
468
471
  property: "og:url",
469
472
  content: p
470
473
  });
471
- for (const h of i)
472
- 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({
473
482
  property: "og:locale:alternate",
474
- content: h.og || h.iso || h.code
483
+ content: L
475
484
  });
476
- return g;
485
+ }
486
+ return d;
477
487
  }
478
- function E(t, e, o) {
479
- const n = e.split(".");
480
- let r = t;
481
- for (let u = 0; u < n.length - 1; u++) {
482
- const a = n[u];
483
- r[a] || (r[a] = {}), r = r[a];
488
+ function G(t, e, a) {
489
+ const r = e.split(".");
490
+ let i = t;
491
+ for (let u = 0; u < r.length - 1; u++) {
492
+ const o = r[u];
493
+ i[o] || (i[o] = {}), i = i[o];
484
494
  }
485
- const c = n[n.length - 1];
486
- c !== void 0 && (r[c] = o);
495
+ const c = r[r.length - 1];
496
+ c !== void 0 && (i[c] = a);
487
497
  }
488
- function ue(t, e) {
489
- const o = B(t), n = w(t), r = T(t), c = o.getRoute(), u = {};
498
+ function ie(t, e) {
499
+ const a = C(t), r = $(t), i = v(t), c = a.getRoute(), u = {};
490
500
  if (e && e.length > 0) {
491
- const a = {};
492
- for (const s of e) {
493
- const i = o.t(s, void 0, void 0, c);
494
- i != null && i !== s && E(a, s, i);
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);
495
505
  }
496
- Object.keys(a).length > 0 && (u[c] = a);
506
+ Object.keys(o).length > 0 && (u[c] = o);
497
507
  } else {
498
- const a = o.getRouteTranslations(n, c);
499
- a && (u[c] = a);
508
+ const o = a.getRouteTranslations(r, c);
509
+ o && (u[c] = o);
500
510
  }
501
511
  return {
502
- locale: n,
503
- fallbackLocale: r,
512
+ locale: r,
513
+ fallbackLocale: i,
504
514
  currentRoute: c,
505
515
  translations: u
506
516
  };
507
517
  }
508
518
  export {
509
- j as AstroI18n,
510
- he as FormatService,
511
- ne as createAstroRouterAdapter,
512
- Y as createI18n,
513
- ee as createI18nMiddleware,
514
- de as defaultPlural,
515
- te as detectLocale,
516
- T as getDefaultLocale,
517
- B as getI18n,
518
- ue as getI18nProps,
519
- w as getLocale,
520
- ae as getLocaleFromPath,
521
- F as getLocales,
522
- oe as getRouteName,
523
- X as i18nIntegration,
524
- me as interpolate,
525
- U as loadTranslationsFromDir,
526
- Z as loadTranslationsIntoI18n,
527
- se as localizePath,
528
- re as removeLocaleFromPath,
529
- le as switchLocalePath,
530
- ie as useI18n,
531
- ce as useLocaleHead
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,
530
+ B as getLocales,
531
+ ee as i18nIntegration,
532
+ he as interpolate,
533
+ J as loadTranslationsFromDir,
534
+ ne as loadTranslationsIntoI18n,
535
+ re as useI18n,
536
+ se as useLocaleHead
532
537
  };
package/package.json CHANGED
@@ -1,22 +1,31 @@
1
1
  {
2
2
  "name": "@i18n-micro/astro",
3
- "version": "1.3.5",
3
+ "version": "1.3.7",
4
4
  "description": "Astro integration for i18n-micro — translations, routing, and islands.",
5
- "type": "module",
5
+ "keywords": [
6
+ "astro",
7
+ "i18n",
8
+ "internationalization",
9
+ "translations"
10
+ ],
11
+ "homepage": "https://github.com/s00d/nuxt-i18n-micro/tree/main/packages/astro#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/s00d/nuxt-i18n-micro/issues"
14
+ },
6
15
  "license": "MIT",
7
- "sideEffects": false,
8
16
  "repository": {
9
17
  "type": "git",
10
18
  "url": "git+https://github.com/s00d/nuxt-i18n-micro.git",
11
19
  "directory": "packages/astro"
12
20
  },
13
- "homepage": "https://github.com/s00d/nuxt-i18n-micro/tree/main/packages/astro#readme",
14
- "bugs": {
15
- "url": "https://github.com/s00d/nuxt-i18n-micro/issues"
16
- },
17
- "engines": {
18
- "node": ">=18"
19
- },
21
+ "files": [
22
+ "dist",
23
+ "src",
24
+ "README.md",
25
+ "LICENSE"
26
+ ],
27
+ "type": "module",
28
+ "sideEffects": false,
20
29
  "main": "./dist/index.cjs",
21
30
  "types": "./dist/index.d.ts",
22
31
  "exports": {
@@ -64,33 +73,35 @@
64
73
  },
65
74
  "./package.json": "./package.json"
66
75
  },
67
- "files": [
68
- "dist",
69
- "src",
70
- "README.md",
71
- "LICENSE"
72
- ],
73
76
  "publishConfig": {
74
77
  "access": "public"
75
78
  },
76
- "keywords": [
77
- "astro",
78
- "i18n",
79
- "internationalization",
80
- "translations"
81
- ],
82
79
  "dependencies": {
83
- "@i18n-micro/types": "1.2.3",
84
- "@i18n-micro/core": "1.3.1",
85
- "@i18n-micro/utils": "1.0.0",
86
- "@i18n-micro/node": "1.2.2"
80
+ "@i18n-micro/core": "1.3.2",
81
+ "@i18n-micro/types": "1.2.5",
82
+ "@i18n-micro/utils": "1.0.2",
83
+ "@i18n-micro/node": "1.2.3"
87
84
  },
88
- "peerDependencies": {
85
+ "devDependencies": {
86
+ "@types/jest": "^29.5.14",
89
87
  "astro": "^5.16.5",
88
+ "jest": "^29.7.0",
89
+ "preact": "^10.0.0",
90
+ "publint": "^0.3.17",
91
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
90
92
  "svelte": "^4.0.0 || ^5.0.0",
91
- "vue": "^3.5.25",
93
+ "ts-jest": "^29.4.6",
94
+ "vite": "^7.3.1",
95
+ "vite-plugin-dts": "^4.5.4",
96
+ "vitest": "^3.2.4",
97
+ "vue": "^3.5.25"
98
+ },
99
+ "peerDependencies": {
100
+ "astro": "^5.16.5",
101
+ "preact": "^10.0.0",
92
102
  "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
93
- "preact": "^10.0.0"
103
+ "svelte": "^4.0.0 || ^5.0.0",
104
+ "vue": "^3.5.25"
94
105
  },
95
106
  "peerDependenciesMeta": {
96
107
  "svelte": {
@@ -106,19 +117,8 @@
106
117
  "optional": true
107
118
  }
108
119
  },
109
- "devDependencies": {
110
- "astro": "^5.16.5",
111
- "vite": "^7.3.1",
112
- "vite-plugin-dts": "^4.5.4",
113
- "jest": "^29.7.0",
114
- "ts-jest": "^29.4.6",
115
- "@types/jest": "^29.5.14",
116
- "svelte": "^4.0.0 || ^5.0.0",
117
- "vue": "^3.5.25",
118
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
119
- "preact": "^10.0.0",
120
- "publint": "^0.3.17",
121
- "vitest": "^3.2.4"
120
+ "engines": {
121
+ "node": ">=18"
122
122
  },
123
123
  "scripts": {
124
124
  "build": "vite build",
package/src/index.ts CHANGED
@@ -4,15 +4,7 @@ import './env.d'
4
4
  // Re-export utilities from core
5
5
  export { defaultPlural, FormatService, interpolate } from '@i18n-micro/core'
6
6
  // Re-export types from @i18n-micro/types
7
- export type {
8
- CleanTranslation,
9
- Getter,
10
- Locale,
11
- LocaleCode,
12
- Params,
13
- PluralFunc,
14
- Translations,
15
- } from '@i18n-micro/types'
7
+ export type { CleanTranslation, Getter, Locale, LocaleCode, Params, PluralFunc, Translations } from '@i18n-micro/types'
16
8
  export { AstroI18n, type AstroI18nOptions } from './composer'
17
9
  // Export integration options type
18
10
  export type { I18nIntegrationOptions } from './integration'
@@ -20,33 +12,13 @@ export type { I18nIntegrationOptions } from './integration'
20
12
  export { createI18n, i18nIntegration } from './integration'
21
13
  export type { LoadedTranslations, LoadTranslationsOptions } from './load-translations'
22
14
  // Export translation loading utilities
23
- export {
24
- loadTranslationsFromDir,
25
- loadTranslationsIntoI18n,
26
- } from './load-translations'
15
+ export { loadTranslationsFromDir, loadTranslationsIntoI18n } from './load-translations'
27
16
  export type { I18nMiddlewareOptions } from './middleware'
28
17
  export { createI18nMiddleware, detectLocale } from './middleware'
29
18
  export { createAstroRouterAdapter } from './router/adapter'
30
19
  // Router abstraction
31
20
  export type { I18nRoutingStrategy } from './router/types'
32
- // Legacy routing utilities (deprecated, use routingStrategy instead)
33
- // Kept for backward compatibility
34
- export {
35
- getLocaleFromPath,
36
- getRouteName,
37
- localizePath,
38
- removeLocaleFromPath,
39
- switchLocalePath,
40
- } from './routing'
41
21
  export type { I18nClientProps, LocaleHeadOptions, LocaleHeadResult } from './utils'
42
22
  // Utilities
43
- export {
44
- getDefaultLocale,
45
- getI18n,
46
- getI18nProps,
47
- getLocale,
48
- getLocales,
49
- useI18n,
50
- useLocaleHead,
51
- } from './utils'
23
+ export { getDefaultLocale, getI18n, getI18nProps, getLocale, getLocales, useI18n, useLocaleHead } from './utils'
52
24
  // It's loaded directly by Astro via entrypoint in integration config
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
 
package/dist/routing.d.ts DELETED
@@ -1,23 +0,0 @@
1
- /**
2
- * Get route name from Astro path
3
- * Extracts route name from path (e.g., /en/about -> about)
4
- */
5
- export declare function getRouteName(path: string, locales?: string[]): string;
6
- /**
7
- * Get locale from path
8
- * Checks if first segment is a locale code
9
- */
10
- export declare function getLocaleFromPath(path: string, defaultLocale?: string, locales?: string[]): string;
11
- /**
12
- * Switch locale in path
13
- * Replaces or adds locale prefix to path
14
- */
15
- export declare function switchLocalePath(path: string, newLocale: string, locales?: string[], defaultLocale?: string): string;
16
- /**
17
- * Localize path with locale prefix
18
- */
19
- export declare function localizePath(path: string, locale: string, locales?: string[], defaultLocale?: string): string;
20
- /**
21
- * Remove locale from path
22
- */
23
- export declare function removeLocaleFromPath(path: string, locales?: string[]): string;
package/src/routing.ts DELETED
@@ -1,94 +0,0 @@
1
- /**
2
- * Get route name from Astro path
3
- * Extracts route name from path (e.g., /en/about -> about)
4
- */
5
- export function getRouteName(path: string, locales: string[] = []): string {
6
- // Normalize the path
7
- const cleanPath = path.replace(/^\//, '').replace(/\/$/, '')
8
-
9
- if (!cleanPath) {
10
- return 'index'
11
- }
12
-
13
- const segments = cleanPath.split('/').filter(Boolean)
14
-
15
- // Remove locale from path if present
16
- const firstSegment = segments[0]
17
- if (firstSegment && locales.includes(firstSegment)) {
18
- segments.shift()
19
- }
20
-
21
- if (segments.length === 0) {
22
- return 'index'
23
- }
24
-
25
- return segments.join('-')
26
- }
27
-
28
- /**
29
- * Get locale from path
30
- * Checks if first segment is a locale code
31
- */
32
- export function getLocaleFromPath(path: string, defaultLocale: string = 'en', locales: string[] = []): string {
33
- const segments = path.split('/').filter(Boolean)
34
- const firstSegment = segments[0]
35
- if (firstSegment && locales.includes(firstSegment)) {
36
- return firstSegment
37
- }
38
-
39
- return defaultLocale
40
- }
41
-
42
- /**
43
- * Switch locale in path
44
- * Replaces or adds locale prefix to path
45
- */
46
- export function switchLocalePath(path: string, newLocale: string, locales: string[] = [], defaultLocale?: string): string {
47
- const segments = path.split('/').filter(Boolean)
48
-
49
- // Remove existing locale if present
50
- const firstSegment = segments[0]
51
- if (firstSegment && locales.includes(firstSegment)) {
52
- segments.shift()
53
- }
54
-
55
- // Add new locale if not default or if default should be included
56
- if (newLocale !== defaultLocale || defaultLocale === undefined) {
57
- segments.unshift(newLocale)
58
- }
59
-
60
- return `/${segments.join('/')}`
61
- }
62
-
63
- /**
64
- * Localize path with locale prefix
65
- */
66
- export function localizePath(path: string, locale: string, locales: string[] = [], defaultLocale?: string): string {
67
- const cleanPath = path.replace(/^\//, '').replace(/\/$/, '') || ''
68
- const segments = cleanPath.split('/').filter(Boolean)
69
-
70
- // Remove existing locale if present
71
- const firstSegment = segments[0]
72
- if (firstSegment && locales.includes(firstSegment)) {
73
- segments.shift()
74
- }
75
-
76
- // Add locale if not default or if default should be included
77
- if (locale !== defaultLocale || defaultLocale === undefined) {
78
- segments.unshift(locale)
79
- }
80
-
81
- return `/${segments.join('/')}`
82
- }
83
-
84
- /**
85
- * Remove locale from path
86
- */
87
- export function removeLocaleFromPath(path: string, locales: string[] = []): string {
88
- const segments = path.split('/').filter(Boolean)
89
- const firstSegment = segments[0]
90
- if (firstSegment && locales.includes(firstSegment)) {
91
- segments.shift()
92
- }
93
- return `/${segments.join('/')}`
94
- }