@i18n-micro/core 1.3.0 → 1.3.2
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/README.md +7 -8
- package/dist/base.d.ts +30 -5
- package/dist/helpers-entry.d.ts +1 -0
- package/dist/helpers.cjs +1 -0
- package/dist/helpers.d.cts +27 -0
- package/dist/helpers.d.ts +9 -0
- package/dist/helpers.mjs +74 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +130 -131
- package/package.json +60 -12
- package/fix.ts +0 -1
- package/jest.config.cjs +0 -7
- package/src/base.ts +0 -194
- package/src/format-service.ts +0 -41
- package/src/helpers.ts +0 -54
- package/src/index.ts +0 -27
- package/src/translation.ts +0 -95
- package/tests/base.test.ts +0 -464
- package/tests/core.test.ts +0 -81
- package/tests/format-service.test.ts +0 -101
- package/tests/helpers.test.ts +0 -103
- package/tsconfig.json +0 -24
- package/vite.config.mts +0 -22
package/README.md
CHANGED
|
@@ -67,14 +67,7 @@ console.log(formattedDate) // '10/5/2023'
|
|
|
67
67
|
console.log(formattedRelativeTime) // 'just now'
|
|
68
68
|
|
|
69
69
|
// Handle locale-specific routing
|
|
70
|
-
const routeService = new RouteService(
|
|
71
|
-
i18nConfig,
|
|
72
|
-
router,
|
|
73
|
-
hashLocaleDefault,
|
|
74
|
-
noPrefixDefault,
|
|
75
|
-
navigateTo,
|
|
76
|
-
setCookie
|
|
77
|
-
)
|
|
70
|
+
const routeService = new RouteService(i18nConfig, router, hashLocaleDefault, noPrefixDefault, navigateTo, setCookie)
|
|
78
71
|
|
|
79
72
|
const localizedRoute = routeService.getLocalizedRoute('/about', currentRoute, 'en')
|
|
80
73
|
console.log(localizedRoute) // Localized route object
|
|
@@ -85,6 +78,7 @@ console.log(localizedRoute) // Localized route object
|
|
|
85
78
|
### `useTranslationHelper`
|
|
86
79
|
|
|
87
80
|
#### Methods
|
|
81
|
+
|
|
88
82
|
- **`hasCache(locale: string, page: string): boolean`**:
|
|
89
83
|
Checks if translations for a specific route and locale are cached.
|
|
90
84
|
- **`getCache(locale: string, routeName: string): Map<string, Translations | unknown> | undefined`**:
|
|
@@ -107,13 +101,16 @@ console.log(localizedRoute) // Localized route object
|
|
|
107
101
|
### `interpolate`
|
|
108
102
|
|
|
109
103
|
#### Function
|
|
104
|
+
|
|
110
105
|
```typescript
|
|
111
106
|
interpolate(template: string, params: Params): string
|
|
112
107
|
```
|
|
108
|
+
|
|
113
109
|
- **`template`**: The translation string with placeholders (e.g., `'Hello, {name}!'`).
|
|
114
110
|
- **`params`**: An object containing key-value pairs for interpolation (e.g., `{ name: 'John' }`).
|
|
115
111
|
|
|
116
112
|
#### Example
|
|
113
|
+
|
|
117
114
|
```typescript
|
|
118
115
|
const result = interpolate('Hello, {name}!', { name: 'John' })
|
|
119
116
|
console.log(result) // 'Hello, John!'
|
|
@@ -122,6 +119,7 @@ console.log(result) // 'Hello, John!'
|
|
|
122
119
|
### `FormatService`
|
|
123
120
|
|
|
124
121
|
#### Methods
|
|
122
|
+
|
|
125
123
|
- **`formatNumber(value: number, locale: string, options?: Intl.NumberFormatOptions): string`**:
|
|
126
124
|
Formats a number according to the specified locale and options.
|
|
127
125
|
- **`formatDate(value: Date | number | string, locale: string, options?: Intl.DateTimeFormatOptions): string`**:
|
|
@@ -132,6 +130,7 @@ console.log(result) // 'Hello, John!'
|
|
|
132
130
|
### `RouteService`
|
|
133
131
|
|
|
134
132
|
#### Methods
|
|
133
|
+
|
|
135
134
|
- **`getCurrentLocale(route?: RouteLocationNormalizedLoaded | RouteLocationResolvedGeneric): string`**:
|
|
136
135
|
Returns the current locale based on the route or configuration.
|
|
137
136
|
- **`getCurrentName(route: RouteLocationNormalizedLoaded | RouteLocationResolvedGeneric): string | null`**:
|
package/dist/base.d.ts
CHANGED
|
@@ -34,15 +34,41 @@ export declare abstract class BaseI18n {
|
|
|
34
34
|
* Get current route name
|
|
35
35
|
*/
|
|
36
36
|
abstract getRoute(): string;
|
|
37
|
+
/**
|
|
38
|
+
* Called before translation lookup — subclasses use for reactivity tracking.
|
|
39
|
+
*/
|
|
40
|
+
protected touch(): void;
|
|
41
|
+
/**
|
|
42
|
+
* Resolve route name from optional route context (string route name or adapter-specific object).
|
|
43
|
+
*/
|
|
44
|
+
protected resolveRouteName(routeContext?: unknown): string;
|
|
45
|
+
/**
|
|
46
|
+
* Lookup translation value. Returns null when missing.
|
|
47
|
+
*/
|
|
48
|
+
protected resolveLookup(key: TranslationKey, routeContext?: unknown): unknown | null;
|
|
49
|
+
/**
|
|
50
|
+
* Check if translation exists in lookup source.
|
|
51
|
+
*/
|
|
52
|
+
protected resolveHas(key: TranslationKey, routeContext?: unknown): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Context passed to missing-key handlers.
|
|
55
|
+
*/
|
|
56
|
+
protected getMissingContext(routeContext?: unknown): {
|
|
57
|
+
locale: string;
|
|
58
|
+
routeName: string;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Warn or invoke handler when translation is missing.
|
|
62
|
+
*/
|
|
63
|
+
protected warnMissing(key: TranslationKey, routeContext?: unknown): void;
|
|
37
64
|
/**
|
|
38
65
|
* Get translation for a key
|
|
39
|
-
* Based on logic from src/runtime/plugins/01.plugin.ts
|
|
40
66
|
*/
|
|
41
|
-
t(key: TranslationKey, params?: Params, defaultValue?: string | null,
|
|
67
|
+
t(key: TranslationKey, params?: Params, defaultValue?: string | null, routeContext?: unknown): CleanTranslation;
|
|
42
68
|
/**
|
|
43
69
|
* Get translation as string
|
|
44
70
|
*/
|
|
45
|
-
ts(key: TranslationKey, params?: Params, defaultValue?: string,
|
|
71
|
+
ts(key: TranslationKey, params?: Params, defaultValue?: string, routeContext?: unknown): string;
|
|
46
72
|
/**
|
|
47
73
|
* Plural translation
|
|
48
74
|
*/
|
|
@@ -61,9 +87,8 @@ export declare abstract class BaseI18n {
|
|
|
61
87
|
tdr(value: Date | number | string, options?: Intl.RelativeTimeFormatOptions): string;
|
|
62
88
|
/**
|
|
63
89
|
* Check if translation exists
|
|
64
|
-
* Based on logic from src/runtime/plugins/01.plugin.ts
|
|
65
90
|
*/
|
|
66
|
-
has(key: TranslationKey,
|
|
91
|
+
has(key: TranslationKey, routeContext?: unknown): boolean;
|
|
67
92
|
/**
|
|
68
93
|
* Clear cache
|
|
69
94
|
*/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { defaultPlural, getByPath, hasTranslationValue, interpolate, isNoPrefixStrategy, isPrefixAndDefaultStrategy, isPrefixExceptDefaultStrategy, isPrefixStrategy, mergeTranslationChunk, resolveTranslation, translationCacheKey, withPrefixStrategy, type MergeTranslationChunkOptions, } from './helpers';
|
package/dist/helpers.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=/\{(\w+)\}/g,c="index";function d(t,r){return`${t}:${r||c}`}function f(t,r){if(t==null)return null;const n=a(t,r);return n===void 0?null:n}function g(t,r){return f(t,r)!==null}function y(t,r,n){return Object.keys(t).length===0?r:n?.preserveExisting?Object.assign({},r,t):Object.assign({},t,r)}function x(t,r){return!r||t.indexOf("{")===-1?t:t.replace(s,(n,e)=>{const i=r[e];return i!==void 0?String(i):`{${e}}`})}function a(t,r){if(t==null||typeof r!="string"||r.length===0)return;if(Object.prototype.hasOwnProperty.call(t,r))return t[r];if(!r.includes("."))return;const n=r.split(".");let e=t;for(const i of n){if(e==null||typeof e!="object")return;const u=e;if(!Object.prototype.hasOwnProperty.call(u,i))return;e=u[i]}return e}function p(t){return t==="prefix"||t==="prefix_and_default"}function P(t){return t==="no_prefix"}function v(t){return t==="prefix"}function S(t){return t==="prefix_except_default"}function h(t){return t==="prefix_and_default"}const _=(t,r,n,e,i)=>{const u=i(t,n);if(!u)return null;const l=u.toString().split("|");if(l.length===0)return null;const o=r<l.length?l[r]:l[l.length-1];return o?o.trim().replace("{count}",r.toString()):null};exports.defaultPlural=_;exports.getByPath=a;exports.hasTranslationValue=g;exports.interpolate=x;exports.isNoPrefixStrategy=P;exports.isPrefixAndDefaultStrategy=h;exports.isPrefixExceptDefaultStrategy=S;exports.isPrefixStrategy=v;exports.mergeTranslationChunk=y;exports.resolveTranslation=f;exports.translationCacheKey=d;exports.withPrefixStrategy=p;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Params, PluralFunc, Strategies } from '@i18n-micro/types';
|
|
2
|
+
export declare function translationCacheKey(locale: string, routeName?: string): string;
|
|
3
|
+
export declare function resolveTranslation(obj: Record<string, unknown> | null | undefined, key: string): unknown | null;
|
|
4
|
+
export declare function hasTranslationValue(obj: Record<string, unknown> | null | undefined, key: string): boolean;
|
|
5
|
+
export interface MergeTranslationChunkOptions {
|
|
6
|
+
/** When true, existing keys win over incoming. Default: incoming wins. */
|
|
7
|
+
preserveExisting?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function mergeTranslationChunk(existing: Record<string, unknown>, incoming: Record<string, unknown>, options?: MergeTranslationChunkOptions): Record<string, unknown>;
|
|
10
|
+
export declare function interpolate(template: string, params: Params): string;
|
|
11
|
+
export declare function getByPath(obj: Record<string, unknown> | null | undefined, path: string): unknown;
|
|
12
|
+
export declare function withPrefixStrategy(strategy: Strategies): strategy is "prefix" | "prefix_and_default";
|
|
13
|
+
export declare function isNoPrefixStrategy(strategy: Strategies): strategy is "no_prefix";
|
|
14
|
+
export declare function isPrefixStrategy(strategy: Strategies): strategy is "prefix";
|
|
15
|
+
export declare function isPrefixExceptDefaultStrategy(strategy: Strategies): strategy is "prefix_except_default";
|
|
16
|
+
export declare function isPrefixAndDefaultStrategy(strategy: Strategies): strategy is "prefix_and_default";
|
|
17
|
+
/**
|
|
18
|
+
* Default pluralization function
|
|
19
|
+
* Splits translation by '|' and selects form based on count
|
|
20
|
+
* @param key - Translation key
|
|
21
|
+
* @param count - Count for pluralization
|
|
22
|
+
* @param params - Parameters for translation
|
|
23
|
+
* @param _locale - Current locale (unused in default implementation)
|
|
24
|
+
* @param getTranslation - Function to get translation value
|
|
25
|
+
* @returns Selected plural form or null if not found
|
|
26
|
+
*/
|
|
27
|
+
export declare const defaultPlural: PluralFunc;
|
package/dist/helpers.d.ts
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import { Params, PluralFunc, Strategies } from '@i18n-micro/types';
|
|
2
|
+
export declare function translationCacheKey(locale: string, routeName?: string): string;
|
|
3
|
+
export declare function resolveTranslation(obj: Record<string, unknown> | null | undefined, key: string): unknown | null;
|
|
4
|
+
export declare function hasTranslationValue(obj: Record<string, unknown> | null | undefined, key: string): boolean;
|
|
5
|
+
export interface MergeTranslationChunkOptions {
|
|
6
|
+
/** When true, existing keys win over incoming. Default: incoming wins. */
|
|
7
|
+
preserveExisting?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function mergeTranslationChunk(existing: Record<string, unknown>, incoming: Record<string, unknown>, options?: MergeTranslationChunkOptions): Record<string, unknown>;
|
|
2
10
|
export declare function interpolate(template: string, params: Params): string;
|
|
11
|
+
export declare function getByPath(obj: Record<string, unknown> | null | undefined, path: string): unknown;
|
|
3
12
|
export declare function withPrefixStrategy(strategy: Strategies): strategy is "prefix" | "prefix_and_default";
|
|
4
13
|
export declare function isNoPrefixStrategy(strategy: Strategies): strategy is "no_prefix";
|
|
5
14
|
export declare function isPrefixStrategy(strategy: Strategies): strategy is "prefix";
|
package/dist/helpers.mjs
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
const f = /\{(\w+)\}/g, c = "index";
|
|
2
|
+
function d(r, t) {
|
|
3
|
+
return `${r}:${t || c}`;
|
|
4
|
+
}
|
|
5
|
+
function s(r, t) {
|
|
6
|
+
if (r == null) return null;
|
|
7
|
+
const e = a(r, t);
|
|
8
|
+
return e === void 0 ? null : e;
|
|
9
|
+
}
|
|
10
|
+
function p(r, t) {
|
|
11
|
+
return s(r, t) !== null;
|
|
12
|
+
}
|
|
13
|
+
function g(r, t, e) {
|
|
14
|
+
return Object.keys(r).length === 0 ? t : e?.preserveExisting ? Object.assign({}, t, r) : Object.assign({}, r, t);
|
|
15
|
+
}
|
|
16
|
+
function x(r, t) {
|
|
17
|
+
return !t || r.indexOf("{") === -1 ? r : r.replace(f, (e, n) => {
|
|
18
|
+
const i = t[n];
|
|
19
|
+
return i !== void 0 ? String(i) : `{${n}}`;
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
function a(r, t) {
|
|
23
|
+
if (r == null || typeof t != "string" || t.length === 0) return;
|
|
24
|
+
if (Object.prototype.hasOwnProperty.call(r, t))
|
|
25
|
+
return r[t];
|
|
26
|
+
if (!t.includes(".")) return;
|
|
27
|
+
const e = t.split(".");
|
|
28
|
+
let n = r;
|
|
29
|
+
for (const i of e) {
|
|
30
|
+
if (n == null || typeof n != "object") return;
|
|
31
|
+
const u = n;
|
|
32
|
+
if (!Object.prototype.hasOwnProperty.call(u, i)) return;
|
|
33
|
+
n = u[i];
|
|
34
|
+
}
|
|
35
|
+
return n;
|
|
36
|
+
}
|
|
37
|
+
function v(r) {
|
|
38
|
+
return r === "prefix" || r === "prefix_and_default";
|
|
39
|
+
}
|
|
40
|
+
function y(r) {
|
|
41
|
+
return r === "no_prefix";
|
|
42
|
+
}
|
|
43
|
+
function _(r) {
|
|
44
|
+
return r === "prefix";
|
|
45
|
+
}
|
|
46
|
+
function O(r) {
|
|
47
|
+
return r === "prefix_except_default";
|
|
48
|
+
}
|
|
49
|
+
function P(r) {
|
|
50
|
+
return r === "prefix_and_default";
|
|
51
|
+
}
|
|
52
|
+
const S = (r, t, e, n, i) => {
|
|
53
|
+
const u = i(r, e);
|
|
54
|
+
if (!u)
|
|
55
|
+
return null;
|
|
56
|
+
const l = u.toString().split("|");
|
|
57
|
+
if (l.length === 0) return null;
|
|
58
|
+
const o = t < l.length ? l[t] : l[l.length - 1];
|
|
59
|
+
return o ? o.trim().replace("{count}", t.toString()) : null;
|
|
60
|
+
};
|
|
61
|
+
export {
|
|
62
|
+
S as defaultPlural,
|
|
63
|
+
a as getByPath,
|
|
64
|
+
p as hasTranslationValue,
|
|
65
|
+
x as interpolate,
|
|
66
|
+
y as isNoPrefixStrategy,
|
|
67
|
+
P as isPrefixAndDefaultStrategy,
|
|
68
|
+
O as isPrefixExceptDefaultStrategy,
|
|
69
|
+
_ as isPrefixStrategy,
|
|
70
|
+
g as mergeTranslationChunk,
|
|
71
|
+
s as resolveTranslation,
|
|
72
|
+
d as translationCacheKey,
|
|
73
|
+
v as withPrefixStrategy
|
|
74
|
+
};
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("./helpers.cjs");class g{formatNumber(t,e,r){return new Intl.NumberFormat(e,r).format(t)}formatDate(t,e,r){const s=new Date(t);return Number.isNaN(s.getTime())?"Invalid Date":new Intl.DateTimeFormat(e,r).format(s)}formatRelativeTime(t,e,r){const s=new Date(t),n=new Intl.RelativeTimeFormat(e,r);if(Number.isNaN(s.getTime()))return n.format(0,"second");const i=Math.floor((Date.now()-s.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:u,seconds:h}of o){const l=Math.floor(i/h);if(l>=1)return n.format(-l,u)}return n.format(0,"second")}}function f(c){const t=c?.translations??new Map;return{hasCache(e,r){return t.has(a.translationCacheKey(e,r))},getCache(e,r){return t.get(a.translationCacheKey(e,r))},setCache(e,r,s){},hasTranslation(e,r){for(const[s,n]of t)if(s.startsWith(`${e}:`)&&a.getByPath(n,r)!==void 0)return!0;return!1},hasPageTranslation(e,r){return t.has(a.translationCacheKey(e,r))},getTranslation(e,r,s){const n=t.get(a.translationCacheKey(e,r));return n?a.resolveTranslation(n,s):null},loadTranslations(e,r,s="index"){const n=a.translationCacheKey(e,s),i=t.get(n);i?Object.assign(i,r):t.set(n,{...r})},setTranslations(e,r,s="index"){t.set(a.translationCacheKey(e,s),r)},loadPageTranslations(e,r,s){const n=a.translationCacheKey(e,r),i=t.get(n);!i||Object.keys(i).length===0?t.set(n,{...s}):Object.assign(i,s)},mergeTranslation(e,r,s,n=!1){const i=a.translationCacheKey(e,r),o=t.get(i);o?Object.assign(o,s):t.set(i,{...s})},clearCache(){t.clear()}}}class m{constructor(t={}){this.formatter=new g,this.helper=f(t.storage),this.formatter=new g,this.pluralFunc=t.plural||a.defaultPlural,this.missingWarn=t.missingWarn??!0,this.missingHandler=t.missingHandler,this.getCustomMissingHandler=t.getCustomMissingHandler}touch(){}resolveRouteName(t){return typeof t=="string"?t:this.getRoute()}resolveLookup(t,e){const r=this.getLocale(),s=this.resolveRouteName(e);let n=this.helper.getTranslation(r,s,String(t));if(n===null){const i=this.getFallbackLocale();r!==i&&(n=this.helper.getTranslation(i,s,String(t)))}return n}resolveHas(t,e){const r=this.getLocale(),s=this.resolveRouteName(e);return this.helper.getTranslation(r,s,String(t))!==null}getMissingContext(t){return{locale:this.getLocale(),routeName:this.resolveRouteName(t)}}warnMissing(t,e){const{locale:r,routeName:s}=this.getMissingContext(e),n=this.getCustomMissingHandler?.();if(n){n(r,String(t),s);return}if(this.missingHandler){this.missingHandler(r,String(t),s);return}this.missingWarn&&process.env.NODE_ENV!=="production"&&typeof window<"u"&&console.warn(`Not found '${t}' key in '${r}' locale messages for route '${s}'.`)}t(t,e,r,s){if(!t)return"";this.touch();const n=this.resolveLookup(t,s);return n==null?(this.warnMissing(t,s),r===void 0?t:r||t):typeof n!="string"||!e?n:a.interpolate(n,e)}ts(t,e,r,s){return this.t(t,e,r,s)?.toString()??r??t}tc(t,e,r){this.touch();const{count:s,...n}=typeof e=="number"?{count:e}:e;if(s===void 0)return r??t;const i=(u,h,l)=>this.t(u,h,l);return this.pluralFunc(t,Number.parseInt(s.toString(),10),n,this.getLocale(),i)??r??t}tn(t,e){return this.touch(),this.formatter.formatNumber(t,this.getLocale(),e)}td(t,e){return this.touch(),this.formatter.formatDate(t,this.getLocale(),e)}tdr(t,e){return this.touch(),this.formatter.formatRelativeTime(t,this.getLocale(),e)}has(t,e){return this.touch(),this.resolveHas(t,e)}clearCache(){this.helper.clearCache()}loadTranslationsCore(t,e,r,s="index"){r?this.helper.mergeTranslation(t,s,e,!0):this.helper.setTranslations(t,e,s)}loadRouteTranslationsCore(t,e,r,s){s?this.helper.mergeTranslation(t,e,r,!0):this.helper.loadPageTranslations(t,e,r)}}exports.defaultPlural=a.defaultPlural;exports.getByPath=a.getByPath;exports.hasTranslationValue=a.hasTranslationValue;exports.interpolate=a.interpolate;exports.isNoPrefixStrategy=a.isNoPrefixStrategy;exports.isPrefixAndDefaultStrategy=a.isPrefixAndDefaultStrategy;exports.isPrefixExceptDefaultStrategy=a.isPrefixExceptDefaultStrategy;exports.isPrefixStrategy=a.isPrefixStrategy;exports.mergeTranslationChunk=a.mergeTranslationChunk;exports.resolveTranslation=a.resolveTranslation;exports.translationCacheKey=a.translationCacheKey;exports.withPrefixStrategy=a.withPrefixStrategy;exports.BaseI18n=m;exports.FormatService=g;exports.useTranslationHelper=f;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { BaseI18n, BaseI18nOptions } from './base';
|
|
2
|
+
import { FormatService } from './format-service';
|
|
3
|
+
import { defaultPlural, getByPath, hasTranslationValue, interpolate, isNoPrefixStrategy, isPrefixAndDefaultStrategy, isPrefixExceptDefaultStrategy, isPrefixStrategy, mergeTranslationChunk, resolveTranslation, translationCacheKey, withPrefixStrategy, MergeTranslationChunkOptions } from './helpers';
|
|
4
|
+
import { TranslationStorage, useTranslationHelper } from './translation';
|
|
5
|
+
export { useTranslationHelper, interpolate, getByPath, hasTranslationValue, mergeTranslationChunk, resolveTranslation, translationCacheKey, withPrefixStrategy, isNoPrefixStrategy, isPrefixStrategy, isPrefixExceptDefaultStrategy, isPrefixAndDefaultStrategy, defaultPlural, FormatService, BaseI18n, type MergeTranslationChunkOptions, type TranslationStorage, type BaseI18nOptions, };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BaseI18n, BaseI18nOptions } from './base';
|
|
2
2
|
import { FormatService } from './format-service';
|
|
3
|
-
import { defaultPlural, interpolate, isNoPrefixStrategy, isPrefixAndDefaultStrategy, isPrefixExceptDefaultStrategy, isPrefixStrategy, withPrefixStrategy } from './helpers';
|
|
3
|
+
import { defaultPlural, getByPath, hasTranslationValue, interpolate, isNoPrefixStrategy, isPrefixAndDefaultStrategy, isPrefixExceptDefaultStrategy, isPrefixStrategy, mergeTranslationChunk, resolveTranslation, translationCacheKey, withPrefixStrategy, MergeTranslationChunkOptions } from './helpers';
|
|
4
4
|
import { TranslationStorage, useTranslationHelper } from './translation';
|
|
5
|
-
export { useTranslationHelper, interpolate, withPrefixStrategy, isNoPrefixStrategy, isPrefixStrategy, isPrefixExceptDefaultStrategy, isPrefixAndDefaultStrategy, defaultPlural, FormatService, BaseI18n, type TranslationStorage, type BaseI18nOptions, };
|
|
5
|
+
export { useTranslationHelper, interpolate, getByPath, hasTranslationValue, mergeTranslationChunk, resolveTranslation, translationCacheKey, withPrefixStrategy, isNoPrefixStrategy, isPrefixStrategy, isPrefixExceptDefaultStrategy, isPrefixAndDefaultStrategy, defaultPlural, FormatService, BaseI18n, type MergeTranslationChunkOptions, type TranslationStorage, type BaseI18nOptions, };
|
package/dist/index.mjs
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { translationCacheKey as a, resolveTranslation as f, getByPath as m, defaultPlural as d, interpolate as v } from "./helpers.mjs";
|
|
2
|
+
import { hasTranslationValue as w, isNoPrefixStrategy as x, isPrefixAndDefaultStrategy as S, isPrefixExceptDefaultStrategy as D, isPrefixStrategy as H, mergeTranslationChunk as L, withPrefixStrategy as M } from "./helpers.mjs";
|
|
3
|
+
class g {
|
|
4
|
+
formatNumber(t, e, s) {
|
|
5
|
+
return new Intl.NumberFormat(e, s).format(t);
|
|
4
6
|
}
|
|
5
|
-
formatDate(t, e,
|
|
7
|
+
formatDate(t, e, s) {
|
|
6
8
|
const r = new Date(t);
|
|
7
|
-
return Number.isNaN(r.getTime()) ? "Invalid Date" : new Intl.DateTimeFormat(e,
|
|
9
|
+
return Number.isNaN(r.getTime()) ? "Invalid Date" : new Intl.DateTimeFormat(e, s).format(r);
|
|
8
10
|
}
|
|
9
|
-
formatRelativeTime(t, e,
|
|
10
|
-
const r = new Date(t);
|
|
11
|
+
formatRelativeTime(t, e, s) {
|
|
12
|
+
const r = new Date(t), n = new Intl.RelativeTimeFormat(e, s);
|
|
11
13
|
if (Number.isNaN(r.getTime()))
|
|
12
|
-
return
|
|
13
|
-
const i = Math.floor((
|
|
14
|
+
return n.format(0, "second");
|
|
15
|
+
const i = Math.floor((Date.now() - r.getTime()) / 1e3), o = [
|
|
14
16
|
{ unit: "year", seconds: 31536e3 },
|
|
15
17
|
{ unit: "month", seconds: 2592e3 },
|
|
16
18
|
{ unit: "day", seconds: 86400 },
|
|
@@ -18,172 +20,164 @@ class f {
|
|
|
18
20
|
{ unit: "minute", seconds: 60 },
|
|
19
21
|
{ unit: "second", seconds: 1 }
|
|
20
22
|
];
|
|
21
|
-
for (const { unit:
|
|
22
|
-
const
|
|
23
|
-
if (
|
|
24
|
-
return
|
|
23
|
+
for (const { unit: u, seconds: h } of o) {
|
|
24
|
+
const l = Math.floor(i / h);
|
|
25
|
+
if (l >= 1)
|
|
26
|
+
return n.format(-l, u);
|
|
25
27
|
}
|
|
26
|
-
return
|
|
28
|
+
return n.format(0, "second");
|
|
27
29
|
}
|
|
28
30
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return t ? s.replace(g, (e, n) => {
|
|
32
|
-
const r = t[n];
|
|
33
|
-
return r !== void 0 ? String(r) : `{${n}}`;
|
|
34
|
-
}) : s;
|
|
35
|
-
}
|
|
36
|
-
function x(s) {
|
|
37
|
-
return s === "prefix" || s === "prefix_and_default";
|
|
38
|
-
}
|
|
39
|
-
function T(s) {
|
|
40
|
-
return s === "no_prefix";
|
|
41
|
-
}
|
|
42
|
-
function $(s) {
|
|
43
|
-
return s === "prefix";
|
|
44
|
-
}
|
|
45
|
-
function v(s) {
|
|
46
|
-
return s === "prefix_except_default";
|
|
47
|
-
}
|
|
48
|
-
function w(s) {
|
|
49
|
-
return s === "prefix_and_default";
|
|
50
|
-
}
|
|
51
|
-
const d = (s, t, e, n, r) => {
|
|
52
|
-
const a = r(s, e);
|
|
53
|
-
if (!a)
|
|
54
|
-
return null;
|
|
55
|
-
const i = a.toString().split("|");
|
|
56
|
-
if (i.length === 0) return null;
|
|
57
|
-
const o = t < i.length ? i[t] : i[i.length - 1];
|
|
58
|
-
return o ? o.trim().replace("{count}", t.toString()) : null;
|
|
59
|
-
};
|
|
60
|
-
function h(s, t) {
|
|
61
|
-
if (!s || typeof t != "string") return null;
|
|
62
|
-
if (t in s) {
|
|
63
|
-
const r = s[t];
|
|
64
|
-
return r;
|
|
65
|
-
}
|
|
66
|
-
const e = t.split(".");
|
|
67
|
-
let n = s;
|
|
68
|
-
for (const r of e)
|
|
69
|
-
if (n && typeof n == "object" && r in n)
|
|
70
|
-
n = n[r];
|
|
71
|
-
else
|
|
72
|
-
return null;
|
|
73
|
-
return n ?? null;
|
|
74
|
-
}
|
|
75
|
-
function p(s) {
|
|
76
|
-
const t = s?.translations ?? /* @__PURE__ */ new Map();
|
|
31
|
+
function T(c) {
|
|
32
|
+
const t = c?.translations ?? /* @__PURE__ */ new Map();
|
|
77
33
|
return {
|
|
78
|
-
hasCache(e,
|
|
79
|
-
|
|
80
|
-
return t.has(`${e}:${r}`);
|
|
34
|
+
hasCache(e, s) {
|
|
35
|
+
return t.has(a(e, s));
|
|
81
36
|
},
|
|
82
|
-
getCache(e,
|
|
83
|
-
|
|
84
|
-
return t.get(`${e}:${r}`);
|
|
37
|
+
getCache(e, s) {
|
|
38
|
+
return t.get(a(e, s));
|
|
85
39
|
},
|
|
86
|
-
setCache(e,
|
|
40
|
+
setCache(e, s, r) {
|
|
87
41
|
},
|
|
88
|
-
hasTranslation(e,
|
|
89
|
-
for (const [r,
|
|
90
|
-
if (r.startsWith(`${e}:`) &&
|
|
42
|
+
hasTranslation(e, s) {
|
|
43
|
+
for (const [r, n] of t)
|
|
44
|
+
if (r.startsWith(`${e}:`) && m(n, s) !== void 0)
|
|
91
45
|
return !0;
|
|
92
46
|
return !1;
|
|
93
47
|
},
|
|
94
|
-
hasPageTranslation(e,
|
|
95
|
-
|
|
96
|
-
return t.has(`${e}:${r}`);
|
|
48
|
+
hasPageTranslation(e, s) {
|
|
49
|
+
return t.has(a(e, s));
|
|
97
50
|
},
|
|
98
|
-
getTranslation(e,
|
|
99
|
-
const
|
|
100
|
-
return
|
|
51
|
+
getTranslation(e, s, r) {
|
|
52
|
+
const n = t.get(a(e, s));
|
|
53
|
+
return n ? f(n, r) : null;
|
|
101
54
|
},
|
|
102
|
-
loadTranslations(e,
|
|
103
|
-
const
|
|
104
|
-
t.set(
|
|
55
|
+
loadTranslations(e, s, r = "index") {
|
|
56
|
+
const n = a(e, r), i = t.get(n);
|
|
57
|
+
i ? Object.assign(i, s) : t.set(n, { ...s });
|
|
105
58
|
},
|
|
106
|
-
setTranslations(e,
|
|
107
|
-
|
|
108
|
-
t.set(`${e}:${a}`, n);
|
|
59
|
+
setTranslations(e, s, r = "index") {
|
|
60
|
+
t.set(a(e, r), s);
|
|
109
61
|
},
|
|
110
|
-
loadPageTranslations(e,
|
|
111
|
-
const
|
|
112
|
-
!
|
|
62
|
+
loadPageTranslations(e, s, r) {
|
|
63
|
+
const n = a(e, s), i = t.get(n);
|
|
64
|
+
!i || Object.keys(i).length === 0 ? t.set(n, { ...r }) : Object.assign(i, r);
|
|
113
65
|
},
|
|
114
|
-
mergeTranslation(e,
|
|
115
|
-
const
|
|
116
|
-
t.set(
|
|
66
|
+
mergeTranslation(e, s, r, n = !1) {
|
|
67
|
+
const i = a(e, s), o = t.get(i);
|
|
68
|
+
o ? Object.assign(o, r) : t.set(i, { ...r });
|
|
117
69
|
},
|
|
118
70
|
clearCache() {
|
|
119
71
|
t.clear();
|
|
120
72
|
}
|
|
121
73
|
};
|
|
122
74
|
}
|
|
123
|
-
class
|
|
75
|
+
class N {
|
|
124
76
|
constructor(t = {}) {
|
|
125
|
-
this.formatter = new
|
|
77
|
+
this.formatter = new g(), this.helper = T(t.storage), this.formatter = new g(), this.pluralFunc = t.plural || d, this.missingWarn = t.missingWarn ?? !0, this.missingHandler = t.missingHandler, this.getCustomMissingHandler = t.getCustomMissingHandler;
|
|
78
|
+
}
|
|
79
|
+
// --- Protected hooks (subclasses may override) ---
|
|
80
|
+
/**
|
|
81
|
+
* Called before translation lookup — subclasses use for reactivity tracking.
|
|
82
|
+
*/
|
|
83
|
+
touch() {
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Resolve route name from optional route context (string route name or adapter-specific object).
|
|
87
|
+
*/
|
|
88
|
+
resolveRouteName(t) {
|
|
89
|
+
return typeof t == "string" ? t : this.getRoute();
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Lookup translation value. Returns null when missing.
|
|
93
|
+
*/
|
|
94
|
+
resolveLookup(t, e) {
|
|
95
|
+
const s = this.getLocale(), r = this.resolveRouteName(e);
|
|
96
|
+
let n = this.helper.getTranslation(s, r, String(t));
|
|
97
|
+
if (n === null) {
|
|
98
|
+
const i = this.getFallbackLocale();
|
|
99
|
+
s !== i && (n = this.helper.getTranslation(i, r, String(t)));
|
|
100
|
+
}
|
|
101
|
+
return n;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Check if translation exists in lookup source.
|
|
105
|
+
*/
|
|
106
|
+
resolveHas(t, e) {
|
|
107
|
+
const s = this.getLocale(), r = this.resolveRouteName(e);
|
|
108
|
+
return this.helper.getTranslation(s, r, String(t)) !== null;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Context passed to missing-key handlers.
|
|
112
|
+
*/
|
|
113
|
+
getMissingContext(t) {
|
|
114
|
+
return { locale: this.getLocale(), routeName: this.resolveRouteName(t) };
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Warn or invoke handler when translation is missing.
|
|
118
|
+
*/
|
|
119
|
+
warnMissing(t, e) {
|
|
120
|
+
const { locale: s, routeName: r } = this.getMissingContext(e), n = this.getCustomMissingHandler?.();
|
|
121
|
+
if (n) {
|
|
122
|
+
n(s, String(t), r);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (this.missingHandler) {
|
|
126
|
+
this.missingHandler(s, String(t), r);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
this.missingWarn && process.env.NODE_ENV !== "production" && typeof window < "u" && console.warn(`Not found '${t}' key in '${s}' locale messages for route '${r}'.`);
|
|
126
130
|
}
|
|
127
131
|
// --- Public methods (implemented in base class) ---
|
|
128
132
|
/**
|
|
129
133
|
* Get translation for a key
|
|
130
|
-
* Based on logic from src/runtime/plugins/01.plugin.ts
|
|
131
134
|
*/
|
|
132
|
-
t(t, e,
|
|
135
|
+
t(t, e, s, r) {
|
|
133
136
|
if (!t) return "";
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
const l = this.getFallbackLocale();
|
|
138
|
-
a !== l && (o = this.helper.getTranslation(l, i, t));
|
|
139
|
-
}
|
|
140
|
-
if (!o) {
|
|
141
|
-
const l = this.getCustomMissingHandler?.();
|
|
142
|
-
l ? l(a, t, i) : this.missingHandler ? this.missingHandler(a, t, i) : this.missingWarn && process.env.NODE_ENV !== "production" && typeof window < "u" && console.warn(`Not found '${t}' key in '${a}' locale messages for route '${i}'.`), o = n === void 0 ? t : n || t;
|
|
143
|
-
}
|
|
144
|
-
return typeof o == "string" && e ? m(o, e) : o;
|
|
137
|
+
this.touch();
|
|
138
|
+
const n = this.resolveLookup(t, r);
|
|
139
|
+
return n == null ? (this.warnMissing(t, r), s === void 0 ? t : s || t) : typeof n != "string" || !e ? n : v(n, e);
|
|
145
140
|
}
|
|
146
141
|
/**
|
|
147
142
|
* Get translation as string
|
|
148
143
|
*/
|
|
149
|
-
ts(t, e,
|
|
150
|
-
return this.t(t, e,
|
|
144
|
+
ts(t, e, s, r) {
|
|
145
|
+
return this.t(t, e, s, r)?.toString() ?? s ?? t;
|
|
151
146
|
}
|
|
152
147
|
/**
|
|
153
148
|
* Plural translation
|
|
154
149
|
*/
|
|
155
|
-
tc(t, e,
|
|
156
|
-
|
|
150
|
+
tc(t, e, s) {
|
|
151
|
+
this.touch();
|
|
152
|
+
const { count: r, ...n } = typeof e == "number" ? { count: e } : e;
|
|
157
153
|
if (r === void 0)
|
|
158
|
-
return
|
|
159
|
-
const i = (
|
|
160
|
-
return this.pluralFunc(t, Number.parseInt(r.toString(), 10),
|
|
154
|
+
return s ?? t;
|
|
155
|
+
const i = (u, h, l) => this.t(u, h, l);
|
|
156
|
+
return this.pluralFunc(t, Number.parseInt(r.toString(), 10), n, this.getLocale(), i) ?? s ?? t;
|
|
161
157
|
}
|
|
162
158
|
/**
|
|
163
159
|
* Format number
|
|
164
160
|
*/
|
|
165
161
|
tn(t, e) {
|
|
166
|
-
return this.formatter.formatNumber(t, this.getLocale(), e);
|
|
162
|
+
return this.touch(), this.formatter.formatNumber(t, this.getLocale(), e);
|
|
167
163
|
}
|
|
168
164
|
/**
|
|
169
165
|
* Format date
|
|
170
166
|
*/
|
|
171
167
|
td(t, e) {
|
|
172
|
-
return this.formatter.formatDate(t, this.getLocale(), e);
|
|
168
|
+
return this.touch(), this.formatter.formatDate(t, this.getLocale(), e);
|
|
173
169
|
}
|
|
174
170
|
/**
|
|
175
171
|
* Format relative time
|
|
176
172
|
*/
|
|
177
173
|
tdr(t, e) {
|
|
178
|
-
return this.formatter.formatRelativeTime(t, this.getLocale(), e);
|
|
174
|
+
return this.touch(), this.formatter.formatRelativeTime(t, this.getLocale(), e);
|
|
179
175
|
}
|
|
180
176
|
/**
|
|
181
177
|
* Check if translation exists
|
|
182
|
-
* Based on logic from src/runtime/plugins/01.plugin.ts
|
|
183
178
|
*/
|
|
184
179
|
has(t, e) {
|
|
185
|
-
|
|
186
|
-
return !!this.helper.getTranslation(r, n, t);
|
|
180
|
+
return this.touch(), this.resolveHas(t, e);
|
|
187
181
|
}
|
|
188
182
|
/**
|
|
189
183
|
* Clear cache
|
|
@@ -196,26 +190,31 @@ class _ {
|
|
|
196
190
|
* Core translation loading logic (without reactivity)
|
|
197
191
|
* Subclasses can override addTranslations/addRouteTranslations to add reactivity
|
|
198
192
|
*/
|
|
199
|
-
loadTranslationsCore(t, e,
|
|
200
|
-
|
|
193
|
+
loadTranslationsCore(t, e, s, r = "index") {
|
|
194
|
+
s ? this.helper.mergeTranslation(t, r, e, !0) : this.helper.setTranslations(t, e, r);
|
|
201
195
|
}
|
|
202
196
|
/**
|
|
203
197
|
* Core route translation loading logic (without reactivity)
|
|
204
198
|
* Subclasses can override addRouteTranslations to add reactivity
|
|
205
199
|
*/
|
|
206
|
-
loadRouteTranslationsCore(t, e,
|
|
207
|
-
r ? this.helper.mergeTranslation(t, e,
|
|
200
|
+
loadRouteTranslationsCore(t, e, s, r) {
|
|
201
|
+
r ? this.helper.mergeTranslation(t, e, s, !0) : this.helper.loadPageTranslations(t, e, s);
|
|
208
202
|
}
|
|
209
203
|
}
|
|
210
204
|
export {
|
|
211
|
-
|
|
212
|
-
|
|
205
|
+
N as BaseI18n,
|
|
206
|
+
g as FormatService,
|
|
213
207
|
d as defaultPlural,
|
|
214
|
-
m as
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
208
|
+
m as getByPath,
|
|
209
|
+
w as hasTranslationValue,
|
|
210
|
+
v as interpolate,
|
|
211
|
+
x as isNoPrefixStrategy,
|
|
212
|
+
S as isPrefixAndDefaultStrategy,
|
|
213
|
+
D as isPrefixExceptDefaultStrategy,
|
|
214
|
+
H as isPrefixStrategy,
|
|
215
|
+
L as mergeTranslationChunk,
|
|
216
|
+
f as resolveTranslation,
|
|
217
|
+
a as translationCacheKey,
|
|
218
|
+
T as useTranslationHelper,
|
|
219
|
+
M as withPrefixStrategy
|
|
221
220
|
};
|