@i18n-micro/astro 1.2.1 → 1.3.0
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/client/core.d.ts +3 -3
- package/dist/client/svelte.d.ts +3 -3
- package/dist/client/svelte.js +2 -2
- package/dist/client/vue.d.ts +3 -3
- package/dist/composer.d.ts +0 -1
- package/dist/index.cjs +2 -2
- package/dist/index.mjs +135 -139
- package/dist/load-translations.d.ts +1 -1
- package/dist/utils.d.ts +5 -6
- package/package.json +4 -4
- package/src/client/core.ts +14 -14
- package/src/client/index.ts +1 -1
- package/src/client/svelte.ts +5 -5
- package/src/client/vue.ts +3 -3
- package/src/composer.ts +1 -5
- package/src/integration.ts +2 -2
- package/src/load-translations.ts +12 -11
- package/src/middleware.ts +2 -2
- package/src/routing.ts +1 -1
- package/src/utils.ts +15 -18
package/dist/client/core.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Params, Translations } from '@i18n-micro/types';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* I18n state for client islands
|
|
4
4
|
*/
|
|
5
5
|
export interface I18nState {
|
|
6
6
|
locale: string;
|
|
@@ -9,7 +9,7 @@ export interface I18nState {
|
|
|
9
9
|
currentRoute: string;
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
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
15
|
* It supports basic translation lookup, interpolation, and fallback to general translations.
|
|
@@ -18,6 +18,6 @@ export interface I18nState {
|
|
|
18
18
|
*/
|
|
19
19
|
export declare function translate(state: I18nState, key: string, params?: Params, defaultValue?: string | null, routeName?: string): string | number | boolean | Translations | null;
|
|
20
20
|
/**
|
|
21
|
-
*
|
|
21
|
+
* Checks if a translation exists in the state
|
|
22
22
|
*/
|
|
23
23
|
export declare function hasTranslation(state: I18nState, key: string, routeName?: string): boolean;
|
package/dist/client/svelte.d.ts
CHANGED
|
@@ -3,12 +3,12 @@ import { Writable } from 'svelte/store';
|
|
|
3
3
|
import { I18nClientProps } from '../utils';
|
|
4
4
|
import { I18nState } from './core';
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
6
|
+
* Creates a Svelte store for i18n state
|
|
7
7
|
*/
|
|
8
8
|
export declare function createI18nStore(props: I18nClientProps): Writable<I18nState>;
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
10
|
+
* Hook for using i18n in Svelte components
|
|
11
|
+
* Use in the component's <script> block
|
|
12
12
|
*/
|
|
13
13
|
export declare function useAstroI18n(store: Writable<I18nState>): {
|
|
14
14
|
store: Writable<I18nState>;
|
package/dist/client/svelte.js
CHANGED
|
@@ -13,7 +13,7 @@ function F(o) {
|
|
|
13
13
|
function P(o) {
|
|
14
14
|
const n = () => v(o), c = (t, e, r, a) => S(n(), t, e, r, a);
|
|
15
15
|
return {
|
|
16
|
-
// Store
|
|
16
|
+
// Store for reactivity in templates (use $i18nStore in templates)
|
|
17
17
|
store: o,
|
|
18
18
|
// Translation methods
|
|
19
19
|
t: c,
|
|
@@ -38,7 +38,7 @@ function P(o) {
|
|
|
38
38
|
return l.formatRelativeTime(t, r.locale, e);
|
|
39
39
|
},
|
|
40
40
|
has: (t, e) => L(n(), t, e),
|
|
41
|
-
//
|
|
41
|
+
// Getters for current state (for use in scripts)
|
|
42
42
|
get locale() {
|
|
43
43
|
return n().locale;
|
|
44
44
|
},
|
package/dist/client/vue.d.ts
CHANGED
|
@@ -3,12 +3,12 @@ import { Ref } from 'vue';
|
|
|
3
3
|
import { I18nClientProps } from '../utils';
|
|
4
4
|
import { I18nState } from './core';
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* Initializes the i18n provider for a Vue island
|
|
7
|
+
* Call in the island's root component
|
|
8
8
|
*/
|
|
9
9
|
export declare function provideI18n(props: I18nClientProps): Ref<I18nState>;
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
11
|
+
* Hook for using i18n in Vue components
|
|
12
12
|
*/
|
|
13
13
|
export declare function useAstroI18n(): {
|
|
14
14
|
t: (key: TranslationKey, params?: Params, defaultValue?: string | null, routeName?: string) => CleanTranslation;
|
package/dist/composer.d.ts
CHANGED
|
@@ -30,6 +30,5 @@ export declare class AstroI18n extends BaseI18n {
|
|
|
30
30
|
addTranslations(locale: string, translations: Translations, merge?: boolean): void;
|
|
31
31
|
addRouteTranslations(locale: string, routeName: string, translations: Translations, merge?: boolean): void;
|
|
32
32
|
mergeTranslations(locale: string, routeName: string, translations: Translations): void;
|
|
33
|
-
mergeGlobalTranslations(locale: string, translations: Translations): void;
|
|
34
33
|
clearCache(): void;
|
|
35
34
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const j=require("@i18n-micro/core"),b=require("node:fs"),I=require("node:path");class w extends j.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[o,i]of Object.entries(e.messages))this.helper.loadTranslations(o,i)}}cloneStorage(e){const s=new Map;for(const[o,i]of e.translations)s.set(o,{...i});return{translations:s}}clone(e){const s=this.cloneStorage(this.storage);return new w({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 o=`${e}:${s}`;return this.storage.translations.get(o)??null}addTranslations(e,s,o=!0){super.loadTranslationsCore(e,s,o)}addRouteTranslations(e,s,o,i=!0){super.loadRouteTranslationsCore(e,s,o,i)}mergeTranslations(e,s,o){this.helper.mergeTranslation(e,s,o,!0)}clearCache(){const e={...this.initialMessages};if(super.clearCache(),Object.keys(e).length>0)for(const[s,o]of Object.entries(e))this.helper.loadTranslations(s,o)}}let $=null;function D(){return $}function C(n){const{locale:e,fallbackLocale:s,translationDir:o,routingStrategy:i}=n;return $=i||null,{name:"@i18n-micro/astro",hooks:{"astro:config:setup":c=>{const{updateConfig:f}=c,t="virtual:i18n-micro/config",l=`\0${t}`,r={defaultLocale:e,fallbackLocale:s||e,locales:n.locales||[],localeCodes:(n.locales||[]).map(a=>a.code),translationDir:o||null,autoDetect:n.autoDetect??!0,redirectToDefault:n.redirectToDefault??!1,localeCookie:n.localeCookie===null?null:n.localeCookie||"i18n-locale",missingWarn:n.missingWarn??!1};f({vite:{plugins:[{name:"vite-plugin-i18n-micro-config",resolveId(a){if(a===t)return l},load(a){if(a===l)return`export const config = ${JSON.stringify(r)}`}}]}})},"astro:config:done":c=>{const{injectTypes:f}=c;f({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(n){return new
|
|
17
|
+
`})}}}}function N(n){return new w(n)}function F(n){const{translationDir:e,rootDir:s=process.cwd(),disablePageLocales:o=!1}=n,i=I.resolve(s,e);if(!b.existsSync(i))return console.warn(`[i18n] Translation directory not found: ${i}`),{root:{},routes:{}};const c={},f={},t=(l,r="")=>{if(!b.existsSync(l))return;const a=b.readdirSync(l);for(const u of a){const h=I.join(l,u);if(b.statSync(h).isDirectory())u==="pages"&&!o?t(h,""):r||o?t(h,r):t(h,u);else if(u.endsWith(".json")){const m=u.replace(".json","");try{const g=b.readFileSync(h,"utf-8"),p=JSON.parse(g);r&&!o?(f[r]||(f[r]={}),f[r][m]=p):c[m]=p}catch(g){console.error(`[i18n] Failed to load translation file: ${h}`,g)}}}};return t(i),{root:c,routes:f}}function q(n,e){const{root:s,routes:o}=F(e);for(const[i,c]of Object.entries(s))n.addTranslations(i,c,!1);for(const[i,c]of Object.entries(o))for(const[f,t]of Object.entries(c)){const l=s[f]||{};n.addRouteTranslations(f,i,{...l,...t},!1)}}function M(n){const{i18n:e,defaultLocale:s,locales:o,localeObjects:i,autoDetect:c=!0,redirectToDefault:f=!1,routingStrategy:t}=n,l=t||D();return async(r,a)=>{if(r.locals.locale&&r.locals.i18n)return a();const u=r.url,h=u.pathname;if(!l){const S=e.clone(s),O=h==="/"||h===""?"index":h.split("/").filter(Boolean).join("-");return S.setRoute(O),r.locals.i18n=S,r.locals.locale=s,r.locals.defaultLocale=s,r.locals.locales=i||o.map(_=>({code:_})),r.locals.currentUrl=u,a()}const d={...l,getCurrentPath:()=>h,getRoute:()=>({fullPath:u.pathname+u.search,query:Object.fromEntries(u.searchParams)})},g=h.split("/").filter(Boolean)[0],p=g!==void 0&&o.includes(g);let P;p&&g?P=g:d.getLocaleFromPath?P=d.getLocaleFromPath(h,s,o):P=s;const L=e.clone(P),y=d.getRouteName?d.getRouteName(h,o):"index";return L.setRoute(y),r.locals.i18n=L,r.locals.locale=P,r.locals.defaultLocale=s,r.locals.locales=i||o.map(S=>({code:S})),r.locals.currentUrl=u,r.locals.routingStrategy=d,a()}}function A(n){const e=[],s=n.split(",");for(const o of s){const[i,c="1.0"]=o.trim().split(";q=");if(Number.parseFloat(c)>0&&i){const t=i.split("-")[0]?.toLowerCase();t&&(e.push(t),i!==t&&e.push(i.toLowerCase()))}}return e}function W(n,e,s,o,i,c="i18n-locale"){const f=D();let t=o;if(f?.getLocaleFromPath)t=f.getLocaleFromPath(n,o,i);else{const r=n.split("/").filter(Boolean)[0];r&&i.includes(r)&&(t=r)}if(c!==null&&t===o&&e.get(c)){const l=e.get(c)?.value;l&&i.includes(l)&&(t=l)}if(t===o)try{const l=s.get("accept-language");if(l){const r=A(l);for(const a of r)if(i.includes(a)){t=a;break}}}catch{}return t}function z(n,e,s){const o=n.map(a=>a.code),i=(a,u=[])=>{const h=a.replace(/^\//,"").replace(/\/$/,"");if(!h)return"index";const d=h.split("/").filter(Boolean),m=d[0];return m&&u.includes(m)&&d.shift(),d.length===0?"index":d.join("-")},c=(a,u="en",h=[])=>{const m=a.split("/").filter(Boolean)[0];return m&&h.includes(m)?m:u},f=(a,u,h=[],d)=>{const m=a.split("/").filter(Boolean),g=m[0];return g&&h.includes(g)&&m.shift(),(u!==d||d===void 0)&&m.unshift(u),`/${m.join("/")}`},t=(a,u,h=[],d)=>{const g=(a.replace(/^\//,"").replace(/\/$/,"")||"").split("/").filter(Boolean),p=g[0];return p&&h.includes(p)&&g.shift(),(u!==d||d===void 0)&&g.unshift(u),`/${g.join("/")}`};return{getCurrentPath:()=>s?s().pathname:typeof window<"u"?window.location.pathname:"/",getRouteName:i,getLocaleFromPath:c,switchLocalePath:f,localizePath:t,removeLocaleFromPath:(a,u=[])=>{const h=a.split("/").filter(Boolean),d=h[0];return d&&u.includes(d)&&h.shift(),`/${h.join("/")}`},resolvePath:(a,u)=>{const h=typeof a=="string"?a:a.path||"/";return t(h,u,o,e)},getRoute:()=>{if(s){const a=s();return{fullPath:a.pathname+a.search,query:Object.fromEntries(a.searchParams)}}if(typeof window<"u"){const a=new URL(window.location.href);return{fullPath:a.pathname+a.search,query:Object.fromEntries(a.searchParams)}}return{fullPath:"/",query:{}}},push:a=>{typeof window<"u"&&(window.location.href=a.path)},replace:a=>{typeof window<"u"&&window.location.replace(a.path)}}}function H(n,e=[]){const s=n.replace(/^\//,"").replace(/\/$/,"");if(!s)return"index";const o=s.split("/").filter(Boolean),i=o[0];return i&&e.includes(i)&&o.shift(),o.length===0?"index":o.join("-")}function U(n,e="en",s=[]){const i=n.split("/").filter(Boolean)[0];return i&&s.includes(i)?i:e}function E(n,e,s=[],o){const i=n.split("/").filter(Boolean),c=i[0];return c&&s.includes(c)&&i.shift(),(e!==o||o===void 0)&&i.unshift(e),`/${i.join("/")}`}function J(n,e,s=[],o){const c=(n.replace(/^\//,"").replace(/\/$/,"")||"").split("/").filter(Boolean),f=c[0];return f&&s.includes(f)&&c.shift(),(e!==o||o===void 0)&&c.unshift(e),`/${c.join("/")}`}function V(n,e=[]){const s=n.split("/").filter(Boolean),o=s[0];return o&&e.includes(o)&&s.shift(),`/${s.join("/")}`}function v(n){const e=n.locals.i18n;if(!e)throw new Error("i18n instance not found. Make sure i18n middleware is configured.");return e}function R(n){return n.locals.locale||"en"}function T(n){return n.locals.defaultLocale||"en"}function k(n){return n.locals.locales||[]}function B(n){return n.locals.routingStrategy||null}function G(n){const e=v(n),s=R(n),o=T(n),i=k(n),c=i.map(t=>t.code),f=B(n);return{locale:s,defaultLocale:o,locales:i,t:(t,l,r,a)=>e.t(t,l,r,a),ts:(t,l,r,a)=>e.ts(t,l,r,a),tc:(t,l,r)=>e.tc(t,l,r),tn:(t,l)=>e.tn(t,l),td:(t,l)=>e.td(t,l),tdr:(t,l)=>e.tdr(t,l),has:(t,l)=>e.has(t,l),getRoute:()=>e.getRoute(),getRouteName:t=>{const l=t||n.url.pathname;if(f?.getRouteName)return f.getRouteName(l,c);const r=l.replace(/^\//,"").replace(/\/$/,"");if(!r)return"index";const a=r.split("/").filter(Boolean),u=a[0];return u&&c.includes(u)&&a.shift(),a.length===0?"index":a.join("-")},getLocaleFromPath:t=>{const l=t||n.url.pathname;if(f?.getLocaleFromPath)return f.getLocaleFromPath(l,o,c);const a=l.split("/").filter(Boolean)[0];return a&&c.includes(a)?a:o},switchLocalePath:t=>{if(f?.switchLocalePath)return f.switchLocalePath(n.url.pathname,t,c,o);const l=n.url.pathname.split("/").filter(Boolean),r=l[0];return r&&c.includes(r)&&l.shift(),t!==o&&l.unshift(t),`/${l.join("/")}`},localizePath:(t,l)=>{if(f?.localizePath)return f.localizePath(t,l||s,c,o);const a=(t.replace(/^\//,"").replace(/\/$/,"")||"").split("/").filter(Boolean),u=a[0];return u&&c.includes(u)&&a.shift(),l&&l!==o&&a.unshift(l),`/${a.join("/")}`},getI18n:()=>e,getBasePath:t=>{const a=(t||n.url).pathname.split("/").filter(Boolean),u=a[0];return u&&c.includes(u)&&a.shift(),a.length>0?`/${a.join("/")}`:"/"},addTranslations:(t,l,r=!0)=>{e.addTranslations(t,l,r)},addRouteTranslations:(t,l,r,a=!0)=>{e.addRouteTranslations(t,l,r,a)},mergeTranslations:(t,l,r)=>{e.mergeTranslations(t,l,r)},clearCache:()=>{e.clearCache()}}}function K(n,e={}){const{baseUrl:s="/",addDirAttribute:o=!0,addSeoAttributes:i=!0}=e,c=R(n),f=T(n),t=k(n),l=t.find(g=>g.code===c);if(!l)return{htmlAttrs:{},link:[],meta:[]};const r=l.iso||c,a=l.dir||"auto",u={htmlAttrs:{lang:r,...o?{dir:a}:{}},link:[],meta:[]};if(!i)return u;const h=`${s}${n.url.pathname}`;u.link.push({rel:"canonical",href:h});const d=B(n),m=t.map(g=>g.code);for(const g of t){if(g.code===c)continue;let p=n.url.pathname;if(d?.switchLocalePath)p=d.switchLocalePath(n.url.pathname,g.code,m,f);else{const L=n.url.pathname.split("/").filter(Boolean),y=L[0];y&&m.includes(y)&&L.shift(),g.code!==f&&L.unshift(g.code),p=`/${L.join("/")}`}const P=`${s}${p}`;u.link.push({rel:"alternate",href:P,hreflang:g.code}),g.iso&&g.iso!==g.code&&u.link.push({rel:"alternate",href:P,hreflang:g.iso})}u.meta.push({property:"og:locale",content:r}),u.meta.push({property:"og:url",content:h});for(const g of t)g.code!==c&&u.meta.push({property:"og:locale:alternate",content:g.iso||g.code});return u}function Q(n,e,s){const o=e.split(".");let i=n;for(let f=0;f<o.length-1;f++){const t=o[f];i[t]||(i[t]={}),i=i[t]}const c=o[o.length-1];c!==void 0&&(i[c]=s)}function X(n,e){const s=v(n),o=R(n),i=T(n),c=s.getRoute(),f={};if(e&&e.length>0){const t={};for(const l of e){const r=s.t(l,void 0,void 0,c);r!=null&&r!==l&&Q(t,l,r)}Object.keys(t).length>0&&(f[c]=t)}else{const t=s.getRouteTranslations(o,c);t&&(f[c]=t)}return{locale:o,fallbackLocale:i,currentRoute:c,translations:f}}Object.defineProperty(exports,"FormatService",{enumerable:!0,get:()=>j.FormatService});Object.defineProperty(exports,"defaultPlural",{enumerable:!0,get:()=>j.defaultPlural});Object.defineProperty(exports,"interpolate",{enumerable:!0,get:()=>j.interpolate});exports.AstroI18n=w;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=k;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;
|
package/dist/index.mjs
CHANGED
|
@@ -1,38 +1,38 @@
|
|
|
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
|
|
3
|
+
import { existsSync as j, readdirSync as _, statSync as C, readFileSync as N } from "node:fs";
|
|
4
4
|
import { resolve as O, join as q } from "node:path";
|
|
5
5
|
class S extends I {
|
|
6
6
|
constructor(e) {
|
|
7
|
-
const
|
|
7
|
+
const a = e._storage || {
|
|
8
8
|
translations: /* @__PURE__ */ new Map()
|
|
9
9
|
};
|
|
10
10
|
if (super({
|
|
11
|
-
storage:
|
|
11
|
+
storage: a,
|
|
12
12
|
plural: e.plural,
|
|
13
13
|
missingWarn: e.missingWarn,
|
|
14
14
|
missingHandler: e.missingHandler
|
|
15
|
-
}), this.initialMessages = {}, this.storage =
|
|
15
|
+
}), this.initialMessages = {}, this.storage = a, this._locale = e.locale, this._fallbackLocale = e.fallbackLocale || e.locale, this._currentRoute = "index", e.messages) {
|
|
16
16
|
this.initialMessages = { ...e.messages };
|
|
17
17
|
for (const [o, i] of Object.entries(e.messages))
|
|
18
18
|
this.helper.loadTranslations(o, i);
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
cloneStorage(e) {
|
|
22
|
-
const
|
|
22
|
+
const a = /* @__PURE__ */ new Map();
|
|
23
23
|
for (const [o, i] of e.translations)
|
|
24
|
-
|
|
25
|
-
return { translations:
|
|
24
|
+
a.set(o, { ...i });
|
|
25
|
+
return { translations: a };
|
|
26
26
|
}
|
|
27
27
|
clone(e) {
|
|
28
|
-
const
|
|
28
|
+
const a = this.cloneStorage(this.storage);
|
|
29
29
|
return new S({
|
|
30
30
|
locale: e || this._locale,
|
|
31
31
|
fallbackLocale: this._fallbackLocale,
|
|
32
32
|
plural: this.pluralFunc,
|
|
33
33
|
missingWarn: this.missingWarn,
|
|
34
34
|
missingHandler: this.missingHandler,
|
|
35
|
-
_storage:
|
|
35
|
+
_storage: a
|
|
36
36
|
});
|
|
37
37
|
}
|
|
38
38
|
get locale() {
|
|
@@ -59,45 +59,42 @@ class S extends I {
|
|
|
59
59
|
getRoute() {
|
|
60
60
|
return this._currentRoute;
|
|
61
61
|
}
|
|
62
|
-
getRouteTranslations(e,
|
|
63
|
-
const o = `${e}:${
|
|
62
|
+
getRouteTranslations(e, a) {
|
|
63
|
+
const o = `${e}:${a}`;
|
|
64
64
|
return this.storage.translations.get(o) ?? null;
|
|
65
65
|
}
|
|
66
|
-
addTranslations(e,
|
|
67
|
-
super.loadTranslationsCore(e,
|
|
66
|
+
addTranslations(e, a, o = !0) {
|
|
67
|
+
super.loadTranslationsCore(e, a, o);
|
|
68
68
|
}
|
|
69
|
-
addRouteTranslations(e,
|
|
70
|
-
super.loadRouteTranslationsCore(e,
|
|
69
|
+
addRouteTranslations(e, a, o, i = !0) {
|
|
70
|
+
super.loadRouteTranslationsCore(e, a, o, i);
|
|
71
71
|
}
|
|
72
|
-
mergeTranslations(e,
|
|
73
|
-
this.helper.mergeTranslation(e,
|
|
74
|
-
}
|
|
75
|
-
mergeGlobalTranslations(e, s) {
|
|
76
|
-
this.helper.mergeGlobalTranslation(e, s, !0);
|
|
72
|
+
mergeTranslations(e, a, o) {
|
|
73
|
+
this.helper.mergeTranslation(e, a, o, !0);
|
|
77
74
|
}
|
|
78
75
|
clearCache() {
|
|
79
76
|
const e = { ...this.initialMessages };
|
|
80
77
|
if (super.clearCache(), Object.keys(e).length > 0)
|
|
81
|
-
for (const [
|
|
82
|
-
this.helper.loadTranslations(
|
|
78
|
+
for (const [a, o] of Object.entries(e))
|
|
79
|
+
this.helper.loadTranslations(a, o);
|
|
83
80
|
}
|
|
84
81
|
}
|
|
85
|
-
let
|
|
82
|
+
let T = null;
|
|
86
83
|
function v() {
|
|
87
|
-
return
|
|
84
|
+
return T;
|
|
88
85
|
}
|
|
89
|
-
function
|
|
90
|
-
const { locale: e, fallbackLocale:
|
|
91
|
-
return
|
|
86
|
+
function E(n) {
|
|
87
|
+
const { locale: e, fallbackLocale: a, translationDir: o, routingStrategy: i } = n;
|
|
88
|
+
return T = i || null, {
|
|
92
89
|
name: "@i18n-micro/astro",
|
|
93
90
|
hooks: {
|
|
94
|
-
// 1.
|
|
91
|
+
// 1. Vite setup (virtual module) happens here
|
|
95
92
|
"astro:config:setup": (c) => {
|
|
96
93
|
const { updateConfig: f } = c, t = "virtual:i18n-micro/config", l = `\0${t}`, r = {
|
|
97
94
|
defaultLocale: e,
|
|
98
|
-
fallbackLocale:
|
|
95
|
+
fallbackLocale: a || e,
|
|
99
96
|
locales: n.locales || [],
|
|
100
|
-
localeCodes: (n.locales || []).map((
|
|
97
|
+
localeCodes: (n.locales || []).map((s) => s.code),
|
|
101
98
|
translationDir: o || null,
|
|
102
99
|
autoDetect: n.autoDetect ?? !0,
|
|
103
100
|
redirectToDefault: n.redirectToDefault ?? !1,
|
|
@@ -109,12 +106,12 @@ function U(n) {
|
|
|
109
106
|
plugins: [
|
|
110
107
|
{
|
|
111
108
|
name: "vite-plugin-i18n-micro-config",
|
|
112
|
-
resolveId(
|
|
113
|
-
if (
|
|
109
|
+
resolveId(s) {
|
|
110
|
+
if (s === t)
|
|
114
111
|
return l;
|
|
115
112
|
},
|
|
116
|
-
load(
|
|
117
|
-
if (
|
|
113
|
+
load(s) {
|
|
114
|
+
if (s === l)
|
|
118
115
|
return `export const config = ${JSON.stringify(r)}`;
|
|
119
116
|
}
|
|
120
117
|
}
|
|
@@ -122,7 +119,7 @@ function U(n) {
|
|
|
122
119
|
}
|
|
123
120
|
});
|
|
124
121
|
},
|
|
125
|
-
// 2.
|
|
122
|
+
// 2. Type injection happens here (per Astro documentation)
|
|
126
123
|
"astro:config:done": (c) => {
|
|
127
124
|
const { injectTypes: f } = c;
|
|
128
125
|
f({
|
|
@@ -149,17 +146,17 @@ function U(n) {
|
|
|
149
146
|
}
|
|
150
147
|
};
|
|
151
148
|
}
|
|
152
|
-
function
|
|
149
|
+
function J(n) {
|
|
153
150
|
return new S(n);
|
|
154
151
|
}
|
|
155
152
|
function M(n) {
|
|
156
|
-
const { translationDir: e, rootDir:
|
|
157
|
-
if (!
|
|
158
|
-
return console.warn(`[i18n] Translation directory not found: ${i}`), {
|
|
153
|
+
const { translationDir: e, rootDir: a = process.cwd(), disablePageLocales: o = !1 } = n, i = O(a, e);
|
|
154
|
+
if (!j(i))
|
|
155
|
+
return console.warn(`[i18n] Translation directory not found: ${i}`), { root: {}, routes: {} };
|
|
159
156
|
const c = {}, f = {}, t = (l, r = "") => {
|
|
160
|
-
if (!
|
|
161
|
-
const
|
|
162
|
-
for (const u of
|
|
157
|
+
if (!j(l)) return;
|
|
158
|
+
const s = _(l);
|
|
159
|
+
for (const u of s) {
|
|
163
160
|
const h = q(l, u);
|
|
164
161
|
if (C(h).isDirectory())
|
|
165
162
|
u === "pages" && !o ? t(h, "") : r || o ? t(h, r) : t(h, u);
|
|
@@ -174,34 +171,36 @@ function M(n) {
|
|
|
174
171
|
}
|
|
175
172
|
}
|
|
176
173
|
};
|
|
177
|
-
return t(i), {
|
|
174
|
+
return t(i), { root: c, routes: f };
|
|
178
175
|
}
|
|
179
|
-
function
|
|
180
|
-
const {
|
|
181
|
-
for (const [i, c] of Object.entries(
|
|
176
|
+
function V(n, e) {
|
|
177
|
+
const { root: a, routes: o } = M(e);
|
|
178
|
+
for (const [i, c] of Object.entries(a))
|
|
182
179
|
n.addTranslations(i, c, !1);
|
|
183
180
|
for (const [i, c] of Object.entries(o))
|
|
184
|
-
for (const [f, t] of Object.entries(c))
|
|
185
|
-
|
|
181
|
+
for (const [f, t] of Object.entries(c)) {
|
|
182
|
+
const l = a[f] || {};
|
|
183
|
+
n.addRouteTranslations(f, i, { ...l, ...t }, !1);
|
|
184
|
+
}
|
|
186
185
|
}
|
|
187
|
-
function
|
|
186
|
+
function G(n) {
|
|
188
187
|
const {
|
|
189
188
|
i18n: e,
|
|
190
|
-
//
|
|
191
|
-
defaultLocale:
|
|
189
|
+
// This is the global singleton with cache
|
|
190
|
+
defaultLocale: a,
|
|
192
191
|
locales: o,
|
|
193
192
|
localeObjects: i,
|
|
194
193
|
autoDetect: c = !0,
|
|
195
194
|
redirectToDefault: f = !1,
|
|
196
195
|
routingStrategy: t
|
|
197
196
|
} = n, l = t || v();
|
|
198
|
-
return async (r,
|
|
197
|
+
return async (r, s) => {
|
|
199
198
|
if (r.locals.locale && r.locals.i18n)
|
|
200
|
-
return
|
|
199
|
+
return s();
|
|
201
200
|
const u = r.url, h = u.pathname;
|
|
202
201
|
if (!l) {
|
|
203
|
-
const
|
|
204
|
-
return
|
|
202
|
+
const b = e.clone(a), B = h === "/" || h === "" ? "index" : h.split("/").filter(Boolean).join("-");
|
|
203
|
+
return b.setRoute(B), r.locals.i18n = b, r.locals.locale = a, r.locals.defaultLocale = a, r.locals.locales = i || o.map((F) => ({ code: F })), r.locals.currentUrl = u, s();
|
|
205
204
|
}
|
|
206
205
|
const d = {
|
|
207
206
|
...l,
|
|
@@ -212,14 +211,14 @@ function V(n) {
|
|
|
212
211
|
})
|
|
213
212
|
}, g = h.split("/").filter(Boolean)[0], p = g !== void 0 && o.includes(g);
|
|
214
213
|
let P;
|
|
215
|
-
p && g ? P = g : d.getLocaleFromPath ? P = d.getLocaleFromPath(h,
|
|
216
|
-
const L = e.clone(P),
|
|
217
|
-
return L.setRoute(
|
|
214
|
+
p && g ? P = g : d.getLocaleFromPath ? P = d.getLocaleFromPath(h, a, o) : P = a;
|
|
215
|
+
const L = e.clone(P), y = d.getRouteName ? d.getRouteName(h, o) : "index";
|
|
216
|
+
return L.setRoute(y), r.locals.i18n = L, r.locals.locale = P, r.locals.defaultLocale = a, r.locals.locales = i || o.map((b) => ({ code: b })), r.locals.currentUrl = u, r.locals.routingStrategy = d, s();
|
|
218
217
|
};
|
|
219
218
|
}
|
|
220
219
|
function W(n) {
|
|
221
|
-
const e = [],
|
|
222
|
-
for (const o of
|
|
220
|
+
const e = [], a = n.split(",");
|
|
221
|
+
for (const o of a) {
|
|
223
222
|
const [i, c = "1.0"] = o.trim().split(";q=");
|
|
224
223
|
if (Number.parseFloat(c) > 0 && i) {
|
|
225
224
|
const t = i.split("-")[0]?.toLowerCase();
|
|
@@ -228,7 +227,7 @@ function W(n) {
|
|
|
228
227
|
}
|
|
229
228
|
return e;
|
|
230
229
|
}
|
|
231
|
-
function K(n, e,
|
|
230
|
+
function K(n, e, a, o, i, c = "i18n-locale") {
|
|
232
231
|
const f = v();
|
|
233
232
|
let t = o;
|
|
234
233
|
if (f?.getLocaleFromPath)
|
|
@@ -243,12 +242,12 @@ function K(n, e, s, o, i, c = "i18n-locale") {
|
|
|
243
242
|
}
|
|
244
243
|
if (t === o)
|
|
245
244
|
try {
|
|
246
|
-
const l =
|
|
245
|
+
const l = a.get("accept-language");
|
|
247
246
|
if (l) {
|
|
248
247
|
const r = W(l);
|
|
249
|
-
for (const
|
|
250
|
-
if (i.includes(
|
|
251
|
-
t =
|
|
248
|
+
for (const s of r)
|
|
249
|
+
if (i.includes(s)) {
|
|
250
|
+
t = s;
|
|
252
251
|
break;
|
|
253
252
|
}
|
|
254
253
|
}
|
|
@@ -256,50 +255,50 @@ function K(n, e, s, o, i, c = "i18n-locale") {
|
|
|
256
255
|
}
|
|
257
256
|
return t;
|
|
258
257
|
}
|
|
259
|
-
function Q(n, e,
|
|
260
|
-
const o = n.map((
|
|
261
|
-
const h =
|
|
258
|
+
function Q(n, e, a) {
|
|
259
|
+
const o = n.map((s) => s.code), i = (s, u = []) => {
|
|
260
|
+
const h = s.replace(/^\//, "").replace(/\/$/, "");
|
|
262
261
|
if (!h)
|
|
263
262
|
return "index";
|
|
264
263
|
const d = h.split("/").filter(Boolean), m = d[0];
|
|
265
264
|
return m && u.includes(m) && d.shift(), d.length === 0 ? "index" : d.join("-");
|
|
266
|
-
}, c = (
|
|
267
|
-
const m =
|
|
265
|
+
}, c = (s, u = "en", h = []) => {
|
|
266
|
+
const m = s.split("/").filter(Boolean)[0];
|
|
268
267
|
return m && h.includes(m) ? m : u;
|
|
269
|
-
}, f = (
|
|
270
|
-
const m =
|
|
268
|
+
}, f = (s, u, h = [], d) => {
|
|
269
|
+
const m = s.split("/").filter(Boolean), g = m[0];
|
|
271
270
|
return g && h.includes(g) && m.shift(), (u !== d || d === void 0) && m.unshift(u), `/${m.join("/")}`;
|
|
272
|
-
}, t = (
|
|
273
|
-
const g = (
|
|
271
|
+
}, t = (s, u, h = [], d) => {
|
|
272
|
+
const g = (s.replace(/^\//, "").replace(/\/$/, "") || "").split("/").filter(Boolean), p = g[0];
|
|
274
273
|
return p && h.includes(p) && g.shift(), (u !== d || d === void 0) && g.unshift(u), `/${g.join("/")}`;
|
|
275
274
|
};
|
|
276
275
|
return {
|
|
277
|
-
getCurrentPath: () =>
|
|
276
|
+
getCurrentPath: () => a ? a().pathname : typeof window < "u" ? window.location.pathname : "/",
|
|
278
277
|
getRouteName: i,
|
|
279
278
|
getLocaleFromPath: c,
|
|
280
279
|
switchLocalePath: f,
|
|
281
280
|
localizePath: t,
|
|
282
|
-
removeLocaleFromPath: (
|
|
283
|
-
const h =
|
|
281
|
+
removeLocaleFromPath: (s, u = []) => {
|
|
282
|
+
const h = s.split("/").filter(Boolean), d = h[0];
|
|
284
283
|
return d && u.includes(d) && h.shift(), `/${h.join("/")}`;
|
|
285
284
|
},
|
|
286
|
-
resolvePath: (
|
|
287
|
-
const h = typeof
|
|
285
|
+
resolvePath: (s, u) => {
|
|
286
|
+
const h = typeof s == "string" ? s : s.path || "/";
|
|
288
287
|
return t(h, u, o, e);
|
|
289
288
|
},
|
|
290
289
|
getRoute: () => {
|
|
291
|
-
if (
|
|
292
|
-
const
|
|
290
|
+
if (a) {
|
|
291
|
+
const s = a();
|
|
293
292
|
return {
|
|
294
|
-
fullPath:
|
|
295
|
-
query: Object.fromEntries(
|
|
293
|
+
fullPath: s.pathname + s.search,
|
|
294
|
+
query: Object.fromEntries(s.searchParams)
|
|
296
295
|
};
|
|
297
296
|
}
|
|
298
297
|
if (typeof window < "u") {
|
|
299
|
-
const
|
|
298
|
+
const s = new URL(window.location.href);
|
|
300
299
|
return {
|
|
301
|
-
fullPath:
|
|
302
|
-
query: Object.fromEntries(
|
|
300
|
+
fullPath: s.pathname + s.search,
|
|
301
|
+
query: Object.fromEntries(s.searchParams)
|
|
303
302
|
};
|
|
304
303
|
}
|
|
305
304
|
return {
|
|
@@ -308,36 +307,36 @@ function Q(n, e, s) {
|
|
|
308
307
|
};
|
|
309
308
|
},
|
|
310
309
|
// Optional: client-side navigation for islands
|
|
311
|
-
push: (
|
|
312
|
-
typeof window < "u" && (window.location.href =
|
|
310
|
+
push: (s) => {
|
|
311
|
+
typeof window < "u" && (window.location.href = s.path);
|
|
313
312
|
},
|
|
314
|
-
replace: (
|
|
315
|
-
typeof window < "u" && window.location.replace(
|
|
313
|
+
replace: (s) => {
|
|
314
|
+
typeof window < "u" && window.location.replace(s.path);
|
|
316
315
|
}
|
|
317
316
|
};
|
|
318
317
|
}
|
|
319
318
|
function X(n, e = []) {
|
|
320
|
-
const
|
|
321
|
-
if (!
|
|
319
|
+
const a = n.replace(/^\//, "").replace(/\/$/, "");
|
|
320
|
+
if (!a)
|
|
322
321
|
return "index";
|
|
323
|
-
const o =
|
|
322
|
+
const o = a.split("/").filter(Boolean), i = o[0];
|
|
324
323
|
return i && e.includes(i) && o.shift(), o.length === 0 ? "index" : o.join("-");
|
|
325
324
|
}
|
|
326
|
-
function Y(n, e = "en",
|
|
325
|
+
function Y(n, e = "en", a = []) {
|
|
327
326
|
const i = n.split("/").filter(Boolean)[0];
|
|
328
|
-
return i &&
|
|
327
|
+
return i && a.includes(i) ? i : e;
|
|
329
328
|
}
|
|
330
|
-
function Z(n, e,
|
|
329
|
+
function Z(n, e, a = [], o) {
|
|
331
330
|
const i = n.split("/").filter(Boolean), c = i[0];
|
|
332
|
-
return c &&
|
|
331
|
+
return c && a.includes(c) && i.shift(), (e !== o || o === void 0) && i.unshift(e), `/${i.join("/")}`;
|
|
333
332
|
}
|
|
334
|
-
function x(n, e,
|
|
333
|
+
function x(n, e, a = [], o) {
|
|
335
334
|
const c = (n.replace(/^\//, "").replace(/\/$/, "") || "").split("/").filter(Boolean), f = c[0];
|
|
336
|
-
return f &&
|
|
335
|
+
return f && a.includes(f) && c.shift(), (e !== o || o === void 0) && c.unshift(e), `/${c.join("/")}`;
|
|
337
336
|
}
|
|
338
337
|
function ee(n, e = []) {
|
|
339
|
-
const
|
|
340
|
-
return o && e.includes(o) &&
|
|
338
|
+
const a = n.split("/").filter(Boolean), o = a[0];
|
|
339
|
+
return o && e.includes(o) && a.shift(), `/${a.join("/")}`;
|
|
341
340
|
}
|
|
342
341
|
function k(n) {
|
|
343
342
|
const e = n.locals.i18n;
|
|
@@ -345,10 +344,10 @@ function k(n) {
|
|
|
345
344
|
throw new Error("i18n instance not found. Make sure i18n middleware is configured.");
|
|
346
345
|
return e;
|
|
347
346
|
}
|
|
348
|
-
function
|
|
347
|
+
function w(n) {
|
|
349
348
|
return n.locals.locale || "en";
|
|
350
349
|
}
|
|
351
|
-
function
|
|
350
|
+
function R(n) {
|
|
352
351
|
return n.locals.defaultLocale || "en";
|
|
353
352
|
}
|
|
354
353
|
function $(n) {
|
|
@@ -358,15 +357,15 @@ function D(n) {
|
|
|
358
357
|
return n.locals.routingStrategy || null;
|
|
359
358
|
}
|
|
360
359
|
function te(n) {
|
|
361
|
-
const e = k(n),
|
|
360
|
+
const e = k(n), a = w(n), o = R(n), i = $(n), c = i.map((t) => t.code), f = D(n);
|
|
362
361
|
return {
|
|
363
362
|
// Current locale
|
|
364
|
-
locale:
|
|
363
|
+
locale: a,
|
|
365
364
|
defaultLocale: o,
|
|
366
365
|
locales: i,
|
|
367
366
|
// Translation methods
|
|
368
|
-
t: (t, l, r,
|
|
369
|
-
ts: (t, l, r,
|
|
367
|
+
t: (t, l, r, s) => e.t(t, l, r, s),
|
|
368
|
+
ts: (t, l, r, s) => e.ts(t, l, r, s),
|
|
370
369
|
tc: (t, l, r) => e.tc(t, l, r),
|
|
371
370
|
tn: (t, l) => e.tn(t, l),
|
|
372
371
|
td: (t, l) => e.td(t, l),
|
|
@@ -380,15 +379,15 @@ function te(n) {
|
|
|
380
379
|
return f.getRouteName(l, c);
|
|
381
380
|
const r = l.replace(/^\//, "").replace(/\/$/, "");
|
|
382
381
|
if (!r) return "index";
|
|
383
|
-
const
|
|
384
|
-
return u && c.includes(u) &&
|
|
382
|
+
const s = r.split("/").filter(Boolean), u = s[0];
|
|
383
|
+
return u && c.includes(u) && s.shift(), s.length === 0 ? "index" : s.join("-");
|
|
385
384
|
},
|
|
386
385
|
getLocaleFromPath: (t) => {
|
|
387
386
|
const l = t || n.url.pathname;
|
|
388
387
|
if (f?.getLocaleFromPath)
|
|
389
388
|
return f.getLocaleFromPath(l, o, c);
|
|
390
|
-
const
|
|
391
|
-
return
|
|
389
|
+
const s = l.split("/").filter(Boolean)[0];
|
|
390
|
+
return s && c.includes(s) ? s : o;
|
|
392
391
|
},
|
|
393
392
|
// Path utilities
|
|
394
393
|
switchLocalePath: (t) => {
|
|
@@ -399,50 +398,47 @@ function te(n) {
|
|
|
399
398
|
},
|
|
400
399
|
localizePath: (t, l) => {
|
|
401
400
|
if (f?.localizePath)
|
|
402
|
-
return f.localizePath(t, l ||
|
|
403
|
-
const
|
|
404
|
-
return u && c.includes(u) &&
|
|
401
|
+
return f.localizePath(t, l || a, c, o);
|
|
402
|
+
const s = (t.replace(/^\//, "").replace(/\/$/, "") || "").split("/").filter(Boolean), u = s[0];
|
|
403
|
+
return u && c.includes(u) && s.shift(), l && l !== o && s.unshift(l), `/${s.join("/")}`;
|
|
405
404
|
},
|
|
406
405
|
// Get i18n instance
|
|
407
406
|
getI18n: () => e,
|
|
408
407
|
// Get base path without locale (for rewrite)
|
|
409
408
|
getBasePath: (t) => {
|
|
410
|
-
const
|
|
411
|
-
return u && c.includes(u) &&
|
|
409
|
+
const s = (t || n.url).pathname.split("/").filter(Boolean), u = s[0];
|
|
410
|
+
return u && c.includes(u) && s.shift(), s.length > 0 ? `/${s.join("/")}` : "/";
|
|
412
411
|
},
|
|
413
412
|
// Translation management
|
|
414
413
|
addTranslations: (t, l, r = !0) => {
|
|
415
414
|
e.addTranslations(t, l, r);
|
|
416
415
|
},
|
|
417
|
-
addRouteTranslations: (t, l, r,
|
|
418
|
-
e.addRouteTranslations(t, l, r,
|
|
416
|
+
addRouteTranslations: (t, l, r, s = !0) => {
|
|
417
|
+
e.addRouteTranslations(t, l, r, s);
|
|
419
418
|
},
|
|
420
419
|
mergeTranslations: (t, l, r) => {
|
|
421
420
|
e.mergeTranslations(t, l, r);
|
|
422
421
|
},
|
|
423
|
-
mergeGlobalTranslations: (t, l) => {
|
|
424
|
-
e.mergeGlobalTranslations(t, l);
|
|
425
|
-
},
|
|
426
422
|
clearCache: () => {
|
|
427
423
|
e.clearCache();
|
|
428
424
|
}
|
|
429
425
|
};
|
|
430
426
|
}
|
|
431
427
|
function ne(n, e = {}) {
|
|
432
|
-
const { baseUrl:
|
|
428
|
+
const { baseUrl: a = "/", addDirAttribute: o = !0, addSeoAttributes: i = !0 } = e, c = w(n), f = R(n), t = $(n), l = t.find((g) => g.code === c);
|
|
433
429
|
if (!l)
|
|
434
430
|
return { htmlAttrs: {}, link: [], meta: [] };
|
|
435
|
-
const r = l.iso || c,
|
|
431
|
+
const r = l.iso || c, s = l.dir || "auto", u = {
|
|
436
432
|
htmlAttrs: {
|
|
437
433
|
lang: r,
|
|
438
|
-
...o ? { dir:
|
|
434
|
+
...o ? { dir: s } : {}
|
|
439
435
|
},
|
|
440
436
|
link: [],
|
|
441
437
|
meta: []
|
|
442
438
|
};
|
|
443
439
|
if (!i)
|
|
444
440
|
return u;
|
|
445
|
-
const h = `${
|
|
441
|
+
const h = `${a}${n.url.pathname}`;
|
|
446
442
|
u.link.push({
|
|
447
443
|
rel: "canonical",
|
|
448
444
|
href: h
|
|
@@ -454,10 +450,10 @@ function ne(n, e = {}) {
|
|
|
454
450
|
if (d?.switchLocalePath)
|
|
455
451
|
p = d.switchLocalePath(n.url.pathname, g.code, m, f);
|
|
456
452
|
else {
|
|
457
|
-
const L = n.url.pathname.split("/").filter(Boolean),
|
|
458
|
-
|
|
453
|
+
const L = n.url.pathname.split("/").filter(Boolean), y = L[0];
|
|
454
|
+
y && m.includes(y) && L.shift(), g.code !== f && L.unshift(g.code), p = `/${L.join("/")}`;
|
|
459
455
|
}
|
|
460
|
-
const P = `${
|
|
456
|
+
const P = `${a}${p}`;
|
|
461
457
|
u.link.push({
|
|
462
458
|
rel: "alternate",
|
|
463
459
|
href: P,
|
|
@@ -482,7 +478,7 @@ function ne(n, e = {}) {
|
|
|
482
478
|
});
|
|
483
479
|
return u;
|
|
484
480
|
}
|
|
485
|
-
function A(n, e,
|
|
481
|
+
function A(n, e, a) {
|
|
486
482
|
const o = e.split(".");
|
|
487
483
|
let i = n;
|
|
488
484
|
for (let f = 0; f < o.length - 1; f++) {
|
|
@@ -490,19 +486,19 @@ function A(n, e, s) {
|
|
|
490
486
|
i[t] || (i[t] = {}), i = i[t];
|
|
491
487
|
}
|
|
492
488
|
const c = o[o.length - 1];
|
|
493
|
-
c !== void 0 && (i[c] =
|
|
489
|
+
c !== void 0 && (i[c] = a);
|
|
494
490
|
}
|
|
495
491
|
function oe(n, e) {
|
|
496
|
-
const
|
|
492
|
+
const a = k(n), o = w(n), i = R(n), c = a.getRoute(), f = {};
|
|
497
493
|
if (e && e.length > 0) {
|
|
498
494
|
const t = {};
|
|
499
495
|
for (const l of e) {
|
|
500
|
-
const r =
|
|
496
|
+
const r = a.t(l, void 0, void 0, c);
|
|
501
497
|
r != null && r !== l && A(t, l, r);
|
|
502
498
|
}
|
|
503
499
|
Object.keys(t).length > 0 && (f[c] = t);
|
|
504
500
|
} else {
|
|
505
|
-
const t =
|
|
501
|
+
const t = a.getRouteTranslations(o, c);
|
|
506
502
|
t && (f[c] = t);
|
|
507
503
|
}
|
|
508
504
|
return {
|
|
@@ -516,21 +512,21 @@ export {
|
|
|
516
512
|
S as AstroI18n,
|
|
517
513
|
le as FormatService,
|
|
518
514
|
Q as createAstroRouterAdapter,
|
|
519
|
-
|
|
520
|
-
|
|
515
|
+
J as createI18n,
|
|
516
|
+
G as createI18nMiddleware,
|
|
521
517
|
re as defaultPlural,
|
|
522
518
|
K as detectLocale,
|
|
523
|
-
|
|
519
|
+
R as getDefaultLocale,
|
|
524
520
|
k as getI18n,
|
|
525
521
|
oe as getI18nProps,
|
|
526
|
-
|
|
522
|
+
w as getLocale,
|
|
527
523
|
Y as getLocaleFromPath,
|
|
528
524
|
$ as getLocales,
|
|
529
525
|
X as getRouteName,
|
|
530
|
-
|
|
526
|
+
E as i18nIntegration,
|
|
531
527
|
ie as interpolate,
|
|
532
528
|
M as loadTranslationsFromDir,
|
|
533
|
-
|
|
529
|
+
V as loadTranslationsIntoI18n,
|
|
534
530
|
x as localizePath,
|
|
535
531
|
ee as removeLocaleFromPath,
|
|
536
532
|
Z as switchLocalePath,
|
|
@@ -21,7 +21,7 @@ export interface LoadTranslationsOptions {
|
|
|
21
21
|
disablePageLocales?: boolean;
|
|
22
22
|
}
|
|
23
23
|
export interface LoadedTranslations {
|
|
24
|
-
|
|
24
|
+
root: Record<string, Translations>;
|
|
25
25
|
routes: Record<string, Record<string, Translations>>;
|
|
26
26
|
}
|
|
27
27
|
/**
|
package/dist/utils.d.ts
CHANGED
|
@@ -42,7 +42,6 @@ export declare function useI18n(astro: AstroGlobal): {
|
|
|
42
42
|
addTranslations: (locale: string, translations: Record<string, unknown>, merge?: boolean) => void;
|
|
43
43
|
addRouteTranslations: (locale: string, routeName: string, translations: Record<string, unknown>, merge?: boolean) => void;
|
|
44
44
|
mergeTranslations: (locale: string, routeName: string, translations: Record<string, unknown>) => void;
|
|
45
|
-
mergeGlobalTranslations: (locale: string, translations: Record<string, unknown>) => void;
|
|
46
45
|
clearCache: () => void;
|
|
47
46
|
};
|
|
48
47
|
/**
|
|
@@ -70,7 +69,7 @@ export interface LocaleHeadResult {
|
|
|
70
69
|
}
|
|
71
70
|
export declare function useLocaleHead(astro: AstroGlobal, options?: LocaleHeadOptions): LocaleHeadResult;
|
|
72
71
|
/**
|
|
73
|
-
* Props
|
|
72
|
+
* Props to pass to client islands (Vue, React, Svelte, Preact)
|
|
74
73
|
*/
|
|
75
74
|
export interface I18nClientProps {
|
|
76
75
|
locale: string;
|
|
@@ -79,9 +78,9 @@ export interface I18nClientProps {
|
|
|
79
78
|
currentRoute: string;
|
|
80
79
|
}
|
|
81
80
|
/**
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
* currentRoute
|
|
81
|
+
* Prepares props to pass to a client island.
|
|
82
|
+
* Accepts a list of keys to pass to the island.
|
|
83
|
+
* Uses i18n methods for proper routesLocaleLinks support.
|
|
84
|
+
* currentRoute is already normalized via middleware (getRouteName), so we use it directly.
|
|
86
85
|
*/
|
|
87
86
|
export declare function getI18nProps(astro: AstroGlobal, keys?: string[]): I18nClientProps;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@i18n-micro/astro",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
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.
|
|
55
|
-
"@i18n-micro/types": "1.1.
|
|
56
|
-
"@i18n-micro/node": "1.
|
|
54
|
+
"@i18n-micro/core": "1.2.0",
|
|
55
|
+
"@i18n-micro/types": "1.1.5",
|
|
56
|
+
"@i18n-micro/node": "1.2.0"
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|
|
59
59
|
"astro": "^5.16.5",
|
package/src/client/core.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { interpolate } from '@i18n-micro/core'
|
|
|
2
2
|
import type { Params, Translations } from '@i18n-micro/types'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* I18n state for client islands
|
|
6
6
|
*/
|
|
7
7
|
export interface I18nState {
|
|
8
8
|
locale: string
|
|
@@ -11,7 +11,7 @@ export interface I18nState {
|
|
|
11
11
|
currentRoute: string
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
//
|
|
14
|
+
// Helper function to find a translation in a Translations object
|
|
15
15
|
// Returns the value as-is, including objects (for nested translations)
|
|
16
16
|
function findTranslation<T = unknown>(translations: Translations | null, key: string): T | null {
|
|
17
17
|
if (translations === null || typeof key !== 'string') {
|
|
@@ -20,11 +20,11 @@ function findTranslation<T = unknown>(translations: Translations | null, key: st
|
|
|
20
20
|
|
|
21
21
|
let value: string | number | boolean | Translations | unknown | null = translations
|
|
22
22
|
|
|
23
|
-
//
|
|
23
|
+
// Direct key access
|
|
24
24
|
if (translations[key]) {
|
|
25
25
|
value = translations[key]
|
|
26
26
|
} else {
|
|
27
|
-
//
|
|
27
|
+
// Search by nested keys (e.g. "nested.message")
|
|
28
28
|
const parts = key.toString().split('.')
|
|
29
29
|
for (const part of parts) {
|
|
30
30
|
if (value && typeof value === 'object' && value !== null && part in value) {
|
|
@@ -41,7 +41,7 @@ function findTranslation<T = unknown>(translations: Translations | null, key: st
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
/**
|
|
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
47
|
* It supports basic translation lookup, interpolation, and fallback to general translations.
|
|
@@ -62,40 +62,40 @@ export function translate(
|
|
|
62
62
|
const route = routeName || state.currentRoute
|
|
63
63
|
let value: string | number | boolean | Translations | null = null
|
|
64
64
|
|
|
65
|
-
// 1.
|
|
65
|
+
// 1. Look in route-specific translations
|
|
66
66
|
if (state.translations[route]) {
|
|
67
67
|
value = findTranslation<string | number | boolean | Translations>(state.translations[route], key)
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
// 2. Fallback
|
|
70
|
+
// 2. Fallback to general translations
|
|
71
71
|
if (!value && state.translations.general) {
|
|
72
72
|
value = findTranslation<string | number | boolean | Translations>(state.translations.general, key)
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
// 3.
|
|
75
|
+
// 3. If not found, use defaultValue or key
|
|
76
76
|
if (!value) {
|
|
77
77
|
value = defaultValue === undefined ? key : defaultValue || key
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
// 4.
|
|
80
|
+
// 4. Parameter interpolation (strings only)
|
|
81
81
|
if (typeof value === 'string' && params) {
|
|
82
82
|
return interpolate(value, params)
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
// 5.
|
|
86
|
-
//
|
|
85
|
+
// 5. Return value as-is (can be string, number, boolean, object, or null)
|
|
86
|
+
// This matches the CleanTranslation type
|
|
87
87
|
return value
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
/**
|
|
91
|
-
*
|
|
91
|
+
* Checks if a translation exists in the state
|
|
92
92
|
*/
|
|
93
93
|
export function hasTranslation(state: I18nState, key: string, routeName?: string): boolean {
|
|
94
94
|
const route = routeName || state.currentRoute
|
|
95
95
|
const routeTranslations = state.translations[route]
|
|
96
96
|
const generalTranslations = state.translations.general
|
|
97
97
|
|
|
98
|
-
//
|
|
98
|
+
// Check in route-specific translations
|
|
99
99
|
if (routeTranslations) {
|
|
100
100
|
const value = findTranslation(routeTranslations, key)
|
|
101
101
|
if (value !== null && typeof value !== 'object') {
|
|
@@ -103,7 +103,7 @@ export function hasTranslation(state: I18nState, key: string, routeName?: string
|
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
//
|
|
106
|
+
// Check in general translations
|
|
107
107
|
if (generalTranslations) {
|
|
108
108
|
const value = findTranslation(generalTranslations, key)
|
|
109
109
|
if (value !== null && typeof value !== 'object') {
|
package/src/client/index.ts
CHANGED
package/src/client/svelte.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { hasTranslation, type I18nState, translate } from './core'
|
|
|
7
7
|
const formatter = new FormatService()
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* Creates a Svelte store for i18n state
|
|
11
11
|
*/
|
|
12
12
|
export function createI18nStore(props: I18nClientProps): Writable<I18nState> {
|
|
13
13
|
return writable<I18nState>({
|
|
@@ -19,8 +19,8 @@ export function createI18nStore(props: I18nClientProps): Writable<I18nState> {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
22
|
+
* Hook for using i18n in Svelte components
|
|
23
|
+
* Use in the component's <script> block
|
|
24
24
|
*/
|
|
25
25
|
export function useAstroI18n(store: Writable<I18nState>) {
|
|
26
26
|
const getState = () => get(store)
|
|
@@ -71,7 +71,7 @@ export function useAstroI18n(store: Writable<I18nState>) {
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
return {
|
|
74
|
-
// Store
|
|
74
|
+
// Store for reactivity in templates (use $i18nStore in templates)
|
|
75
75
|
store,
|
|
76
76
|
|
|
77
77
|
// Translation methods
|
|
@@ -83,7 +83,7 @@ export function useAstroI18n(store: Writable<I18nState>) {
|
|
|
83
83
|
tdr,
|
|
84
84
|
has,
|
|
85
85
|
|
|
86
|
-
//
|
|
86
|
+
// Getters for current state (for use in scripts)
|
|
87
87
|
get locale() {
|
|
88
88
|
return getState().locale
|
|
89
89
|
},
|
package/src/client/vue.ts
CHANGED
|
@@ -9,8 +9,8 @@ const formatter = new FormatService()
|
|
|
9
9
|
const I18nSymbol = Symbol('i18n-astro') as InjectionKey<Ref<I18nState>>
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
12
|
+
* Initializes the i18n provider for a Vue island
|
|
13
|
+
* Call in the island's root component
|
|
14
14
|
*/
|
|
15
15
|
export function provideI18n(props: I18nClientProps): Ref<I18nState> {
|
|
16
16
|
const state = ref<I18nState>({
|
|
@@ -24,7 +24,7 @@ export function provideI18n(props: I18nClientProps): Ref<I18nState> {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
|
-
*
|
|
27
|
+
* Hook for using i18n in Vue components
|
|
28
28
|
*/
|
|
29
29
|
export function useAstroI18n() {
|
|
30
30
|
const state = inject(I18nSymbol)
|
package/src/composer.ts
CHANGED
|
@@ -35,7 +35,7 @@ export class AstroI18n extends BaseI18n {
|
|
|
35
35
|
this.storage = storage
|
|
36
36
|
this._locale = options.locale
|
|
37
37
|
this._fallbackLocale = options.fallbackLocale || options.locale
|
|
38
|
-
this._currentRoute = '
|
|
38
|
+
this._currentRoute = 'index'
|
|
39
39
|
|
|
40
40
|
if (options.messages) {
|
|
41
41
|
this.initialMessages = { ...options.messages }
|
|
@@ -115,10 +115,6 @@ export class AstroI18n extends BaseI18n {
|
|
|
115
115
|
this.helper.mergeTranslation(locale, routeName, translations, true)
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
public mergeGlobalTranslations(locale: string, translations: Translations): void {
|
|
119
|
-
this.helper.mergeGlobalTranslation(locale, translations, true)
|
|
120
|
-
}
|
|
121
|
-
|
|
122
118
|
public override clearCache(): void {
|
|
123
119
|
const initialMessages = { ...this.initialMessages }
|
|
124
120
|
|
package/src/integration.ts
CHANGED
|
@@ -39,7 +39,7 @@ export function i18nIntegration(options: I18nIntegrationOptions): AstroIntegrati
|
|
|
39
39
|
return {
|
|
40
40
|
name: '@i18n-micro/astro',
|
|
41
41
|
hooks: {
|
|
42
|
-
// 1.
|
|
42
|
+
// 1. Vite setup (virtual module) happens here
|
|
43
43
|
'astro:config:setup': (params) => {
|
|
44
44
|
const { updateConfig } = params as HookParameters<'astro:config:setup'>
|
|
45
45
|
|
|
@@ -79,7 +79,7 @@ export function i18nIntegration(options: I18nIntegrationOptions): AstroIntegrati
|
|
|
79
79
|
})
|
|
80
80
|
},
|
|
81
81
|
|
|
82
|
-
// 2.
|
|
82
|
+
// 2. Type injection happens here (per Astro documentation)
|
|
83
83
|
'astro:config:done': (params) => {
|
|
84
84
|
const { injectTypes } = params as HookParameters<'astro:config:done'>
|
|
85
85
|
|
package/src/load-translations.ts
CHANGED
|
@@ -26,7 +26,7 @@ export interface LoadTranslationsOptions {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
export interface LoadedTranslations {
|
|
29
|
-
|
|
29
|
+
root: Record<string, Translations>
|
|
30
30
|
routes: Record<string, Record<string, Translations>>
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -43,10 +43,10 @@ export function loadTranslationsFromDir(options: LoadTranslationsOptions): Loade
|
|
|
43
43
|
|
|
44
44
|
if (!existsSync(fullTranslationDir)) {
|
|
45
45
|
console.warn(`[i18n] Translation directory not found: ${fullTranslationDir}`)
|
|
46
|
-
return {
|
|
46
|
+
return { root: {}, routes: {} }
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
const
|
|
49
|
+
const root: Record<string, Translations> = {}
|
|
50
50
|
const routes: Record<string, Record<string, Translations>> = {}
|
|
51
51
|
|
|
52
52
|
/**
|
|
@@ -84,8 +84,8 @@ export function loadTranslationsFromDir(options: LoadTranslationsOptions): Loade
|
|
|
84
84
|
}
|
|
85
85
|
routes[routePrefix][locale] = translations
|
|
86
86
|
} else {
|
|
87
|
-
//
|
|
88
|
-
|
|
87
|
+
// Root-level translation
|
|
88
|
+
root[locale] = translations
|
|
89
89
|
}
|
|
90
90
|
} catch (error) {
|
|
91
91
|
console.error(`[i18n] Failed to load translation file: ${fullPath}`, error)
|
|
@@ -96,7 +96,7 @@ export function loadTranslationsFromDir(options: LoadTranslationsOptions): Loade
|
|
|
96
96
|
|
|
97
97
|
loadFiles(fullTranslationDir)
|
|
98
98
|
|
|
99
|
-
return {
|
|
99
|
+
return { root, routes }
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
/**
|
|
@@ -112,17 +112,18 @@ export function loadTranslationsIntoI18n(
|
|
|
112
112
|
},
|
|
113
113
|
options: LoadTranslationsOptions,
|
|
114
114
|
): void {
|
|
115
|
-
const {
|
|
115
|
+
const { root, routes } = loadTranslationsFromDir(options)
|
|
116
116
|
|
|
117
|
-
// Load
|
|
118
|
-
for (const [locale, translations] of Object.entries(
|
|
117
|
+
// Load root-level translations as index
|
|
118
|
+
for (const [locale, translations] of Object.entries(root)) {
|
|
119
119
|
i18n.addTranslations(locale, translations, false)
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
// Load route-specific translations
|
|
122
|
+
// Load route-specific translations (with root baked in)
|
|
123
123
|
for (const [routeName, routeTranslations] of Object.entries(routes)) {
|
|
124
124
|
for (const [locale, translations] of Object.entries(routeTranslations)) {
|
|
125
|
-
|
|
125
|
+
const base = root[locale] || {}
|
|
126
|
+
i18n.addRouteTranslations(locale, routeName, { ...base, ...translations }, false)
|
|
126
127
|
}
|
|
127
128
|
}
|
|
128
129
|
}
|
package/src/middleware.ts
CHANGED
|
@@ -21,7 +21,7 @@ export interface I18nMiddlewareOptions {
|
|
|
21
21
|
*/
|
|
22
22
|
export function createI18nMiddleware(options: I18nMiddlewareOptions): MiddlewareHandler {
|
|
23
23
|
const {
|
|
24
|
-
i18n: globalI18n, //
|
|
24
|
+
i18n: globalI18n, // This is the global singleton with cache
|
|
25
25
|
defaultLocale,
|
|
26
26
|
locales,
|
|
27
27
|
localeObjects,
|
|
@@ -93,7 +93,7 @@ export function createI18nMiddleware(options: I18nMiddlewareOptions): Middleware
|
|
|
93
93
|
const requestI18n = globalI18n.clone(detectedLocale)
|
|
94
94
|
|
|
95
95
|
// 4. Set route name using routing strategy
|
|
96
|
-
const routeName = contextStrategy.getRouteName ? contextStrategy.getRouteName(pathname, locales) : '
|
|
96
|
+
const routeName = contextStrategy.getRouteName ? contextStrategy.getRouteName(pathname, locales) : 'index'
|
|
97
97
|
requestI18n.setRoute(routeName)
|
|
98
98
|
|
|
99
99
|
// 5. Store in locals (Type-safe now thanks to astro-shim.d.ts)
|
package/src/routing.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Extracts route name from path (e.g., /en/about -> about)
|
|
4
4
|
*/
|
|
5
5
|
export function getRouteName(path: string, locales: string[] = []): string {
|
|
6
|
-
//
|
|
6
|
+
// Normalize the path
|
|
7
7
|
const cleanPath = path.replace(/^\//, '').replace(/\/$/, '')
|
|
8
8
|
|
|
9
9
|
if (!cleanPath) {
|
package/src/utils.ts
CHANGED
|
@@ -179,9 +179,6 @@ export function useI18n(astro: AstroGlobal) {
|
|
|
179
179
|
mergeTranslations: (locale: string, routeName: string, translations: Record<string, unknown>): void => {
|
|
180
180
|
i18n.mergeTranslations(locale, routeName, translations)
|
|
181
181
|
},
|
|
182
|
-
mergeGlobalTranslations: (locale: string, translations: Record<string, unknown>): void => {
|
|
183
|
-
i18n.mergeGlobalTranslations(locale, translations)
|
|
184
|
-
},
|
|
185
182
|
clearCache: (): void => {
|
|
186
183
|
i18n.clearCache()
|
|
187
184
|
},
|
|
@@ -312,7 +309,7 @@ export function useLocaleHead(astro: AstroGlobal, options: LocaleHeadOptions = {
|
|
|
312
309
|
}
|
|
313
310
|
|
|
314
311
|
/**
|
|
315
|
-
* Props
|
|
312
|
+
* Props to pass to client islands (Vue, React, Svelte, Preact)
|
|
316
313
|
*/
|
|
317
314
|
export interface I18nClientProps {
|
|
318
315
|
locale: string
|
|
@@ -322,7 +319,7 @@ export interface I18nClientProps {
|
|
|
322
319
|
}
|
|
323
320
|
|
|
324
321
|
/**
|
|
325
|
-
*
|
|
322
|
+
* Creates a nested structure from a key (e.g. 'islands.vue.title' -> { islands: { vue: { title: value } } })
|
|
326
323
|
*/
|
|
327
324
|
function setNestedValue(obj: Translations, key: string, value: unknown): void {
|
|
328
325
|
const parts = key.split('.')
|
|
@@ -341,30 +338,30 @@ function setNestedValue(obj: Translations, key: string, value: unknown): void {
|
|
|
341
338
|
}
|
|
342
339
|
|
|
343
340
|
/**
|
|
344
|
-
*
|
|
345
|
-
*
|
|
346
|
-
*
|
|
347
|
-
* currentRoute
|
|
341
|
+
* Prepares props to pass to a client island.
|
|
342
|
+
* Accepts a list of keys to pass to the island.
|
|
343
|
+
* Uses i18n methods for proper routesLocaleLinks support.
|
|
344
|
+
* currentRoute is already normalized via middleware (getRouteName), so we use it directly.
|
|
348
345
|
*/
|
|
349
346
|
export function getI18nProps(astro: AstroGlobal, keys?: string[]): I18nClientProps {
|
|
350
347
|
const i18n = getI18n(astro)
|
|
351
348
|
const locale = getLocale(astro)
|
|
352
349
|
const fallbackLocale = getDefaultLocale(astro)
|
|
353
|
-
// currentRoute
|
|
354
|
-
// getRouteName
|
|
350
|
+
// currentRoute is already normalized via middleware.setRoute(getRouteName(...))
|
|
351
|
+
// getRouteName takes routesLocaleLinks into account if configured
|
|
355
352
|
const currentRoute = i18n.getRoute()
|
|
356
353
|
|
|
357
354
|
const translations: Record<string, Translations> = {}
|
|
358
355
|
|
|
359
|
-
//
|
|
356
|
+
// If keys are specified, extract only those from cache
|
|
360
357
|
if (keys && keys.length > 0) {
|
|
361
358
|
const extracted: Translations = {}
|
|
362
359
|
|
|
363
|
-
//
|
|
364
|
-
//
|
|
360
|
+
// Use i18n methods to get translations
|
|
361
|
+
// This guarantees proper routesLocaleLinks support
|
|
365
362
|
for (const key of keys) {
|
|
366
|
-
//
|
|
367
|
-
//
|
|
363
|
+
// Use i18n.t() which internally uses helper.getTranslation
|
|
364
|
+
// and properly resolves the cache key considering routesLocaleLinks
|
|
368
365
|
const value = i18n.t(key, undefined, undefined, currentRoute)
|
|
369
366
|
if (value !== null && value !== undefined && value !== key) {
|
|
370
367
|
setNestedValue(extracted, key, value)
|
|
@@ -375,8 +372,8 @@ export function getI18nProps(astro: AstroGlobal, keys?: string[]): I18nClientPro
|
|
|
375
372
|
translations[currentRoute] = extracted
|
|
376
373
|
}
|
|
377
374
|
} else {
|
|
378
|
-
//
|
|
379
|
-
//
|
|
375
|
+
// If no keys specified, get route-specific translations
|
|
376
|
+
// Use the public getRouteTranslations method for safe access
|
|
380
377
|
const routeTrans = i18n.getRouteTranslations(locale, currentRoute)
|
|
381
378
|
if (routeTrans) {
|
|
382
379
|
translations[currentRoute] = routeTrans
|