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