@i18n-micro/core 1.0.27 → 1.0.28
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/base.d.ts +91 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.mjs +343 -246
- package/package.json +4 -4
- package/src/base.ts +250 -0
- package/src/index.ts +3 -0
- package/src/route-service.ts +5 -4
- package/tests/base.test.ts +510 -0
- package/tests/route-service.test.ts +23 -3
package/dist/base.d.ts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { useTranslationHelper, TranslationCache } from './translation';
|
|
2
|
+
import { FormatService } from './format-service';
|
|
3
|
+
import { Translations, Params, PluralFunc, CleanTranslation, TranslationKey, MissingHandler } from '@i18n-micro/types';
|
|
4
|
+
export interface BaseI18nOptions {
|
|
5
|
+
cache?: TranslationCache;
|
|
6
|
+
plural?: PluralFunc;
|
|
7
|
+
missingWarn?: boolean;
|
|
8
|
+
missingHandler?: (locale: string, key: string, routeName: string) => void;
|
|
9
|
+
getPreviousPageInfo?: () => {
|
|
10
|
+
locale: string;
|
|
11
|
+
routeName: string;
|
|
12
|
+
} | null;
|
|
13
|
+
getCustomMissingHandler?: () => MissingHandler | null;
|
|
14
|
+
enablePreviousPageFallback?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Abstract base class for i18n adapters
|
|
18
|
+
*
|
|
19
|
+
* Contains all common translation logic (t, ts, tc, tn, td, tdr, has).
|
|
20
|
+
* Adapters must implement abstract methods to provide current state (locale, fallbackLocale, route).
|
|
21
|
+
*/
|
|
22
|
+
export declare abstract class BaseI18n {
|
|
23
|
+
helper: ReturnType<typeof useTranslationHelper>;
|
|
24
|
+
formatter: FormatService;
|
|
25
|
+
pluralFunc: PluralFunc;
|
|
26
|
+
missingWarn: boolean;
|
|
27
|
+
missingHandler?: (locale: string, key: string, routeName: string) => void;
|
|
28
|
+
getPreviousPageInfo?: () => {
|
|
29
|
+
locale: string;
|
|
30
|
+
routeName: string;
|
|
31
|
+
} | null;
|
|
32
|
+
getCustomMissingHandler?: () => MissingHandler | null;
|
|
33
|
+
enablePreviousPageFallback: boolean;
|
|
34
|
+
constructor(options?: BaseI18nOptions);
|
|
35
|
+
/**
|
|
36
|
+
* Get current locale
|
|
37
|
+
*/
|
|
38
|
+
abstract getLocale(): string;
|
|
39
|
+
/**
|
|
40
|
+
* Get fallback locale
|
|
41
|
+
*/
|
|
42
|
+
abstract getFallbackLocale(): string;
|
|
43
|
+
/**
|
|
44
|
+
* Get current route name
|
|
45
|
+
*/
|
|
46
|
+
abstract getRoute(): string;
|
|
47
|
+
/**
|
|
48
|
+
* Get translation for a key
|
|
49
|
+
* Based on logic from src/runtime/plugins/01.plugin.ts
|
|
50
|
+
*/
|
|
51
|
+
t(key: TranslationKey, params?: Params, defaultValue?: string | null, routeName?: string): CleanTranslation;
|
|
52
|
+
/**
|
|
53
|
+
* Get translation as string
|
|
54
|
+
*/
|
|
55
|
+
ts(key: TranslationKey, params?: Params, defaultValue?: string, routeName?: string): string;
|
|
56
|
+
/**
|
|
57
|
+
* Plural translation
|
|
58
|
+
*/
|
|
59
|
+
tc(key: TranslationKey, count: number | Params, defaultValue?: string): string;
|
|
60
|
+
/**
|
|
61
|
+
* Format number
|
|
62
|
+
*/
|
|
63
|
+
tn(value: number, options?: Intl.NumberFormatOptions): string;
|
|
64
|
+
/**
|
|
65
|
+
* Format date
|
|
66
|
+
*/
|
|
67
|
+
td(value: Date | number | string, options?: Intl.DateTimeFormatOptions): string;
|
|
68
|
+
/**
|
|
69
|
+
* Format relative time
|
|
70
|
+
*/
|
|
71
|
+
tdr(value: Date | number | string, options?: Intl.RelativeTimeFormatOptions): string;
|
|
72
|
+
/**
|
|
73
|
+
* Check if translation exists
|
|
74
|
+
* Based on logic from src/runtime/plugins/01.plugin.ts
|
|
75
|
+
*/
|
|
76
|
+
has(key: TranslationKey, routeName?: string): boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Clear cache
|
|
79
|
+
*/
|
|
80
|
+
clearCache(): void;
|
|
81
|
+
/**
|
|
82
|
+
* Core translation loading logic (without reactivity)
|
|
83
|
+
* Subclasses can override addTranslations/addRouteTranslations to add reactivity
|
|
84
|
+
*/
|
|
85
|
+
loadTranslationsCore(locale: string, translations: Translations, merge: boolean): void;
|
|
86
|
+
/**
|
|
87
|
+
* Core route translation loading logic (without reactivity)
|
|
88
|
+
* Subclasses can override addRouteTranslations to add reactivity
|
|
89
|
+
*/
|
|
90
|
+
loadRouteTranslationsCore(locale: string, routeName: string, translations: Translations, merge: boolean): void;
|
|
91
|
+
}
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const R={},x={},P=[],w={};function b(a){return Array.isArray(a)||typeof a=="object"&&a!==null?JSON.parse(JSON.stringify(a)):a}function $(a,e){let r=a;if(a===null||typeof e!="string")return null;if(a[e])r=a[e];else{const n=e.toString().split(".");for(const i of n)if(r&&typeof r=="object"&&i in r)r=r[i];else return null}return typeof r=="object"&&r!==null?b(r):r??null}function C(a){return typeof a=="object"&&a!==null&&"value"in a?a.value:a}function m(a,e,r){const n=C(a);n[e]=r}function d(a,e){return C(a)[e]}function N(a){const e=(a==null?void 0:a.generalLocaleCache)??R,r=(a==null?void 0:a.routeLocaleCache)??x,n=(a==null?void 0:a.dynamicTranslationsCaches)??P,i=(a==null?void 0:a.serverTranslationCache)??w;return{hasCache(t,s){const o=`${t}:${s}`;return(d(i,o)??new Map).size>0},getCache(t,s){const o=`${t}:${s}`;return d(i,o)},setCache(t,s,o){const l=`${t}:${s}`;m(i,l,o)},mergeTranslation(t,s,o,l=!1){const u=`${t}:${s}`,c=d(r,u);(c||l)&&m(r,u,{...c??{},...o});const f=process.env.NODE_ENV!=="production";!c&&f&&console.warn(`[i18n] mergeTranslation called for '${u}' which was not pre-loaded. Skipping merge. Use force: true if this is intentional.`)},mergeGlobalTranslation(t,s,o=!1){const l=d(e,t);!o&&!l&&console.error(`marge: route ${t} not loaded`),m(e,t,{...l??{},...s})},hasGeneralTranslation(t){return!!d(e,t)},hasPageTranslation(t,s){const o=`${t}:${s}`;return!!d(r,o)},hasTranslation:(t,s)=>{const o=C(n);for(const u of o)if($(u[t]||null,s)!==null)return!0;const l=d(e,t);return $(l||null,s)!==null},getTranslation:(t,s,o)=>{const l=`${t}:${s}`,u=d(i,l),c=u==null?void 0:u.get(o);if(c)return c;let f=null;const v=C(n);for(const g of v)if(f=$(g[t]||null,o),f!==null)break;if(!f){const g=d(r,l),p=d(e,t);f=$(g||null,o)??$(p||null,o)}if(f){const g=u??new Map;g.set(o,f),m(i,l,g)}return f},async loadPageTranslations(t,s,o){const l=`${t}:${s}`;m(r,l,{...o})},async loadTranslations(t,s){m(e,t,{...s})},clearCache(){const t=C(e);Object.keys(t).forEach(u=>{m(e,u,{})});const s=C(r);Object.keys(s).forEach(u=>{m(r,u,{})});const o=C(n);o.length=0;const l=C(i);Object.keys(l).forEach(u=>{const c=d(i,u);c==null||c.clear()})}}}function T(a,e){let r=a;for(const n in e)r=r.split(`{${n}}`).join(String(e[n]));return r}function y(a){return a==="prefix"||a==="prefix_and_default"}function h(a){return a==="no_prefix"}function D(a){return a==="prefix"}function L(a){return a==="prefix_except_default"}function q(a){return a==="prefix_and_default"}const z=(a,e,r,n,i)=>{const t=i(a,r);if(!t)return null;const s=t.toString().split("|");if(s.length===0)return null;const o=e<s.length?s[e]:s[s.length-1];return o?o.trim().replace("{count}",e.toString()):null};class F{constructor(e,r,n,i,t,s,o=null,l=null){this.i18nConfig=e,this.router=r,this.hashLocaleDefault=n,this.noPrefixDefault=i,this.navigateTo=t,this.setCookie=s,this.cookieLocaleDefault=o,this.cookieLocaleName=l}extractLocaleFromPath(e){var o,l;if(!e)return null;const n=(o=e.split("?")[0])==null?void 0:o.split("#")[0];if(!n||n==="/")return null;const i=n.split("/").filter(Boolean);if(i.length===0)return null;const t=i[0];return t&&(((l=this.i18nConfig.locales)==null?void 0:l.map(u=>u.code))||[]).includes(t)?t:null}getCurrentLocale(e){var i;if(e=e??this.router.currentRoute.value,this.i18nConfig.hashMode&&this.hashLocaleDefault)return this.hashLocaleDefault;if(h(this.i18nConfig.strategy)&&this.noPrefixDefault)return this.noPrefixDefault;if((i=e.params)!=null&&i.locale)return e.params.locale.toString();const r=e.path||e.fullPath||"",n=this.extractLocaleFromPath(r);return n||(this.cookieLocaleDefault?this.cookieLocaleDefault:(this.i18nConfig.defaultLocale||"en").toString())}getCurrentName(e){var i;const r=this.getCurrentLocale(e),n=(i=this.i18nConfig.locales)==null?void 0:i.find(t=>t.code===r);return(n==null?void 0:n.displayName)??null}getRouteName(e,r){return(e.name??"").toString().toString().replace("localized-","").replace(new RegExp(`-${r}$`),"")}getPluginRouteName(e,r){return this.i18nConfig.disablePageLocales?"general":this.getRouteName(e,r)}getFullPathWithBaseUrl(e,r){let i=this.router.resolve(r).fullPath;e!=null&&e.baseDefault&&(i=i.replace(new RegExp(`^/${e.code}`),""));let t=e.baseUrl;return t||(t=""),t!=null&&t.endsWith("/")&&(t=t.slice(0,-1)),t+i}switchLocaleRoute(e,r,n,i){var f,v;const t=(f=this.i18nConfig.locales)==null?void 0:f.find(g=>g.code===r),s=this.getRouteName(n,e);if(this.router.hasRoute(`localized-${s}-${r}`)){const p={...i!=null&&i[r]?{...i[r]}:{...n.params??{}}};delete p.locale,h(this.i18nConfig.strategy)||(p.locale=r);const S={name:`localized-${s}-${r}`,params:p,query:n.query,hash:n.hash};return t!=null&&t.baseUrl?this.getFullPathWithBaseUrl(t,S):S}let o=s;const u={...i!=null&&i[r]?{...i[r]}:{...n.params??{}}};delete u.locale,h(this.i18nConfig.strategy)||(s==="custom-fallback-route"?o=s:o=r!==this.i18nConfig.defaultLocale||y(this.i18nConfig.strategy)?`localized-${s}`:s,h(this.i18nConfig.strategy)||(r!==this.i18nConfig.defaultLocale||y(this.i18nConfig.strategy))&&(u.locale=r));const c={name:o,params:u,query:n.query,hash:n.hash};return h(this.i18nConfig.strategy)&&((v=this.i18nConfig.locales)==null||v.forEach((g,p)=>{c.name.endsWith(`-${g.code}`)&&(c.name=c.name.slice(0,-g.code-1))})),t!=null&&t.baseUrl?this.getFullPathWithBaseUrl(t,c):c}resolveParams(e){const r=typeof e=="object"&&"params"in e&&typeof e.params=="object"?{...e.params}:{};if(typeof e=="string"){const n=this.router.resolve(e);n&&n.params&&Object.assign(r,n.params)}return r}handlePrefixStrategy(e){if(!y(this.i18nConfig.strategy))return e;const r=this.i18nConfig.defaultLocale;let n=e;typeof e=="string"&&(n=this.router.resolve("/"+r+e));const i=this.getRouteName(n,r),t=this.resolveParams(n);return h(this.i18nConfig.strategy)||(t.locale=r),this.router.hasRoute(`localized-${i}`)?this.router.resolve({name:`localized-${i}`,query:n.query,hash:n.hash,params:t}):this.router.hasRoute(`localized-${i}-${r}`)?this.router.resolve({name:`localized-${i}-${r}`,query:n.query,hash:n.hash,params:t}):e}createLocalizedRoute(e,r,n){const i=this.router.resolve(e),t=this.getRouteName(i,n).replace(new RegExp(`-${this.i18nConfig.defaultLocale}$`),"");if(!h(this.i18nConfig.strategy)&&(!t||t==="")){let u=this.router.resolve(e).path.replace(new RegExp(`^/${n}/`),"/");return(n!==this.i18nConfig.defaultLocale||y(this.i18nConfig.strategy))&&(u="/"+n+u),this.router.resolve({path:u,query:i.query,hash:i.hash})}if(this.router.hasRoute(`localized-${t}-${n}`)){const l=this.resolveParams(i);return h(this.i18nConfig.strategy)||(l.locale=n),this.router.resolve({name:`localized-${t}-${n}`,params:l,query:i.query,hash:i.hash})}const s=n!==this.i18nConfig.defaultLocale||y(this.i18nConfig.strategy)?`localized-${t}`:t;if(!this.router.hasRoute(s)){const l=this.resolveParams(e);return delete l.locale,this.router.hasRoute(t)?this.router.resolve({name:t,params:l,query:i.query,hash:i.hash}):this.router.resolve("/")}const o=this.resolveParams(e);return delete o.locale,h(this.i18nConfig.strategy)||(n!==this.i18nConfig.defaultLocale||y(this.i18nConfig.strategy))&&(o.locale=n),this.router.resolve({name:s,params:o,query:i.query,hash:i.hash})}getLocalizedRoute(e,r,n){const i=n||this.getCurrentLocale(r),t=this.handlePrefixStrategy(e);return this.createLocalizedRoute(t,r,i)}updateCookies(e){this.i18nConfig.hashMode&&(this.setCookie("hash-locale",e),this.hashLocaleDefault=e),h(this.i18nConfig.strategy)&&(this.setCookie("no-prefix-locale",e),this.noPrefixDefault=e),!this.i18nConfig.hashMode&&!h(this.i18nConfig.strategy)&&this.cookieLocaleName&&(this.setCookie(this.cookieLocaleName,e),this.cookieLocaleDefault=e)}getCurrentRoute(){return this.router.currentRoute.value}resolveRouteWithStrategy(e,r,n){return h(this.i18nConfig.strategy)?this.router.resolve(e):r!==this.i18nConfig.defaultLocale||y(this.i18nConfig.strategy)?this.router.resolve(`/${n}${e}`):this.router.resolve(e)}switchLocaleLogic(e,r,n){const i=this.getCurrentLocale();let t;typeof n=="string"?t=this.resolveRouteWithStrategy(n,e,i):t=n??this.getCurrentRoute(),this.updateCookies(e);const s=this.switchLocaleRoute(i,e,t,r);return typeof s=="string"&&s.startsWith("http")?this.navigateTo(s,{redirectCode:200,external:!0}):(h(this.i18nConfig.strategy)&&(s.force=!0),this.router.push(s))}resolveLocalizedRoute(e,r){const n=this.getCurrentRoute(),i=this.getCurrentLocale(),t=r??i;let s;if(typeof e=="string")if(e.startsWith("/"))s=this.resolveRouteWithStrategy(e,t,i);else{const o=e;this.router.hasRoute(o)?s=this.router.resolve({name:o}):(e=`/${e}`,s=this.resolveRouteWithStrategy(e,t,i))}else s=e;return this.getLocalizedRoute(s,n,t)}}class j{formatNumber(e,r,n){return new Intl.NumberFormat(r,n).format(e)}formatDate(e,r,n){const i=new Date(e);return Number.isNaN(i.getTime())?"Invalid Date":new Intl.DateTimeFormat(r,n).format(i)}formatRelativeTime(e,r,n){const i=new Date(e);if(Number.isNaN(i.getTime()))return new Intl.RelativeTimeFormat(r,n).format(0,"second");const s=Math.floor((new Date().getTime()-i.getTime())/1e3),o=[{unit:"year",seconds:31536e3},{unit:"month",seconds:2592e3},{unit:"day",seconds:86400},{unit:"hour",seconds:3600},{unit:"minute",seconds:60},{unit:"second",seconds:1}];for(const{unit:l,seconds:u}of o){const c=Math.floor(s/u);if(c>=1)return new Intl.RelativeTimeFormat(r,n).format(-c,l)}return new Intl.RelativeTimeFormat(r,n).format(0,"second")}}exports.FormatService=j;exports.RouteService=F;exports.defaultPlural=z;exports.interpolate=T;exports.isNoPrefixStrategy=h;exports.isPrefixAndDefaultStrategy=q;exports.isPrefixExceptDefaultStrategy=L;exports.isPrefixStrategy=D;exports.useTranslationHelper=N;exports.withPrefixStrategy=y;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const L={},T={},N=[],w={};function x(o){return Array.isArray(o)||typeof o=="object"&&o!==null?JSON.parse(JSON.stringify(o)):o}function v(o,e){let t=o;if(o===null||typeof e!="string")return null;if(o[e])t=o[e];else{const r=e.toString().split(".");for(const n of r)if(t&&typeof t=="object"&&n in t)t=t[n];else return null}return typeof t=="object"&&t!==null?x(t):t??null}function C(o){return typeof o=="object"&&o!==null&&"value"in o?o.value:o}function d(o,e,t){const r=C(o);r[e]=t}function g(o,e){return C(o)[e]}function R(o){const e=o?.generalLocaleCache??L,t=o?.routeLocaleCache??T,r=o?.dynamicTranslationsCaches??N,n=o?.serverTranslationCache??w;return{hasCache(s,i){const a=`${s}:${i}`;return(g(n,a)??new Map).size>0},getCache(s,i){const a=`${s}:${i}`;return g(n,a)},setCache(s,i,a){const l=`${s}:${i}`;d(n,l,a)},mergeTranslation(s,i,a,l=!1){const c=`${s}:${i}`,u=g(t,c);(u||l)&&d(t,c,{...u??{},...a});const h=process.env.NODE_ENV!=="production";!u&&h&&console.warn(`[i18n] mergeTranslation called for '${c}' which was not pre-loaded. Skipping merge. Use force: true if this is intentional.`)},mergeGlobalTranslation(s,i,a=!1){const l=g(e,s);!a&&!l&&console.error(`marge: route ${s} not loaded`),d(e,s,{...l??{},...i})},hasGeneralTranslation(s){return!!g(e,s)},hasPageTranslation(s,i){const a=`${s}:${i}`;return!!g(t,a)},hasTranslation:(s,i)=>{const a=C(r);for(const c of a)if(v(c[s]||null,i)!==null)return!0;const l=g(e,s);return v(l||null,i)!==null},getTranslation:(s,i,a)=>{const l=`${s}:${i}`,c=g(n,l),u=c?.get(a);if(u)return u;let h=null;const y=C(r);for(const m of y)if(h=v(m[s]||null,a),h!==null)break;if(!h){const m=g(t,l),S=g(e,s);h=v(m||null,a)??v(S||null,a)}if(h){const m=c??new Map;m.set(a,h),d(n,l,m)}return h},async loadPageTranslations(s,i,a){const l=`${s}:${i}`;d(t,l,{...a})},async loadTranslations(s,i){d(e,s,{...i})},clearCache(){const s=C(e);Object.keys(s).forEach(c=>{d(e,c,{})});const i=C(t);Object.keys(i).forEach(c=>{d(t,c,{})});const a=C(r);a.length=0;const l=C(n);Object.keys(l).forEach(c=>{g(n,c)?.clear()})}}}function b(o,e){let t=o;for(const r in e)t=t.split(`{${r}}`).join(String(e[r]));return t}function p(o){return o==="prefix"||o==="prefix_and_default"}function f(o){return o==="no_prefix"}function D(o){return o==="prefix"}function F(o){return o==="prefix_except_default"}function q(o){return o==="prefix_and_default"}const $=(o,e,t,r,n)=>{const s=n(o,t);if(!s)return null;const i=s.toString().split("|");if(i.length===0)return null;const a=e<i.length?i[e]:i[i.length-1];return a?a.trim().replace("{count}",e.toString()):null};class z{constructor(e,t,r,n,s,i,a=null,l=null){this.i18nConfig=e,this.router=t,this.hashLocaleDefault=r,this.noPrefixDefault=n,this.navigateTo=s,this.setCookie=i,this.cookieLocaleDefault=a,this.cookieLocaleName=l}extractLocaleFromPath(e){if(!e)return null;const r=e.split("?")[0]?.split("#")[0];if(!r||r==="/")return null;const n=r.split("/").filter(Boolean);if(n.length===0)return null;const s=n[0];return s&&(this.i18nConfig.locales?.map(a=>a.code)||[]).includes(s)?s:null}getCurrentLocale(e){if(e=e??this.router.currentRoute.value,this.i18nConfig.hashMode&&this.hashLocaleDefault)return this.hashLocaleDefault;if(f(this.i18nConfig.strategy)&&this.noPrefixDefault)return this.noPrefixDefault;if(e.params?.locale)return e.params.locale.toString();const t=e.path||e.fullPath||"",r=this.extractLocaleFromPath(t);return r||(this.cookieLocaleDefault?this.cookieLocaleDefault:(this.i18nConfig.defaultLocale||"en").toString())}getCurrentName(e){const t=this.getCurrentLocale(e);return this.i18nConfig.locales?.find(n=>n.code===t)?.displayName??null}getRouteName(e,t){return(e.name??"").toString().toString().replace("localized-","").replace(new RegExp(`-${t}$`),"")}getPluginRouteName(e,t){return this.i18nConfig.disablePageLocales?"general":this.getRouteName(e,t)}getFullPathWithBaseUrl(e,t){let n=this.router.resolve(t).fullPath;e?.baseDefault&&(n=n.replace(new RegExp(`^/${e.code}`),""));let s=e.baseUrl;return s||(s=""),s?.endsWith("/")&&(s=s.slice(0,-1)),s+n}switchLocaleRoute(e,t,r,n){const s=this.i18nConfig.locales?.find(h=>h.code===t),i=this.getRouteName(r,e);if(this.router.hasRoute(`localized-${i}-${t}`)){const y={...n?.[t]?{...n[t]}:{...r.params??{}}};delete y.locale,f(this.i18nConfig.strategy)||(y.locale=t);const m={name:`localized-${i}-${t}`,params:y,query:r.query,hash:r.hash};return s?.baseUrl?this.getFullPathWithBaseUrl(s,m):m}let a=i;const c={...n?.[t]?{...n[t]}:{...r.params??{}}};delete c.locale,f(this.i18nConfig.strategy)||(i==="custom-fallback-route"?a=i:a=t!==this.i18nConfig.defaultLocale||p(this.i18nConfig.strategy)?`localized-${i}`:i,f(this.i18nConfig.strategy)||(t!==this.i18nConfig.defaultLocale||p(this.i18nConfig.strategy))&&(c.locale=t));const u={name:a,params:c,query:r.query,hash:r.hash};return f(this.i18nConfig.strategy)&&this.i18nConfig.locales?.forEach((h,y)=>{u.name.endsWith(`-${h.code}`)&&(u.name=u.name.slice(0,-h.code-1))}),s?.baseUrl?this.getFullPathWithBaseUrl(s,u):u}resolveParams(e){const t=typeof e=="object"&&"params"in e&&typeof e.params=="object"?{...e.params}:{};if(typeof e=="string"){const r=this.router.resolve(e);r&&r.params&&Object.assign(t,r.params)}return t}handlePrefixStrategy(e){if(!p(this.i18nConfig.strategy))return e;const t=this.i18nConfig.defaultLocale;let r=e;typeof e=="string"&&(r=this.router.resolve("/"+t+e));const n=this.getRouteName(r,t),s=this.resolveParams(r);return f(this.i18nConfig.strategy)||(s.locale=t),this.router.hasRoute(`localized-${n}`)?this.router.resolve({name:`localized-${n}`,query:r.query,hash:r.hash,params:s}):this.router.hasRoute(`localized-${n}-${t}`)?this.router.resolve({name:`localized-${n}-${t}`,query:r.query,hash:r.hash,params:s}):e}createLocalizedRoute(e,t,r){const n=this.router.resolve(e),s=this.getRouteName(n,r).replace(new RegExp(`-${this.i18nConfig.defaultLocale}$`),"");if(!f(this.i18nConfig.strategy)&&(!s||s==="")){let c=this.router.resolve(e).path.replace(new RegExp(`^/${r}/`),"/");return(r!==this.i18nConfig.defaultLocale||p(this.i18nConfig.strategy))&&(c="/"+r+c),this.router.resolve({path:c,query:n.query,hash:n.hash})}if(this.router.hasRoute(`localized-${s}-${r}`)){const l=this.resolveParams(n);return f(this.i18nConfig.strategy)||(l.locale=r),this.router.resolve({name:`localized-${s}-${r}`,params:l,query:n.query,hash:n.hash})}const i=r!==this.i18nConfig.defaultLocale||p(this.i18nConfig.strategy)?`localized-${s}`:s;if(!this.router.hasRoute(i)){const l=this.resolveParams(e);return delete l.locale,this.router.hasRoute(s)?this.router.resolve({name:s,params:l,query:n.query,hash:n.hash}):this.router.resolve("/")}const a=this.resolveParams(e);return delete a.locale,f(this.i18nConfig.strategy)||(r!==this.i18nConfig.defaultLocale||p(this.i18nConfig.strategy))&&(a.locale=r),this.router.resolve({name:i,params:a,query:n.query,hash:n.hash})}getLocalizedRoute(e,t,r){const n=r||this.getCurrentLocale(t),s=this.handlePrefixStrategy(e);return this.createLocalizedRoute(s,t,n)}updateCookies(e){const t=this.cookieLocaleName||this.i18nConfig.localeCookie||"user-locale";this.i18nConfig.hashMode&&(this.setCookie("hash-locale",e),this.hashLocaleDefault=e),f(this.i18nConfig.strategy)&&(this.setCookie(t,e),this.noPrefixDefault=e),!this.i18nConfig.hashMode&&!f(this.i18nConfig.strategy)&&t&&(this.setCookie(t,e),this.cookieLocaleDefault=e)}getCurrentRoute(){return this.router.currentRoute.value}resolveRouteWithStrategy(e,t,r){return f(this.i18nConfig.strategy)?this.router.resolve(e):t!==this.i18nConfig.defaultLocale||p(this.i18nConfig.strategy)?this.router.resolve(`/${r}${e}`):this.router.resolve(e)}switchLocaleLogic(e,t,r){const n=this.getCurrentLocale();let s;typeof r=="string"?s=this.resolveRouteWithStrategy(r,e,n):s=r??this.getCurrentRoute(),this.updateCookies(e);const i=this.switchLocaleRoute(n,e,s,t);return typeof i=="string"&&i.startsWith("http")?this.navigateTo(i,{redirectCode:200,external:!0}):(f(this.i18nConfig.strategy)&&(i.force=!0),this.router.push(i))}resolveLocalizedRoute(e,t){const r=this.getCurrentRoute(),n=this.getCurrentLocale(),s=t??n;let i;if(typeof e=="string")if(e.startsWith("/"))i=this.resolveRouteWithStrategy(e,s,n);else{const a=e;this.router.hasRoute(a)?i=this.router.resolve({name:a}):(e=`/${e}`,i=this.resolveRouteWithStrategy(e,s,n))}else i=e;return this.getLocalizedRoute(i,r,s)}}class P{formatNumber(e,t,r){return new Intl.NumberFormat(t,r).format(e)}formatDate(e,t,r){const n=new Date(e);return Number.isNaN(n.getTime())?"Invalid Date":new Intl.DateTimeFormat(t,r).format(n)}formatRelativeTime(e,t,r){const n=new Date(e);if(Number.isNaN(n.getTime()))return new Intl.RelativeTimeFormat(t,r).format(0,"second");const i=Math.floor((new Date().getTime()-n.getTime())/1e3),a=[{unit:"year",seconds:31536e3},{unit:"month",seconds:2592e3},{unit:"day",seconds:86400},{unit:"hour",seconds:3600},{unit:"minute",seconds:60},{unit:"second",seconds:1}];for(const{unit:l,seconds:c}of a){const u=Math.floor(i/c);if(u>=1)return new Intl.RelativeTimeFormat(t,r).format(-u,l)}return new Intl.RelativeTimeFormat(t,r).format(0,"second")}}class E{constructor(e={}){this.formatter=new P,this.helper=R(e.cache),this.formatter=new P,this.pluralFunc=e.plural||$,this.missingWarn=e.missingWarn??!0,this.missingHandler=e.missingHandler,this.getPreviousPageInfo=e.getPreviousPageInfo,this.getCustomMissingHandler=e.getCustomMissingHandler,this.enablePreviousPageFallback=e.enablePreviousPageFallback??!1}t(e,t,r,n){if(!e)return"";const s=this.getLocale(),i=n||this.getRoute();let a=this.helper.getTranslation(s,i,e);if(!a&&this.enablePreviousPageFallback&&this.getPreviousPageInfo){const l=this.getPreviousPageInfo();if(l){const c=this.helper.getTranslation(l.locale,l.routeName,e);c&&(a=c,process.env.NODE_ENV!=="production"&&console.log(`Using fallback translation from previous route: ${l.routeName} -> ${e}`))}}if(!a){const l=this.getFallbackLocale();s!==l&&(a=this.helper.getTranslation(l,i,e))}if(!a){const l=this.getCustomMissingHandler?.();l?l(s,e,i):this.missingHandler?this.missingHandler(s,e,i):this.missingWarn&&process.env.NODE_ENV!=="production"&&typeof window<"u"&&console.warn(`Not found '${e}' key in '${s}' locale messages for route '${i}'.`),a=r===void 0?e:r||e}return typeof a=="string"&&t?b(a,t):a}ts(e,t,r,n){return this.t(e,t,r,n)?.toString()??r??e}tc(e,t,r){const{count:n,...s}=typeof t=="number"?{count:t}:t;if(n===void 0)return r??e;const i=(l,c,u)=>this.t(l,c,u);return this.pluralFunc(e,Number.parseInt(n.toString()),s,this.getLocale(),i)??r??e}tn(e,t){return this.formatter.formatNumber(e,this.getLocale(),t)}td(e,t){return this.formatter.formatDate(e,this.getLocale(),t)}tdr(e,t){return this.formatter.formatRelativeTime(e,this.getLocale(),t)}has(e,t){const r=t||this.getRoute(),n=this.getLocale();return!!this.helper.getTranslation(n,r,e)}clearCache(){this.helper.clearCache()}loadTranslationsCore(e,t,r){r?this.helper.mergeGlobalTranslation(e,t,!0):this.helper.loadTranslations(e,t)}loadRouteTranslationsCore(e,t,r,n){n?this.helper.mergeTranslation(e,t,r,!0):this.helper.loadPageTranslations(e,t,r)}}exports.BaseI18n=E;exports.FormatService=P;exports.RouteService=z;exports.defaultPlural=$;exports.interpolate=b;exports.isNoPrefixStrategy=f;exports.isPrefixAndDefaultStrategy=q;exports.isPrefixExceptDefaultStrategy=F;exports.isPrefixStrategy=D;exports.useTranslationHelper=R;exports.withPrefixStrategy=p;
|
package/dist/index.d.ts
CHANGED
|
@@ -2,4 +2,5 @@ import { useTranslationHelper, TranslationCache } from './translation';
|
|
|
2
2
|
import { RouteService } from './route-service';
|
|
3
3
|
import { FormatService } from './format-service';
|
|
4
4
|
import { interpolate, withPrefixStrategy, isNoPrefixStrategy, isPrefixStrategy, isPrefixExceptDefaultStrategy, isPrefixAndDefaultStrategy, defaultPlural } from './helpers';
|
|
5
|
-
|
|
5
|
+
import { BaseI18n, BaseI18nOptions } from './base';
|
|
6
|
+
export { useTranslationHelper, interpolate, withPrefixStrategy, isNoPrefixStrategy, isPrefixStrategy, isPrefixExceptDefaultStrategy, isPrefixAndDefaultStrategy, defaultPlural, RouteService, FormatService, BaseI18n, type TranslationCache, type BaseI18nOptions, };
|