@i18n-micro/astro 1.3.1 → 1.3.3

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.
@@ -12,7 +12,7 @@ export interface I18nState {
12
12
  * Pure function to get a translation from state
13
13
  *
14
14
  * Note: This is a simplified version optimized for client-side islands.
15
- * It supports basic translation lookup, interpolation, and fallback to general translations.
15
+ * It supports basic translation lookup and interpolation.
16
16
  * Returns CleanTranslation which can be string, number, boolean, object, or null.
17
17
  * For advanced features like Linked Messages (@:path.to.key), use the server-side i18n instance.
18
18
  */
@@ -1,4 +1,4 @@
1
- import { h as s, t as o } from "../core-D32Y48CN.js";
1
+ import { h as s, t as o } from "../core-Bk6qZuDf.js";
2
2
  import { I18nProvider as a, useAstroI18n as n } from "./preact.js";
3
3
  import { I18nProvider as u, useAstroI18n as A } from "./react.js";
4
4
  import { createI18nStore as f, useAstroI18n as i } from "./svelte.js";
@@ -1,7 +1,7 @@
1
1
  import { FormatService as g, defaultPlural as w } from "@i18n-micro/core";
2
2
  import { createContext as x, createElement as L } from "preact";
3
3
  import { useState as P, useContext as S, useMemo as a } from "preact/hooks";
4
- import { t as C, h as A } from "../core-D32Y48CN.js";
4
+ import { t as C, h as A } from "../core-Bk6qZuDf.js";
5
5
  const s = new g(), i = x(null), F = ({ children: t, value: o }) => {
6
6
  const [l] = P(() => ({
7
7
  locale: o.locale,
@@ -1,6 +1,6 @@
1
1
  import { FormatService as g, defaultPlural as w } from "@i18n-micro/core";
2
2
  import x, { createContext as L, useState as P, useContext as S, useMemo as a } from "react";
3
- import { t as C, h as A } from "../core-D32Y48CN.js";
3
+ import { t as C, h as A } from "../core-Bk6qZuDf.js";
4
4
  const s = new g(), i = L(null);
5
5
  function D({ children: t, value: o }) {
6
6
  const [l] = P(() => ({
@@ -1,6 +1,6 @@
1
1
  import { FormatService as R, defaultPlural as b } from "@i18n-micro/core";
2
2
  import { writable as d, get as v } from "svelte/store";
3
- import { h as L, t as S } from "../core-D32Y48CN.js";
3
+ import { h as L, t as S } from "../core-Bk6qZuDf.js";
4
4
  const l = new R();
5
5
  function F(o) {
6
6
  return d({
@@ -1,5 +1,5 @@
1
1
  import { FormatService as wt, defaultPlural as yt } from "@i18n-micro/core";
2
- import { h as St, t as Ot } from "../core-D32Y48CN.js";
2
+ import { h as St, t as Ot } from "../core-Bk6qZuDf.js";
3
3
  // @__NO_SIDE_EFFECTS__
4
4
  function Rt(e) {
5
5
  const t = /* @__PURE__ */ Object.create(null);
@@ -0,0 +1 @@
1
+ "use strict";const s=require("@i18n-micro/core");function l(r,t){if(r===null||typeof t!="string")return null;let n=r;if(r[t])n=r[t];else{const o=t.toString().split(".");for(const u of o)if(n&&typeof n=="object"&&n!==null&&u in n)n=n[u];else return null}return n??null}function f(r,t,n,o,u){if(!t)return o||t||"";const i=u||r.currentRoute;let e=null;return r.translations[i]&&(e=l(r.translations[i],t)),e||(e=o===void 0?t:o||t),typeof e=="string"&&n?s.interpolate(e,n):e}function c(r,t,n){const o=n||r.currentRoute,u=r.translations[o];if(u){const i=l(u,t);if(i!==null&&typeof i!="object")return!0}return!1}exports.hasTranslation=c;exports.translate=f;
@@ -0,0 +1,37 @@
1
+ import { interpolate as f } from "@i18n-micro/core";
2
+ function e(r, t) {
3
+ if (r === null || typeof t != "string")
4
+ return null;
5
+ let n = r;
6
+ if (r[t])
7
+ n = r[t];
8
+ else {
9
+ const o = t.toString().split(".");
10
+ for (const u of o)
11
+ if (n && typeof n == "object" && n !== null && u in n)
12
+ n = n[u];
13
+ else
14
+ return null;
15
+ }
16
+ return n ?? null;
17
+ }
18
+ function c(r, t, n, o, u) {
19
+ if (!t)
20
+ return o || t || "";
21
+ const l = u || r.currentRoute;
22
+ let i = null;
23
+ return r.translations[l] && (i = e(r.translations[l], t)), i || (i = o === void 0 ? t : o || t), typeof i == "string" && n ? f(i, n) : i;
24
+ }
25
+ function a(r, t, n) {
26
+ const o = n || r.currentRoute, u = r.translations[o];
27
+ if (u) {
28
+ const l = e(u, t);
29
+ if (l !== null && typeof l != "object")
30
+ return !0;
31
+ }
32
+ return !1;
33
+ }
34
+ export {
35
+ a as h,
36
+ c as t
37
+ };
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"),S=require("node:fs"),k=require("node:path");class j extends w.BaseI18n{constructor(e){const s=e._storage||{translations:new Map};if(super({storage:s,plural:e.plural,missingWarn:e.missingWarn,missingHandler:e.missingHandler}),this.initialMessages={},this.storage=s,this._locale=e.locale,this._fallbackLocale=e.fallbackLocale||e.locale,this._currentRoute="index",e.messages){this.initialMessages={...e.messages};for(const[a,i]of Object.entries(e.messages))this.helper.loadTranslations(a,i)}}cloneStorage(e){const s=new Map;for(const[a,i]of e.translations)s.set(a,{...i});return{translations:s}}clone(e){const s=this.cloneStorage(this.storage);return new j({locale:e||this._locale,fallbackLocale:this._fallbackLocale,plural:this.pluralFunc,missingWarn:this.missingWarn,missingHandler:this.missingHandler,_storage:s})}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,s){const a=`${e}:${s}`;return this.storage.translations.get(a)??null}addTranslations(e,s,a=!0){super.loadTranslationsCore(e,s,a)}addRouteTranslations(e,s,a,i=!0){super.loadRouteTranslationsCore(e,s,a,i)}mergeTranslations(e,s,a){this.helper.mergeTranslation(e,s,a,!0)}clearCache(){const e={...this.initialMessages};if(super.clearCache(),Object.keys(e).length>0)for(const[s,a]of Object.entries(e))this.helper.loadTranslations(s,a)}}let I=null;function D(){return I}function C(t){const{locale:e,fallbackLocale:s,translationDir:a,routingStrategy:i}=t;return I=i||null,{name:"@i18n-micro/astro",hooks:{"astro:config:setup":c=>{const{updateConfig:u}=c,n="virtual:i18n-micro/config",l=`\0${n}`,r={defaultLocale:e,fallbackLocale:s||e,locales:t.locales||[],localeCodes:(t.locales||[]).map(o=>o.code),translationDir:a||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(o){if(o===n)return l},load(o){if(o===l)return`export const config = ${JSON.stringify(r)}`}}]}})},"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"),j=require("node:fs"),D=require("node:path");class T extends R.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[a,i]of Object.entries(e.messages))this.helper.loadTranslations(a,i)}}cloneStorage(e){const l=new Map;for(const[a,i]of e.translations)l.set(a,{...i});return{translations:l}}clone(e){const l=this.cloneStorage(this.storage);return new T({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 a=`${e}:${l}`;return this.storage.translations.get(a)??null}addTranslations(e,l,a=!0){super.loadTranslationsCore(e,l,a)}addRouteTranslations(e,l,a,i=!0){super.loadRouteTranslationsCore(e,l,a,i)}mergeTranslations(e,l,a){this.helper.mergeTranslation(e,l,a,!0)}clearCache(){const e={...this.initialMessages};if(super.clearCache(),Object.keys(e).length>0)for(const[l,a]of Object.entries(e))this.helper.loadTranslations(l,a)}}let F=null;function B(){return F}function C(t){const{locale:e,fallbackLocale:l,translationDir:a,routingStrategy:i}=t;return F=i||null,{name:"@i18n-micro/astro",hooks:{"astro:config:setup":c=>{const{updateConfig:u}=c,n="virtual:i18n-micro/config",s=`\0${n}`,r={defaultLocale:e,fallbackLocale:l||e,locales:t.locales||[],localeCodes:(t.locales||[]).map(o=>o.code),translationDir:a||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(o){if(o===n)return s},load(o){if(o===s)return`export const config = ${JSON.stringify(r)}`}}]}})},"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 N(t){return new j(t)}function F(t){const{translationDir:e,rootDir:s=process.cwd(),disablePageLocales:a=!1}=t,i=k.resolve(s,e);if(!S.existsSync(i))return console.warn(`[i18n] Translation directory not found: ${i}`),{root:{},routes:{}};const c={},u={},n=(l,r="")=>{if(!S.existsSync(l))return;const o=S.readdirSync(l);for(const g of o){const f=k.join(l,g);if(S.statSync(f).isDirectory())g==="pages"&&!a?n(f,""):r||a?n(f,r):n(f,g);else if(g.endsWith(".json")){const m=g.replace(".json","");try{const p=S.readFileSync(f,"utf-8"),h=JSON.parse(p);r&&!a?(u[r]||(u[r]={}),u[r][m]=h):c[m]=h}catch(p){console.error(`[i18n] Failed to load translation file: ${f}`,p)}}}};return n(i),{root:c,routes:u}}function q(t,e){const{root:s,routes:a}=F(e);for(const[i,c]of Object.entries(s))t.addTranslations(i,c,!1);for(const[i,c]of Object.entries(a))for(const[u,n]of Object.entries(c)){const l=s[u]||{};t.addRouteTranslations(u,i,{...l,...n},!1)}}function M(t){const{i18n:e,defaultLocale:s,locales:a,localeObjects:i,autoDetect:c=!0,redirectToDefault:u=!1,routingStrategy:n}=t,l=n||D();return async(r,o)=>{if(r.locals.locale&&r.locals.i18n)return o();const g=r.url,f=g.pathname;if(!l){const b=e.clone(s),O=f==="/"||f===""?"index":f.split("/").filter(Boolean).join("-");return b.setRoute(O),r.locals.i18n=b,r.locals.locale=s,r.locals.defaultLocale=s,r.locals.locales=i||a.map(_=>({code:_})),r.locals.currentUrl=g,o()}const d={...l,getCurrentPath:()=>f,getRoute:()=>({fullPath:g.pathname+g.search,query:Object.fromEntries(g.searchParams)})},p=f.split("/").filter(Boolean)[0],h=p!==void 0&&a.includes(p);let P;h&&p?P=p:d.getLocaleFromPath?P=d.getLocaleFromPath(f,s,a):P=s;const L=e.clone(P),y=d.getRouteName?d.getRouteName(f,a):"index";return L.setRoute(y),r.locals.i18n=L,r.locals.locale=P,r.locals.defaultLocale=s,r.locals.locales=i||a.map(b=>({code:b})),r.locals.currentUrl=g,r.locals.routingStrategy=d,o()}}function A(t){const e=[],s=t.split(",");for(const a of s){const[i,c="1.0"]=a.trim().split(";q=");if(Number.parseFloat(c)>0&&i){const n=i.split("-")[0]?.toLowerCase();n&&(e.push(n),i!==n&&e.push(i.toLowerCase()))}}return e}function W(t,e,s,a,i,c="i18n-locale"){const u=D();let n=a;if(u?.getLocaleFromPath)n=u.getLocaleFromPath(t,a,i);else{const r=t.split("/").filter(Boolean)[0];r&&i.includes(r)&&(n=r)}if(c!==null&&n===a&&e.get(c)){const l=e.get(c)?.value;l&&i.includes(l)&&(n=l)}if(n===a)try{const l=s.get("accept-language");if(l){const r=A(l);for(const o of r)if(i.includes(o)){n=o;break}}}catch{}return n}function z(t,e,s){const a=t.map(o=>o.code),i=(o,g=[])=>{const f=o.replace(/^\//,"").replace(/\/$/,"");if(!f)return"index";const d=f.split("/").filter(Boolean),m=d[0];return m&&g.includes(m)&&d.shift(),d.length===0?"index":d.join("-")},c=(o,g="en",f=[])=>{const m=o.split("/").filter(Boolean)[0];return m&&f.includes(m)?m:g},u=(o,g,f=[],d)=>{const m=o.split("/").filter(Boolean),p=m[0];return p&&f.includes(p)&&m.shift(),(g!==d||d===void 0)&&m.unshift(g),`/${m.join("/")}`},n=(o,g,f=[],d)=>{const p=(o.replace(/^\//,"").replace(/\/$/,"")||"").split("/").filter(Boolean),h=p[0];return h&&f.includes(h)&&p.shift(),(g!==d||d===void 0)&&p.unshift(g),`/${p.join("/")}`};return{getCurrentPath:()=>s?s().pathname:typeof window<"u"?window.location.pathname:"/",getRouteName:i,getLocaleFromPath:c,switchLocalePath:u,localizePath:n,removeLocaleFromPath:(o,g=[])=>{const f=o.split("/").filter(Boolean),d=f[0];return d&&g.includes(d)&&f.shift(),`/${f.join("/")}`},resolvePath:(o,g)=>{const f=typeof o=="string"?o:o.path||"/";return n(f,g,a,e)},getRoute:()=>{if(s){const o=s();return{fullPath:o.pathname+o.search,query:Object.fromEntries(o.searchParams)}}if(typeof window<"u"){const o=new URL(window.location.href);return{fullPath:o.pathname+o.search,query:Object.fromEntries(o.searchParams)}}return{fullPath:"/",query:{}}},push:o=>{typeof window<"u"&&(window.location.href=o.path)},replace:o=>{typeof window<"u"&&window.location.replace(o.path)}}}function H(t,e=[]){const s=t.replace(/^\//,"").replace(/\/$/,"");if(!s)return"index";const a=s.split("/").filter(Boolean),i=a[0];return i&&e.includes(i)&&a.shift(),a.length===0?"index":a.join("-")}function U(t,e="en",s=[]){const i=t.split("/").filter(Boolean)[0];return i&&s.includes(i)?i:e}function E(t,e,s=[],a){const i=t.split("/").filter(Boolean),c=i[0];return c&&s.includes(c)&&i.shift(),(e!==a||a===void 0)&&i.unshift(e),`/${i.join("/")}`}function J(t,e,s=[],a){const c=(t.replace(/^\//,"").replace(/\/$/,"")||"").split("/").filter(Boolean),u=c[0];return u&&s.includes(u)&&c.shift(),(e!==a||a===void 0)&&c.unshift(e),`/${c.join("/")}`}function V(t,e=[]){const s=t.split("/").filter(Boolean),a=s[0];return a&&e.includes(a)&&s.shift(),`/${s.join("/")}`}function v(t){const e=t.locals.i18n;if(!e)throw new Error("i18n instance not found. Make sure i18n middleware is configured.");return e}function R(t){return t.locals.locale||"en"}function T(t){return t.locals.defaultLocale||"en"}function $(t){return t.locals.locales||[]}function B(t){return t.locals.routingStrategy||null}function G(t){const e=v(t),s=R(t),a=T(t),i=$(t),c=i.map(n=>n.code),u=B(t);return{locale:s,defaultLocale:a,locales:i,t:(n,l,r,o)=>e.t(n,l,r,o),ts:(n,l,r,o)=>e.ts(n,l,r,o),tc:(n,l,r)=>e.tc(n,l,r),tn:(n,l)=>e.tn(n,l),td:(n,l)=>e.td(n,l),tdr:(n,l)=>e.tdr(n,l),has:(n,l)=>e.has(n,l),getRoute:()=>e.getRoute(),getRouteName:n=>{const l=n||t.url.pathname;if(u?.getRouteName)return u.getRouteName(l,c);const r=l.replace(/^\//,"").replace(/\/$/,"");if(!r)return"index";const o=r.split("/").filter(Boolean),g=o[0];return g&&c.includes(g)&&o.shift(),o.length===0?"index":o.join("-")},getLocaleFromPath:n=>{const l=n||t.url.pathname;if(u?.getLocaleFromPath)return u.getLocaleFromPath(l,a,c);const o=l.split("/").filter(Boolean)[0];return o&&c.includes(o)?o:a},switchLocalePath:n=>{if(u?.switchLocalePath)return u.switchLocalePath(t.url.pathname,n,c,a);const l=t.url.pathname.split("/").filter(Boolean),r=l[0];return r&&c.includes(r)&&l.shift(),n!==a&&l.unshift(n),`/${l.join("/")}`},localizePath:(n,l)=>{if(u?.localizePath)return u.localizePath(n,l||s,c,a);const o=(n.replace(/^\//,"").replace(/\/$/,"")||"").split("/").filter(Boolean),g=o[0];return g&&c.includes(g)&&o.shift(),l&&l!==a&&o.unshift(l),`/${o.join("/")}`},getI18n:()=>e,getBasePath:n=>{const o=(n||t.url).pathname.split("/").filter(Boolean),g=o[0];return g&&c.includes(g)&&o.shift(),o.length>0?`/${o.join("/")}`:"/"},addTranslations:(n,l,r=!0)=>{e.addTranslations(n,l,r)},addRouteTranslations:(n,l,r,o=!0)=>{e.addRouteTranslations(n,l,r,o)},mergeTranslations:(n,l,r)=>{e.mergeTranslations(n,l,r)},clearCache:()=>{e.clearCache()}}}function K(t,e={}){const{baseUrl:s="/",addDirAttribute:a=!0,addSeoAttributes:i=!0}=e,c=R(t),u=T(t),l=$(t).filter(h=>!h.disabled),r=l.find(h=>h.code===c);if(!r)return{htmlAttrs:{},link:[],meta:[]};const o=r.iso||c,g=r.dir||"auto",f={htmlAttrs:{lang:o,...a?{dir:g}:{}},link:[],meta:[]};if(!i)return f;const d=`${s}${t.url.pathname}`;f.link.push({rel:"canonical",href:d});const m=B(t),p=l.map(h=>h.code);for(const h of l){let P=t.url.pathname;if(m?.switchLocalePath)P=m.switchLocalePath(t.url.pathname,h.code,p,u);else{const y=t.url.pathname.split("/").filter(Boolean),b=y[0];b&&p.includes(b)&&y.shift(),h.code!==u&&y.unshift(h.code),P=`/${y.join("/")}`}const L=`${s}${P}`;f.link.push({rel:"alternate",href:L,hreflang:h.code}),h.iso&&h.iso!==h.code&&f.link.push({rel:"alternate",href:L,hreflang:h.iso})}{let h=t.url.pathname;if(m?.switchLocalePath)h=m.switchLocalePath(t.url.pathname,u,p,u);else{const P=t.url.pathname.split("/").filter(Boolean),L=P[0];L&&p.includes(L)&&P.shift(),h=`/${P.join("/")}`}f.link.push({rel:"alternate",href:`${s}${h}`,hreflang:"x-default"})}f.meta.push({property:"og:locale",content:o}),f.meta.push({property:"og:url",content:d});for(const h of l)h.code!==c&&f.meta.push({property:"og:locale:alternate",content:h.iso||h.code});return f}function Q(t,e,s){const a=e.split(".");let i=t;for(let u=0;u<a.length-1;u++){const n=a[u];i[n]||(i[n]={}),i=i[n]}const c=a[a.length-1];c!==void 0&&(i[c]=s)}function X(t,e){const s=v(t),a=R(t),i=T(t),c=s.getRoute(),u={};if(e&&e.length>0){const n={};for(const l of e){const r=s.t(l,void 0,void 0,c);r!=null&&r!==l&&Q(n,l,r)}Object.keys(n).length>0&&(u[c]=n)}else{const n=s.getRouteTranslations(a,c);n&&(u[c]=n)}return{locale:a,fallbackLocale:i,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=j;exports.createAstroRouterAdapter=z;exports.createI18n=N;exports.createI18nMiddleware=M;exports.detectLocale=W;exports.getDefaultLocale=T;exports.getI18n=v;exports.getI18nProps=X;exports.getLocale=R;exports.getLocaleFromPath=U;exports.getLocales=$;exports.getRouteName=H;exports.i18nIntegration=C;exports.loadTranslationsFromDir=F;exports.loadTranslationsIntoI18n=q;exports.localizePath=J;exports.removeLocaleFromPath=V;exports.switchLocalePath=E;exports.useI18n=G;exports.useLocaleHead=K;
17
+ `})}}}}function N(t){return new T(t)}function O(t){const{translationDir:e,rootDir:l=process.cwd(),disablePageLocales:a=!1}=t,i=D.resolve(l,e);if(!j.existsSync(i))return console.warn(`[i18n] Translation directory not found: ${i}`),{root:{},routes:{}};const c={},u={},n=(s,r="")=>{if(!j.existsSync(s))return;const o=j.readdirSync(s);for(const f of o){const g=D.join(s,f);if(j.statSync(g).isDirectory())f==="pages"&&!a?n(g,""):r||a?n(g,r):n(g,f);else if(f.endsWith(".json")){const p=f.replace(".json","");try{const m=j.readFileSync(g,"utf-8"),P=JSON.parse(m);r&&!a?(u[r]||(u[r]={}),u[r][p]=P):c[p]=P}catch(m){console.error(`[i18n] Failed to load translation file: ${g}`,m)}}}};return n(i),{root:c,routes:u}}function q(t,e){const{root:l,routes:a}=O(e);for(const[i,c]of Object.entries(l))t.addTranslations(i,c,!1);for(const[i,c]of Object.entries(a))for(const[u,n]of Object.entries(c)){const s=l[u]||{};t.addRouteTranslations(u,i,{...s,...n},!1)}}function M(t){const{i18n:e,defaultLocale:l,locales:a,localeObjects:i,autoDetect:c=!0,redirectToDefault:u=!1,routingStrategy:n}=t,s=n||B();return async(r,o)=>{if(r.locals.locale&&r.locals.i18n)return o();const f=r.url,g=f.pathname;if(!s){const L=e.clone(l),S=g==="/"||g===""?"index":g.split("/").filter(Boolean).join("-");return L.setRoute(S),r.locals.i18n=L,r.locals.locale=l,r.locals.defaultLocale=l,r.locals.locales=i||a.map(w=>({code:w})),r.locals.currentUrl=f,o()}const h={...s,getCurrentPath:()=>g,getRoute:()=>({fullPath:f.pathname+f.search,query:Object.fromEntries(f.searchParams)})},m=g.split("/").filter(Boolean)[0],P=m!==void 0&&a.includes(m);let y;P&&m?y=m:h.getLocaleFromPath?y=h.getLocaleFromPath(g,l,a):y=l;const d=e.clone(y),b=h.getRouteName?h.getRouteName(g,a):"index";return d.setRoute(b),r.locals.i18n=d,r.locals.locale=y,r.locals.defaultLocale=l,r.locals.locales=i||a.map(L=>({code:L})),r.locals.currentUrl=f,r.locals.routingStrategy=h,o()}}function A(t){const e=[],l=t.split(",");for(const a of l){const[i,c="1.0"]=a.trim().split(";q=");if(Number.parseFloat(c)>0&&i){const n=i.split("-")[0]?.toLowerCase();n&&(e.push(n),i!==n&&e.push(i.toLowerCase()))}}return e}function W(t,e,l,a,i,c="i18n-locale"){const u=B();let n=a;if(u?.getLocaleFromPath)n=u.getLocaleFromPath(t,a,i);else{const r=t.split("/").filter(Boolean)[0];r&&i.includes(r)&&(n=r)}if(c!==null&&n===a&&e.get(c)){const s=e.get(c)?.value;s&&i.includes(s)&&(n=s)}if(n===a)try{const s=l.get("accept-language");if(s){const r=A(s);for(const o of r)if(i.includes(o)){n=o;break}}}catch{}return n}function z(t,e,l){const a=t.map(o=>o.code),i=(o,f=[])=>{const g=o.replace(/^\//,"").replace(/\/$/,"");if(!g)return"index";const h=g.split("/").filter(Boolean),p=h[0];return p&&f.includes(p)&&h.shift(),h.length===0?"index":h.join("-")},c=(o,f="en",g=[])=>{const p=o.split("/").filter(Boolean)[0];return p&&g.includes(p)?p:f},u=(o,f,g=[],h)=>{const p=o.split("/").filter(Boolean),m=p[0];return m&&g.includes(m)&&p.shift(),(f!==h||h===void 0)&&p.unshift(f),`/${p.join("/")}`},n=(o,f,g=[],h)=>{const m=(o.replace(/^\//,"").replace(/\/$/,"")||"").split("/").filter(Boolean),P=m[0];return P&&g.includes(P)&&m.shift(),(f!==h||h===void 0)&&m.unshift(f),`/${m.join("/")}`};return{getCurrentPath:()=>l?l().pathname:typeof window<"u"?window.location.pathname:"/",getRouteName:i,getLocaleFromPath:c,switchLocalePath:u,localizePath:n,removeLocaleFromPath:(o,f=[])=>{const g=o.split("/").filter(Boolean),h=g[0];return h&&f.includes(h)&&g.shift(),`/${g.join("/")}`},resolvePath:(o,f)=>{const g=typeof o=="string"?o:o.path||"/";return n(g,f,a,e)},getRoute:()=>{if(l){const o=l();return{fullPath:o.pathname+o.search,query:Object.fromEntries(o.searchParams)}}if(typeof window<"u"){const o=new URL(window.location.href);return{fullPath:o.pathname+o.search,query:Object.fromEntries(o.searchParams)}}return{fullPath:"/",query:{}}},push:o=>{typeof window<"u"&&(window.location.href=o.path)},replace:o=>{typeof window<"u"&&window.location.replace(o.path)}}}function H(t,e=[]){const l=t.replace(/^\//,"").replace(/\/$/,"");if(!l)return"index";const a=l.split("/").filter(Boolean),i=a[0];return i&&e.includes(i)&&a.shift(),a.length===0?"index":a.join("-")}function U(t,e="en",l=[]){const i=t.split("/").filter(Boolean)[0];return i&&l.includes(i)?i:e}function E(t,e,l=[],a){const i=t.split("/").filter(Boolean),c=i[0];return c&&l.includes(c)&&i.shift(),(e!==a||a===void 0)&&i.unshift(e),`/${i.join("/")}`}function J(t,e,l=[],a){const c=(t.replace(/^\//,"").replace(/\/$/,"")||"").split("/").filter(Boolean),u=c[0];return u&&l.includes(u)&&c.shift(),(e!==a||a===void 0)&&c.unshift(e),`/${c.join("/")}`}function V(t,e=[]){const l=t.split("/").filter(Boolean),a=l[0];return a&&e.includes(a)&&l.shift(),`/${l.join("/")}`}function k(t){const e=t.locals.i18n;if(!e)throw new Error("i18n instance not found. Make sure i18n middleware is configured.");return e}function v(t){return t.locals.locale||"en"}function $(t){return t.locals.defaultLocale||"en"}function I(t){return t.locals.locales||[]}function _(t){return t.locals.routingStrategy||null}function G(t){const e=k(t),l=v(t),a=$(t),i=I(t),c=i.map(n=>n.code),u=_(t);return{locale:l,defaultLocale:a,locales:i,t:(n,s,r,o)=>e.t(n,s,r,o),ts:(n,s,r,o)=>e.ts(n,s,r,o),tc:(n,s,r)=>e.tc(n,s,r),tn:(n,s)=>e.tn(n,s),td:(n,s)=>e.td(n,s),tdr:(n,s)=>e.tdr(n,s),has:(n,s)=>e.has(n,s),getRoute:()=>e.getRoute(),getRouteName:n=>{const s=n||t.url.pathname;if(u?.getRouteName)return u.getRouteName(s,c);const r=s.replace(/^\//,"").replace(/\/$/,"");if(!r)return"index";const o=r.split("/").filter(Boolean),f=o[0];return f&&c.includes(f)&&o.shift(),o.length===0?"index":o.join("-")},getLocaleFromPath:n=>{const s=n||t.url.pathname;if(u?.getLocaleFromPath)return u.getLocaleFromPath(s,a,c);const o=s.split("/").filter(Boolean)[0];return o&&c.includes(o)?o:a},switchLocalePath:n=>{if(u?.switchLocalePath)return u.switchLocalePath(t.url.pathname,n,c,a);const s=t.url.pathname.split("/").filter(Boolean),r=s[0];return r&&c.includes(r)&&s.shift(),n!==a&&s.unshift(n),`/${s.join("/")}`},localizePath:(n,s)=>{if(u?.localizePath)return u.localizePath(n,s||l,c,a);const o=(n.replace(/^\//,"").replace(/\/$/,"")||"").split("/").filter(Boolean),f=o[0];return f&&c.includes(f)&&o.shift(),s&&s!==a&&o.unshift(s),`/${o.join("/")}`},getI18n:()=>e,getBasePath:n=>{const o=(n||t.url).pathname.split("/").filter(Boolean),f=o[0];return f&&c.includes(f)&&o.shift(),o.length>0?`/${o.join("/")}`:"/"},addTranslations:(n,s,r=!0)=>{e.addTranslations(n,s,r)},addRouteTranslations:(n,s,r,o=!0)=>{e.addRouteTranslations(n,s,r,o)},mergeTranslations:(n,s,r)=>{e.mergeTranslations(n,s,r)},clearCache:()=>{e.clearCache()}}}function K(t,e={}){const{baseUrl:l="/",addDirAttribute:a=!0,addSeoAttributes:i=!0}=e,c=v(t),u=$(t),s=I(t).filter(d=>!d.disabled),r=s.filter(d=>d.seo!==!1),o=s.find(d=>d.code===c);if(!o)return{htmlAttrs:{},link:[],meta:[]};const f=o.iso||c,g=o.dir||"auto",h={htmlAttrs:{lang:f,...a?{dir:g}:{}},link:[],meta:[]};if(!i)return h;const p=`${l}${t.url.pathname}`;h.link.push({rel:"canonical",href:p});const m=_(t),P=s.map(d=>d.code);for(const d of r){let b=t.url.pathname;if(m?.switchLocalePath)b=m.switchLocalePath(t.url.pathname,d.code,P,u);else{const S=t.url.pathname.split("/").filter(Boolean),w=S[0];w&&P.includes(w)&&S.shift(),d.code!==u&&S.unshift(d.code),b=`/${S.join("/")}`}const L=`${l}${b}`;h.link.push({rel:"alternate",href:L,hreflang:d.code}),d.iso&&d.iso!==d.code&&h.link.push({rel:"alternate",href:L,hreflang:d.iso})}if(s.find(d=>d.code===u)?.seo!==!1){let d=t.url.pathname;if(m?.switchLocalePath)d=m.switchLocalePath(t.url.pathname,u,P,u);else{const b=t.url.pathname.split("/").filter(Boolean),L=b[0];L&&P.includes(L)&&b.shift(),d=`/${b.join("/")}`}h.link.push({rel:"alternate",href:`${l}${d}`,hreflang:"x-default"})}h.meta.push({property:"og:locale",content:f}),h.meta.push({property:"og:url",content:p});for(const d of r)d.code!==c&&h.meta.push({property:"og:locale:alternate",content:d.og||d.iso||d.code});return h}function Q(t,e,l){const a=e.split(".");let i=t;for(let u=0;u<a.length-1;u++){const n=a[u];i[n]||(i[n]={}),i=i[n]}const c=a[a.length-1];c!==void 0&&(i[c]=l)}function X(t,e){const l=k(t),a=v(t),i=$(t),c=l.getRoute(),u={};if(e&&e.length>0){const n={};for(const s of e){const r=l.t(s,void 0,void 0,c);r!=null&&r!==s&&Q(n,s,r)}Object.keys(n).length>0&&(u[c]=n)}else{const n=l.getRouteTranslations(a,c);n&&(u[c]=n)}return{locale:a,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=T;exports.createAstroRouterAdapter=z;exports.createI18n=N;exports.createI18nMiddleware=M;exports.detectLocale=W;exports.getDefaultLocale=$;exports.getI18n=k;exports.getI18nProps=X;exports.getLocale=v;exports.getLocaleFromPath=U;exports.getLocales=I;exports.getRouteName=H;exports.i18nIntegration=C;exports.loadTranslationsFromDir=O;exports.loadTranslationsIntoI18n=q;exports.localizePath=J;exports.removeLocaleFromPath=V;exports.switchLocalePath=E;exports.useI18n=G;exports.useLocaleHead=K;
package/dist/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  import { BaseI18n as I } from "@i18n-micro/core";
2
2
  import { FormatService as le, defaultPlural as re, interpolate as ie } from "@i18n-micro/core";
3
- import { existsSync as j, readdirSync as _, statSync as C, readFileSync as N } from "node:fs";
4
- import { resolve as O, join as q } from "node:path";
5
- class S extends I {
3
+ import { existsSync as $, readdirSync as O, statSync as _, readFileSync as C } from "node:fs";
4
+ import { resolve as N, join as q } from "node:path";
5
+ class j extends I {
6
6
  constructor(e) {
7
7
  const s = e._storage || {
8
8
  translations: /* @__PURE__ */ new Map()
@@ -26,7 +26,7 @@ class S extends I {
26
26
  }
27
27
  clone(e) {
28
28
  const s = this.cloneStorage(this.storage);
29
- return new S({
29
+ return new j({
30
30
  locale: e || this._locale,
31
31
  fallbackLocale: this._fallbackLocale,
32
32
  plural: this.pluralFunc,
@@ -79,13 +79,13 @@ class S extends I {
79
79
  this.helper.loadTranslations(s, a);
80
80
  }
81
81
  }
82
- let T = null;
83
- function $() {
84
- return T;
82
+ let v = null;
83
+ function k() {
84
+ return v;
85
85
  }
86
86
  function E(t) {
87
87
  const { locale: e, fallbackLocale: s, translationDir: a, routingStrategy: i } = t;
88
- return T = i || null, {
88
+ return v = i || null, {
89
89
  name: "@i18n-micro/astro",
90
90
  hooks: {
91
91
  // 1. Vite setup (virtual module) happens here
@@ -147,26 +147,26 @@ function E(t) {
147
147
  };
148
148
  }
149
149
  function J(t) {
150
- return new S(t);
150
+ return new j(t);
151
151
  }
152
152
  function M(t) {
153
- const { translationDir: e, rootDir: s = process.cwd(), disablePageLocales: a = !1 } = t, i = O(s, e);
154
- if (!j(i))
153
+ const { translationDir: e, rootDir: s = process.cwd(), disablePageLocales: a = !1 } = t, i = N(s, e);
154
+ if (!$(i))
155
155
  return console.warn(`[i18n] Translation directory not found: ${i}`), { root: {}, routes: {} };
156
156
  const c = {}, u = {}, n = (l, r = "") => {
157
- if (!j(l)) return;
158
- const o = _(l);
159
- for (const g of o) {
160
- const f = q(l, g);
161
- if (C(f).isDirectory())
162
- g === "pages" && !a ? n(f, "") : r || a ? n(f, r) : n(f, g);
163
- else if (g.endsWith(".json")) {
164
- const m = g.replace(".json", "");
157
+ if (!$(l)) return;
158
+ const o = O(l);
159
+ for (const f of o) {
160
+ const g = q(l, f);
161
+ if (_(g).isDirectory())
162
+ f === "pages" && !a ? n(g, "") : r || a ? n(g, r) : n(g, f);
163
+ else if (f.endsWith(".json")) {
164
+ const p = f.replace(".json", "");
165
165
  try {
166
- const p = N(f, "utf-8"), h = JSON.parse(p);
167
- r && !a ? (u[r] || (u[r] = {}), u[r][m] = h) : c[m] = h;
168
- } catch (p) {
169
- console.error(`[i18n] Failed to load translation file: ${f}`, p);
166
+ const m = C(g, "utf-8"), L = JSON.parse(m);
167
+ r && !a ? (u[r] || (u[r] = {}), u[r][p] = L) : c[p] = L;
168
+ } catch (m) {
169
+ console.error(`[i18n] Failed to load translation file: ${g}`, m);
170
170
  }
171
171
  }
172
172
  }
@@ -193,27 +193,27 @@ function G(t) {
193
193
  autoDetect: c = !0,
194
194
  redirectToDefault: u = !1,
195
195
  routingStrategy: n
196
- } = t, l = n || $();
196
+ } = t, l = n || k();
197
197
  return async (r, o) => {
198
198
  if (r.locals.locale && r.locals.i18n)
199
199
  return o();
200
- const g = r.url, f = g.pathname;
200
+ const f = r.url, g = f.pathname;
201
201
  if (!l) {
202
- const b = e.clone(s), B = f === "/" || f === "" ? "index" : f.split("/").filter(Boolean).join("-");
203
- return b.setRoute(B), r.locals.i18n = b, r.locals.locale = s, r.locals.defaultLocale = s, r.locals.locales = i || a.map((F) => ({ code: F })), r.locals.currentUrl = g, o();
202
+ const P = e.clone(s), S = g === "/" || g === "" ? "index" : g.split("/").filter(Boolean).join("-");
203
+ return P.setRoute(S), r.locals.i18n = P, r.locals.locale = s, r.locals.defaultLocale = s, r.locals.locales = i || a.map((w) => ({ code: w })), r.locals.currentUrl = f, o();
204
204
  }
205
- const d = {
205
+ const h = {
206
206
  ...l,
207
- getCurrentPath: () => f,
207
+ getCurrentPath: () => g,
208
208
  getRoute: () => ({
209
- fullPath: g.pathname + g.search,
210
- query: Object.fromEntries(g.searchParams)
209
+ fullPath: f.pathname + f.search,
210
+ query: Object.fromEntries(f.searchParams)
211
211
  })
212
- }, p = f.split("/").filter(Boolean)[0], h = p !== void 0 && a.includes(p);
213
- let P;
214
- h && p ? P = p : d.getLocaleFromPath ? P = d.getLocaleFromPath(f, s, a) : P = s;
215
- const L = e.clone(P), y = d.getRouteName ? d.getRouteName(f, a) : "index";
216
- return L.setRoute(y), r.locals.i18n = L, r.locals.locale = P, r.locals.defaultLocale = s, r.locals.locales = i || a.map((b) => ({ code: b })), r.locals.currentUrl = g, r.locals.routingStrategy = d, o();
212
+ }, m = g.split("/").filter(Boolean)[0], L = m !== void 0 && a.includes(m);
213
+ let y;
214
+ L && m ? y = m : h.getLocaleFromPath ? y = h.getLocaleFromPath(g, s, a) : y = s;
215
+ const d = e.clone(y), b = h.getRouteName ? h.getRouteName(g, a) : "index";
216
+ return d.setRoute(b), r.locals.i18n = d, r.locals.locale = y, r.locals.defaultLocale = s, r.locals.locales = i || a.map((P) => ({ code: P })), r.locals.currentUrl = f, r.locals.routingStrategy = h, o();
217
217
  };
218
218
  }
219
219
  function W(t) {
@@ -228,7 +228,7 @@ function W(t) {
228
228
  return e;
229
229
  }
230
230
  function K(t, e, s, a, i, c = "i18n-locale") {
231
- const u = $();
231
+ const u = k();
232
232
  let n = a;
233
233
  if (u?.getLocaleFromPath)
234
234
  n = u.getLocaleFromPath(t, a, i);
@@ -256,21 +256,21 @@ function K(t, e, s, a, i, c = "i18n-locale") {
256
256
  return n;
257
257
  }
258
258
  function x(t, e, s) {
259
- const a = t.map((o) => o.code), i = (o, g = []) => {
260
- const f = o.replace(/^\//, "").replace(/\/$/, "");
261
- if (!f)
259
+ const a = t.map((o) => o.code), i = (o, f = []) => {
260
+ const g = o.replace(/^\//, "").replace(/\/$/, "");
261
+ if (!g)
262
262
  return "index";
263
- const d = f.split("/").filter(Boolean), m = d[0];
264
- return m && g.includes(m) && d.shift(), d.length === 0 ? "index" : d.join("-");
265
- }, c = (o, g = "en", f = []) => {
266
- const m = o.split("/").filter(Boolean)[0];
267
- return m && f.includes(m) ? m : g;
268
- }, u = (o, g, f = [], d) => {
269
- const m = o.split("/").filter(Boolean), p = m[0];
270
- return p && f.includes(p) && m.shift(), (g !== d || d === void 0) && m.unshift(g), `/${m.join("/")}`;
271
- }, n = (o, g, f = [], d) => {
272
- const p = (o.replace(/^\//, "").replace(/\/$/, "") || "").split("/").filter(Boolean), h = p[0];
273
- return h && f.includes(h) && p.shift(), (g !== d || d === void 0) && p.unshift(g), `/${p.join("/")}`;
263
+ const h = g.split("/").filter(Boolean), p = h[0];
264
+ return p && f.includes(p) && h.shift(), h.length === 0 ? "index" : h.join("-");
265
+ }, c = (o, f = "en", g = []) => {
266
+ const p = o.split("/").filter(Boolean)[0];
267
+ return p && g.includes(p) ? p : f;
268
+ }, u = (o, f, g = [], h) => {
269
+ const p = o.split("/").filter(Boolean), m = p[0];
270
+ return m && g.includes(m) && p.shift(), (f !== h || h === void 0) && p.unshift(f), `/${p.join("/")}`;
271
+ }, n = (o, f, g = [], h) => {
272
+ const m = (o.replace(/^\//, "").replace(/\/$/, "") || "").split("/").filter(Boolean), L = m[0];
273
+ return L && g.includes(L) && m.shift(), (f !== h || h === void 0) && m.unshift(f), `/${m.join("/")}`;
274
274
  };
275
275
  return {
276
276
  getCurrentPath: () => s ? s().pathname : typeof window < "u" ? window.location.pathname : "/",
@@ -278,13 +278,13 @@ function x(t, e, s) {
278
278
  getLocaleFromPath: c,
279
279
  switchLocalePath: u,
280
280
  localizePath: n,
281
- removeLocaleFromPath: (o, g = []) => {
282
- const f = o.split("/").filter(Boolean), d = f[0];
283
- return d && g.includes(d) && f.shift(), `/${f.join("/")}`;
281
+ removeLocaleFromPath: (o, f = []) => {
282
+ const g = o.split("/").filter(Boolean), h = g[0];
283
+ return h && f.includes(h) && g.shift(), `/${g.join("/")}`;
284
284
  },
285
- resolvePath: (o, g) => {
286
- const f = typeof o == "string" ? o : o.path || "/";
287
- return n(f, g, a, e);
285
+ resolvePath: (o, f) => {
286
+ const g = typeof o == "string" ? o : o.path || "/";
287
+ return n(g, f, a, e);
288
288
  },
289
289
  getRoute: () => {
290
290
  if (s) {
@@ -338,26 +338,26 @@ function ee(t, e = []) {
338
338
  const s = t.split("/").filter(Boolean), a = s[0];
339
339
  return a && e.includes(a) && s.shift(), `/${s.join("/")}`;
340
340
  }
341
- function v(t) {
341
+ function D(t) {
342
342
  const e = t.locals.i18n;
343
343
  if (!e)
344
344
  throw new Error("i18n instance not found. Make sure i18n middleware is configured.");
345
345
  return e;
346
346
  }
347
- function w(t) {
347
+ function R(t) {
348
348
  return t.locals.locale || "en";
349
349
  }
350
- function R(t) {
350
+ function T(t) {
351
351
  return t.locals.defaultLocale || "en";
352
352
  }
353
- function k(t) {
353
+ function B(t) {
354
354
  return t.locals.locales || [];
355
355
  }
356
- function D(t) {
356
+ function F(t) {
357
357
  return t.locals.routingStrategy || null;
358
358
  }
359
359
  function te(t) {
360
- const e = v(t), s = w(t), a = R(t), i = k(t), c = i.map((n) => n.code), u = D(t);
360
+ const e = D(t), s = R(t), a = T(t), i = B(t), c = i.map((n) => n.code), u = F(t);
361
361
  return {
362
362
  // Current locale
363
363
  locale: s,
@@ -379,8 +379,8 @@ function te(t) {
379
379
  return u.getRouteName(l, c);
380
380
  const r = l.replace(/^\//, "").replace(/\/$/, "");
381
381
  if (!r) return "index";
382
- const o = r.split("/").filter(Boolean), g = o[0];
383
- return g && c.includes(g) && o.shift(), o.length === 0 ? "index" : o.join("-");
382
+ const o = r.split("/").filter(Boolean), f = o[0];
383
+ return f && c.includes(f) && o.shift(), o.length === 0 ? "index" : o.join("-");
384
384
  },
385
385
  getLocaleFromPath: (n) => {
386
386
  const l = n || t.url.pathname;
@@ -399,15 +399,15 @@ function te(t) {
399
399
  localizePath: (n, l) => {
400
400
  if (u?.localizePath)
401
401
  return u.localizePath(n, l || s, c, a);
402
- const o = (n.replace(/^\//, "").replace(/\/$/, "") || "").split("/").filter(Boolean), g = o[0];
403
- return g && c.includes(g) && o.shift(), l && l !== a && o.unshift(l), `/${o.join("/")}`;
402
+ const o = (n.replace(/^\//, "").replace(/\/$/, "") || "").split("/").filter(Boolean), f = o[0];
403
+ return f && c.includes(f) && o.shift(), l && l !== a && o.unshift(l), `/${o.join("/")}`;
404
404
  },
405
405
  // Get i18n instance
406
406
  getI18n: () => e,
407
407
  // Get base path without locale (for rewrite)
408
408
  getBasePath: (n) => {
409
- const o = (n || t.url).pathname.split("/").filter(Boolean), g = o[0];
410
- return g && c.includes(g) && o.shift(), o.length > 0 ? `/${o.join("/")}` : "/";
409
+ const o = (n || t.url).pathname.split("/").filter(Boolean), f = o[0];
410
+ return f && c.includes(f) && o.shift(), o.length > 0 ? `/${o.join("/")}` : "/";
411
411
  },
412
412
  // Translation management
413
413
  addTranslations: (n, l, r = !0) => {
@@ -425,71 +425,71 @@ function te(t) {
425
425
  };
426
426
  }
427
427
  function ne(t, e = {}) {
428
- const { baseUrl: s = "/", addDirAttribute: a = !0, addSeoAttributes: i = !0 } = e, c = w(t), u = R(t), l = k(t).filter((h) => !h.disabled), r = l.find((h) => h.code === c);
429
- if (!r)
428
+ const { baseUrl: s = "/", addDirAttribute: a = !0, addSeoAttributes: i = !0 } = e, c = R(t), u = T(t), l = B(t).filter((d) => !d.disabled), r = l.filter((d) => d.seo !== !1), o = l.find((d) => d.code === c);
429
+ if (!o)
430
430
  return { htmlAttrs: {}, link: [], meta: [] };
431
- const o = r.iso || c, g = r.dir || "auto", f = {
431
+ const f = o.iso || c, g = o.dir || "auto", h = {
432
432
  htmlAttrs: {
433
- lang: o,
433
+ lang: f,
434
434
  ...a ? { dir: g } : {}
435
435
  },
436
436
  link: [],
437
437
  meta: []
438
438
  };
439
439
  if (!i)
440
- return f;
441
- const d = `${s}${t.url.pathname}`;
442
- f.link.push({
440
+ return h;
441
+ const p = `${s}${t.url.pathname}`;
442
+ h.link.push({
443
443
  rel: "canonical",
444
- href: d
444
+ href: p
445
445
  });
446
- const m = D(t), p = l.map((h) => h.code);
447
- for (const h of l) {
448
- let P = t.url.pathname;
446
+ const m = F(t), L = l.map((d) => d.code);
447
+ for (const d of r) {
448
+ let b = t.url.pathname;
449
449
  if (m?.switchLocalePath)
450
- P = m.switchLocalePath(t.url.pathname, h.code, p, u);
450
+ b = m.switchLocalePath(t.url.pathname, d.code, L, u);
451
451
  else {
452
- const y = t.url.pathname.split("/").filter(Boolean), b = y[0];
453
- b && p.includes(b) && y.shift(), h.code !== u && y.unshift(h.code), P = `/${y.join("/")}`;
452
+ const S = t.url.pathname.split("/").filter(Boolean), w = S[0];
453
+ w && L.includes(w) && S.shift(), d.code !== u && S.unshift(d.code), b = `/${S.join("/")}`;
454
454
  }
455
- const L = `${s}${P}`;
456
- f.link.push({
455
+ const P = `${s}${b}`;
456
+ h.link.push({
457
457
  rel: "alternate",
458
- href: L,
459
- hreflang: h.code
460
- }), h.iso && h.iso !== h.code && f.link.push({
458
+ href: P,
459
+ hreflang: d.code
460
+ }), d.iso && d.iso !== d.code && h.link.push({
461
461
  rel: "alternate",
462
- href: L,
463
- hreflang: h.iso
462
+ href: P,
463
+ hreflang: d.iso
464
464
  });
465
465
  }
466
- {
467
- let h = t.url.pathname;
466
+ if (l.find((d) => d.code === u)?.seo !== !1) {
467
+ let d = t.url.pathname;
468
468
  if (m?.switchLocalePath)
469
- h = m.switchLocalePath(t.url.pathname, u, p, u);
469
+ d = m.switchLocalePath(t.url.pathname, u, L, u);
470
470
  else {
471
- const P = t.url.pathname.split("/").filter(Boolean), L = P[0];
472
- L && p.includes(L) && P.shift(), h = `/${P.join("/")}`;
471
+ const b = t.url.pathname.split("/").filter(Boolean), P = b[0];
472
+ P && L.includes(P) && b.shift(), d = `/${b.join("/")}`;
473
473
  }
474
- f.link.push({
474
+ h.link.push({
475
475
  rel: "alternate",
476
- href: `${s}${h}`,
476
+ href: `${s}${d}`,
477
477
  hreflang: "x-default"
478
478
  });
479
479
  }
480
- f.meta.push({
480
+ h.meta.push({
481
481
  property: "og:locale",
482
- content: o
483
- }), f.meta.push({
482
+ content: f
483
+ }), h.meta.push({
484
484
  property: "og:url",
485
- content: d
485
+ content: p
486
486
  });
487
- for (const h of l)
488
- h.code !== c && f.meta.push({
487
+ for (const d of r)
488
+ d.code !== c && h.meta.push({
489
489
  property: "og:locale:alternate",
490
- content: h.iso || h.code
490
+ content: d.og || d.iso || d.code
491
491
  });
492
- return f;
492
+ return h;
493
493
  }
494
494
  function A(t, e, s) {
495
495
  const a = e.split(".");
@@ -502,7 +502,7 @@ function A(t, e, s) {
502
502
  c !== void 0 && (i[c] = s);
503
503
  }
504
504
  function oe(t, e) {
505
- const s = v(t), a = w(t), i = R(t), c = s.getRoute(), u = {};
505
+ const s = D(t), a = R(t), i = T(t), c = s.getRoute(), u = {};
506
506
  if (e && e.length > 0) {
507
507
  const n = {};
508
508
  for (const l of e) {
@@ -522,19 +522,19 @@ function oe(t, e) {
522
522
  };
523
523
  }
524
524
  export {
525
- S as AstroI18n,
525
+ j as AstroI18n,
526
526
  le as FormatService,
527
527
  x as createAstroRouterAdapter,
528
528
  J as createI18n,
529
529
  G as createI18nMiddleware,
530
530
  re as defaultPlural,
531
531
  K as detectLocale,
532
- R as getDefaultLocale,
533
- v as getI18n,
532
+ T as getDefaultLocale,
533
+ D as getI18n,
534
534
  oe as getI18nProps,
535
- w as getLocale,
535
+ R as getLocale,
536
536
  X as getLocaleFromPath,
537
- k as getLocales,
537
+ B as getLocales,
538
538
  Q as getRouteName,
539
539
  E as i18nIntegration,
540
540
  ie as interpolate,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@i18n-micro/astro",
3
- "version": "1.3.1",
3
+ "version": "1.3.3",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",
@@ -51,9 +51,9 @@
51
51
  "access": "public"
52
52
  },
53
53
  "dependencies": {
54
- "@i18n-micro/core": "1.2.0",
55
- "@i18n-micro/node": "1.2.0",
56
- "@i18n-micro/types": "1.1.6"
54
+ "@i18n-micro/core": "1.3.0",
55
+ "@i18n-micro/types": "1.2.1",
56
+ "@i18n-micro/node": "1.2.0"
57
57
  },
58
58
  "peerDependencies": {
59
59
  "astro": "^5.16.5",
@@ -44,7 +44,7 @@ function findTranslation<T = unknown>(translations: Translations | null, key: st
44
44
  * Pure function to get a translation from state
45
45
  *
46
46
  * Note: This is a simplified version optimized for client-side islands.
47
- * It supports basic translation lookup, interpolation, and fallback to general translations.
47
+ * It supports basic translation lookup and interpolation.
48
48
  * Returns CleanTranslation which can be string, number, boolean, object, or null.
49
49
  * For advanced features like Linked Messages (@:path.to.key), use the server-side i18n instance.
50
50
  */
@@ -62,28 +62,18 @@ export function translate(
62
62
  const route = routeName || state.currentRoute
63
63
  let value: string | number | boolean | Translations | null = null
64
64
 
65
- // 1. Look in route-specific translations
66
65
  if (state.translations[route]) {
67
66
  value = findTranslation<string | number | boolean | Translations>(state.translations[route], key)
68
67
  }
69
68
 
70
- // 2. Fallback to general translations
71
- if (!value && state.translations.general) {
72
- value = findTranslation<string | number | boolean | Translations>(state.translations.general, key)
73
- }
74
-
75
- // 3. If not found, use defaultValue or key
69
+ // If not found, use defaultValue or key
76
70
  if (!value) {
77
71
  value = defaultValue === undefined ? key : defaultValue || key
78
72
  }
79
73
 
80
- // 4. Parameter interpolation (strings only)
81
74
  if (typeof value === 'string' && params) {
82
75
  return interpolate(value, params)
83
76
  }
84
-
85
- // 5. Return value as-is (can be string, number, boolean, object, or null)
86
- // This matches the CleanTranslation type
87
77
  return value
88
78
  }
89
79
 
@@ -93,9 +83,7 @@ export function translate(
93
83
  export function hasTranslation(state: I18nState, key: string, routeName?: string): boolean {
94
84
  const route = routeName || state.currentRoute
95
85
  const routeTranslations = state.translations[route]
96
- const generalTranslations = state.translations.general
97
86
 
98
- // Check in route-specific translations
99
87
  if (routeTranslations) {
100
88
  const value = findTranslation(routeTranslations, key)
101
89
  if (value !== null && typeof value !== 'object') {
@@ -103,13 +91,5 @@ export function hasTranslation(state: I18nState, key: string, routeName?: string
103
91
  }
104
92
  }
105
93
 
106
- // Check in general translations
107
- if (generalTranslations) {
108
- const value = findTranslation(generalTranslations, key)
109
- if (value !== null && typeof value !== 'object') {
110
- return true
111
- }
112
- }
113
-
114
94
  return false
115
95
  }
@@ -65,7 +65,6 @@ export function loadTranslationsFromDir(options: LoadTranslationsOptions): Loade
65
65
  if (entry === 'pages' && !disablePageLocales) {
66
66
  loadFiles(fullPath, '')
67
67
  } else if (routePrefix || disablePageLocales) {
68
- // Continue in general translations
69
68
  loadFiles(fullPath, routePrefix)
70
69
  } else {
71
70
  // This is a route directory (e.g., pages/home/)
package/src/utils.ts CHANGED
@@ -217,6 +217,7 @@ export function useLocaleHead(astro: AstroGlobal, options: LocaleHeadOptions = {
217
217
  const defaultLocale = getDefaultLocale(astro)
218
218
  const allLocales = getLocales(astro)
219
219
  const locales = allLocales.filter((l) => !l.disabled)
220
+ const localesForSeo = locales.filter((l) => l.seo !== false)
220
221
  const currentLocaleObj = locales.find((l) => l.code === locale)
221
222
 
222
223
  if (!currentLocaleObj) {
@@ -251,7 +252,7 @@ export function useLocaleHead(astro: AstroGlobal, options: LocaleHeadOptions = {
251
252
  const allLocaleCodes = locales.map((l) => l.code)
252
253
 
253
254
  // Alternate languages (includes current locale for self-referencing hreflang, per Google guidelines)
254
- for (const loc of locales) {
255
+ for (const loc of localesForSeo) {
255
256
  let alternatePath = astro.url.pathname
256
257
  if (routingStrategy?.switchLocalePath) {
257
258
  alternatePath = routingStrategy.switchLocalePath(astro.url.pathname, loc.code, allLocaleCodes, defaultLocale)
@@ -287,7 +288,8 @@ export function useLocaleHead(astro: AstroGlobal, options: LocaleHeadOptions = {
287
288
  // x-default hreflang — points to the default locale's URL.
288
289
  // Tells search engines which URL to show when none of the
289
290
  // specified languages match the user's browser settings.
290
- {
291
+ const defaultLocaleObj = locales.find((l) => l.code === defaultLocale)
292
+ if (defaultLocaleObj?.seo !== false) {
291
293
  let xDefaultPath = astro.url.pathname
292
294
  if (routingStrategy?.switchLocalePath) {
293
295
  xDefaultPath = routingStrategy.switchLocalePath(astro.url.pathname, defaultLocale, allLocaleCodes, defaultLocale)
@@ -318,11 +320,11 @@ export function useLocaleHead(astro: AstroGlobal, options: LocaleHeadOptions = {
318
320
  })
319
321
 
320
322
  // Alternate OG locales
321
- for (const loc of locales) {
323
+ for (const loc of localesForSeo) {
322
324
  if (loc.code === locale) continue
323
325
  result.meta.push({
324
326
  property: 'og:locale:alternate',
325
- content: loc.iso || loc.code,
327
+ content: loc.og || loc.iso || loc.code,
326
328
  })
327
329
  }
328
330
 
@@ -1 +0,0 @@
1
- "use strict";const s=require("@i18n-micro/core");function u(n,t){if(n===null||typeof t!="string")return null;let o=n;if(n[t])o=n[t];else{const l=t.toString().split(".");for(const e of l)if(o&&typeof o=="object"&&o!==null&&e in o)o=o[e];else return null}return o??null}function a(n,t,o,l,e){if(!t)return l||t||"";const i=e||n.currentRoute;let r=null;return n.translations[i]&&(r=u(n.translations[i],t)),!r&&n.translations.general&&(r=u(n.translations.general,t)),r||(r=l===void 0?t:l||t),typeof r=="string"&&o?s.interpolate(r,o):r}function f(n,t,o){const l=o||n.currentRoute,e=n.translations[l],i=n.translations.general;if(e){const r=u(e,t);if(r!==null&&typeof r!="object")return!0}if(i){const r=u(i,t);if(r!==null&&typeof r!="object")return!0}return!1}exports.hasTranslation=f;exports.translate=a;
@@ -1,42 +0,0 @@
1
- import { interpolate as s } from "@i18n-micro/core";
2
- function u(n, t) {
3
- if (n === null || typeof t != "string")
4
- return null;
5
- let o = n;
6
- if (n[t])
7
- o = n[t];
8
- else {
9
- const l = t.toString().split(".");
10
- for (const i of l)
11
- if (o && typeof o == "object" && o !== null && i in o)
12
- o = o[i];
13
- else
14
- return null;
15
- }
16
- return o ?? null;
17
- }
18
- function a(n, t, o, l, i) {
19
- if (!t)
20
- return l || t || "";
21
- const e = i || n.currentRoute;
22
- let r = null;
23
- return n.translations[e] && (r = u(n.translations[e], t)), !r && n.translations.general && (r = u(n.translations.general, t)), r || (r = l === void 0 ? t : l || t), typeof r == "string" && o ? s(r, o) : r;
24
- }
25
- function c(n, t, o) {
26
- const l = o || n.currentRoute, i = n.translations[l], e = n.translations.general;
27
- if (i) {
28
- const r = u(i, t);
29
- if (r !== null && typeof r != "object")
30
- return !0;
31
- }
32
- if (e) {
33
- const r = u(e, t);
34
- if (r !== null && typeof r != "object")
35
- return !0;
36
- }
37
- return !1;
38
- }
39
- export {
40
- c as h,
41
- a as t
42
- };