@i18n-micro/astro 1.3.7 → 1.3.8
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/composer.d.ts +3 -1
- package/dist/index.cjs +2 -2
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +223 -207
- package/dist/integration.d.ts +1 -2
- package/dist/middleware.d.ts +1 -1
- package/dist/routing-context.d.ts +4 -0
- package/dist/utils.d.ts +10 -2
- package/package.json +10 -13
- package/src/composer.ts +7 -1
- package/src/index.ts +1 -1
- package/src/integration.ts +3 -10
- package/src/middleware.ts +4 -4
- package/src/routing-context.ts +23 -0
- package/src/utils.ts +3 -9
package/dist/composer.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BaseI18n, TranslationStorage } from '@i18n-micro/core';
|
|
1
|
+
import { BaseI18n, DateTimeFormatsConfig, NumberFormatsConfig, TranslationStorage } from '@i18n-micro/core';
|
|
2
2
|
import { PluralFunc, Translations } from '@i18n-micro/types';
|
|
3
3
|
export interface AstroI18nOptions {
|
|
4
4
|
locale: string;
|
|
@@ -7,6 +7,8 @@ export interface AstroI18nOptions {
|
|
|
7
7
|
plural?: PluralFunc;
|
|
8
8
|
missingWarn?: boolean;
|
|
9
9
|
missingHandler?: (locale: string, key: string, routeName: string) => void;
|
|
10
|
+
numberFormats?: NumberFormatsConfig;
|
|
11
|
+
datetimeFormats?: DateTimeFormatsConfig;
|
|
10
12
|
_storage?: TranslationStorage;
|
|
11
13
|
}
|
|
12
14
|
export declare class AstroI18n extends BaseI18n {
|
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 T=require("@i18n-micro/core"),E=require("node:async_hooks"),w=require("node:fs"),R=require("node:path"),B=require("@i18n-micro/utils/parse-path"),z=require("@i18n-micro/utils/accept-language");class j extends T.BaseI18n{constructor(e){const o=e._storage||{translations:new Map};if(super({storage:o,plural:e.plural,missingWarn:e.missingWarn,missingHandler:e.missingHandler,numberFormats:e.numberFormats,datetimeFormats:e.datetimeFormats}),this.initialMessages={},this.storage=o,this._locale=e.locale,this._fallbackLocale=e.fallbackLocale||e.locale,this._currentRoute="index",e.messages){this.initialMessages={...e.messages};for(const[a,i]of Object.entries(e.messages))this.helper.loadTranslations(a,i)}}cloneStorage(e){const o=new Map;for(const[a,i]of e.translations)o.set(a,{...i});return{translations:o}}clone(e){const o=this.cloneStorage(this.storage);return new j({locale:e||this._locale,fallbackLocale:this._fallbackLocale,plural:this.pluralFunc,missingWarn:this.missingWarn,missingHandler:this.missingHandler,numberFormats:this.formatter.getNumberFormats(),datetimeFormats:this.formatter.getDateTimeFormats(),_storage:o})}get locale(){return this._locale}set locale(e){this._locale=e}get fallbackLocale(){return this._fallbackLocale}set fallbackLocale(e){this._fallbackLocale=e}setRoute(e){this._currentRoute=e}getLocale(){return this._locale}getFallbackLocale(){return this._fallbackLocale}getRoute(){return this._currentRoute}getRouteTranslations(e,o){const a=`${e}:${o}`;return this.storage.translations.get(a)??null}addTranslations(e,o,a=!0){super.loadTranslationsCore(e,o,a)}addRouteTranslations(e,o,a,i=!0){super.loadRouteTranslationsCore(e,o,a,i)}mergeTranslations(e,o,a){this.helper.mergeTranslation(e,o,a,!0)}clearCache(){const e={...this.initialMessages};if(super.clearCache(),Object.keys(e).length>0)for(const[o,a]of Object.entries(e))this.helper.loadTranslations(o,a)}}let N=null;const q=new E.AsyncLocalStorage;function D(){const t=q.getStore();return t!==void 0?t:N}function A(t){N=t}function M(t,e){return q.run(t,e)}function x(t){const{locale:e,fallbackLocale:o,translationDir:a,routingStrategy:i}=t;return A(i||null),{name:"@i18n-micro/astro",hooks:{"astro:config:setup":c=>{const{updateConfig:u}=c,s="virtual:i18n-micro/config",r=`\0${s}`,l={defaultLocale:e,fallbackLocale:o||e,locales:t.locales||[],localeCodes:(t.locales||[]).map(n=>n.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(n){if(n===s)return r},load(n){if(n===r)return`export const config = ${JSON.stringify(l)}`}}]}})},"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
|
|
17
|
+
`})}}}}function G(t){return new j(t)}function W(t,e){if(w.existsSync(t))for(const o of w.readdirSync(t)){const a=R.join(t,o);if(w.statSync(a).isDirectory()){W(a,e);continue}o.endsWith(".json")&&e(a)}}function U(t){const{translationDir:e,rootDir:o=process.cwd(),disablePageLocales:a=!1}=t,i=R.resolve(o,e);if(!w.existsSync(i))return console.warn(`[i18n] Translation directory not found: ${i}`),{root:{},routes:{}};const c={root:{},routes:{}};return W(i,u=>{const s=R.relative(i,u).split(R.sep).join("/");try{const r=w.readFileSync(u,"utf-8"),l=JSON.parse(r);B.storeLoadedTranslationFile(c,s,l,a)}catch(r){console.error(`[i18n] Failed to load translation file: ${u}`,r)}}),c}function V(t,e){const{root:o,routes:a}=U(e);for(const[i,c]of Object.entries(o))t.addTranslations(i,c,!1);for(const[i,c]of Object.entries(a))for(const[u,s]of Object.entries(c))t.addRouteTranslations(u,i,B.mergeRouteTranslationsWithRoot(o[u],s),!1)}function J(t){const{i18n:e,defaultLocale:o,locales:a,localeObjects:i,autoDetect:c=!0,redirectToDefault:u=!1,routingStrategy:s}=t,r=s||D();return async(l,n)=>{if(l.locals.locale&&l.locals.i18n)return n();const f=l.url,d=f.pathname;if(!r){const b=e.clone(o),y=d==="/"||d===""?"index":d.split("/").filter(Boolean).join("-");return b.setRoute(y),l.locals.i18n=b,l.locals.locale=o,l.locals.defaultLocale=o,l.locals.locales=i||a.map(S=>({code:S})),l.locals.currentUrl=f,n()}const h={...r,getCurrentPath:()=>d,getRoute:()=>({fullPath:f.pathname+f.search,query:Object.fromEntries(f.searchParams)})},p=d.split("/").filter(Boolean)[0],P=p!==void 0&&a.includes(p);let L;P&&p?L=p:h.getLocaleFromPath?L=h.getLocaleFromPath(d,o,a):L=o;const k=e.clone(L),g=h.getRouteName?h.getRouteName(d,a):"index";return k.setRoute(g),l.locals.i18n=k,l.locals.locale=L,l.locals.defaultLocale=o,l.locals.locales=i||a.map(b=>({code:b})),l.locals.currentUrl=f,l.locals.routingStrategy=h,M(h,()=>n())}}function K(t,e,o,a,i,c="i18n-locale",u){const s=u??D();let r=a;if(s?.getLocaleFromPath)r=s.getLocaleFromPath(t,a,i);else{const n=t.split("/").filter(Boolean)[0];n&&i.includes(n)&&(r=n)}if(c!==null&&r===a&&e.get(c)){const l=e.get(c)?.value;l&&i.includes(l)&&(r=l)}if(r===a)try{const l=z.detectLocaleFromAcceptLanguage(o.get("accept-language")??void 0,i);l&&(r=l)}catch{}return r}function Z(t,e,o){const a=t.map(n=>n.code),i=(n,f=[])=>{const d=n.replace(/^\//,"").replace(/\/$/,"");if(!d)return"index";const h=d.split("/").filter(Boolean),m=h[0];return m&&f.includes(m)&&h.shift(),h.length===0?"index":h.join("-")},c=(n,f="en",d=[])=>{const m=n.split("/").filter(Boolean)[0];return m&&d.includes(m)?m:f},u=(n,f,d=[],h)=>{const m=n.split("/").filter(Boolean),p=m[0];return p&&d.includes(p)&&m.shift(),(f!==h||h===void 0)&&m.unshift(f),`/${m.join("/")}`},s=(n,f,d=[],h)=>{const p=(n.replace(/^\//,"").replace(/\/$/,"")||"").split("/").filter(Boolean),P=p[0];return P&&d.includes(P)&&p.shift(),(f!==h||h===void 0)&&p.unshift(f),`/${p.join("/")}`};return{getCurrentPath:()=>o?o().pathname:typeof window<"u"?window.location.pathname:"/",getRouteName:i,getLocaleFromPath:c,switchLocalePath:u,localizePath:s,removeLocaleFromPath:(n,f=[])=>{const d=n.split("/").filter(Boolean),h=d[0];return h&&f.includes(h)&&d.shift(),`/${d.join("/")}`},resolvePath:(n,f)=>{const d=typeof n=="string"?n:n.path||"/";return s(d,f,a,e)},getRoute:()=>{if(o){const n=o();return{fullPath:n.pathname+n.search,query:Object.fromEntries(n.searchParams)}}if(typeof window<"u"){const n=new URL(window.location.href);return{fullPath:n.pathname+n.search,query:Object.fromEntries(n.searchParams)}}return{fullPath:"/",query:{}}},push:n=>{typeof window<"u"&&(window.location.href=n.path)},replace:n=>{typeof window<"u"&&window.location.replace(n.path)}}}function F(t){const e=t.og?.trim();if(e)return e;const o=t.iso?.trim();if(!o)return null;const a=o.indexOf("_");if(a>0){const c=o.slice(0,a),u=o.slice(a+1);if(c.length>=2&&u.length===2)return`${c.toLowerCase()}_${u.toUpperCase()}`}const i=o.indexOf("-");if(i>0){const c=o.slice(0,i),u=o.slice(i+1);if(c.length>=2&&u.length===2&&/^[A-Za-z]{2}$/.test(u))return`${c.toLowerCase()}_${u.toUpperCase()}`}return null}function C(t,e={}){if(F(t)!==null||e.missingWarn===!1||process.env.NODE_ENV==="production")return;const o=e.tag??"og:locale",a=String(t.code??"unknown"),i=t.iso?`, iso: '${t.iso}'`:"";console.warn(`[i18n] Cannot derive ${o} for locale '${a}'${i}. Set locale.og (e.g. 'en_US') or use iso with a 2-letter region (e.g. 'en-US').`)}function I(t){const e=t.locals.i18n;if(!e)throw new Error("i18n instance not found. Make sure i18n middleware is configured.");return e}function v(t){return t.locals.locale||"en"}function $(t){return t.locals.defaultLocale||"en"}function _(t){return t.locals.locales||[]}function H(t){return t.locals.routingStrategy||null}function Q(t){const e=I(t),o=v(t),a=$(t),i=_(t),c=i.map(s=>s.code),u=H(t);return{locale:o,defaultLocale:a,locales:i,t:(s,r,l,n)=>e.t(s,r,l,n),ts:(s,r,l,n)=>e.ts(s,r,l,n),tc:(s,r,l)=>e.tc(s,r,l),tn:e.tn.bind(e),td:e.td.bind(e),tdr:e.tdr.bind(e),has:(s,r)=>e.has(s,r),getRoute:()=>e.getRoute(),getRouteName:s=>{const r=s||t.url.pathname;if(u?.getRouteName)return u.getRouteName(r,c);const l=r.replace(/^\//,"").replace(/\/$/,"");if(!l)return"index";const n=l.split("/").filter(Boolean),f=n[0];return f&&c.includes(f)&&n.shift(),n.length===0?"index":n.join("-")},getLocaleFromPath:s=>{const r=s||t.url.pathname;if(u?.getLocaleFromPath)return u.getLocaleFromPath(r,a,c);const n=r.split("/").filter(Boolean)[0];return n&&c.includes(n)?n:a},switchLocalePath:s=>{if(u?.switchLocalePath)return u.switchLocalePath(t.url.pathname,s,c,a);const r=t.url.pathname.split("/").filter(Boolean),l=r[0];return l&&c.includes(l)&&r.shift(),s!==a&&r.unshift(s),`/${r.join("/")}`},localizePath:(s,r)=>{if(u?.localizePath)return u.localizePath(s,r||o,c,a);const n=(s.replace(/^\//,"").replace(/\/$/,"")||"").split("/").filter(Boolean),f=n[0];return f&&c.includes(f)&&n.shift(),r&&r!==a&&n.unshift(r),`/${n.join("/")}`},getI18n:()=>e,getBasePath:s=>{const n=(s||t.url).pathname.split("/").filter(Boolean),f=n[0];return f&&c.includes(f)&&n.shift(),n.length>0?`/${n.join("/")}`:"/"},addTranslations:(s,r,l=!0)=>{e.addTranslations(s,r,l)},addRouteTranslations:(s,r,l,n=!0)=>{e.addRouteTranslations(s,r,l,n)},mergeTranslations:(s,r,l)=>{e.mergeTranslations(s,r,l)},clearCache:()=>{e.clearCache()}}}function X(t,e={}){const{baseUrl:o="/",addDirAttribute:a=!0,addSeoAttributes:i=!0}=e,c=v(t),u=$(t),r=_(t).filter(g=>!g.disabled),l=r.filter(g=>g.seo!==!1),n=r.find(g=>g.code===c);if(!n)return{htmlAttrs:{},link:[],meta:[]};const f=n.iso||c,d=F(n),h=n.dir||"auto",m={htmlAttrs:{lang:f,...a?{dir:h}:{}},link:[],meta:[]};if(!i)return m;const p=`${o}${t.url.pathname}`;m.link.push({rel:"canonical",href:p});const P=H(t),L=r.map(g=>g.code);for(const g of l){let b=t.url.pathname;if(P?.switchLocalePath)b=P.switchLocalePath(t.url.pathname,g.code,L,u);else{const S=t.url.pathname.split("/").filter(Boolean),O=S[0];O&&L.includes(O)&&S.shift(),g.code!==u&&S.unshift(g.code),b=`/${S.join("/")}`}const y=`${o}${b}`;m.link.push({rel:"alternate",href:y,hreflang:g.code}),g.iso&&g.iso!==g.code&&m.link.push({rel:"alternate",href:y,hreflang:g.iso})}if(r.find(g=>g.code===u)?.seo!==!1){let g=t.url.pathname;if(P?.switchLocalePath)g=P.switchLocalePath(t.url.pathname,u,L,u);else{const b=t.url.pathname.split("/").filter(Boolean),y=b[0];y&&L.includes(y)&&b.shift(),g=`/${b.join("/")}`}m.link.push({rel:"alternate",href:`${o}${g}`,hreflang:"x-default"})}d?m.meta.push({property:"og:locale",content:d}):C(n,{tag:"og:locale"}),m.meta.push({property:"og:url",content:p});for(const g of l){if(g.code===c)continue;const b=F(g);if(!b){C(g,{tag:"og:locale:alternate"});continue}m.meta.push({property:"og:locale:alternate",content:b})}return m}function Y(t,e,o){const a=e.split(".");let i=t;for(let u=0;u<a.length-1;u++){const s=a[u];i[s]||(i[s]={}),i=i[s]}const c=a[a.length-1];c!==void 0&&(i[c]=o)}function ee(t,e){const o=I(t),a=v(t),i=$(t),c=o.getRoute(),u={};if(e&&e.length>0){const s={};for(const r of e){const l=o.t(r,void 0,void 0,c);l!=null&&l!==r&&Y(s,r,l)}Object.keys(s).length>0&&(u[c]=s)}else{const s=o.getRouteTranslations(a,c);s&&(u[c]=s)}return{locale:a,fallbackLocale:i,currentRoute:c,translations:u}}Object.defineProperty(exports,"FormatService",{enumerable:!0,get:()=>T.FormatService});Object.defineProperty(exports,"defaultPlural",{enumerable:!0,get:()=>T.defaultPlural});Object.defineProperty(exports,"interpolate",{enumerable:!0,get:()=>T.interpolate});exports.AstroI18n=j;exports.createAstroRouterAdapter=Z;exports.createI18n=G;exports.createI18nMiddleware=J;exports.detectLocale=K;exports.getDefaultLocale=$;exports.getGlobalRoutingStrategy=D;exports.getI18n=I;exports.getI18nProps=ee;exports.getLocale=v;exports.getLocales=_;exports.i18nIntegration=x;exports.loadTranslationsFromDir=U;exports.loadTranslationsIntoI18n=V;exports.runWithRoutingStrategy=M;exports.setGlobalRoutingStrategy=A;exports.useI18n=Q;exports.useLocaleHead=X;
|
package/dist/index.d.cts
CHANGED
|
@@ -3,6 +3,7 @@ export type { CleanTranslation, Getter, Locale, LocaleCode, Params, PluralFunc,
|
|
|
3
3
|
export { AstroI18n, type AstroI18nOptions } from './composer';
|
|
4
4
|
export type { I18nIntegrationOptions } from './integration';
|
|
5
5
|
export { createI18n, i18nIntegration } from './integration';
|
|
6
|
+
export { getGlobalRoutingStrategy, runWithRoutingStrategy, setGlobalRoutingStrategy } from './routing-context';
|
|
6
7
|
export type { LoadedTranslations, LoadTranslationsOptions } from './load-translations';
|
|
7
8
|
export { loadTranslationsFromDir, loadTranslationsIntoI18n } from './load-translations';
|
|
8
9
|
export type { I18nMiddlewareOptions } from './middleware';
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export type { CleanTranslation, Getter, Locale, LocaleCode, Params, PluralFunc,
|
|
|
3
3
|
export { AstroI18n, type AstroI18nOptions } from './composer';
|
|
4
4
|
export type { I18nIntegrationOptions } from './integration';
|
|
5
5
|
export { createI18n, i18nIntegration } from './integration';
|
|
6
|
+
export { getGlobalRoutingStrategy, runWithRoutingStrategy, setGlobalRoutingStrategy } from './routing-context';
|
|
6
7
|
export type { LoadedTranslations, LoadTranslationsOptions } from './load-translations';
|
|
7
8
|
export { loadTranslationsFromDir, loadTranslationsIntoI18n } from './load-translations';
|
|
8
9
|
export type { I18nMiddlewareOptions } from './middleware';
|
package/dist/index.mjs
CHANGED
|
@@ -1,40 +1,45 @@
|
|
|
1
|
-
import { BaseI18n as
|
|
2
|
-
import { FormatService as
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
1
|
+
import { BaseI18n as W } from "@i18n-micro/core";
|
|
2
|
+
import { FormatService as pe, defaultPlural as Le, interpolate as Pe } from "@i18n-micro/core";
|
|
3
|
+
import { AsyncLocalStorage as A } from "node:async_hooks";
|
|
4
|
+
import { existsSync as F, readdirSync as M, statSync as U, readFileSync as q } from "node:fs";
|
|
5
|
+
import { resolve as E, join as H, relative as x, sep as z } from "node:path";
|
|
6
|
+
import { mergeRouteTranslationsWithRoot as V, storeLoadedTranslationFile as G } from "@i18n-micro/utils/parse-path";
|
|
7
|
+
import { detectLocaleFromAcceptLanguage as J } from "@i18n-micro/utils/accept-language";
|
|
8
|
+
class T extends W {
|
|
8
9
|
constructor(e) {
|
|
9
|
-
const
|
|
10
|
+
const o = e._storage || {
|
|
10
11
|
translations: /* @__PURE__ */ new Map()
|
|
11
12
|
};
|
|
12
13
|
if (super({
|
|
13
|
-
storage:
|
|
14
|
+
storage: o,
|
|
14
15
|
plural: e.plural,
|
|
15
16
|
missingWarn: e.missingWarn,
|
|
16
|
-
missingHandler: e.missingHandler
|
|
17
|
-
|
|
17
|
+
missingHandler: e.missingHandler,
|
|
18
|
+
numberFormats: e.numberFormats,
|
|
19
|
+
datetimeFormats: e.datetimeFormats
|
|
20
|
+
}), this.initialMessages = {}, this.storage = o, this._locale = e.locale, this._fallbackLocale = e.fallbackLocale || e.locale, this._currentRoute = "index", e.messages) {
|
|
18
21
|
this.initialMessages = { ...e.messages };
|
|
19
|
-
for (const [
|
|
20
|
-
this.helper.loadTranslations(
|
|
22
|
+
for (const [a, i] of Object.entries(e.messages))
|
|
23
|
+
this.helper.loadTranslations(a, i);
|
|
21
24
|
}
|
|
22
25
|
}
|
|
23
26
|
cloneStorage(e) {
|
|
24
|
-
const
|
|
25
|
-
for (const [
|
|
26
|
-
|
|
27
|
-
return { translations:
|
|
27
|
+
const o = /* @__PURE__ */ new Map();
|
|
28
|
+
for (const [a, i] of e.translations)
|
|
29
|
+
o.set(a, { ...i });
|
|
30
|
+
return { translations: o };
|
|
28
31
|
}
|
|
29
32
|
clone(e) {
|
|
30
|
-
const
|
|
33
|
+
const o = this.cloneStorage(this.storage);
|
|
31
34
|
return new T({
|
|
32
35
|
locale: e || this._locale,
|
|
33
36
|
fallbackLocale: this._fallbackLocale,
|
|
34
37
|
plural: this.pluralFunc,
|
|
35
38
|
missingWarn: this.missingWarn,
|
|
36
39
|
missingHandler: this.missingHandler,
|
|
37
|
-
|
|
40
|
+
numberFormats: this.formatter.getNumberFormats(),
|
|
41
|
+
datetimeFormats: this.formatter.getDateTimeFormats(),
|
|
42
|
+
_storage: o
|
|
38
43
|
});
|
|
39
44
|
}
|
|
40
45
|
get locale() {
|
|
@@ -61,43 +66,51 @@ class T extends N {
|
|
|
61
66
|
getRoute() {
|
|
62
67
|
return this._currentRoute;
|
|
63
68
|
}
|
|
64
|
-
getRouteTranslations(e,
|
|
65
|
-
const
|
|
66
|
-
return this.storage.translations.get(
|
|
69
|
+
getRouteTranslations(e, o) {
|
|
70
|
+
const a = `${e}:${o}`;
|
|
71
|
+
return this.storage.translations.get(a) ?? null;
|
|
67
72
|
}
|
|
68
|
-
addTranslations(e,
|
|
69
|
-
super.loadTranslationsCore(e,
|
|
73
|
+
addTranslations(e, o, a = !0) {
|
|
74
|
+
super.loadTranslationsCore(e, o, a);
|
|
70
75
|
}
|
|
71
|
-
addRouteTranslations(e,
|
|
72
|
-
super.loadRouteTranslationsCore(e,
|
|
76
|
+
addRouteTranslations(e, o, a, i = !0) {
|
|
77
|
+
super.loadRouteTranslationsCore(e, o, a, i);
|
|
73
78
|
}
|
|
74
|
-
mergeTranslations(e,
|
|
75
|
-
this.helper.mergeTranslation(e,
|
|
79
|
+
mergeTranslations(e, o, a) {
|
|
80
|
+
this.helper.mergeTranslation(e, o, a, !0);
|
|
76
81
|
}
|
|
77
82
|
clearCache() {
|
|
78
83
|
const e = { ...this.initialMessages };
|
|
79
84
|
if (super.clearCache(), Object.keys(e).length > 0)
|
|
80
|
-
for (const [
|
|
81
|
-
this.helper.loadTranslations(
|
|
85
|
+
for (const [o, a] of Object.entries(e))
|
|
86
|
+
this.helper.loadTranslations(o, a);
|
|
82
87
|
}
|
|
83
88
|
}
|
|
84
|
-
let
|
|
85
|
-
|
|
86
|
-
|
|
89
|
+
let D = null;
|
|
90
|
+
const _ = new A();
|
|
91
|
+
function O() {
|
|
92
|
+
const t = _.getStore();
|
|
93
|
+
return t !== void 0 ? t : D;
|
|
87
94
|
}
|
|
88
|
-
function
|
|
89
|
-
|
|
90
|
-
|
|
95
|
+
function K(t) {
|
|
96
|
+
D = t;
|
|
97
|
+
}
|
|
98
|
+
function Z(t, e) {
|
|
99
|
+
return _.run(t, e);
|
|
100
|
+
}
|
|
101
|
+
function le(t) {
|
|
102
|
+
const { locale: e, fallbackLocale: o, translationDir: a, routingStrategy: i } = t;
|
|
103
|
+
return K(i || null), {
|
|
91
104
|
name: "@i18n-micro/astro",
|
|
92
105
|
hooks: {
|
|
93
106
|
// 1. Vite setup (virtual module) happens here
|
|
94
107
|
"astro:config:setup": (c) => {
|
|
95
|
-
const { updateConfig: u } = c,
|
|
108
|
+
const { updateConfig: u } = c, s = "virtual:i18n-micro/config", l = `\0${s}`, r = {
|
|
96
109
|
defaultLocale: e,
|
|
97
|
-
fallbackLocale:
|
|
110
|
+
fallbackLocale: o || e,
|
|
98
111
|
locales: t.locales || [],
|
|
99
112
|
localeCodes: (t.locales || []).map((n) => n.code),
|
|
100
|
-
translationDir:
|
|
113
|
+
translationDir: a || null,
|
|
101
114
|
autoDetect: t.autoDetect ?? !0,
|
|
102
115
|
redirectToDefault: t.redirectToDefault ?? !1,
|
|
103
116
|
localeCookie: t.localeCookie === null ? null : t.localeCookie || "i18n-locale",
|
|
@@ -109,12 +122,12 @@ function ee(t) {
|
|
|
109
122
|
{
|
|
110
123
|
name: "vite-plugin-i18n-micro-config",
|
|
111
124
|
resolveId(n) {
|
|
112
|
-
if (n ===
|
|
125
|
+
if (n === s)
|
|
113
126
|
return l;
|
|
114
127
|
},
|
|
115
128
|
load(n) {
|
|
116
129
|
if (n === l)
|
|
117
|
-
return `export const config = ${JSON.stringify(
|
|
130
|
+
return `export const config = ${JSON.stringify(r)}`;
|
|
118
131
|
}
|
|
119
132
|
}
|
|
120
133
|
]
|
|
@@ -148,131 +161,131 @@ function ee(t) {
|
|
|
148
161
|
}
|
|
149
162
|
};
|
|
150
163
|
}
|
|
151
|
-
function
|
|
164
|
+
function re(t) {
|
|
152
165
|
return new T(t);
|
|
153
166
|
}
|
|
154
|
-
function
|
|
155
|
-
if (
|
|
156
|
-
for (const
|
|
157
|
-
const
|
|
158
|
-
if (
|
|
159
|
-
|
|
167
|
+
function C(t, e) {
|
|
168
|
+
if (F(t))
|
|
169
|
+
for (const o of M(t)) {
|
|
170
|
+
const a = H(t, o);
|
|
171
|
+
if (U(a).isDirectory()) {
|
|
172
|
+
C(a, e);
|
|
160
173
|
continue;
|
|
161
174
|
}
|
|
162
|
-
|
|
175
|
+
o.endsWith(".json") && e(a);
|
|
163
176
|
}
|
|
164
177
|
}
|
|
165
|
-
function
|
|
166
|
-
const { translationDir: e, rootDir:
|
|
167
|
-
if (!
|
|
178
|
+
function Q(t) {
|
|
179
|
+
const { translationDir: e, rootDir: o = process.cwd(), disablePageLocales: a = !1 } = t, i = E(o, e);
|
|
180
|
+
if (!F(i))
|
|
168
181
|
return console.warn(`[i18n] Translation directory not found: ${i}`), { root: {}, routes: {} };
|
|
169
182
|
const c = { root: {}, routes: {} };
|
|
170
|
-
return
|
|
171
|
-
const
|
|
183
|
+
return C(i, (u) => {
|
|
184
|
+
const s = x(i, u).split(z).join("/");
|
|
172
185
|
try {
|
|
173
|
-
const l =
|
|
174
|
-
|
|
186
|
+
const l = q(u, "utf-8"), r = JSON.parse(l);
|
|
187
|
+
G(c, s, r, a);
|
|
175
188
|
} catch (l) {
|
|
176
189
|
console.error(`[i18n] Failed to load translation file: ${u}`, l);
|
|
177
190
|
}
|
|
178
191
|
}), c;
|
|
179
192
|
}
|
|
180
|
-
function
|
|
181
|
-
const { root:
|
|
182
|
-
for (const [i, c] of Object.entries(
|
|
193
|
+
function se(t, e) {
|
|
194
|
+
const { root: o, routes: a } = Q(e);
|
|
195
|
+
for (const [i, c] of Object.entries(o))
|
|
183
196
|
t.addTranslations(i, c, !1);
|
|
184
|
-
for (const [i, c] of Object.entries(
|
|
185
|
-
for (const [u,
|
|
186
|
-
t.addRouteTranslations(u, i,
|
|
197
|
+
for (const [i, c] of Object.entries(a))
|
|
198
|
+
for (const [u, s] of Object.entries(c))
|
|
199
|
+
t.addRouteTranslations(u, i, V(o[u], s), !1);
|
|
187
200
|
}
|
|
188
|
-
function
|
|
201
|
+
function ie(t) {
|
|
189
202
|
const {
|
|
190
203
|
i18n: e,
|
|
191
204
|
// This is the global singleton with cache
|
|
192
|
-
defaultLocale:
|
|
193
|
-
locales:
|
|
205
|
+
defaultLocale: o,
|
|
206
|
+
locales: a,
|
|
194
207
|
localeObjects: i,
|
|
195
208
|
autoDetect: c = !0,
|
|
196
209
|
redirectToDefault: u = !1,
|
|
197
|
-
routingStrategy:
|
|
198
|
-
} = t, l =
|
|
199
|
-
return async (
|
|
200
|
-
if (
|
|
210
|
+
routingStrategy: s
|
|
211
|
+
} = t, l = s || O();
|
|
212
|
+
return async (r, n) => {
|
|
213
|
+
if (r.locals.locale && r.locals.i18n)
|
|
201
214
|
return n();
|
|
202
|
-
const f =
|
|
215
|
+
const f = r.url, h = f.pathname;
|
|
203
216
|
if (!l) {
|
|
204
|
-
const L = e.clone(
|
|
205
|
-
return L.setRoute(S),
|
|
217
|
+
const L = e.clone(o), S = h === "/" || h === "" ? "index" : h.split("/").filter(Boolean).join("-");
|
|
218
|
+
return L.setRoute(S), r.locals.i18n = L, r.locals.locale = o, r.locals.defaultLocale = o, r.locals.locales = i || a.map((y) => ({ code: y })), r.locals.currentUrl = f, n();
|
|
206
219
|
}
|
|
207
|
-
const
|
|
220
|
+
const d = {
|
|
208
221
|
...l,
|
|
209
222
|
getCurrentPath: () => h,
|
|
210
223
|
getRoute: () => ({
|
|
211
224
|
fullPath: f.pathname + f.search,
|
|
212
225
|
query: Object.fromEntries(f.searchParams)
|
|
213
226
|
})
|
|
214
|
-
}, p = h.split("/").filter(Boolean)[0], b = p !== void 0 &&
|
|
227
|
+
}, p = h.split("/").filter(Boolean)[0], b = p !== void 0 && a.includes(p);
|
|
215
228
|
let P;
|
|
216
|
-
b && p ? P = p :
|
|
217
|
-
const w = e.clone(P), g =
|
|
218
|
-
return w.setRoute(g),
|
|
229
|
+
b && p ? P = p : d.getLocaleFromPath ? P = d.getLocaleFromPath(h, o, a) : P = o;
|
|
230
|
+
const w = e.clone(P), g = d.getRouteName ? d.getRouteName(h, a) : "index";
|
|
231
|
+
return w.setRoute(g), r.locals.i18n = w, r.locals.locale = P, r.locals.defaultLocale = o, r.locals.locales = i || a.map((L) => ({ code: L })), r.locals.currentUrl = f, r.locals.routingStrategy = d, Z(d, () => n());
|
|
219
232
|
};
|
|
220
233
|
}
|
|
221
|
-
function
|
|
222
|
-
const
|
|
223
|
-
let
|
|
224
|
-
if (
|
|
225
|
-
|
|
234
|
+
function ce(t, e, o, a, i, c = "i18n-locale", u) {
|
|
235
|
+
const s = u ?? O();
|
|
236
|
+
let l = a;
|
|
237
|
+
if (s?.getLocaleFromPath)
|
|
238
|
+
l = s.getLocaleFromPath(t, a, i);
|
|
226
239
|
else {
|
|
227
|
-
const
|
|
228
|
-
|
|
240
|
+
const n = t.split("/").filter(Boolean)[0];
|
|
241
|
+
n && i.includes(n) && (l = n);
|
|
229
242
|
}
|
|
230
|
-
if (c !== null &&
|
|
231
|
-
const
|
|
232
|
-
|
|
243
|
+
if (c !== null && l === a && e.get(c)) {
|
|
244
|
+
const r = e.get(c)?.value;
|
|
245
|
+
r && i.includes(r) && (l = r);
|
|
233
246
|
}
|
|
234
|
-
if (
|
|
247
|
+
if (l === a)
|
|
235
248
|
try {
|
|
236
|
-
const
|
|
237
|
-
|
|
249
|
+
const r = J(o.get("accept-language") ?? void 0, i);
|
|
250
|
+
r && (l = r);
|
|
238
251
|
} catch {
|
|
239
252
|
}
|
|
240
|
-
return
|
|
253
|
+
return l;
|
|
241
254
|
}
|
|
242
|
-
function
|
|
243
|
-
const
|
|
255
|
+
function ue(t, e, o) {
|
|
256
|
+
const a = t.map((n) => n.code), i = (n, f = []) => {
|
|
244
257
|
const h = n.replace(/^\//, "").replace(/\/$/, "");
|
|
245
258
|
if (!h)
|
|
246
259
|
return "index";
|
|
247
|
-
const
|
|
248
|
-
return
|
|
260
|
+
const d = h.split("/").filter(Boolean), m = d[0];
|
|
261
|
+
return m && f.includes(m) && d.shift(), d.length === 0 ? "index" : d.join("-");
|
|
249
262
|
}, c = (n, f = "en", h = []) => {
|
|
250
|
-
const
|
|
251
|
-
return
|
|
252
|
-
}, u = (n, f, h = [],
|
|
253
|
-
const
|
|
254
|
-
return p && h.includes(p) &&
|
|
255
|
-
},
|
|
263
|
+
const m = n.split("/").filter(Boolean)[0];
|
|
264
|
+
return m && h.includes(m) ? m : f;
|
|
265
|
+
}, u = (n, f, h = [], d) => {
|
|
266
|
+
const m = n.split("/").filter(Boolean), p = m[0];
|
|
267
|
+
return p && h.includes(p) && m.shift(), (f !== d || d === void 0) && m.unshift(f), `/${m.join("/")}`;
|
|
268
|
+
}, s = (n, f, h = [], d) => {
|
|
256
269
|
const p = (n.replace(/^\//, "").replace(/\/$/, "") || "").split("/").filter(Boolean), b = p[0];
|
|
257
|
-
return b && h.includes(b) && p.shift(), (f !==
|
|
270
|
+
return b && h.includes(b) && p.shift(), (f !== d || d === void 0) && p.unshift(f), `/${p.join("/")}`;
|
|
258
271
|
};
|
|
259
272
|
return {
|
|
260
|
-
getCurrentPath: () =>
|
|
273
|
+
getCurrentPath: () => o ? o().pathname : typeof window < "u" ? window.location.pathname : "/",
|
|
261
274
|
getRouteName: i,
|
|
262
275
|
getLocaleFromPath: c,
|
|
263
276
|
switchLocalePath: u,
|
|
264
|
-
localizePath:
|
|
277
|
+
localizePath: s,
|
|
265
278
|
removeLocaleFromPath: (n, f = []) => {
|
|
266
|
-
const h = n.split("/").filter(Boolean),
|
|
267
|
-
return
|
|
279
|
+
const h = n.split("/").filter(Boolean), d = h[0];
|
|
280
|
+
return d && f.includes(d) && h.shift(), `/${h.join("/")}`;
|
|
268
281
|
},
|
|
269
282
|
resolvePath: (n, f) => {
|
|
270
283
|
const h = typeof n == "string" ? n : n.path || "/";
|
|
271
|
-
return
|
|
284
|
+
return s(h, f, a, e);
|
|
272
285
|
},
|
|
273
286
|
getRoute: () => {
|
|
274
|
-
if (
|
|
275
|
-
const n =
|
|
287
|
+
if (o) {
|
|
288
|
+
const n = o();
|
|
276
289
|
return {
|
|
277
290
|
fullPath: n.pathname + n.search,
|
|
278
291
|
query: Object.fromEntries(n.searchParams)
|
|
@@ -302,17 +315,17 @@ function le(t, e, a) {
|
|
|
302
315
|
function R(t) {
|
|
303
316
|
const e = t.og?.trim();
|
|
304
317
|
if (e) return e;
|
|
305
|
-
const
|
|
306
|
-
if (!
|
|
307
|
-
const
|
|
308
|
-
if (
|
|
309
|
-
const c =
|
|
318
|
+
const o = t.iso?.trim();
|
|
319
|
+
if (!o) return null;
|
|
320
|
+
const a = o.indexOf("_");
|
|
321
|
+
if (a > 0) {
|
|
322
|
+
const c = o.slice(0, a), u = o.slice(a + 1);
|
|
310
323
|
if (c.length >= 2 && u.length === 2)
|
|
311
324
|
return `${c.toLowerCase()}_${u.toUpperCase()}`;
|
|
312
325
|
}
|
|
313
|
-
const i =
|
|
326
|
+
const i = o.indexOf("-");
|
|
314
327
|
if (i > 0) {
|
|
315
|
-
const c =
|
|
328
|
+
const c = o.slice(0, i), u = o.slice(i + 1);
|
|
316
329
|
if (c.length >= 2 && u.length === 2 && /^[A-Za-z]{2}$/.test(u))
|
|
317
330
|
return `${c.toLowerCase()}_${u.toUpperCase()}`;
|
|
318
331
|
}
|
|
@@ -320,12 +333,12 @@ function R(t) {
|
|
|
320
333
|
}
|
|
321
334
|
function k(t, e = {}) {
|
|
322
335
|
if (R(t) !== null || e.missingWarn === !1 || process.env.NODE_ENV === "production") return;
|
|
323
|
-
const
|
|
336
|
+
const o = e.tag ?? "og:locale", a = String(t.code ?? "unknown"), i = t.iso ? `, iso: '${t.iso}'` : "";
|
|
324
337
|
console.warn(
|
|
325
|
-
`[i18n] Cannot derive ${
|
|
338
|
+
`[i18n] Cannot derive ${o} for locale '${a}'${i}. Set locale.og (e.g. 'en_US') or use iso with a 2-letter region (e.g. 'en-US').`
|
|
326
339
|
);
|
|
327
340
|
}
|
|
328
|
-
function
|
|
341
|
+
function B(t) {
|
|
329
342
|
const e = t.locals.i18n;
|
|
330
343
|
if (!e)
|
|
331
344
|
throw new Error("i18n instance not found. Make sure i18n middleware is configured.");
|
|
@@ -337,101 +350,101 @@ function $(t) {
|
|
|
337
350
|
function v(t) {
|
|
338
351
|
return t.locals.defaultLocale || "en";
|
|
339
352
|
}
|
|
340
|
-
function
|
|
353
|
+
function I(t) {
|
|
341
354
|
return t.locals.locales || [];
|
|
342
355
|
}
|
|
343
|
-
function
|
|
356
|
+
function N(t) {
|
|
344
357
|
return t.locals.routingStrategy || null;
|
|
345
358
|
}
|
|
346
|
-
function
|
|
347
|
-
const e =
|
|
359
|
+
function fe(t) {
|
|
360
|
+
const e = B(t), o = $(t), a = v(t), i = I(t), c = i.map((s) => s.code), u = N(t);
|
|
348
361
|
return {
|
|
349
362
|
// Current locale
|
|
350
|
-
locale:
|
|
351
|
-
defaultLocale:
|
|
363
|
+
locale: o,
|
|
364
|
+
defaultLocale: a,
|
|
352
365
|
locales: i,
|
|
353
366
|
// Translation methods
|
|
354
|
-
t: (
|
|
355
|
-
ts: (
|
|
356
|
-
tc: (
|
|
357
|
-
tn:
|
|
358
|
-
td:
|
|
359
|
-
tdr:
|
|
360
|
-
has: (
|
|
367
|
+
t: (s, l, r, n) => e.t(s, l, r, n),
|
|
368
|
+
ts: (s, l, r, n) => e.ts(s, l, r, n),
|
|
369
|
+
tc: (s, l, r) => e.tc(s, l, r),
|
|
370
|
+
tn: e.tn.bind(e),
|
|
371
|
+
td: e.td.bind(e),
|
|
372
|
+
tdr: e.tdr.bind(e),
|
|
373
|
+
has: (s, l) => e.has(s, l),
|
|
361
374
|
// Route management
|
|
362
375
|
getRoute: () => e.getRoute(),
|
|
363
|
-
getRouteName: (
|
|
364
|
-
const l =
|
|
376
|
+
getRouteName: (s) => {
|
|
377
|
+
const l = s || t.url.pathname;
|
|
365
378
|
if (u?.getRouteName)
|
|
366
379
|
return u.getRouteName(l, c);
|
|
367
|
-
const
|
|
368
|
-
if (!
|
|
369
|
-
const n =
|
|
380
|
+
const r = l.replace(/^\//, "").replace(/\/$/, "");
|
|
381
|
+
if (!r) return "index";
|
|
382
|
+
const n = r.split("/").filter(Boolean), f = n[0];
|
|
370
383
|
return f && c.includes(f) && n.shift(), n.length === 0 ? "index" : n.join("-");
|
|
371
384
|
},
|
|
372
|
-
getLocaleFromPath: (
|
|
373
|
-
const l =
|
|
385
|
+
getLocaleFromPath: (s) => {
|
|
386
|
+
const l = s || t.url.pathname;
|
|
374
387
|
if (u?.getLocaleFromPath)
|
|
375
|
-
return u.getLocaleFromPath(l,
|
|
388
|
+
return u.getLocaleFromPath(l, a, c);
|
|
376
389
|
const n = l.split("/").filter(Boolean)[0];
|
|
377
|
-
return n && c.includes(n) ? n :
|
|
390
|
+
return n && c.includes(n) ? n : a;
|
|
378
391
|
},
|
|
379
392
|
// Path utilities
|
|
380
|
-
switchLocalePath: (
|
|
393
|
+
switchLocalePath: (s) => {
|
|
381
394
|
if (u?.switchLocalePath)
|
|
382
|
-
return u.switchLocalePath(t.url.pathname,
|
|
383
|
-
const l = t.url.pathname.split("/").filter(Boolean),
|
|
384
|
-
return
|
|
395
|
+
return u.switchLocalePath(t.url.pathname, s, c, a);
|
|
396
|
+
const l = t.url.pathname.split("/").filter(Boolean), r = l[0];
|
|
397
|
+
return r && c.includes(r) && l.shift(), s !== a && l.unshift(s), `/${l.join("/")}`;
|
|
385
398
|
},
|
|
386
|
-
localizePath: (
|
|
399
|
+
localizePath: (s, l) => {
|
|
387
400
|
if (u?.localizePath)
|
|
388
|
-
return u.localizePath(
|
|
389
|
-
const n = (
|
|
390
|
-
return f && c.includes(f) && n.shift(), l && l !==
|
|
401
|
+
return u.localizePath(s, l || o, c, a);
|
|
402
|
+
const n = (s.replace(/^\//, "").replace(/\/$/, "") || "").split("/").filter(Boolean), f = n[0];
|
|
403
|
+
return f && c.includes(f) && n.shift(), l && l !== a && n.unshift(l), `/${n.join("/")}`;
|
|
391
404
|
},
|
|
392
405
|
// Get i18n instance
|
|
393
406
|
getI18n: () => e,
|
|
394
407
|
// Get base path without locale (for rewrite)
|
|
395
|
-
getBasePath: (
|
|
396
|
-
const n = (
|
|
408
|
+
getBasePath: (s) => {
|
|
409
|
+
const n = (s || t.url).pathname.split("/").filter(Boolean), f = n[0];
|
|
397
410
|
return f && c.includes(f) && n.shift(), n.length > 0 ? `/${n.join("/")}` : "/";
|
|
398
411
|
},
|
|
399
412
|
// Translation management
|
|
400
|
-
addTranslations: (
|
|
401
|
-
e.addTranslations(
|
|
413
|
+
addTranslations: (s, l, r = !0) => {
|
|
414
|
+
e.addTranslations(s, l, r);
|
|
402
415
|
},
|
|
403
|
-
addRouteTranslations: (
|
|
404
|
-
e.addRouteTranslations(
|
|
416
|
+
addRouteTranslations: (s, l, r, n = !0) => {
|
|
417
|
+
e.addRouteTranslations(s, l, r, n);
|
|
405
418
|
},
|
|
406
|
-
mergeTranslations: (
|
|
407
|
-
e.mergeTranslations(
|
|
419
|
+
mergeTranslations: (s, l, r) => {
|
|
420
|
+
e.mergeTranslations(s, l, r);
|
|
408
421
|
},
|
|
409
422
|
clearCache: () => {
|
|
410
423
|
e.clearCache();
|
|
411
424
|
}
|
|
412
425
|
};
|
|
413
426
|
}
|
|
414
|
-
function
|
|
415
|
-
const { baseUrl:
|
|
427
|
+
function ge(t, e = {}) {
|
|
428
|
+
const { baseUrl: o = "/", addDirAttribute: a = !0, addSeoAttributes: i = !0 } = e, c = $(t), u = v(t), l = I(t).filter((g) => !g.disabled), r = l.filter((g) => g.seo !== !1), n = l.find((g) => g.code === c);
|
|
416
429
|
if (!n)
|
|
417
430
|
return { htmlAttrs: {}, link: [], meta: [] };
|
|
418
|
-
const f = n.iso || c, h = R(n),
|
|
431
|
+
const f = n.iso || c, h = R(n), d = n.dir || "auto", m = {
|
|
419
432
|
htmlAttrs: {
|
|
420
433
|
lang: f,
|
|
421
|
-
...
|
|
434
|
+
...a ? { dir: d } : {}
|
|
422
435
|
},
|
|
423
436
|
link: [],
|
|
424
437
|
meta: []
|
|
425
438
|
};
|
|
426
439
|
if (!i)
|
|
427
|
-
return
|
|
428
|
-
const p = `${
|
|
429
|
-
|
|
440
|
+
return m;
|
|
441
|
+
const p = `${o}${t.url.pathname}`;
|
|
442
|
+
m.link.push({
|
|
430
443
|
rel: "canonical",
|
|
431
444
|
href: p
|
|
432
445
|
});
|
|
433
|
-
const b =
|
|
434
|
-
for (const g of
|
|
446
|
+
const b = N(t), P = l.map((g) => g.code);
|
|
447
|
+
for (const g of r) {
|
|
435
448
|
let L = t.url.pathname;
|
|
436
449
|
if (b?.switchLocalePath)
|
|
437
450
|
L = b.switchLocalePath(t.url.pathname, g.code, P, u);
|
|
@@ -439,12 +452,12 @@ function se(t, e = {}) {
|
|
|
439
452
|
const y = t.url.pathname.split("/").filter(Boolean), j = y[0];
|
|
440
453
|
j && P.includes(j) && y.shift(), g.code !== u && y.unshift(g.code), L = `/${y.join("/")}`;
|
|
441
454
|
}
|
|
442
|
-
const S = `${
|
|
443
|
-
|
|
455
|
+
const S = `${o}${L}`;
|
|
456
|
+
m.link.push({
|
|
444
457
|
rel: "alternate",
|
|
445
458
|
href: S,
|
|
446
459
|
hreflang: g.code
|
|
447
|
-
}), g.iso && g.iso !== g.code &&
|
|
460
|
+
}), g.iso && g.iso !== g.code && m.link.push({
|
|
448
461
|
rel: "alternate",
|
|
449
462
|
href: S,
|
|
450
463
|
hreflang: g.iso
|
|
@@ -458,58 +471,58 @@ function se(t, e = {}) {
|
|
|
458
471
|
const L = t.url.pathname.split("/").filter(Boolean), S = L[0];
|
|
459
472
|
S && P.includes(S) && L.shift(), g = `/${L.join("/")}`;
|
|
460
473
|
}
|
|
461
|
-
|
|
474
|
+
m.link.push({
|
|
462
475
|
rel: "alternate",
|
|
463
|
-
href: `${
|
|
476
|
+
href: `${o}${g}`,
|
|
464
477
|
hreflang: "x-default"
|
|
465
478
|
});
|
|
466
479
|
}
|
|
467
|
-
h ?
|
|
480
|
+
h ? m.meta.push({
|
|
468
481
|
property: "og:locale",
|
|
469
482
|
content: h
|
|
470
|
-
}) : k(n, { tag: "og:locale" }),
|
|
483
|
+
}) : k(n, { tag: "og:locale" }), m.meta.push({
|
|
471
484
|
property: "og:url",
|
|
472
485
|
content: p
|
|
473
486
|
});
|
|
474
|
-
for (const g of
|
|
487
|
+
for (const g of r) {
|
|
475
488
|
if (g.code === c) continue;
|
|
476
489
|
const L = R(g);
|
|
477
490
|
if (!L) {
|
|
478
491
|
k(g, { tag: "og:locale:alternate" });
|
|
479
492
|
continue;
|
|
480
493
|
}
|
|
481
|
-
|
|
494
|
+
m.meta.push({
|
|
482
495
|
property: "og:locale:alternate",
|
|
483
496
|
content: L
|
|
484
497
|
});
|
|
485
498
|
}
|
|
486
|
-
return
|
|
499
|
+
return m;
|
|
487
500
|
}
|
|
488
|
-
function
|
|
489
|
-
const
|
|
501
|
+
function X(t, e, o) {
|
|
502
|
+
const a = e.split(".");
|
|
490
503
|
let i = t;
|
|
491
|
-
for (let u = 0; u <
|
|
492
|
-
const
|
|
493
|
-
i[
|
|
504
|
+
for (let u = 0; u < a.length - 1; u++) {
|
|
505
|
+
const s = a[u];
|
|
506
|
+
i[s] || (i[s] = {}), i = i[s];
|
|
494
507
|
}
|
|
495
|
-
const c =
|
|
496
|
-
c !== void 0 && (i[c] =
|
|
508
|
+
const c = a[a.length - 1];
|
|
509
|
+
c !== void 0 && (i[c] = o);
|
|
497
510
|
}
|
|
498
|
-
function
|
|
499
|
-
const
|
|
511
|
+
function he(t, e) {
|
|
512
|
+
const o = B(t), a = $(t), i = v(t), c = o.getRoute(), u = {};
|
|
500
513
|
if (e && e.length > 0) {
|
|
501
|
-
const
|
|
514
|
+
const s = {};
|
|
502
515
|
for (const l of e) {
|
|
503
|
-
const
|
|
504
|
-
|
|
516
|
+
const r = o.t(l, void 0, void 0, c);
|
|
517
|
+
r != null && r !== l && X(s, l, r);
|
|
505
518
|
}
|
|
506
|
-
Object.keys(
|
|
519
|
+
Object.keys(s).length > 0 && (u[c] = s);
|
|
507
520
|
} else {
|
|
508
|
-
const
|
|
509
|
-
|
|
521
|
+
const s = o.getRouteTranslations(a, c);
|
|
522
|
+
s && (u[c] = s);
|
|
510
523
|
}
|
|
511
524
|
return {
|
|
512
|
-
locale:
|
|
525
|
+
locale: a,
|
|
513
526
|
fallbackLocale: i,
|
|
514
527
|
currentRoute: c,
|
|
515
528
|
translations: u
|
|
@@ -517,21 +530,24 @@ function ie(t, e) {
|
|
|
517
530
|
}
|
|
518
531
|
export {
|
|
519
532
|
T as AstroI18n,
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
533
|
+
pe as FormatService,
|
|
534
|
+
ue as createAstroRouterAdapter,
|
|
535
|
+
re as createI18n,
|
|
536
|
+
ie as createI18nMiddleware,
|
|
537
|
+
Le as defaultPlural,
|
|
538
|
+
ce as detectLocale,
|
|
526
539
|
v as getDefaultLocale,
|
|
527
|
-
|
|
528
|
-
|
|
540
|
+
O as getGlobalRoutingStrategy,
|
|
541
|
+
B as getI18n,
|
|
542
|
+
he as getI18nProps,
|
|
529
543
|
$ as getLocale,
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
544
|
+
I as getLocales,
|
|
545
|
+
le as i18nIntegration,
|
|
546
|
+
Pe as interpolate,
|
|
547
|
+
Q as loadTranslationsFromDir,
|
|
548
|
+
se as loadTranslationsIntoI18n,
|
|
549
|
+
Z as runWithRoutingStrategy,
|
|
550
|
+
K as setGlobalRoutingStrategy,
|
|
551
|
+
fe as useI18n,
|
|
552
|
+
ge as useLocaleHead
|
|
537
553
|
};
|
package/dist/integration.d.ts
CHANGED
|
@@ -16,8 +16,7 @@ export interface I18nIntegrationOptions extends Omit<ModuleOptions, 'plural'> {
|
|
|
16
16
|
translationDir?: string;
|
|
17
17
|
routingStrategy?: I18nRoutingStrategy;
|
|
18
18
|
}
|
|
19
|
-
export
|
|
20
|
-
export declare function setGlobalRoutingStrategy(strategy: I18nRoutingStrategy | null): void;
|
|
19
|
+
export { getGlobalRoutingStrategy, runWithRoutingStrategy, setGlobalRoutingStrategy } from './routing-context';
|
|
21
20
|
/**
|
|
22
21
|
* Astro Integration for i18n-micro
|
|
23
22
|
*/
|
package/dist/middleware.d.ts
CHANGED
|
@@ -22,4 +22,4 @@ export declare function detectLocale(pathname: string, cookies: {
|
|
|
22
22
|
get: (name: string) => {
|
|
23
23
|
value: string;
|
|
24
24
|
} | undefined;
|
|
25
|
-
}, headers: Headers, defaultLocale: string, locales: string[], localeCookie?: string | null): string;
|
|
25
|
+
}, headers: Headers, defaultLocale: string, locales: string[], localeCookie?: string | null, routingStrategy?: I18nRoutingStrategy | null): string;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { I18nRoutingStrategy } from './router/types';
|
|
2
|
+
export declare function getGlobalRoutingStrategy(): I18nRoutingStrategy | null;
|
|
3
|
+
export declare function setGlobalRoutingStrategy(strategy: I18nRoutingStrategy | null): void;
|
|
4
|
+
export declare function runWithRoutingStrategy<T>(strategy: I18nRoutingStrategy | null, fn: () => T): T;
|
package/dist/utils.d.ts
CHANGED
|
@@ -28,8 +28,16 @@ export declare function useI18n(astro: AstroGlobal): {
|
|
|
28
28
|
t: (key: TranslationKey, params?: Params, defaultValue?: string | null, routeName?: string) => CleanTranslation;
|
|
29
29
|
ts: (key: TranslationKey, params?: Params, defaultValue?: string, routeName?: string) => string;
|
|
30
30
|
tc: (key: TranslationKey, count: number | Params, defaultValue?: string) => string;
|
|
31
|
-
tn:
|
|
32
|
-
|
|
31
|
+
tn: {
|
|
32
|
+
(value: number, options?: Intl.NumberFormatOptions): string;
|
|
33
|
+
(value: number, key: string, overrides?: Intl.NumberFormatOptions): string;
|
|
34
|
+
(value: number, key: string, locale: string, overrides?: Intl.NumberFormatOptions): string;
|
|
35
|
+
};
|
|
36
|
+
td: {
|
|
37
|
+
(value: Date | number | string, options?: Intl.DateTimeFormatOptions): string;
|
|
38
|
+
(value: Date | number | string, key: string, overrides?: Intl.DateTimeFormatOptions): string;
|
|
39
|
+
(value: Date | number | string, key: string, locale: string, overrides?: Intl.DateTimeFormatOptions): string;
|
|
40
|
+
};
|
|
33
41
|
tdr: (value: Date | number | string, options?: Intl.RelativeTimeFormatOptions) => string;
|
|
34
42
|
has: (key: TranslationKey, routeName?: string) => boolean;
|
|
35
43
|
getRoute: () => string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@i18n-micro/astro",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.8",
|
|
4
4
|
"description": "Astro integration for i18n-micro — translations, routing, and islands.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"astro",
|
|
@@ -77,27 +77,24 @@
|
|
|
77
77
|
"access": "public"
|
|
78
78
|
},
|
|
79
79
|
"dependencies": {
|
|
80
|
-
"@i18n-micro/
|
|
81
|
-
"@i18n-micro/
|
|
82
|
-
"@i18n-micro/utils": "1.0.
|
|
83
|
-
"@i18n-micro/node": "1.2.
|
|
80
|
+
"@i18n-micro/types": "1.2.7",
|
|
81
|
+
"@i18n-micro/core": "1.3.8",
|
|
82
|
+
"@i18n-micro/utils": "1.0.8",
|
|
83
|
+
"@i18n-micro/node": "1.2.4"
|
|
84
84
|
},
|
|
85
85
|
"devDependencies": {
|
|
86
|
-
"
|
|
87
|
-
"astro": "^5.16.5",
|
|
88
|
-
"jest": "^29.7.0",
|
|
86
|
+
"astro": "^5.0.0 || ^6.0.0 || ^7.0.0",
|
|
89
87
|
"preact": "^10.0.0",
|
|
90
88
|
"publint": "^0.3.17",
|
|
91
89
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
92
90
|
"svelte": "^4.0.0 || ^5.0.0",
|
|
93
|
-
"
|
|
94
|
-
"vite": "^7.3.1",
|
|
91
|
+
"vite": "^7.3.6",
|
|
95
92
|
"vite-plugin-dts": "^4.5.4",
|
|
96
|
-
"vitest": "^
|
|
93
|
+
"vitest": "^4.1.10",
|
|
97
94
|
"vue": "^3.5.25"
|
|
98
95
|
},
|
|
99
96
|
"peerDependencies": {
|
|
100
|
-
"astro": "^5.
|
|
97
|
+
"astro": "^5.0.0 || ^6.0.0 || ^7.0.0",
|
|
101
98
|
"preact": "^10.0.0",
|
|
102
99
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
103
100
|
"svelte": "^4.0.0 || ^5.0.0",
|
|
@@ -124,7 +121,7 @@
|
|
|
124
121
|
"build": "vite build",
|
|
125
122
|
"check:package": "publint",
|
|
126
123
|
"dev": "cd playground && astro dev",
|
|
127
|
-
"test": "
|
|
124
|
+
"test": "vitest run",
|
|
128
125
|
"test:dist": "vitest run --config vitest.dist.config.ts",
|
|
129
126
|
"typecheck": "tsc --noEmit"
|
|
130
127
|
}
|
package/src/composer.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BaseI18n, type TranslationStorage } from '@i18n-micro/core'
|
|
1
|
+
import { BaseI18n, type DateTimeFormatsConfig, type NumberFormatsConfig, type TranslationStorage } from '@i18n-micro/core'
|
|
2
2
|
import type { PluralFunc, Translations } from '@i18n-micro/types'
|
|
3
3
|
|
|
4
4
|
export interface AstroI18nOptions {
|
|
@@ -8,6 +8,8 @@ export interface AstroI18nOptions {
|
|
|
8
8
|
plural?: PluralFunc
|
|
9
9
|
missingWarn?: boolean
|
|
10
10
|
missingHandler?: (locale: string, key: string, routeName: string) => void
|
|
11
|
+
numberFormats?: NumberFormatsConfig
|
|
12
|
+
datetimeFormats?: DateTimeFormatsConfig
|
|
11
13
|
_storage?: TranslationStorage
|
|
12
14
|
}
|
|
13
15
|
|
|
@@ -30,6 +32,8 @@ export class AstroI18n extends BaseI18n {
|
|
|
30
32
|
plural: options.plural,
|
|
31
33
|
missingWarn: options.missingWarn,
|
|
32
34
|
missingHandler: options.missingHandler,
|
|
35
|
+
numberFormats: options.numberFormats,
|
|
36
|
+
datetimeFormats: options.datetimeFormats,
|
|
33
37
|
})
|
|
34
38
|
|
|
35
39
|
this.storage = storage
|
|
@@ -62,6 +66,8 @@ export class AstroI18n extends BaseI18n {
|
|
|
62
66
|
plural: this.pluralFunc,
|
|
63
67
|
missingWarn: this.missingWarn,
|
|
64
68
|
missingHandler: this.missingHandler,
|
|
69
|
+
numberFormats: this.formatter.getNumberFormats(),
|
|
70
|
+
datetimeFormats: this.formatter.getDateTimeFormats(),
|
|
65
71
|
_storage: isolatedStorage,
|
|
66
72
|
})
|
|
67
73
|
}
|
package/src/index.ts
CHANGED
|
@@ -8,8 +8,8 @@ export type { CleanTranslation, Getter, Locale, LocaleCode, Params, PluralFunc,
|
|
|
8
8
|
export { AstroI18n, type AstroI18nOptions } from './composer'
|
|
9
9
|
// Export integration options type
|
|
10
10
|
export type { I18nIntegrationOptions } from './integration'
|
|
11
|
-
// Main exports
|
|
12
11
|
export { createI18n, i18nIntegration } from './integration'
|
|
12
|
+
export { getGlobalRoutingStrategy, runWithRoutingStrategy, setGlobalRoutingStrategy } from './routing-context'
|
|
13
13
|
export type { LoadedTranslations, LoadTranslationsOptions } from './load-translations'
|
|
14
14
|
// Export translation loading utilities
|
|
15
15
|
export { loadTranslationsFromDir, loadTranslationsIntoI18n } from './load-translations'
|
package/src/integration.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Locale, ModuleOptions, PluralFunc } from '@i18n-micro/types'
|
|
2
2
|
import type { AstroIntegration, HookParameters } from 'astro'
|
|
3
3
|
import { AstroI18n, type AstroI18nOptions } from './composer'
|
|
4
|
+
import { setGlobalRoutingStrategy } from './routing-context'
|
|
4
5
|
import type { I18nRoutingStrategy } from './router/types'
|
|
5
6
|
|
|
6
7
|
export interface I18nIntegrationOptions extends Omit<ModuleOptions, 'plural'> {
|
|
@@ -18,15 +19,7 @@ export interface I18nIntegrationOptions extends Omit<ModuleOptions, 'plural'> {
|
|
|
18
19
|
routingStrategy?: I18nRoutingStrategy
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
export function getGlobalRoutingStrategy(): I18nRoutingStrategy | null {
|
|
24
|
-
return globalRoutingStrategy
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function setGlobalRoutingStrategy(strategy: I18nRoutingStrategy | null): void {
|
|
28
|
-
globalRoutingStrategy = strategy
|
|
29
|
-
}
|
|
22
|
+
export { getGlobalRoutingStrategy, runWithRoutingStrategy, setGlobalRoutingStrategy } from './routing-context'
|
|
30
23
|
|
|
31
24
|
/**
|
|
32
25
|
* Astro Integration for i18n-micro
|
|
@@ -34,7 +27,7 @@ export function setGlobalRoutingStrategy(strategy: I18nRoutingStrategy | null):
|
|
|
34
27
|
export function i18nIntegration(options: I18nIntegrationOptions): AstroIntegration {
|
|
35
28
|
const { locale: defaultLocale, fallbackLocale, translationDir, routingStrategy } = options
|
|
36
29
|
|
|
37
|
-
|
|
30
|
+
setGlobalRoutingStrategy(routingStrategy || null)
|
|
38
31
|
|
|
39
32
|
return {
|
|
40
33
|
name: '@i18n-micro/astro',
|
package/src/middleware.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { Locale } from '@i18n-micro/types'
|
|
|
2
2
|
import { detectLocaleFromAcceptLanguage } from '@i18n-micro/utils/accept-language'
|
|
3
3
|
import type { MiddlewareHandler } from 'astro'
|
|
4
4
|
import type { AstroI18n } from './composer'
|
|
5
|
-
import { getGlobalRoutingStrategy } from './
|
|
5
|
+
import { getGlobalRoutingStrategy, runWithRoutingStrategy } from './routing-context'
|
|
6
6
|
import type { I18nRoutingStrategy } from './router/types'
|
|
7
7
|
// Import shim to ensure App.Locals is available
|
|
8
8
|
import './env.d'
|
|
@@ -106,7 +106,7 @@ export function createI18nMiddleware(options: I18nMiddlewareOptions): Middleware
|
|
|
106
106
|
context.locals.currentUrl = url
|
|
107
107
|
context.locals.routingStrategy = contextStrategy
|
|
108
108
|
|
|
109
|
-
return next()
|
|
109
|
+
return runWithRoutingStrategy(contextStrategy, () => next())
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
|
|
@@ -120,9 +120,9 @@ export function detectLocale(
|
|
|
120
120
|
defaultLocale: string,
|
|
121
121
|
locales: string[],
|
|
122
122
|
localeCookie: string | null = 'i18n-locale',
|
|
123
|
+
routingStrategy?: I18nRoutingStrategy | null,
|
|
123
124
|
): string {
|
|
124
|
-
|
|
125
|
-
const strategy = getGlobalRoutingStrategy()
|
|
125
|
+
const strategy = routingStrategy ?? getGlobalRoutingStrategy()
|
|
126
126
|
|
|
127
127
|
// 1. Try path
|
|
128
128
|
let locale = defaultLocale
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from 'node:async_hooks'
|
|
2
|
+
import type { I18nRoutingStrategy } from './router/types'
|
|
3
|
+
|
|
4
|
+
/** Integration-time default strategy (immutable after setup). */
|
|
5
|
+
let installedRoutingStrategy: I18nRoutingStrategy | null = null
|
|
6
|
+
|
|
7
|
+
/** Per-request strategy override for concurrent SSR. */
|
|
8
|
+
const requestRoutingStrategy = new AsyncLocalStorage<I18nRoutingStrategy | null>()
|
|
9
|
+
|
|
10
|
+
export function getGlobalRoutingStrategy(): I18nRoutingStrategy | null {
|
|
11
|
+
const store = requestRoutingStrategy.getStore()
|
|
12
|
+
// Distinguish an explicit per-request override (including `null`, i.e. routing
|
|
13
|
+
// disabled for this request) from "no request context" (`undefined`).
|
|
14
|
+
return store !== undefined ? store : installedRoutingStrategy
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function setGlobalRoutingStrategy(strategy: I18nRoutingStrategy | null): void {
|
|
18
|
+
installedRoutingStrategy = strategy
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function runWithRoutingStrategy<T>(strategy: I18nRoutingStrategy | null, fn: () => T): T {
|
|
22
|
+
return requestRoutingStrategy.run(strategy, fn)
|
|
23
|
+
}
|
package/src/utils.ts
CHANGED
|
@@ -73,15 +73,9 @@ export function useI18n(astro: AstroGlobal) {
|
|
|
73
73
|
tc: (key: TranslationKey, count: number | Params, defaultValue?: string): string => {
|
|
74
74
|
return i18n.tc(key, count, defaultValue)
|
|
75
75
|
},
|
|
76
|
-
tn: (
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
td: (value: Date | number | string, options?: Intl.DateTimeFormatOptions): string => {
|
|
80
|
-
return i18n.td(value, options)
|
|
81
|
-
},
|
|
82
|
-
tdr: (value: Date | number | string, options?: Intl.RelativeTimeFormatOptions): string => {
|
|
83
|
-
return i18n.tdr(value, options)
|
|
84
|
-
},
|
|
76
|
+
tn: i18n.tn.bind(i18n),
|
|
77
|
+
td: i18n.td.bind(i18n),
|
|
78
|
+
tdr: i18n.tdr.bind(i18n),
|
|
85
79
|
has: (key: TranslationKey, routeName?: string): boolean => {
|
|
86
80
|
return i18n.has(key, routeName)
|
|
87
81
|
},
|