@stacksjs/i18n 0.70.72 → 0.70.74
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -1
- package/dist/loader.d.ts +4 -1
- package/dist/types.d.ts +104 -145
- package/package.json +2 -2
- package/src/bootstrap.ts +1 -1
- package/src/formatter.ts +1 -1
- package/src/loader.ts +3 -1
- package/src/locale-switch.ts +1 -1
- package/src/pluralization.ts +13 -10
- package/src/translator.ts +3 -2
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var GG=import.meta.require;function JG(G,J){return KG(J)(G)}function KG(G){let J=G.split("-")[0].toLowerCase(),K=j[J];if(K)return K;return()=>"other"}function M(G,J="|"){let K=G.split(J).map((U)=>U.trim()),Z=new Map;if(K.length===1)Z.set("other",K[0]);else if(K.length===2)Z.set("one",K[0]),Z.set("other",K[1]);else if(K.length===3)Z.set("zero",K[0]),Z.set("one",K[1]),Z.set("other",K[2]);else if(K.length>=4){let U=["zero","one","two","few","many","other"];for(let _=0;_<K.length&&_<U.length;_++)Z.set(U[_],K[_])}return Z}function S(G,J,K){let Z=JG(J,K);if(G.has(Z))return G.get(Z);if(G.has("other"))return G.get("other");let U=G.values().next();return U.done?"":U.value}var j={en:(G)=>G===1?"one":"other",de:(G)=>G===1?"one":"other",nl:(G)=>G===1?"one":"other",es:(G)=>G===1?"one":"other",it:(G)=>G===1?"one":"other",pt:(G)=>G===1?"one":"other",sv:(G)=>G===1?"one":"other",da:(G)=>G===1?"one":"other",no:(G)=>G===1?"one":"other",fi:(G)=>G===1?"one":"other",el:(G)=>G===1?"one":"other",he:(G)=>G===1?"one":"other",hu:(G)=>G===1?"one":"other",tr:(G)=>G===1?"one":"other",zh:()=>"other",ja:()=>"other",ko:()=>"other",vi:()=>"other",th:()=>"other",id:()=>"other",ms:()=>"other",fr:(G)=>G===0||G===1?"one":"other",ru:(G)=>{let J=G%10,K=G%100;if(J===1&&K!==11)return"one";if(J>=2&&J<=4&&(K<12||K>14))return"few";if(J===0||J>=5&&J<=9||K>=11&&K<=14)return"many";return"other"},uk:(G)=>{let J=G%10,K=G%100;if(J===1&&K!==11)return"one";if(J>=2&&J<=4&&(K<12||K>14))return"few";if(J===0||J>=5&&J<=9||K>=11&&K<=14)return"many";return"other"},pl:(G)=>{let J=G%10,K=G%100;if(G===1)return"one";if(J>=2&&J<=4&&(K<12||K>14))return"few";if(J===0||J===1||J>=5&&J<=9||K>=12&&K<=14)return"many";return"other"},cs:(G)=>{if(G===1)return"one";if(G>=2&&G<=4)return"few";return"other"},sk:(G)=>{if(G===1)return"one";if(G>=2&&G<=4)return"few";return"other"},ar:(G)=>{if(G===0)return"zero";if(G===1)return"one";if(G===2)return"two";let J=G%100;if(J>=3&&J<=10)return"few";if(J>=11&&J<=99)return"many";return"other"},cy:(G)=>{if(G===0)return"zero";if(G===1)return"one";if(G===2)return"two";if(G===3)return"few";if(G===6)return"many";return"other"},sl:(G)=>{let J=G%100;if(J===1)return"one";if(J===2)return"two";if(J===3||J===4)return"few";return"other"},ga:(G)=>{if(G===1)return"one";if(G===2)return"two";if(G>=3&&G<=6)return"few";if(G>=7&&G<=10)return"many";return"other"},lt:(G)=>{let J=G%10,K=G%100;if(J===1&&(K<11||K>19))return"one";if(J>=2&&J<=9&&(K<11||K>19))return"few";return"other"},lv:(G)=>{let J=G%10,K=G%100;if(G===0)return"zero";if(J===1&&K!==11)return"one";return"other"},ro:(G)=>{if(G===1)return"one";let J=G%100;if(G===0||J>=1&&J<=19)return"few";return"other"},hi:(G)=>G===0||G===1?"one":"other"};function bG(){return Object.keys(j)}function vG(G){return G.split("-")[0].toLowerCase()in j}function hG(G,J){let K=G.split("-")[0].toLowerCase();j[K]=J}var g={locale:"en",fallbackLocale:"en",availableLocales:["en"],messages:{},warnMissing:!0,escapeValues:!1,keySeparator:".",pluralSeparator:"|"},H="en",R="en",N={},z={...g};class D{_locale;_fallbackLocale;_messages;_config;constructor(G={}){this._config={...g,...G},this._locale=this._config.locale,this._fallbackLocale=this._config.fallbackLocale,this._messages=this._config.messages||{}}get locale(){return this._locale}set locale(G){this._locale=G}get fallbackLocale(){return this._fallbackLocale}get availableLocales(){return Object.keys(this._messages)}t=(G,J,K)=>{return this.translate(G,J,K)};tc=(G,J,K,Z)=>{return this.translatePlural(G,J,K,Z)};te=(G,J)=>{return this.hasTranslation(G,J)};tm=(G,J)=>{return this.getMessage(G,J)};setLocale=(G)=>{this._locale=G};addTranslations=(G,J)=>{if(!this._messages[G])this._messages[G]={};this._messages[G]=P(this._messages[G],J)};d=(G,J)=>{let K=typeof G==="number"?new Date(G):G,Z=this._config.dateTimeFormats?.[this._locale]?.[J||"short"]||{};return new Intl.DateTimeFormat(this._locale,Z).format(K)};n=(G,J)=>{let K=this._config.numberFormats?.[this._locale]?.[J||"decimal"]||{};return new Intl.NumberFormat(this._locale,K).format(G)};translate(G,J,K){let Z=K||this._locale,U=this.getMessage(G,Z);if(U===void 0){let _=Z.indexOf("-");if(_>0){let B=Z.slice(0,_);if(B!==this._fallbackLocale)U=this.getMessage(G,B)}}if(U===void 0&&Z!==this._fallbackLocale)U=this.getMessage(G,this._fallbackLocale);if(U===void 0){if(this._config.warnMissing)console.warn(`[i18n] Missing translation: "${G}" for locale "${Z}"`);if(this._config.missingHandler){let _=this._config.missingHandler(Z,G);if(_!==void 0)return _}return G}if(typeof U!=="string")return G;return this.interpolate(U,J)}translatePlural(G,J,K,Z){let U=Z||this._locale,_=this.getMessage(G,U);if(_===void 0&&U!==this._fallbackLocale)_=this.getMessage(G,this._fallbackLocale);if(_===void 0||typeof _!=="string"){if(this._config.warnMissing)console.warn(`[i18n] Missing plural translation: "${G}" for locale "${U}"`);return G}let B=M(_,this._config.pluralSeparator),$=S(B,J,U),X={count:J,n:J,...K};return this.interpolate($,X)}hasTranslation(G,J){let K=J||this._locale;return this.getMessage(G,K)!==void 0}getMessage(G,J){let K=this._messages[J];if(!K)return;let Z=G.split(this._config.keySeparator||"."),U=K;for(let _ of Z){if(U===void 0||typeof U==="string")return;U=U[_]}return U}interpolate(G,J){if(!J)return G;return G.replace(/\{(\w+)\}/g,(K,Z)=>{let U=J[Z];if(U===void 0||U===null)return K;let _=String(U);return this._config.escapeValues?XG(_):_})}}function x(G){H=G}function E(){return H}function yG(G){R=G}function V(){return Object.keys(N)}function q(G,J){if(!N[G])N[G]={};N[G]=P(N[G],J)}function F(G){for(let[J,K]of Object.entries(G))q(J,K)}function p(G,J){return T(G,J||H)!==void 0}function T(G,J){let K=N[J];if(!K)return;let Z=G.split(z.keySeparator||"."),U=K;for(let _ of Z){if(U===void 0||typeof U==="string")return;U=U[_]}return U}function m(G,J){if(!J)return G;return G.replace(/\{(\w+)\}/g,(K,Z)=>{let U=J[Z];if(U===void 0||U===null)return K;return String(U)})}function d(G,J,K){let Z=K||H,U=T(G,Z);if(U===void 0&&Z!==R)U=T(G,R);if(U===void 0){if(z.warnMissing)console.warn(`[i18n] Missing translation: "${G}" for locale "${Z}"`);return G}if(typeof U!=="string")return G;return m(U,J)}var UG=d;function ZG(G,J,K,Z){let U=Z||H,_=T(G,U);if(_===void 0&&U!==R)_=T(G,R);if(_===void 0||typeof _!=="string")return G;let B=M(_,z.pluralSeparator),$=S(B,J,U),X={count:J,n:J,...K};return m($,X)}function _G(G,J){return p(G,J)}function $G(G,J){return T(G,J||H)}function u(G={}){return new D(G)}function BG(G={}){return u(G)}function i(G){if(z={...z,...G},G.locale)H=G.locale;if(G.fallbackLocale)R=G.fallbackLocale;if(G.messages)F(G.messages)}function P(G,J){let K={...G};for(let Z of Object.keys(J)){let U=J[Z],_=K[Z];if(typeof U==="object"&&U!==null&&typeof _==="object"&&_!==null)K[Z]=P(_,U);else K[Z]=U}return K}function XG(G){let J={"&":"&","<":"<",">":">",'"':""","'":"'"};return G.replace(/[&<>"']/g,(K)=>J[K]||K)}function EG(G,J="medium",K){let Z=K||E(),U=O(G),_=typeof J==="string"?{dateStyle:J}:J;return new Intl.DateTimeFormat(Z,_).format(U)}function QG(G,J="short",K){let Z=K||E(),U=O(G),_=typeof J==="string"?{timeStyle:J}:J;return new Intl.DateTimeFormat(Z,_).format(U)}function WG(G,J="medium",K="short",Z){let U=Z||E(),_=O(G);return new Intl.DateTimeFormat(U,{dateStyle:J,timeStyle:K}).format(_)}function YG(G,J=new Date,K="long",Z){let U=Z||E(),_=O(G),B=O(J),$=_.getTime()-B.getTime(),X=Math.round($/1000),Q=Math.round(X/60),W=Math.round(Q/60),A=Math.round(W/24),Y=Math.round(A/7),I=Math.round(A/30),C=Math.round(A/365),w=new Intl.RelativeTimeFormat(U,{style:K});if(Math.abs(X)<60)return w.format(X,"second");if(Math.abs(Q)<60)return w.format(Q,"minute");if(Math.abs(W)<24)return w.format(W,"hour");if(Math.abs(A)<7)return w.format(A,"day");if(Math.abs(Y)<4)return w.format(Y,"week");if(Math.abs(I)<12)return w.format(I,"month");return w.format(C,"year")}function AG(G,J={},K){let Z=K||E(),U={...J};if(J.compact)U.notation="compact",U.compactDisplay="short";if(J.precision!==void 0)U.minimumFractionDigits=J.precision,U.maximumFractionDigits=J.precision;return new Intl.NumberFormat(Z,U).format(G)}function IG(G,J="USD",K={},Z){let U=Z||E();return new Intl.NumberFormat(U,{style:"currency",currency:J,...K}).format(G)}function wG(G,J={},K){let Z=K||E();return new Intl.NumberFormat(Z,{style:"percent",...J}).format(G)}function mG(G,J,K="short",Z){let U=Z||E();return new Intl.NumberFormat(U,{style:"unit",unit:J,unitDisplay:K}).format(G)}function dG(G,J=2,K){let Z=K||E();if(G===0)return"0 B";let U=1024,_=["B","KB","MB","GB","TB","PB","EB","ZB","YB"],B=Math.floor(Math.log(G)/Math.log(U)),$=G/Math.pow(U,B);return`${new Intl.NumberFormat(Z,{minimumFractionDigits:0,maximumFractionDigits:J}).format($)} ${_[B]}`}function HG(G,J="conjunction",K="long",Z){let U=Z||E();return new Intl.ListFormat(U,{type:J,style:K}).format(G)}function c(G,J){let K=J||E();return new Intl.PluralRules(K).select(G)}function uG(G,J,K){let Z=c(G,K);return J[Z]??J.other}function b(G,J="language",K="long",Z){let U=Z||E();try{return new Intl.DisplayNames(U,{type:J,style:K}).of(G)}catch{return}}function iG(G,J){return b(G,"language","long",J)}function cG(G,J){return b(G,"region","long",J)}function nG(G,J){return b(G,"currency","long",J)}function rG(G,J,K={},Z){let U=Z||E();return new Intl.Collator(U,K).compare(G,J)}function sG(G,J={},K){let Z=K||E(),U=new Intl.Collator(Z,J);return[...G].sort((_,B)=>U.compare(_,B))}function O(G){if(G instanceof Date)return G;if(typeof G==="number")return new Date(G);return new Date(G)}function NG(G){let K=(G||E()).split("-")[0].toLowerCase();return["ar","he","fa","ur","yi","ps","sd","ug","ku","ckb"].includes(K)?"rtl":"ltr"}function tG(G){return NG(G)==="rtl"}import{existsSync as RG,readdirSync as n}from"fs";import{readFile as TG}from"fs/promises";import{basename as r,extname as v,join as h}from"path";import{log as zG}from"@stacksjs/logging";async function L(G){let{directory:J,extensions:K=[".json",".yaml",".yml",".ts",".js"],recursive:Z=!1,namespaceSeparator:U="."}=G,_={};if(!RG(J))return zG.warn(`[i18n] Translation directory not found: ${J}`),_;return await s(J,_,K,Z,U,""),F(_),_}async function s(G,J,K,Z,U,_){let B=n(G,{withFileTypes:!0});for(let $ of B){let X=h(G,$.name);if($.isDirectory()){let Q=$.name;if(jG(Q))await FG(X,Q,J,K);else if(Z){let W=_?`${_}${U}${$.name}`:$.name;await s(X,J,K,Z,U,W)}}else if($.isFile()){let Q=v($.name);if(K.includes(Q)){let W=r($.name,Q);if(!J[W])J[W]={};let A=await k(X);if(_)VG(J[W],_,A,U);else J[W]=f(J[W],A)}}}}async function FG(G,J,K,Z){if(!K[J])K[J]={};let U=n(G,{withFileTypes:!0});for(let _ of U){if(!_.isFile())continue;let B=v(_.name);if(!Z.includes(B))continue;let $=h(G,_.name),X=r(_.name,B),Q=await k($);if(X===J)K[J]=f(K[J],Q);else K[J][X]=Q}}async function k(G){let J=v(G).toLowerCase(),K=await TG(G,"utf8");switch(J){case".json":try{return JSON.parse(K)}catch{throw Error(`Invalid JSON in translation file: ${G}`)}case".yaml":case".yml":return CG(K);case".ts":case".js":{let Z=await import(G);return Z.default||Z}default:throw Error(`Unsupported file type: ${J}`)}}async function OG(G,J){let K=await k(J);return q(G,K),K}function CG(G){try{let J=Bun.YAML.parse(G);if(!J||typeof J!=="object"||Array.isArray(J))throw Error("YAML content must be an object at the root level");return J}catch(J){let K=J instanceof Error?J.message:"Unknown YAML parse error";throw Error(`Invalid YAML translation file: ${K}`)}}function jG(G){return/^[a-z]{2}(?:-[A-Z]{2})?(?:-[A-Za-z]+)?$/i.test(G)}function VG(G,J,K,Z){let U=J.split(Z),_=G;for(let $=0;$<U.length-1;$++){let X=U[$];if(!_[X]||typeof _[X]==="string")_[X]={};_=_[X]}let B=U[U.length-1];_[B]=K}function f(G,J){let K={...G};for(let Z of Object.keys(J)){let U=J[Z],_=K[Z];if(typeof U==="object"&&U!==null&&typeof _==="object"&&_!==null)K[Z]=f(_,U);else K[Z]=U}return K}function KJ(G,J={}){return{load:()=>L({directory:G,...J}),loadLocale:(K,Z)=>OG(K,h(G,Z))}}async function UJ(G){let{loadTranslations:J}=await import("@stacksjs/ts-i18n"),K=await J(G);return F(K),K}var _J={en:{code:"en",name:"English",nativeName:"English",direction:"ltr"},"en-US":{code:"en-US",name:"English (US)",nativeName:"English (US)",direction:"ltr",region:"US"},"en-GB":{code:"en-GB",name:"English (UK)",nativeName:"English (UK)",direction:"ltr",region:"GB"},es:{code:"es",name:"Spanish",nativeName:"Espa\xF1ol",direction:"ltr"},fr:{code:"fr",name:"French",nativeName:"Fran\xE7ais",direction:"ltr"},de:{code:"de",name:"German",nativeName:"Deutsch",direction:"ltr"},it:{code:"it",name:"Italian",nativeName:"Italiano",direction:"ltr"},pt:{code:"pt",name:"Portuguese",nativeName:"Portugu\xEAs",direction:"ltr"},"pt-BR":{code:"pt-BR",name:"Portuguese (Brazil)",nativeName:"Portugu\xEAs (Brasil)",direction:"ltr",region:"BR"},zh:{code:"zh",name:"Chinese",nativeName:"\u4E2D\u6587",direction:"ltr"},"zh-CN":{code:"zh-CN",name:"Chinese (Simplified)",nativeName:"\u7B80\u4F53\u4E2D\u6587",direction:"ltr",region:"CN"},"zh-TW":{code:"zh-TW",name:"Chinese (Traditional)",nativeName:"\u7E41\u9AD4\u4E2D\u6587",direction:"ltr",region:"TW"},ja:{code:"ja",name:"Japanese",nativeName:"\u65E5\u672C\u8A9E",direction:"ltr"},ko:{code:"ko",name:"Korean",nativeName:"\uD55C\uAD6D\uC5B4",direction:"ltr"},ar:{code:"ar",name:"Arabic",nativeName:"\u0627\u0644\u0639\u0631\u0628\u064A\u0629",direction:"rtl"},he:{code:"he",name:"Hebrew",nativeName:"\u05E2\u05D1\u05E8\u05D9\u05EA",direction:"rtl"},ru:{code:"ru",name:"Russian",nativeName:"\u0420\u0443\u0441\u0441\u043A\u0438\u0439",direction:"ltr"},nl:{code:"nl",name:"Dutch",nativeName:"Nederlands",direction:"ltr"},pl:{code:"pl",name:"Polish",nativeName:"Polski",direction:"ltr"},tr:{code:"tr",name:"Turkish",nativeName:"T\xFCrk\xE7e",direction:"ltr"},vi:{code:"vi",name:"Vietnamese",nativeName:"Ti\u1EBFng Vi\u1EC7t",direction:"ltr"},th:{code:"th",name:"Thai",nativeName:"\u0E44\u0E17\u0E22",direction:"ltr"},hi:{code:"hi",name:"Hindi",nativeName:"\u0939\u093F\u0928\u094D\u0926\u0940",direction:"ltr"}};import{loadTranslations as FJ,generateTypes as OJ,generateTypesFromModule as CJ,generateSampleConfig as jJ,writeOutputs as VJ,createTranslator as qJ}from"@stacksjs/ts-i18n";import{existsSync as qG}from"fs";import{config as y}from"@stacksjs/config";import{projectPath as MG}from"@stacksjs/path";var t=!1;async function o(){if(t)return;let G=MG("locales");if(qG(G))await L({directory:G,extensions:[".yaml",".yml",".json"]});let J=y.app,K=J?.locale??"en",Z=J?.fallbackLocale??K,U=V();i({locale:K,fallbackLocale:Z,availableLocales:U.length>0?U:[K],warnMissing:(J?.env??process.env.APP_ENV)!=="production"}),t=!0}function l(G){let K=y.app?.locale??"en",Z=new Set(V());if(!Z.size)Z.add(K);let U=(Y)=>{let I=Y.trim().toLowerCase();if(Z.has(I))return I;let C=I.split("-")[0];if(Z.has(C))return C;return K};if(!G)return K;let _=new URL(G.url),B=_.pathname,$=G.headers.get("x-stx-locale");if($)return U($);for(let Y of Z){if(Y===K)continue;if(B===`/${Y}`||B===`/${Y}/`)return U(Y);if(B.startsWith(`/${Y}/`))return U(Y)}let X=_.searchParams.get("locale");if(X)return U(X);let W=(G.headers.get("cookie")??"").match(/(?:^|;\s*)locale=([a-z]{2}(?:-[a-z]{2})?)(?:;|$)/i);if(W?.[1])return U(W[1]);let A=G.headers.get("accept-language")??"";for(let Y of A.split(",")){let I=Y.split(";")[0]?.trim();if(I)return U(I)}return K}async function SG(G){await o();let J=l(G);return x(J),J}function DG(G,J){let K=G.trim().toLowerCase();if(J.locales.includes(K))return K;let Z=K.split("-")[0];if(J.locales.includes(Z))return Z;return null}function a(G,J){for(let K of J){if(G===`/${K}`||G===`/${K}/`)return{locale:K,path:"/"};if(G.startsWith(`/${K}/`))return{locale:K,path:G.slice(K.length+1)}}return{locale:null,path:G}}function e(G,J,K){if(J===K)return G;if(G==="/")return`/${J}/`;if(G==="/404.html")return`/${J}/404.html`;return`/${J}${G}`}function xG(G,J,K){let Z=DG(J,K);if(!Z)return Response.redirect(new URL("/",G.url).href,302);let U=G.headers.get("referer"),_="/";if(U)try{let Q=new URL(U);if(!Q.pathname.startsWith("/locale/"))_=a(Q.pathname,K.locales).path||"/"}catch{_="/"}let B=e(_,Z,K.defaultLocale),$=new URL(B,G.url),X=Response.redirect($.href,302);return X.headers.append("Set-Cookie",`locale=${Z}; Path=/; Max-Age=31536000; SameSite=Lax`),X}export{VJ as writeI18nOutputs,BG as useI18n,UG as trans,$G as tm,_G as te,ZG as tc,d as t,a as stripLocalePrefix,sG as sortStrings,x as setLocale,yG as setFallbackLocale,S as selectPluralForm,uG as selectPlural,l as resolveRequestLocale,M as parsePluralForms,e as localizePath,FJ as loadTranslationsFromDisk,F as loadTranslations,OG as loadLocale,UJ as loadFromTsI18n,L as loadFromDirectory,k as loadFile,tG as isRTL,p as hasTranslation,vG as hasPluralRule,NG as getTextDirection,bG as getSupportedPluralLocales,cG as getRegionName,KG as getPluralRule,JG as getPluralCategory,E as getLocale,iG as getLanguageName,b as getDisplayName,nG as getCurrencyName,V as getAvailableLocales,CJ as generateI18nTypesFromModule,OJ as generateI18nTypes,jJ as generateI18nSampleConfig,mG as formatUnit,QG as formatTime,YG as formatRelativeTime,c as formatPlural,wG as formatPercent,AG as formatNumber,HG as formatList,WG as formatDateTime,EG as formatDate,IG as formatCurrency,dG as formatBytes,o as ensureLocalesLoaded,qJ as createSimpleTranslator,xG as createLocaleSwitchResponse,KJ as createLoader,u as createI18n,i as configure,rG as compareStrings,SG as applyRequestLocale,q as addTranslations,hG as addPluralRule,_J as LOCALE_INFO,D as I18n};
|
|
2
|
+
var GG=import.meta.require;function JG(G,J){return KG(J)(G)}function KG(G){let J=G.split("-")[0]?.toLowerCase()??G.toLowerCase(),K=j[J];if(K)return K;return()=>"other"}function M(G,J="|"){let K=G.split(J).map((U)=>U.trim()),Z=new Map;if(K.length===1)Z.set("other",K[0]??"");else if(K.length===2)Z.set("one",K[0]??""),Z.set("other",K[1]??"");else if(K.length===3)Z.set("zero",K[0]??""),Z.set("one",K[1]??""),Z.set("other",K[2]??"");else if(K.length>=4){let U=["zero","one","two","few","many","other"];for(let _=0;_<K.length&&_<U.length;_++){let $=U[_],B=K[_];if($!==void 0&&B!==void 0)Z.set($,B)}}return Z}function S(G,J,K){let Z=JG(J,K);if(G.has(Z))return G.get(Z);if(G.has("other"))return G.get("other");let U=G.values().next();return U.done?"":U.value}var j={en:(G)=>G===1?"one":"other",de:(G)=>G===1?"one":"other",nl:(G)=>G===1?"one":"other",es:(G)=>G===1?"one":"other",it:(G)=>G===1?"one":"other",pt:(G)=>G===1?"one":"other",sv:(G)=>G===1?"one":"other",da:(G)=>G===1?"one":"other",no:(G)=>G===1?"one":"other",fi:(G)=>G===1?"one":"other",el:(G)=>G===1?"one":"other",he:(G)=>G===1?"one":"other",hu:(G)=>G===1?"one":"other",tr:(G)=>G===1?"one":"other",zh:()=>"other",ja:()=>"other",ko:()=>"other",vi:()=>"other",th:()=>"other",id:()=>"other",ms:()=>"other",fr:(G)=>G===0||G===1?"one":"other",ru:(G)=>{let J=G%10,K=G%100;if(J===1&&K!==11)return"one";if(J>=2&&J<=4&&(K<12||K>14))return"few";if(J===0||J>=5&&J<=9||K>=11&&K<=14)return"many";return"other"},uk:(G)=>{let J=G%10,K=G%100;if(J===1&&K!==11)return"one";if(J>=2&&J<=4&&(K<12||K>14))return"few";if(J===0||J>=5&&J<=9||K>=11&&K<=14)return"many";return"other"},pl:(G)=>{let J=G%10,K=G%100;if(G===1)return"one";if(J>=2&&J<=4&&(K<12||K>14))return"few";if(J===0||J===1||J>=5&&J<=9||K>=12&&K<=14)return"many";return"other"},cs:(G)=>{if(G===1)return"one";if(G>=2&&G<=4)return"few";return"other"},sk:(G)=>{if(G===1)return"one";if(G>=2&&G<=4)return"few";return"other"},ar:(G)=>{if(G===0)return"zero";if(G===1)return"one";if(G===2)return"two";let J=G%100;if(J>=3&&J<=10)return"few";if(J>=11&&J<=99)return"many";return"other"},cy:(G)=>{if(G===0)return"zero";if(G===1)return"one";if(G===2)return"two";if(G===3)return"few";if(G===6)return"many";return"other"},sl:(G)=>{let J=G%100;if(J===1)return"one";if(J===2)return"two";if(J===3||J===4)return"few";return"other"},ga:(G)=>{if(G===1)return"one";if(G===2)return"two";if(G>=3&&G<=6)return"few";if(G>=7&&G<=10)return"many";return"other"},lt:(G)=>{let J=G%10,K=G%100;if(J===1&&(K<11||K>19))return"one";if(J>=2&&J<=9&&(K<11||K>19))return"few";return"other"},lv:(G)=>{let J=G%10,K=G%100;if(G===0)return"zero";if(J===1&&K!==11)return"one";return"other"},ro:(G)=>{if(G===1)return"one";let J=G%100;if(G===0||J>=1&&J<=19)return"few";return"other"},hi:(G)=>G===0||G===1?"one":"other"};function bG(){return Object.keys(j)}function vG(G){return(G.split("-")[0]?.toLowerCase()??G.toLowerCase())in j}function hG(G,J){let K=G.split("-")[0]?.toLowerCase()??G.toLowerCase();j[K]=J}var g={locale:"en",fallbackLocale:"en",availableLocales:["en"],messages:{},warnMissing:!0,escapeValues:!1,keySeparator:".",pluralSeparator:"|"},H="en",R="en",N={},F={...g};class D{_locale;_fallbackLocale;_messages;_config;constructor(G={}){this._config={...g,...G},this._locale=this._config.locale,this._fallbackLocale=this._config.fallbackLocale,this._messages=this._config.messages||{}}get locale(){return this._locale}set locale(G){this._locale=G}get fallbackLocale(){return this._fallbackLocale}get availableLocales(){return Object.keys(this._messages)}t=(G,J,K)=>{return this.translate(G,J,K)};tc=(G,J,K,Z)=>{return this.translatePlural(G,J,K,Z)};te=(G,J)=>{return this.hasTranslation(G,J)};tm=(G,J)=>{return this.getMessage(G,J??this.locale)};setLocale=(G)=>{this._locale=G};addTranslations=(G,J)=>{if(!this._messages[G])this._messages[G]={};this._messages[G]=P(this._messages[G],J)};d=(G,J)=>{let K=typeof G==="number"?new Date(G):G,Z=this._config.dateTimeFormats?.[this._locale]?.[J||"short"]||{};return new Intl.DateTimeFormat(this._locale,Z).format(K)};n=(G,J)=>{let K=this._config.numberFormats?.[this._locale]?.[J||"decimal"]||{};return new Intl.NumberFormat(this._locale,K).format(G)};translate(G,J,K){let Z=K||this._locale,U=this.getMessage(G,Z);if(U===void 0){let _=Z.indexOf("-");if(_>0){let $=Z.slice(0,_);if($!==this._fallbackLocale)U=this.getMessage(G,$)}}if(U===void 0&&Z!==this._fallbackLocale)U=this.getMessage(G,this._fallbackLocale);if(U===void 0){if(this._config.warnMissing)console.warn(`[i18n] Missing translation: "${G}" for locale "${Z}"`);if(this._config.missingHandler){let _=this._config.missingHandler(Z,G);if(_!==void 0)return _}return G}if(typeof U!=="string")return G;return this.interpolate(U,J)}translatePlural(G,J,K,Z){let U=Z||this._locale,_=this.getMessage(G,U);if(_===void 0&&U!==this._fallbackLocale)_=this.getMessage(G,this._fallbackLocale);if(_===void 0||typeof _!=="string"){if(this._config.warnMissing)console.warn(`[i18n] Missing plural translation: "${G}" for locale "${U}"`);return G}let $=M(_,this._config.pluralSeparator),B=S($,J,U),X={count:J,n:J,...K};return this.interpolate(B,X)}hasTranslation(G,J){let K=J||this._locale;return this.getMessage(G,K)!==void 0}getMessage(G,J){let K=this._messages[J];if(!K)return;let Z=G.split(this._config.keySeparator||"."),U=K;for(let _ of Z){if(U===void 0||typeof U==="string")return;U=U[_]}return U}interpolate(G,J){if(!J)return G;return G.replace(/\{(\w+)\}/g,(K,Z)=>{let U=J[Z];if(U===void 0||U===null)return K;let _=String(U);return this._config.escapeValues?XG(_):_})}}function x(G){H=G}function E(){return H}function yG(G){R=G}function V(){return Object.keys(N)}function q(G,J){if(!N[G])N[G]={};N[G]=P(N[G],J)}function O(G){for(let[J,K]of Object.entries(G))q(J,K)}function p(G,J){return T(G,J||H)!==void 0}function T(G,J){let K=N[J];if(!K)return;let Z=G.split(F.keySeparator||"."),U=K;for(let _ of Z){if(U===void 0||typeof U==="string")return;U=U[_]}return U}function m(G,J){if(!J)return G;return G.replace(/\{(\w+)\}/g,(K,Z)=>{let U=J[Z];if(U===void 0||U===null)return K;return String(U)})}function d(G,J,K){let Z=K||H,U=T(G,Z);if(U===void 0&&Z!==R)U=T(G,R);if(U===void 0){if(F.warnMissing)console.warn(`[i18n] Missing translation: "${G}" for locale "${Z}"`);return G}if(typeof U!=="string")return G;return m(U,J)}var UG=d;function ZG(G,J,K,Z){let U=Z||H,_=T(G,U);if(_===void 0&&U!==R)_=T(G,R);if(_===void 0||typeof _!=="string")return G;let $=M(_,F.pluralSeparator),B=S($,J,U),X={count:J,n:J,...K};return m(B,X)}function _G(G,J){return p(G,J)}function $G(G,J){return T(G,J||H)}function u(G={}){return new D(G)}function BG(G={}){return u(G)}function i(G){if(F={...F,...G},G.locale)H=G.locale;if(G.fallbackLocale)R=G.fallbackLocale;if(G.messages)O(G.messages)}function P(G,J){let K={...G};for(let Z of Object.keys(J)){let U=J[Z],_=K[Z];if(typeof U==="object"&&U!==null&&typeof _==="object"&&_!==null)K[Z]=P(_,U);else if(U!==void 0)K[Z]=U}return K}function XG(G){let J={"&":"&","<":"<",">":">",'"':""","'":"'"};return G.replace(/[&<>"']/g,(K)=>J[K]||K)}function EG(G,J="medium",K){let Z=K||E(),U=C(G),_=typeof J==="string"?{dateStyle:J}:J;return new Intl.DateTimeFormat(Z,_).format(U)}function QG(G,J="short",K){let Z=K||E(),U=C(G),_=typeof J==="string"?{timeStyle:J}:J;return new Intl.DateTimeFormat(Z,_).format(U)}function WG(G,J="medium",K="short",Z){let U=Z||E(),_=C(G);return new Intl.DateTimeFormat(U,{dateStyle:J,timeStyle:K}).format(_)}function YG(G,J=new Date,K="long",Z){let U=Z||E(),_=C(G),$=C(J),B=_.getTime()-$.getTime(),X=Math.round(B/1000),Q=Math.round(X/60),W=Math.round(Q/60),A=Math.round(W/24),Y=Math.round(A/7),I=Math.round(A/30),z=Math.round(A/365),w=new Intl.RelativeTimeFormat(U,{style:K});if(Math.abs(X)<60)return w.format(X,"second");if(Math.abs(Q)<60)return w.format(Q,"minute");if(Math.abs(W)<24)return w.format(W,"hour");if(Math.abs(A)<7)return w.format(A,"day");if(Math.abs(Y)<4)return w.format(Y,"week");if(Math.abs(I)<12)return w.format(I,"month");return w.format(z,"year")}function AG(G,J={},K){let Z=K||E(),U={...J};if(J.compact)U.notation="compact",U.compactDisplay="short";if(J.precision!==void 0)U.minimumFractionDigits=J.precision,U.maximumFractionDigits=J.precision;return new Intl.NumberFormat(Z,U).format(G)}function IG(G,J="USD",K={},Z){let U=Z||E();return new Intl.NumberFormat(U,{style:"currency",currency:J,...K}).format(G)}function wG(G,J={},K){let Z=K||E();return new Intl.NumberFormat(Z,{style:"percent",...J}).format(G)}function mG(G,J,K="short",Z){let U=Z||E();return new Intl.NumberFormat(U,{style:"unit",unit:J,unitDisplay:K}).format(G)}function dG(G,J=2,K){let Z=K||E();if(G===0)return"0 B";let U=1024,_=["B","KB","MB","GB","TB","PB","EB","ZB","YB"],$=Math.floor(Math.log(G)/Math.log(U)),B=G/Math.pow(U,$);return`${new Intl.NumberFormat(Z,{minimumFractionDigits:0,maximumFractionDigits:J}).format(B)} ${_[$]}`}function HG(G,J="conjunction",K="long",Z){let U=Z||E();return new Intl.ListFormat(U,{type:J,style:K}).format(G)}function n(G,J){let K=J||E();return new Intl.PluralRules(K).select(G)}function uG(G,J,K){let Z=n(G,K);return J[Z]??J.other}function b(G,J="language",K="long",Z){let U=Z||E();try{return new Intl.DisplayNames(U,{type:J,style:K}).of(G)}catch{return}}function iG(G,J){return b(G,"language","long",J)}function nG(G,J){return b(G,"region","long",J)}function cG(G,J){return b(G,"currency","long",J)}function rG(G,J,K={},Z){let U=Z||E();return new Intl.Collator(U,K).compare(G,J)}function sG(G,J={},K){let Z=K||E(),U=new Intl.Collator(Z,J);return[...G].sort((_,$)=>U.compare(_,$))}function C(G){if(G instanceof Date)return G;if(typeof G==="number")return new Date(G);return new Date(G)}function NG(G){let J=G||E(),K=(J.split("-")[0]??J).toLowerCase();return["ar","he","fa","ur","yi","ps","sd","ug","ku","ckb"].includes(K)?"rtl":"ltr"}function tG(G){return NG(G)==="rtl"}import{existsSync as RG,readdirSync as c}from"fs";import{readFile as TG}from"fs/promises";import{basename as r,extname as v,join as h}from"path";import{log as zG}from"@stacksjs/logging";async function L(G){let{directory:J,extensions:K=[".json",".yaml",".yml",".ts",".js"],recursive:Z=!1,namespaceSeparator:U="."}=G,_={};if(!RG(J))return zG.warn(`[i18n] Translation directory not found: ${J}`),_;return await s(J,_,K,Z,U,""),O(_),_}async function s(G,J,K,Z,U,_){let $=c(G,{withFileTypes:!0});for(let B of $){let X=h(G,B.name);if(B.isDirectory()){let Q=B.name;if(jG(Q))await FG(X,Q,J,K);else if(Z){let W=_?`${_}${U}${B.name}`:B.name;await s(X,J,K,Z,U,W)}}else if(B.isFile()){let Q=v(B.name);if(K.includes(Q)){let W=r(B.name,Q);if(!J[W])J[W]={};let A=await k(X);if(_)VG(J[W],_,A,U);else J[W]=f(J[W],A)}}}}async function FG(G,J,K,Z){if(!K[J])K[J]={};let U=c(G,{withFileTypes:!0});for(let _ of U){if(!_.isFile())continue;let $=v(_.name);if(!Z.includes($))continue;let B=h(G,_.name),X=r(_.name,$),Q=await k(B);if(X===J)K[J]=f(K[J],Q);else K[J][X]=Q}}async function k(G){let J=v(G).toLowerCase(),K=await TG(G,"utf8");switch(J){case".json":try{return JSON.parse(K)}catch{throw Error(`Invalid JSON in translation file: ${G}`)}case".yaml":case".yml":return CG(K);case".ts":case".js":{let Z=await import(G);return Z.default||Z}default:throw Error(`Unsupported file type: ${J}`)}}async function OG(G,J){let K=await k(J);return q(G,K),K}function CG(G){try{let J=Bun.YAML.parse(G);if(!J||typeof J!=="object"||Array.isArray(J))throw Error("YAML content must be an object at the root level");return J}catch(J){let K=J instanceof Error?J.message:"Unknown YAML parse error";throw Error(`Invalid YAML translation file: ${K}`)}}function jG(G){return/^[a-z]{2}(?:-[A-Z]{2})?(?:-[A-Za-z]+)?$/i.test(G)}function VG(G,J,K,Z){let U=J.split(Z),_=G;for(let B=0;B<U.length-1;B++){let X=U[B];if(!X)continue;if(!_[X]||typeof _[X]==="string")_[X]={};_=_[X]}let $=U[U.length-1];if($)_[$]=K}function f(G,J){let K={...G};for(let Z of Object.keys(J)){let U=J[Z];if(U===void 0)continue;let _=K[Z];if(typeof U==="object"&&U!==null&&typeof _==="object"&&_!==null)K[Z]=f(_,U);else K[Z]=U}return K}function KJ(G,J={}){return{load:()=>L({directory:G,...J}),loadLocale:(K,Z)=>OG(K,h(G,Z))}}async function UJ(G){let{loadTranslations:J}=await import("@stacksjs/ts-i18n"),K=await J(G);return O(K),K}var _J={en:{code:"en",name:"English",nativeName:"English",direction:"ltr"},"en-US":{code:"en-US",name:"English (US)",nativeName:"English (US)",direction:"ltr",region:"US"},"en-GB":{code:"en-GB",name:"English (UK)",nativeName:"English (UK)",direction:"ltr",region:"GB"},es:{code:"es",name:"Spanish",nativeName:"Espa\xF1ol",direction:"ltr"},fr:{code:"fr",name:"French",nativeName:"Fran\xE7ais",direction:"ltr"},de:{code:"de",name:"German",nativeName:"Deutsch",direction:"ltr"},it:{code:"it",name:"Italian",nativeName:"Italiano",direction:"ltr"},pt:{code:"pt",name:"Portuguese",nativeName:"Portugu\xEAs",direction:"ltr"},"pt-BR":{code:"pt-BR",name:"Portuguese (Brazil)",nativeName:"Portugu\xEAs (Brasil)",direction:"ltr",region:"BR"},zh:{code:"zh",name:"Chinese",nativeName:"\u4E2D\u6587",direction:"ltr"},"zh-CN":{code:"zh-CN",name:"Chinese (Simplified)",nativeName:"\u7B80\u4F53\u4E2D\u6587",direction:"ltr",region:"CN"},"zh-TW":{code:"zh-TW",name:"Chinese (Traditional)",nativeName:"\u7E41\u9AD4\u4E2D\u6587",direction:"ltr",region:"TW"},ja:{code:"ja",name:"Japanese",nativeName:"\u65E5\u672C\u8A9E",direction:"ltr"},ko:{code:"ko",name:"Korean",nativeName:"\uD55C\uAD6D\uC5B4",direction:"ltr"},ar:{code:"ar",name:"Arabic",nativeName:"\u0627\u0644\u0639\u0631\u0628\u064A\u0629",direction:"rtl"},he:{code:"he",name:"Hebrew",nativeName:"\u05E2\u05D1\u05E8\u05D9\u05EA",direction:"rtl"},ru:{code:"ru",name:"Russian",nativeName:"\u0420\u0443\u0441\u0441\u043A\u0438\u0439",direction:"ltr"},nl:{code:"nl",name:"Dutch",nativeName:"Nederlands",direction:"ltr"},pl:{code:"pl",name:"Polish",nativeName:"Polski",direction:"ltr"},tr:{code:"tr",name:"Turkish",nativeName:"T\xFCrk\xE7e",direction:"ltr"},vi:{code:"vi",name:"Vietnamese",nativeName:"Ti\u1EBFng Vi\u1EC7t",direction:"ltr"},th:{code:"th",name:"Thai",nativeName:"\u0E44\u0E17\u0E22",direction:"ltr"},hi:{code:"hi",name:"Hindi",nativeName:"\u0939\u093F\u0928\u094D\u0926\u0940",direction:"ltr"}};import{loadTranslations as FJ,generateTypes as OJ,generateTypesFromModule as CJ,generateSampleConfig as jJ,writeOutputs as VJ,createTranslator as qJ}from"@stacksjs/ts-i18n";import{existsSync as qG}from"fs";import{config as y}from"@stacksjs/config";import{projectPath as MG}from"@stacksjs/path";var t=!1;async function o(){if(t)return;let G=MG("locales");if(qG(G))await L({directory:G,extensions:[".yaml",".yml",".json"]});let J=y.app,K=J?.locale??"en",Z=J?.fallbackLocale??K,U=V();i({locale:K,fallbackLocale:Z,availableLocales:U.length>0?U:[K],warnMissing:(J?.env??process.env.APP_ENV)!=="production"}),t=!0}function l(G){let K=y.app?.locale??"en",Z=new Set(V());if(!Z.size)Z.add(K);let U=(Y)=>{let I=Y.trim().toLowerCase();if(Z.has(I))return I;let z=I.split("-")[0];if(z&&Z.has(z))return z;return K};if(!G)return K;let _=new URL(G.url),$=_.pathname,B=G.headers.get("x-stx-locale");if(B)return U(B);for(let Y of Z){if(Y===K)continue;if($===`/${Y}`||$===`/${Y}/`)return U(Y);if($.startsWith(`/${Y}/`))return U(Y)}let X=_.searchParams.get("locale");if(X)return U(X);let W=(G.headers.get("cookie")??"").match(/(?:^|;\s*)locale=([a-z]{2}(?:-[a-z]{2})?)(?:;|$)/i);if(W?.[1])return U(W[1]);let A=G.headers.get("accept-language")??"";for(let Y of A.split(",")){let I=Y.split(";")[0]?.trim();if(I)return U(I)}return K}async function SG(G){await o();let J=l(G);return x(J),J}function DG(G,J){let K=G.trim().toLowerCase();if(J.locales.includes(K))return K;let Z=K.split("-")[0];if(Z&&J.locales.includes(Z))return Z;return null}function a(G,J){for(let K of J){if(G===`/${K}`||G===`/${K}/`)return{locale:K,path:"/"};if(G.startsWith(`/${K}/`))return{locale:K,path:G.slice(K.length+1)}}return{locale:null,path:G}}function e(G,J,K){if(J===K)return G;if(G==="/")return`/${J}/`;if(G==="/404.html")return`/${J}/404.html`;return`/${J}${G}`}function xG(G,J,K){let Z=DG(J,K);if(!Z)return Response.redirect(new URL("/",G.url).href,302);let U=G.headers.get("referer"),_="/";if(U)try{let Q=new URL(U);if(!Q.pathname.startsWith("/locale/"))_=a(Q.pathname,K.locales).path||"/"}catch{_="/"}let $=e(_,Z,K.defaultLocale),B=new URL($,G.url),X=Response.redirect(B.href,302);return X.headers.append("Set-Cookie",`locale=${Z}; Path=/; Max-Age=31536000; SameSite=Lax`),X}export{VJ as writeI18nOutputs,BG as useI18n,UG as trans,$G as tm,_G as te,ZG as tc,d as t,a as stripLocalePrefix,sG as sortStrings,x as setLocale,yG as setFallbackLocale,S as selectPluralForm,uG as selectPlural,l as resolveRequestLocale,M as parsePluralForms,e as localizePath,FJ as loadTranslationsFromDisk,O as loadTranslations,OG as loadLocale,UJ as loadFromTsI18n,L as loadFromDirectory,k as loadFile,tG as isRTL,p as hasTranslation,vG as hasPluralRule,NG as getTextDirection,bG as getSupportedPluralLocales,nG as getRegionName,KG as getPluralRule,JG as getPluralCategory,E as getLocale,iG as getLanguageName,b as getDisplayName,cG as getCurrencyName,V as getAvailableLocales,CJ as generateI18nTypesFromModule,OJ as generateI18nTypes,jJ as generateI18nSampleConfig,mG as formatUnit,QG as formatTime,YG as formatRelativeTime,n as formatPlural,wG as formatPercent,AG as formatNumber,HG as formatList,WG as formatDateTime,EG as formatDate,IG as formatCurrency,dG as formatBytes,o as ensureLocalesLoaded,qJ as createSimpleTranslator,xG as createLocaleSwitchResponse,KJ as createLoader,u as createI18n,i as configure,rG as compareStrings,SG as applyRequestLocale,q as addTranslations,hG as addPluralRule,_J as LOCALE_INFO,D as I18n};
|
package/dist/loader.d.ts
CHANGED
|
@@ -14,7 +14,10 @@ export declare function loadLocale(locale: string, path: string): Promise<Transl
|
|
|
14
14
|
/**
|
|
15
15
|
* Create a translation loader for a specific directory
|
|
16
16
|
*/
|
|
17
|
-
export declare function createLoader(directory: string, options?: Partial<Omit<LoaderOptions, 'directory'>>):
|
|
17
|
+
export declare function createLoader(directory: string, options?: Partial<Omit<LoaderOptions, 'directory'>>): {
|
|
18
|
+
load: () => unknown;
|
|
19
|
+
loadLocale: (locale: string, filename: string) => unknown
|
|
20
|
+
};
|
|
18
21
|
/**
|
|
19
22
|
* Load translations via `@stacksjs/ts-i18n` and register them with the
|
|
20
23
|
* global translator. This is the recommended path for new projects —
|
package/dist/types.d.ts
CHANGED
|
@@ -1,151 +1,110 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Common locales with metadata
|
|
3
|
+
* @defaultValue
|
|
4
|
+
* ```ts
|
|
5
|
+
* {
|
|
6
|
+
* en: { code: 'en', name: 'English', nativeName: 'English', direction: 'ltr' },
|
|
7
|
+
* 'en-US': {
|
|
8
|
+
* code: 'en-US',
|
|
9
|
+
* name: 'English (US)',
|
|
10
|
+
* nativeName: 'English (US)',
|
|
11
|
+
* direction: 'ltr',
|
|
12
|
+
* region: 'US'
|
|
13
|
+
* },
|
|
14
|
+
* 'en-GB': {
|
|
15
|
+
* code: 'en-GB',
|
|
16
|
+
* name: 'English (UK)',
|
|
17
|
+
* nativeName: 'English (UK)',
|
|
18
|
+
* direction: 'ltr',
|
|
19
|
+
* region: 'GB'
|
|
20
|
+
* },
|
|
21
|
+
* es: { code: 'es', name: 'Spanish', nativeName: 'Espa\u00f1ol', direction: 'ltr' },
|
|
22
|
+
* fr: { code: 'fr', name: 'French', nativeName: 'Fran\u00e7ais', direction: 'ltr' },
|
|
23
|
+
* de: { code: 'de', name: 'German', nativeName: 'Deutsch', direction: 'ltr' },
|
|
24
|
+
* it: { code: 'it', name: 'Italian', nativeName: 'Italiano', direction: 'ltr' },
|
|
25
|
+
* pt: {
|
|
26
|
+
* code: 'pt',
|
|
27
|
+
* name: 'Portuguese',
|
|
28
|
+
* nativeName: 'Portugu\u00eas',
|
|
29
|
+
* direction: 'ltr'
|
|
30
|
+
* },
|
|
31
|
+
* 'pt-BR': {
|
|
32
|
+
* code: 'pt-BR',
|
|
33
|
+
* name: 'Portuguese (Brazil)',
|
|
34
|
+
* nativeName: 'Portugu\u00eas (Brasil)',
|
|
35
|
+
* direction: 'ltr',
|
|
36
|
+
* region: 'BR'
|
|
37
|
+
* },
|
|
38
|
+
* zh: { code: 'zh', name: 'Chinese', nativeName: '\u4e2d\u6587', direction: 'ltr' },
|
|
39
|
+
* 'zh-CN': {
|
|
40
|
+
* code: 'zh-CN',
|
|
41
|
+
* name: 'Chinese (Simplified)',
|
|
42
|
+
* nativeName: '\u7b80\u4f53\u4e2d\u6587',
|
|
43
|
+
* direction: 'ltr',
|
|
44
|
+
* region: 'CN'
|
|
45
|
+
* },
|
|
46
|
+
* 'zh-TW': {
|
|
47
|
+
* code: 'zh-TW',
|
|
48
|
+
* name: 'Chinese (Traditional)',
|
|
49
|
+
* nativeName: '\u7e41\u9ad4\u4e2d\u6587',
|
|
50
|
+
* direction: 'ltr',
|
|
51
|
+
* region: 'TW'
|
|
52
|
+
* },
|
|
53
|
+
* ja: {
|
|
54
|
+
* code: 'ja',
|
|
55
|
+
* name: 'Japanese',
|
|
56
|
+
* nativeName: '\u65e5\u672c\u8a9e',
|
|
57
|
+
* direction: 'ltr'
|
|
58
|
+
* },
|
|
59
|
+
* ko: {
|
|
60
|
+
* code: 'ko',
|
|
61
|
+
* name: 'Korean',
|
|
62
|
+
* nativeName: '\ud55c\uad6d\uc5b4',
|
|
63
|
+
* direction: 'ltr'
|
|
64
|
+
* },
|
|
65
|
+
* ar: {
|
|
66
|
+
* code: 'ar',
|
|
67
|
+
* name: 'Arabic',
|
|
68
|
+
* nativeName: '\u0627\u0644\u0639\u0631\u0628\u064a\u0629',
|
|
69
|
+
* direction: 'rtl'
|
|
70
|
+
* },
|
|
71
|
+
* he: {
|
|
72
|
+
* code: 'he',
|
|
73
|
+
* name: 'Hebrew',
|
|
74
|
+
* nativeName: '\u05e2\u05d1\u05e8\u05d9\u05ea',
|
|
75
|
+
* direction: 'rtl'
|
|
76
|
+
* },
|
|
77
|
+
* ru: {
|
|
78
|
+
* code: 'ru',
|
|
79
|
+
* name: 'Russian',
|
|
80
|
+
* nativeName: '\u0420\u0443\u0441\u0441\u043a\u0438\u0439',
|
|
81
|
+
* direction: 'ltr'
|
|
82
|
+
* },
|
|
83
|
+
* nl: { code: 'nl', name: 'Dutch', nativeName: 'Nederlands', direction: 'ltr' },
|
|
84
|
+
* pl: { code: 'pl', name: 'Polish', nativeName: 'Polski', direction: 'ltr' },
|
|
85
|
+
* tr: {
|
|
86
|
+
* code: 'tr',
|
|
87
|
+
* name: 'Turkish',
|
|
88
|
+
* nativeName: 'T\u00fcrk\u00e7e',
|
|
89
|
+
* direction: 'ltr'
|
|
90
|
+
* },
|
|
91
|
+
* vi: {
|
|
92
|
+
* code: 'vi',
|
|
93
|
+
* name: 'Vietnamese',
|
|
94
|
+
* nativeName: 'Ti\u1ebfng Vi\u1ec7t',
|
|
95
|
+
* direction: 'ltr'
|
|
96
|
+
* },
|
|
97
|
+
* th: { code: 'th', name: 'Thai', nativeName: '\u0e44\u0e17\u0e22', direction: 'ltr' },
|
|
98
|
+
* hi: {
|
|
99
|
+
* code: 'hi',
|
|
100
|
+
* name: 'Hindi',
|
|
101
|
+
* nativeName: '\u0939\u093f\u0928\u094d\u0926\u0940',
|
|
102
|
+
* direction: 'ltr'
|
|
103
|
+
* }
|
|
104
|
+
* }
|
|
105
|
+
* ```
|
|
3
106
|
*/
|
|
4
|
-
export declare const LOCALE_INFO:
|
|
5
|
-
en: {
|
|
6
|
-
code: 'en';
|
|
7
|
-
name: 'English';
|
|
8
|
-
nativeName: 'English';
|
|
9
|
-
direction: 'ltr'
|
|
10
|
-
};
|
|
11
|
-
'en-US': {
|
|
12
|
-
code: 'en-US';
|
|
13
|
-
name: 'English (US)';
|
|
14
|
-
nativeName: 'English (US)';
|
|
15
|
-
direction: 'ltr';
|
|
16
|
-
region: 'US'
|
|
17
|
-
};
|
|
18
|
-
'en-GB': {
|
|
19
|
-
code: 'en-GB';
|
|
20
|
-
name: 'English (UK)';
|
|
21
|
-
nativeName: 'English (UK)';
|
|
22
|
-
direction: 'ltr';
|
|
23
|
-
region: 'GB'
|
|
24
|
-
};
|
|
25
|
-
es: {
|
|
26
|
-
code: 'es';
|
|
27
|
-
name: 'Spanish';
|
|
28
|
-
nativeName: 'Espa\u00f1ol';
|
|
29
|
-
direction: 'ltr'
|
|
30
|
-
};
|
|
31
|
-
fr: {
|
|
32
|
-
code: 'fr';
|
|
33
|
-
name: 'French';
|
|
34
|
-
nativeName: 'Fran\u00e7ais';
|
|
35
|
-
direction: 'ltr'
|
|
36
|
-
};
|
|
37
|
-
de: {
|
|
38
|
-
code: 'de';
|
|
39
|
-
name: 'German';
|
|
40
|
-
nativeName: 'Deutsch';
|
|
41
|
-
direction: 'ltr'
|
|
42
|
-
};
|
|
43
|
-
it: {
|
|
44
|
-
code: 'it';
|
|
45
|
-
name: 'Italian';
|
|
46
|
-
nativeName: 'Italiano';
|
|
47
|
-
direction: 'ltr'
|
|
48
|
-
};
|
|
49
|
-
pt: {
|
|
50
|
-
code: 'pt';
|
|
51
|
-
name: 'Portuguese';
|
|
52
|
-
nativeName: 'Portugu\u00eas';
|
|
53
|
-
direction: 'ltr'
|
|
54
|
-
};
|
|
55
|
-
'pt-BR': {
|
|
56
|
-
code: 'pt-BR';
|
|
57
|
-
name: 'Portuguese (Brazil)';
|
|
58
|
-
nativeName: 'Portugu\u00eas (Brasil)';
|
|
59
|
-
direction: 'ltr';
|
|
60
|
-
region: 'BR'
|
|
61
|
-
};
|
|
62
|
-
zh: {
|
|
63
|
-
code: 'zh';
|
|
64
|
-
name: 'Chinese';
|
|
65
|
-
nativeName: '\u4e2d\u6587';
|
|
66
|
-
direction: 'ltr'
|
|
67
|
-
};
|
|
68
|
-
'zh-CN': {
|
|
69
|
-
code: 'zh-CN';
|
|
70
|
-
name: 'Chinese (Simplified)';
|
|
71
|
-
nativeName: '\u7b80\u4f53\u4e2d\u6587';
|
|
72
|
-
direction: 'ltr';
|
|
73
|
-
region: 'CN'
|
|
74
|
-
};
|
|
75
|
-
'zh-TW': {
|
|
76
|
-
code: 'zh-TW';
|
|
77
|
-
name: 'Chinese (Traditional)';
|
|
78
|
-
nativeName: '\u7e41\u9ad4\u4e2d\u6587';
|
|
79
|
-
direction: 'ltr';
|
|
80
|
-
region: 'TW'
|
|
81
|
-
};
|
|
82
|
-
ja: {
|
|
83
|
-
code: 'ja';
|
|
84
|
-
name: 'Japanese';
|
|
85
|
-
nativeName: '\u65e5\u672c\u8a9e';
|
|
86
|
-
direction: 'ltr'
|
|
87
|
-
};
|
|
88
|
-
ko: {
|
|
89
|
-
code: 'ko';
|
|
90
|
-
name: 'Korean';
|
|
91
|
-
nativeName: '\ud55c\uad6d\uc5b4';
|
|
92
|
-
direction: 'ltr'
|
|
93
|
-
};
|
|
94
|
-
ar: {
|
|
95
|
-
code: 'ar';
|
|
96
|
-
name: 'Arabic';
|
|
97
|
-
nativeName: '\u0627\u0644\u0639\u0631\u0628\u064a\u0629';
|
|
98
|
-
direction: 'rtl'
|
|
99
|
-
};
|
|
100
|
-
he: {
|
|
101
|
-
code: 'he';
|
|
102
|
-
name: 'Hebrew';
|
|
103
|
-
nativeName: '\u05e2\u05d1\u05e8\u05d9\u05ea';
|
|
104
|
-
direction: 'rtl'
|
|
105
|
-
};
|
|
106
|
-
ru: {
|
|
107
|
-
code: 'ru';
|
|
108
|
-
name: 'Russian';
|
|
109
|
-
nativeName: '\u0420\u0443\u0441\u0441\u043a\u0438\u0439';
|
|
110
|
-
direction: 'ltr'
|
|
111
|
-
};
|
|
112
|
-
nl: {
|
|
113
|
-
code: 'nl';
|
|
114
|
-
name: 'Dutch';
|
|
115
|
-
nativeName: 'Nederlands';
|
|
116
|
-
direction: 'ltr'
|
|
117
|
-
};
|
|
118
|
-
pl: {
|
|
119
|
-
code: 'pl';
|
|
120
|
-
name: 'Polish';
|
|
121
|
-
nativeName: 'Polski';
|
|
122
|
-
direction: 'ltr'
|
|
123
|
-
};
|
|
124
|
-
tr: {
|
|
125
|
-
code: 'tr';
|
|
126
|
-
name: 'Turkish';
|
|
127
|
-
nativeName: 'T\u00fcrk\u00e7e';
|
|
128
|
-
direction: 'ltr'
|
|
129
|
-
};
|
|
130
|
-
vi: {
|
|
131
|
-
code: 'vi';
|
|
132
|
-
name: 'Vietnamese';
|
|
133
|
-
nativeName: 'Ti\u1ebfng Vi\u1ec7t';
|
|
134
|
-
direction: 'ltr'
|
|
135
|
-
};
|
|
136
|
-
th: {
|
|
137
|
-
code: 'th';
|
|
138
|
-
name: 'Thai';
|
|
139
|
-
nativeName: '\u0e44\u0e17\u0e22';
|
|
140
|
-
direction: 'ltr'
|
|
141
|
-
};
|
|
142
|
-
hi: {
|
|
143
|
-
code: 'hi';
|
|
144
|
-
name: 'Hindi';
|
|
145
|
-
nativeName: '\u0939\u093f\u0928\u094d\u0926\u0940';
|
|
146
|
-
direction: 'ltr'
|
|
147
|
-
}
|
|
148
|
-
};
|
|
107
|
+
export declare const LOCALE_INFO: Record<string, LocaleInfo>;
|
|
149
108
|
/**
|
|
150
109
|
* Plural forms for a translation
|
|
151
110
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacksjs/i18n",
|
|
3
|
-
"version": "0.70.
|
|
3
|
+
"version": "0.70.74",
|
|
4
4
|
"description": "Internationalization system for Stacks.js applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -40,6 +40,6 @@
|
|
|
40
40
|
"@stacksjs/ts-i18n": "^0.1.9"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@stacksjs/development": "0.70.
|
|
43
|
+
"@stacksjs/development": "0.70.74"
|
|
44
44
|
}
|
|
45
45
|
}
|
package/src/bootstrap.ts
CHANGED
|
@@ -54,7 +54,7 @@ export function resolveRequestLocale(request?: Request): string {
|
|
|
54
54
|
if (available.has(normalized))
|
|
55
55
|
return normalized
|
|
56
56
|
const short = normalized.split('-')[0]
|
|
57
|
-
if (available.has(short))
|
|
57
|
+
if (short && available.has(short))
|
|
58
58
|
return short
|
|
59
59
|
return defaultLocale
|
|
60
60
|
}
|
package/src/formatter.ts
CHANGED
|
@@ -383,7 +383,7 @@ function toDate(date: Date | number | string): Date {
|
|
|
383
383
|
*/
|
|
384
384
|
export function getTextDirection(locale?: string): 'ltr' | 'rtl' {
|
|
385
385
|
const targetLocale = locale || getLocale()
|
|
386
|
-
const lang = targetLocale.split('-')[0].toLowerCase()
|
|
386
|
+
const lang = (targetLocale.split('-')[0] ?? targetLocale).toLowerCase()
|
|
387
387
|
|
|
388
388
|
// RTL languages
|
|
389
389
|
const rtlLanguages = ['ar', 'he', 'fa', 'ur', 'yi', 'ps', 'sd', 'ug', 'ku', 'ckb']
|
package/src/loader.ts
CHANGED
|
@@ -250,6 +250,7 @@ function setNested(
|
|
|
250
250
|
|
|
251
251
|
for (let i = 0; i < parts.length - 1; i++) {
|
|
252
252
|
const part = parts[i]
|
|
253
|
+
if (!part) continue
|
|
253
254
|
if (!current[part] || typeof current[part] === 'string') {
|
|
254
255
|
current[part] = {}
|
|
255
256
|
}
|
|
@@ -257,7 +258,7 @@ function setNested(
|
|
|
257
258
|
}
|
|
258
259
|
|
|
259
260
|
const lastPart = parts[parts.length - 1]
|
|
260
|
-
current[lastPart] = value
|
|
261
|
+
if (lastPart) current[lastPart] = value
|
|
261
262
|
}
|
|
262
263
|
|
|
263
264
|
/**
|
|
@@ -268,6 +269,7 @@ function deepMerge(target: TranslationMessages, source: TranslationMessages): Tr
|
|
|
268
269
|
|
|
269
270
|
for (const key of Object.keys(source)) {
|
|
270
271
|
const sourceValue = source[key]
|
|
272
|
+
if (sourceValue === undefined) continue
|
|
271
273
|
const targetValue = result[key]
|
|
272
274
|
|
|
273
275
|
if (
|
package/src/locale-switch.ts
CHANGED
|
@@ -14,7 +14,7 @@ function normalizeLocale(code: string, config: LocaleSwitchConfig): string | nul
|
|
|
14
14
|
if (config.locales.includes(normalized))
|
|
15
15
|
return normalized
|
|
16
16
|
const short = normalized.split('-')[0]
|
|
17
|
-
if (config.locales.includes(short))
|
|
17
|
+
if (short && config.locales.includes(short))
|
|
18
18
|
return short
|
|
19
19
|
return null
|
|
20
20
|
}
|
package/src/pluralization.ts
CHANGED
|
@@ -22,7 +22,7 @@ export function getPluralCategory(n: number, locale: string): PluralCategory {
|
|
|
22
22
|
*/
|
|
23
23
|
export function getPluralRule(locale: string): PluralRule {
|
|
24
24
|
// Get base language code
|
|
25
|
-
const lang = locale.split('-')[0].toLowerCase()
|
|
25
|
+
const lang = locale.split('-')[0]?.toLowerCase() ?? locale.toLowerCase()
|
|
26
26
|
|
|
27
27
|
const rule = pluralRules[lang]
|
|
28
28
|
if (rule) return rule
|
|
@@ -48,22 +48,25 @@ export function parsePluralForms(
|
|
|
48
48
|
const forms = new Map<PluralCategory, string>()
|
|
49
49
|
|
|
50
50
|
if (parts.length === 1) {
|
|
51
|
-
forms.set('other', parts[0])
|
|
51
|
+
forms.set('other', parts[0] ?? '')
|
|
52
52
|
}
|
|
53
53
|
else if (parts.length === 2) {
|
|
54
|
-
forms.set('one', parts[0])
|
|
55
|
-
forms.set('other', parts[1])
|
|
54
|
+
forms.set('one', parts[0] ?? '')
|
|
55
|
+
forms.set('other', parts[1] ?? '')
|
|
56
56
|
}
|
|
57
57
|
else if (parts.length === 3) {
|
|
58
|
-
forms.set('zero', parts[0])
|
|
59
|
-
forms.set('one', parts[1])
|
|
60
|
-
forms.set('other', parts[2])
|
|
58
|
+
forms.set('zero', parts[0] ?? '')
|
|
59
|
+
forms.set('one', parts[1] ?? '')
|
|
60
|
+
forms.set('other', parts[2] ?? '')
|
|
61
61
|
}
|
|
62
62
|
else if (parts.length >= 4) {
|
|
63
63
|
// Extended format: zero | one | two | few | many | other
|
|
64
64
|
const categories: PluralCategory[] = ['zero', 'one', 'two', 'few', 'many', 'other']
|
|
65
65
|
for (let i = 0; i < parts.length && i < categories.length; i++) {
|
|
66
|
-
|
|
66
|
+
const category = categories[i]
|
|
67
|
+
const part = parts[i]
|
|
68
|
+
if (category !== undefined && part !== undefined)
|
|
69
|
+
forms.set(category, part)
|
|
67
70
|
}
|
|
68
71
|
}
|
|
69
72
|
|
|
@@ -274,7 +277,7 @@ export function getSupportedPluralLocales(): string[] {
|
|
|
274
277
|
* Check if a locale has custom plural rules
|
|
275
278
|
*/
|
|
276
279
|
export function hasPluralRule(locale: string): boolean {
|
|
277
|
-
const lang = locale.split('-')[0].toLowerCase()
|
|
280
|
+
const lang = locale.split('-')[0]?.toLowerCase() ?? locale.toLowerCase()
|
|
278
281
|
return lang in pluralRules
|
|
279
282
|
}
|
|
280
283
|
|
|
@@ -282,6 +285,6 @@ export function hasPluralRule(locale: string): boolean {
|
|
|
282
285
|
* Add a custom plural rule for a locale
|
|
283
286
|
*/
|
|
284
287
|
export function addPluralRule(locale: string, rule: PluralRule): void {
|
|
285
|
-
const lang = locale.split('-')[0].toLowerCase()
|
|
288
|
+
const lang = locale.split('-')[0]?.toLowerCase() ?? locale.toLowerCase()
|
|
286
289
|
pluralRules[lang] = rule
|
|
287
290
|
}
|
package/src/translator.ts
CHANGED
|
@@ -92,7 +92,7 @@ export class I18n implements I18nInstance {
|
|
|
92
92
|
* Get translation message
|
|
93
93
|
*/
|
|
94
94
|
tm = (key: string, locale?: string): TranslationMessages | string | undefined => {
|
|
95
|
-
return this.getMessage(key, locale)
|
|
95
|
+
return this.getMessage(key, locale ?? this.locale)
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
/**
|
|
@@ -478,7 +478,8 @@ function deepMerge(target: TranslationMessages, source: TranslationMessages): Tr
|
|
|
478
478
|
)
|
|
479
479
|
}
|
|
480
480
|
else {
|
|
481
|
-
|
|
481
|
+
if (sourceValue !== undefined)
|
|
482
|
+
result[key] = sourceValue
|
|
482
483
|
}
|
|
483
484
|
}
|
|
484
485
|
|