locl-js 2.0.0 → 2.0.1
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 +49 -27
- package/dist/{LocL-fN9Yari8.d.mts → LocL-v4yNIiKt.d.mts} +2 -1
- package/dist/{LocL-fN9Yari8.d.ts → LocL-v4yNIiKt.d.ts} +2 -1
- package/dist/compat.d.mts +26 -16
- package/dist/compat.d.ts +26 -16
- package/dist/compat.js +35 -34
- package/dist/compat.mjs +35 -34
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +20 -13
- package/dist/index.mjs +20 -13
- package/dist/react.d.mts +25 -27
- package/dist/react.d.ts +25 -27
- package/dist/react.js +9 -8
- package/dist/react.mjs +9 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
**LocL** is an ultra-fast, lightweight, and fully-featured TypeScript internationalization (i18n) library. Designed for modern web applications, backend services, and multi-framework setups, it provides compile-time type-safety, automatic pluralization, ICU-style select branching, built-in formatters, and reactive subscriptions with **zero external dependencies**.
|
|
6
6
|
|
|
7
|
-
It is inspired by libraries like `i18next` and `react-i18next`, but engineered with a focus on strict TypeScript type checking, sub-millisecond execution, clean APIs, and 100% test coverage
|
|
7
|
+
It is inspired by libraries like `i18next` and `react-i18next`, but engineered with a focus on strict TypeScript type checking, sub-millisecond execution, clean APIs, and **100% test coverage across every statement, branch, and function**.
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
@@ -16,12 +16,12 @@ It is inspired by libraries like `i18next` and `react-i18next`, but engineered w
|
|
|
16
16
|
- **`createLocLReact` Hook Factory**: Zero-declaration, pre-bound React suite.
|
|
17
17
|
- **`LocLRegister` Declaration Merging**: Ambient global autocomplete for standalone imports.
|
|
18
18
|
- **📦 Zero Dependencies & Lightweight**: Pure TypeScript with no runtime dependencies.
|
|
19
|
-
- **🔄 Drop-in i18next Compat**: Swap existing `i18next` codebases effortlessly using `locl-js/compat` without rewriting translation call sites. Supports colon namespaces (`auth:login`), default fallbacks, and event listener cleanup.
|
|
19
|
+
- **🔄 Drop-in i18next Compat**: Swap existing `i18next` codebases effortlessly using `locl-js/compat` without rewriting translation call sites. Supports colon namespaces (`auth:login`), strict parameter checking, default fallbacks, and event listener cleanup.
|
|
20
20
|
- **🌐 Multi-Framework Reactive Store**: Implements the standard reactive store contract via `translator.subscribe()`, working out of the box in Svelte, Vue, Solid, and Node.js.
|
|
21
21
|
- **🔢 Automatic Plurals**: Handles object plurals (`{ zero, one, other }`) and suffix plurals (`_zero`, `_one`, `_other`) directly via `t()` or dedicated `plural()`.
|
|
22
22
|
- **🔀 ICU Select Support**: Conditional branching (`{gender, select, male {He} female {She} other {They}}`) with nested parameter interpolation (`{gender, select, male {He has {count} items}}`).
|
|
23
23
|
- **🔧 Built-in & Custom Formatters**: Format dates, numbers, currencies, strings, and booleans inline via pipe syntax (`{val | number}`, `{date | date:short}`).
|
|
24
|
-
- **⚡ High Performance Caching**: Granular scope-based translation caching and multi-proxy instance reuse.
|
|
24
|
+
- **⚡ High Performance Caching**: Granular scope-based translation caching and multi-proxy instance reuse with zero proxy-of-proxy overhead.
|
|
25
25
|
- **🛡️ Prototype-Safe Dynamic Resources**: Safely merge resources dynamically at runtime with built-in prototype pollution guards.
|
|
26
26
|
- **💯 100% Test Coverage**: Fully verified across every line, branch, function, and edge case.
|
|
27
27
|
|
|
@@ -114,7 +114,7 @@ translator.t("staticNotice");
|
|
|
114
114
|
|
|
115
115
|
### Workflow A: Zero-Declaration Factory (`createLocLReact`) ⭐ *Recommended*
|
|
116
116
|
|
|
117
|
-
No `.d.ts` declaration merging required.
|
|
117
|
+
No `.d.ts` declaration merging required. Pass your translator instance to `createLocLReact` once and export pre-bound, 100% typed components and hooks:
|
|
118
118
|
|
|
119
119
|
```tsx
|
|
120
120
|
// src/i18n-react.ts
|
|
@@ -162,7 +162,7 @@ function Header() {
|
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
function Profile() {
|
|
165
|
-
// Scoped autocomplete: keys are restricted to the "user" namespace!
|
|
165
|
+
// Scoped autocomplete: keys are restricted strictly to the "user" namespace!
|
|
166
166
|
const { t } = useTranslation("user");
|
|
167
167
|
|
|
168
168
|
return (
|
|
@@ -183,7 +183,7 @@ function Profile() {
|
|
|
183
183
|
|
|
184
184
|
### Workflow B: Global Type Registry (`LocLRegister`)
|
|
185
185
|
|
|
186
|
-
If you prefer importing directly from `"locl-js/react"`, augment `LocLRegister` once in your project (e.g. `src/i18n.d.ts`):
|
|
186
|
+
If you prefer importing hooks and components directly from `"locl-js/react"`, augment `LocLRegister` once in your project (e.g. `src/i18n.d.ts`):
|
|
187
187
|
|
|
188
188
|
```typescript
|
|
189
189
|
import { translator } from "./i18n";
|
|
@@ -195,7 +195,7 @@ declare module "locl-js/react" {
|
|
|
195
195
|
}
|
|
196
196
|
```
|
|
197
197
|
|
|
198
|
-
Now, standalone imports automatically have full autocomplete everywhere:
|
|
198
|
+
Now, standalone imports automatically have full autocomplete everywhere without passing any generic arguments:
|
|
199
199
|
|
|
200
200
|
```tsx
|
|
201
201
|
import { useTranslation, Trans } from "locl-js/react";
|
|
@@ -224,38 +224,60 @@ Renders complex translations containing formatting tags (`<bold>read</bold>`, `<
|
|
|
224
224
|
/>
|
|
225
225
|
```
|
|
226
226
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
- **
|
|
227
|
+
#### Key Capabilities
|
|
228
|
+
|
|
229
|
+
- **Strict Key Validation**: Autocompletes valid keys and flags typos at compile time.
|
|
230
|
+
- **Strict Value Validation**: If the template contains `{name}`, `values={{ name: ... }}` is required at compile time.
|
|
231
|
+
- **Dynamic Key Fallback**: Unregistered or dynamic keys are allowed whenever an explicit `fallback` string is provided (`fallback="Default string"`).
|
|
232
|
+
- **Scope Support**: Narrow keys using the `scope` prop: `<Trans scope="user" i18nKey="greeting" values={{ name: "Alice" }} />`.
|
|
233
|
+
- **Standalone `translator` Prop**: When passing `translator={translator}`, `Trans` automatically infers the dictionary and provides autocomplete for that translator's keys.
|
|
234
|
+
- **Tag Element Replacement**: Clones JSX elements (e.g. `<strong />`) while preserving inner text as children.
|
|
235
|
+
- **Function Renderers**: Supports custom render functions: `(content) => <span style={{ fontWeight: "bold" }}>{content}</span>`.
|
|
236
|
+
- **Reactive Updates**: Subscribes to `useSyncExternalStore` so language changes re-render smoothly.
|
|
230
237
|
|
|
231
238
|
---
|
|
232
239
|
|
|
233
240
|
## Drop-in `i18next` Compatibility (`locl-js/compat`)
|
|
234
241
|
|
|
235
|
-
Migrate existing `i18next` codebases effortlessly without refactoring callsites:
|
|
242
|
+
Migrate existing `i18next` codebases effortlessly without refactoring callsites. `locl-js/compat` preserves `i18next` runtime flexibility while offering full compile-time strict type checking:
|
|
236
243
|
|
|
237
244
|
```typescript
|
|
238
|
-
import { initLocL } from "locl-js";
|
|
245
|
+
import { initLocL, defineResources } from "locl-js";
|
|
239
246
|
import { toI18next, createI18nextCompat } from "locl-js/compat";
|
|
240
247
|
|
|
248
|
+
const resources = defineResources({
|
|
249
|
+
en: {
|
|
250
|
+
common: {
|
|
251
|
+
hello: "Hello, {name}!",
|
|
252
|
+
save: "Save"
|
|
253
|
+
},
|
|
254
|
+
apple_one: "1 apple",
|
|
255
|
+
apple_other: "{count} apples"
|
|
256
|
+
}
|
|
257
|
+
});
|
|
241
258
|
const locl = initLocL({ resources, fallbackLanguage: "en" });
|
|
242
259
|
export const i18n = toI18next(locl);
|
|
243
260
|
|
|
244
|
-
//
|
|
245
|
-
i18n.t("common:
|
|
246
|
-
i18n.t("common.
|
|
247
|
-
|
|
248
|
-
|
|
261
|
+
// Colon and dot syntax autocompleted and strictly enforced:
|
|
262
|
+
i18n.t("common:hello", { name: "Maria" }); // Requires { name }!
|
|
263
|
+
i18n.t("common.save"); // Static key: options optional!
|
|
264
|
+
|
|
265
|
+
// Plurals strictly enforce { count: number }:
|
|
266
|
+
i18n.t("apple", { count: 5 });
|
|
267
|
+
|
|
268
|
+
// Dynamic and fallback keys:
|
|
269
|
+
i18n.t("missing.key", "Default Fallback");
|
|
270
|
+
i18n.t("missing.key", { defaultValue: "Fallback Text" });
|
|
249
271
|
|
|
250
|
-
//
|
|
251
|
-
i18n.
|
|
272
|
+
// Key existence check (with autocomplete for colon and dot keys):
|
|
273
|
+
i18n.exists("common:save"); // true
|
|
252
274
|
|
|
253
|
-
//
|
|
275
|
+
// Resource bundle management:
|
|
254
276
|
i18n.addResourceBundle("en", "dynamic", { title: "Title" });
|
|
255
|
-
i18n.hasResourceBundle("en", "dynamic");
|
|
256
|
-
i18n.getResourceBundle("en", "dynamic");
|
|
277
|
+
i18n.hasResourceBundle("en", "dynamic"); // true
|
|
278
|
+
i18n.getResourceBundle("en", "dynamic"); // { title: "Title" }
|
|
257
279
|
|
|
258
|
-
// Event listeners with
|
|
280
|
+
// Event listeners with cleanup callback:
|
|
259
281
|
const unbind = i18n.on("languageChanged", (lng) => {
|
|
260
282
|
console.log("Language changed to", lng);
|
|
261
283
|
});
|
|
@@ -476,16 +498,16 @@ console.log(multiT.t("dashboard.welcome", { name: "Alice" })); // "Welcome, Alic
|
|
|
476
498
|
|
|
477
499
|
### React Exports (`locl-js/react`)
|
|
478
500
|
|
|
479
|
-
- **`createLocLReact(translator)`**: Returns a pre-bound React suite (`LocLProvider`, `useTranslation`, `useLocL`, `Trans`).
|
|
501
|
+
- **`createLocLReact(translator)`**: Returns a pre-bound, zero-declaration React suite (`LocLProvider`, `useTranslation`, `useLocL`, `Trans`, `LocLContext`).
|
|
480
502
|
- **`LocLProvider`**: React Context Provider for the active translator.
|
|
481
|
-
- **`useTranslation(scope?, customTranslator?)`**: Translation hook with
|
|
503
|
+
- **`useTranslation(scope?, customTranslator?)`**: Translation hook with namespace scoping support.
|
|
482
504
|
- **`useLocL(customTranslator?)`**: Hook returning translator instance and reactive language state.
|
|
483
|
-
- **`<Trans />`**: Rich JSX
|
|
505
|
+
- **`<Trans />`**: Rich JSX component interpolation component supporting strict key/param checking, fallbacks, and scope narrowing.
|
|
484
506
|
- **`LocLRegister`**: Ambient interface for global type registration.
|
|
485
507
|
|
|
486
508
|
### Compat Exports (`locl-js/compat`)
|
|
487
509
|
|
|
488
|
-
- **`toI18next(translator)`**: Wraps a LocL instance into an `i18next`-compatible API.
|
|
510
|
+
- **`toI18next(translator)`**: Wraps a LocL instance into an `i18next`-compatible API with strict parameter checking.
|
|
489
511
|
- **`createI18nextCompat(translator)`**: Alias of `toI18next`.
|
|
490
512
|
|
|
491
513
|
### `LocL` Instance Methods
|
|
@@ -432,6 +432,7 @@ declare class LocL<T extends Record<string, any>, Fallback extends keyof T & str
|
|
|
432
432
|
private interpolate;
|
|
433
433
|
private applyFormat;
|
|
434
434
|
private makeReadOnly;
|
|
435
|
+
private isUnsafeObjectKey;
|
|
435
436
|
}
|
|
436
437
|
|
|
437
|
-
export { type Formatter as F, type InterpolationOptions as I, type LocLConfig as L, type NestedKeyOf as N, type
|
|
438
|
+
export { type Formatter as F, type InterpolationOptions as I, type LocLConfig as L, type NestedKeyOf as N, type PluralParamsFor as P, type ScopeType as S, type TranslationObjectFor as T, LocL as a, type LangWithPlurals as b, type ParamsFor as c, type PathValue as d, type IsEmptyParams as e, type PluralKeys as f, type Language as g, type Scope as h };
|
|
@@ -432,6 +432,7 @@ declare class LocL<T extends Record<string, any>, Fallback extends keyof T & str
|
|
|
432
432
|
private interpolate;
|
|
433
433
|
private applyFormat;
|
|
434
434
|
private makeReadOnly;
|
|
435
|
+
private isUnsafeObjectKey;
|
|
435
436
|
}
|
|
436
437
|
|
|
437
|
-
export { type Formatter as F, type InterpolationOptions as I, type LocLConfig as L, type NestedKeyOf as N, type
|
|
438
|
+
export { type Formatter as F, type InterpolationOptions as I, type LocLConfig as L, type NestedKeyOf as N, type PluralParamsFor as P, type ScopeType as S, type TranslationObjectFor as T, LocL as a, type LangWithPlurals as b, type ParamsFor as c, type PathValue as d, type IsEmptyParams as e, type PluralKeys as f, type Language as g, type Scope as h };
|
package/dist/compat.d.mts
CHANGED
|
@@ -1,22 +1,36 @@
|
|
|
1
|
-
import { N as NestedKeyOf, I as InterpolationOptions, a as LocL } from './LocL-
|
|
1
|
+
import { N as NestedKeyOf, I as InterpolationOptions, P as PluralParamsFor, c as ParamsFor, d as PathValue, e as IsEmptyParams, T as TranslationObjectFor, f as PluralKeys, a as LocL } from './LocL-v4yNIiKt.mjs';
|
|
2
2
|
import { DefaultResources, DefaultFallback } from './react.mjs';
|
|
3
3
|
import 'react';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
type I18nextKey<
|
|
9
|
-
[K in keyof T & string]: T[K] extends object ? `${K}:${NestedKeyOf<T[K]>}` | `${K}.${NestedKeyOf<T[K]>}` | `${K}` : `${K}`;
|
|
10
|
-
}[keyof T & string] | NestedKeyOf<T> : string;
|
|
5
|
+
type NormalizeKey<K extends string> = K extends `${infer NS}:${infer Rest}` ? `${NS}.${Rest}` : K;
|
|
6
|
+
type ColonKeys<K extends string> = K extends `${infer NS}.${infer Rest}` ? `${NS}:${Rest}` | `${NS}.${Rest}` : K;
|
|
7
|
+
type BaseKeys<Tr, PK extends string> = ((Tr extends object ? NestedKeyOf<Tr> : never) | PK) & string;
|
|
8
|
+
type I18nextKey<Tr, PK extends string> = ColonKeys<BaseKeys<Tr, PK>>;
|
|
11
9
|
interface I18nextOptions extends InterpolationOptions {
|
|
12
10
|
ns?: string;
|
|
13
11
|
defaultValue?: string;
|
|
14
12
|
count?: number;
|
|
15
|
-
[key: string]: any;
|
|
16
13
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
type I18nextParamsFor<K extends string, Tr, PK extends string> = NormalizeKey<K> extends PK ? PluralParamsFor<NormalizeKey<K>, Tr> : ParamsFor<PathValue<Tr, NormalizeKey<K>>>;
|
|
15
|
+
type I18nextHasParams<K extends string, Tr, PK extends string> = NormalizeKey<K> extends PK ? true : IsEmptyParams<ParamsFor<PathValue<Tr, NormalizeKey<K>>>> extends true ? false : true;
|
|
16
|
+
type I18nextOptionsFor<K extends string, Tr, PK extends string> = I18nextParamsFor<K, Tr, PK> & I18nextOptions;
|
|
17
|
+
interface I18nextTranslation<T extends Record<string, any> = DefaultResources, Fallback extends keyof T & string = DefaultFallback<T>, Tr = TranslationObjectFor<undefined, T, Fallback>, PK extends string = PluralKeys<undefined, T, Fallback>> {
|
|
18
|
+
<K extends I18nextKey<Tr, PK>>(key: K, ...args: I18nextHasParams<K, Tr, PK> extends true ? [options: I18nextOptionsFor<K, Tr, PK>] : [options?: I18nextOptions]): string;
|
|
19
|
+
<K extends I18nextKey<Tr, PK>>(key: K, defaultValue: string, ...args: I18nextHasParams<K, Tr, PK> extends true ? [options: I18nextOptionsFor<K, Tr, PK>] : [options?: I18nextOptions]): string;
|
|
20
|
+
(key: string, defaultValue: string, options?: I18nextOptions): string;
|
|
21
|
+
(key: string, options: {
|
|
22
|
+
defaultValue: string;
|
|
23
|
+
} & I18nextOptions): string;
|
|
24
|
+
(key: string, options: {
|
|
25
|
+
ns: string;
|
|
26
|
+
} & I18nextOptions): string;
|
|
27
|
+
}
|
|
28
|
+
interface I18nextCompat<T extends Record<string, any> = DefaultResources, Fallback extends keyof T & string = DefaultFallback<T>, Tr = TranslationObjectFor<undefined, T, Fallback>, PK extends string = PluralKeys<undefined, T, Fallback>> {
|
|
29
|
+
t: I18nextTranslation<T, Fallback>;
|
|
30
|
+
exists<K extends I18nextKey<Tr, PK>>(key: K, options?: {
|
|
31
|
+
ns?: string;
|
|
32
|
+
[key: string]: any;
|
|
33
|
+
}): boolean;
|
|
20
34
|
exists(key: string, options?: {
|
|
21
35
|
ns?: string;
|
|
22
36
|
[key: string]: any;
|
|
@@ -34,11 +48,7 @@ interface I18nextCompat<T extends Record<string, any> = DefaultResources, Fallba
|
|
|
34
48
|
loadNamespaces(ns: string | string[], callback?: () => void): Promise<void>;
|
|
35
49
|
translator: LocL<T, Fallback, any, any, any>;
|
|
36
50
|
}
|
|
37
|
-
/**
|
|
38
|
-
* Wraps a LocL instance in an i18next-compatible interface.
|
|
39
|
-
* Supports both colon (`common:login`) and dotted namespaces with full IDE autocomplete.
|
|
40
|
-
*/
|
|
41
51
|
declare function toI18next<T extends Record<string, any> = DefaultResources, Fallback extends keyof T & string = DefaultFallback<T>>(translator: LocL<T, Fallback, any, any, any>): I18nextCompat<T, Fallback>;
|
|
42
52
|
declare const createI18nextCompat: typeof toI18next;
|
|
43
53
|
|
|
44
|
-
export { type I18nextCompat, type I18nextKey, type I18nextOptions, createI18nextCompat, toI18next };
|
|
54
|
+
export { type BaseKeys, type ColonKeys, type I18nextCompat, type I18nextHasParams, type I18nextKey, type I18nextOptions, type I18nextOptionsFor, type I18nextParamsFor, type I18nextTranslation, type NormalizeKey, createI18nextCompat, toI18next };
|
package/dist/compat.d.ts
CHANGED
|
@@ -1,22 +1,36 @@
|
|
|
1
|
-
import { N as NestedKeyOf, I as InterpolationOptions, a as LocL } from './LocL-
|
|
1
|
+
import { N as NestedKeyOf, I as InterpolationOptions, P as PluralParamsFor, c as ParamsFor, d as PathValue, e as IsEmptyParams, T as TranslationObjectFor, f as PluralKeys, a as LocL } from './LocL-v4yNIiKt.js';
|
|
2
2
|
import { DefaultResources, DefaultFallback } from './react.js';
|
|
3
3
|
import 'react';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
type I18nextKey<
|
|
9
|
-
[K in keyof T & string]: T[K] extends object ? `${K}:${NestedKeyOf<T[K]>}` | `${K}.${NestedKeyOf<T[K]>}` | `${K}` : `${K}`;
|
|
10
|
-
}[keyof T & string] | NestedKeyOf<T> : string;
|
|
5
|
+
type NormalizeKey<K extends string> = K extends `${infer NS}:${infer Rest}` ? `${NS}.${Rest}` : K;
|
|
6
|
+
type ColonKeys<K extends string> = K extends `${infer NS}.${infer Rest}` ? `${NS}:${Rest}` | `${NS}.${Rest}` : K;
|
|
7
|
+
type BaseKeys<Tr, PK extends string> = ((Tr extends object ? NestedKeyOf<Tr> : never) | PK) & string;
|
|
8
|
+
type I18nextKey<Tr, PK extends string> = ColonKeys<BaseKeys<Tr, PK>>;
|
|
11
9
|
interface I18nextOptions extends InterpolationOptions {
|
|
12
10
|
ns?: string;
|
|
13
11
|
defaultValue?: string;
|
|
14
12
|
count?: number;
|
|
15
|
-
[key: string]: any;
|
|
16
13
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
type I18nextParamsFor<K extends string, Tr, PK extends string> = NormalizeKey<K> extends PK ? PluralParamsFor<NormalizeKey<K>, Tr> : ParamsFor<PathValue<Tr, NormalizeKey<K>>>;
|
|
15
|
+
type I18nextHasParams<K extends string, Tr, PK extends string> = NormalizeKey<K> extends PK ? true : IsEmptyParams<ParamsFor<PathValue<Tr, NormalizeKey<K>>>> extends true ? false : true;
|
|
16
|
+
type I18nextOptionsFor<K extends string, Tr, PK extends string> = I18nextParamsFor<K, Tr, PK> & I18nextOptions;
|
|
17
|
+
interface I18nextTranslation<T extends Record<string, any> = DefaultResources, Fallback extends keyof T & string = DefaultFallback<T>, Tr = TranslationObjectFor<undefined, T, Fallback>, PK extends string = PluralKeys<undefined, T, Fallback>> {
|
|
18
|
+
<K extends I18nextKey<Tr, PK>>(key: K, ...args: I18nextHasParams<K, Tr, PK> extends true ? [options: I18nextOptionsFor<K, Tr, PK>] : [options?: I18nextOptions]): string;
|
|
19
|
+
<K extends I18nextKey<Tr, PK>>(key: K, defaultValue: string, ...args: I18nextHasParams<K, Tr, PK> extends true ? [options: I18nextOptionsFor<K, Tr, PK>] : [options?: I18nextOptions]): string;
|
|
20
|
+
(key: string, defaultValue: string, options?: I18nextOptions): string;
|
|
21
|
+
(key: string, options: {
|
|
22
|
+
defaultValue: string;
|
|
23
|
+
} & I18nextOptions): string;
|
|
24
|
+
(key: string, options: {
|
|
25
|
+
ns: string;
|
|
26
|
+
} & I18nextOptions): string;
|
|
27
|
+
}
|
|
28
|
+
interface I18nextCompat<T extends Record<string, any> = DefaultResources, Fallback extends keyof T & string = DefaultFallback<T>, Tr = TranslationObjectFor<undefined, T, Fallback>, PK extends string = PluralKeys<undefined, T, Fallback>> {
|
|
29
|
+
t: I18nextTranslation<T, Fallback>;
|
|
30
|
+
exists<K extends I18nextKey<Tr, PK>>(key: K, options?: {
|
|
31
|
+
ns?: string;
|
|
32
|
+
[key: string]: any;
|
|
33
|
+
}): boolean;
|
|
20
34
|
exists(key: string, options?: {
|
|
21
35
|
ns?: string;
|
|
22
36
|
[key: string]: any;
|
|
@@ -34,11 +48,7 @@ interface I18nextCompat<T extends Record<string, any> = DefaultResources, Fallba
|
|
|
34
48
|
loadNamespaces(ns: string | string[], callback?: () => void): Promise<void>;
|
|
35
49
|
translator: LocL<T, Fallback, any, any, any>;
|
|
36
50
|
}
|
|
37
|
-
/**
|
|
38
|
-
* Wraps a LocL instance in an i18next-compatible interface.
|
|
39
|
-
* Supports both colon (`common:login`) and dotted namespaces with full IDE autocomplete.
|
|
40
|
-
*/
|
|
41
51
|
declare function toI18next<T extends Record<string, any> = DefaultResources, Fallback extends keyof T & string = DefaultFallback<T>>(translator: LocL<T, Fallback, any, any, any>): I18nextCompat<T, Fallback>;
|
|
42
52
|
declare const createI18nextCompat: typeof toI18next;
|
|
43
53
|
|
|
44
|
-
export { type I18nextCompat, type I18nextKey, type I18nextOptions, createI18nextCompat, toI18next };
|
|
54
|
+
export { type BaseKeys, type ColonKeys, type I18nextCompat, type I18nextHasParams, type I18nextKey, type I18nextOptions, type I18nextOptionsFor, type I18nextParamsFor, type I18nextTranslation, type NormalizeKey, createI18nextCompat, toI18next };
|
package/dist/compat.js
CHANGED
|
@@ -38,41 +38,42 @@ function toI18next(translator) {
|
|
|
38
38
|
translator.subscribe((newLang, prevLang) => {
|
|
39
39
|
emit("languageChanged", newLang, prevLang);
|
|
40
40
|
});
|
|
41
|
+
const tFunction = (key, arg1, arg2) => {
|
|
42
|
+
let defaultValue;
|
|
43
|
+
let options = {};
|
|
44
|
+
if (typeof arg1 === "string") {
|
|
45
|
+
defaultValue = arg1;
|
|
46
|
+
options = typeof arg2 === "object" && arg2 !== null ? arg2 : {};
|
|
47
|
+
} else if (typeof arg1 === "object" && arg1 !== null) {
|
|
48
|
+
options = arg1;
|
|
49
|
+
defaultValue = options.defaultValue;
|
|
50
|
+
}
|
|
51
|
+
let lookupKey = key;
|
|
52
|
+
let ns = options.ns;
|
|
53
|
+
if (key.includes(":")) {
|
|
54
|
+
const colonIdx = key.indexOf(":");
|
|
55
|
+
ns = key.slice(0, colonIdx);
|
|
56
|
+
lookupKey = key.slice(colonIdx + 1);
|
|
57
|
+
}
|
|
58
|
+
let activeTranslator = translator;
|
|
59
|
+
if (ns) {
|
|
60
|
+
activeTranslator = translator.withConfig({ scope: ns });
|
|
61
|
+
}
|
|
62
|
+
let result;
|
|
63
|
+
if (typeof options.count === "number") {
|
|
64
|
+
result = activeTranslator.plural(lookupKey, options);
|
|
65
|
+
} else {
|
|
66
|
+
result = activeTranslator.t(lookupKey, options);
|
|
67
|
+
}
|
|
68
|
+
const keyExists = activeTranslator.get(lookupKey) !== void 0 || result !== lookupKey;
|
|
69
|
+
if (!keyExists && defaultValue !== void 0) {
|
|
70
|
+
return defaultValue;
|
|
71
|
+
}
|
|
72
|
+
return result ?? defaultValue ?? key;
|
|
73
|
+
};
|
|
41
74
|
const compat = {
|
|
42
75
|
translator,
|
|
43
|
-
t
|
|
44
|
-
let defaultValue;
|
|
45
|
-
let options = {};
|
|
46
|
-
if (typeof arg1 === "string") {
|
|
47
|
-
defaultValue = arg1;
|
|
48
|
-
options = typeof arg2 === "object" && arg2 !== null ? arg2 : {};
|
|
49
|
-
} else if (typeof arg1 === "object" && arg1 !== null) {
|
|
50
|
-
options = arg1;
|
|
51
|
-
defaultValue = options.defaultValue;
|
|
52
|
-
}
|
|
53
|
-
let lookupKey = key;
|
|
54
|
-
let ns = options.ns;
|
|
55
|
-
if (key.includes(":")) {
|
|
56
|
-
const colonIdx = key.indexOf(":");
|
|
57
|
-
ns = key.slice(0, colonIdx);
|
|
58
|
-
lookupKey = key.slice(colonIdx + 1);
|
|
59
|
-
}
|
|
60
|
-
let activeTranslator = translator;
|
|
61
|
-
if (ns) {
|
|
62
|
-
activeTranslator = translator.withConfig({ scope: ns });
|
|
63
|
-
}
|
|
64
|
-
let result;
|
|
65
|
-
if (typeof options.count === "number") {
|
|
66
|
-
result = activeTranslator.plural(lookupKey, options);
|
|
67
|
-
} else {
|
|
68
|
-
result = activeTranslator.t(lookupKey, options);
|
|
69
|
-
}
|
|
70
|
-
const keyExists = activeTranslator.get(lookupKey) !== void 0 || result !== lookupKey;
|
|
71
|
-
if (!keyExists && defaultValue !== void 0) {
|
|
72
|
-
return defaultValue;
|
|
73
|
-
}
|
|
74
|
-
return result ?? defaultValue ?? key;
|
|
75
|
-
},
|
|
76
|
+
t: tFunction,
|
|
76
77
|
exists(key, options) {
|
|
77
78
|
let lookupKey = key;
|
|
78
79
|
let ns = options?.ns;
|
|
@@ -112,7 +113,7 @@ function toI18next(translator) {
|
|
|
112
113
|
addResources(lng, ns, resources) {
|
|
113
114
|
translator.addResources(lng, { [ns]: resources });
|
|
114
115
|
},
|
|
115
|
-
addResourceBundle(lng, ns, resources
|
|
116
|
+
addResourceBundle(lng, ns, resources) {
|
|
116
117
|
translator.addResources(lng, { [ns]: resources });
|
|
117
118
|
},
|
|
118
119
|
hasResourceBundle(lng, ns) {
|
package/dist/compat.mjs
CHANGED
|
@@ -13,41 +13,42 @@ function toI18next(translator) {
|
|
|
13
13
|
translator.subscribe((newLang, prevLang) => {
|
|
14
14
|
emit("languageChanged", newLang, prevLang);
|
|
15
15
|
});
|
|
16
|
+
const tFunction = (key, arg1, arg2) => {
|
|
17
|
+
let defaultValue;
|
|
18
|
+
let options = {};
|
|
19
|
+
if (typeof arg1 === "string") {
|
|
20
|
+
defaultValue = arg1;
|
|
21
|
+
options = typeof arg2 === "object" && arg2 !== null ? arg2 : {};
|
|
22
|
+
} else if (typeof arg1 === "object" && arg1 !== null) {
|
|
23
|
+
options = arg1;
|
|
24
|
+
defaultValue = options.defaultValue;
|
|
25
|
+
}
|
|
26
|
+
let lookupKey = key;
|
|
27
|
+
let ns = options.ns;
|
|
28
|
+
if (key.includes(":")) {
|
|
29
|
+
const colonIdx = key.indexOf(":");
|
|
30
|
+
ns = key.slice(0, colonIdx);
|
|
31
|
+
lookupKey = key.slice(colonIdx + 1);
|
|
32
|
+
}
|
|
33
|
+
let activeTranslator = translator;
|
|
34
|
+
if (ns) {
|
|
35
|
+
activeTranslator = translator.withConfig({ scope: ns });
|
|
36
|
+
}
|
|
37
|
+
let result;
|
|
38
|
+
if (typeof options.count === "number") {
|
|
39
|
+
result = activeTranslator.plural(lookupKey, options);
|
|
40
|
+
} else {
|
|
41
|
+
result = activeTranslator.t(lookupKey, options);
|
|
42
|
+
}
|
|
43
|
+
const keyExists = activeTranslator.get(lookupKey) !== void 0 || result !== lookupKey;
|
|
44
|
+
if (!keyExists && defaultValue !== void 0) {
|
|
45
|
+
return defaultValue;
|
|
46
|
+
}
|
|
47
|
+
return result ?? defaultValue ?? key;
|
|
48
|
+
};
|
|
16
49
|
const compat = {
|
|
17
50
|
translator,
|
|
18
|
-
t
|
|
19
|
-
let defaultValue;
|
|
20
|
-
let options = {};
|
|
21
|
-
if (typeof arg1 === "string") {
|
|
22
|
-
defaultValue = arg1;
|
|
23
|
-
options = typeof arg2 === "object" && arg2 !== null ? arg2 : {};
|
|
24
|
-
} else if (typeof arg1 === "object" && arg1 !== null) {
|
|
25
|
-
options = arg1;
|
|
26
|
-
defaultValue = options.defaultValue;
|
|
27
|
-
}
|
|
28
|
-
let lookupKey = key;
|
|
29
|
-
let ns = options.ns;
|
|
30
|
-
if (key.includes(":")) {
|
|
31
|
-
const colonIdx = key.indexOf(":");
|
|
32
|
-
ns = key.slice(0, colonIdx);
|
|
33
|
-
lookupKey = key.slice(colonIdx + 1);
|
|
34
|
-
}
|
|
35
|
-
let activeTranslator = translator;
|
|
36
|
-
if (ns) {
|
|
37
|
-
activeTranslator = translator.withConfig({ scope: ns });
|
|
38
|
-
}
|
|
39
|
-
let result;
|
|
40
|
-
if (typeof options.count === "number") {
|
|
41
|
-
result = activeTranslator.plural(lookupKey, options);
|
|
42
|
-
} else {
|
|
43
|
-
result = activeTranslator.t(lookupKey, options);
|
|
44
|
-
}
|
|
45
|
-
const keyExists = activeTranslator.get(lookupKey) !== void 0 || result !== lookupKey;
|
|
46
|
-
if (!keyExists && defaultValue !== void 0) {
|
|
47
|
-
return defaultValue;
|
|
48
|
-
}
|
|
49
|
-
return result ?? defaultValue ?? key;
|
|
50
|
-
},
|
|
51
|
+
t: tFunction,
|
|
51
52
|
exists(key, options) {
|
|
52
53
|
let lookupKey = key;
|
|
53
54
|
let ns = options?.ns;
|
|
@@ -87,7 +88,7 @@ function toI18next(translator) {
|
|
|
87
88
|
addResources(lng, ns, resources) {
|
|
88
89
|
translator.addResources(lng, { [ns]: resources });
|
|
89
90
|
},
|
|
90
|
-
addResourceBundle(lng, ns, resources
|
|
91
|
+
addResourceBundle(lng, ns, resources) {
|
|
91
92
|
translator.addResources(lng, { [ns]: resources });
|
|
92
93
|
},
|
|
93
94
|
hasResourceBundle(lng, ns) {
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as ScopeType, F as Formatter, L as LocLConfig, a as LocL } from './LocL-
|
|
2
|
-
export { b as LangWithPlurals } from './LocL-
|
|
1
|
+
import { S as ScopeType, F as Formatter, L as LocLConfig, a as LocL } from './LocL-v4yNIiKt.mjs';
|
|
2
|
+
export { b as LangWithPlurals } from './LocL-v4yNIiKt.mjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Initializes a new LocL instance.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as ScopeType, F as Formatter, L as LocLConfig, a as LocL } from './LocL-
|
|
2
|
-
export { b as LangWithPlurals } from './LocL-
|
|
1
|
+
import { S as ScopeType, F as Formatter, L as LocLConfig, a as LocL } from './LocL-v4yNIiKt.js';
|
|
2
|
+
export { b as LangWithPlurals } from './LocL-v4yNIiKt.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Initializes a new LocL instance.
|
package/dist/index.js
CHANGED
|
@@ -305,25 +305,26 @@ var LocL = class _LocL {
|
|
|
305
305
|
* @param value - The translation value.
|
|
306
306
|
*/
|
|
307
307
|
addResource(lang, key, value) {
|
|
308
|
-
if (
|
|
309
|
-
|
|
308
|
+
if (this.isUnsafeObjectKey(lang)) {
|
|
309
|
+
return;
|
|
310
310
|
}
|
|
311
311
|
const keys = key.split(".");
|
|
312
|
+
if (keys.some((k) => this.isUnsafeObjectKey(k))) {
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
if (!this.resources[lang]) {
|
|
316
|
+
this.resources[lang] = /* @__PURE__ */ Object.create(null);
|
|
317
|
+
}
|
|
312
318
|
let current = this.resources[lang];
|
|
313
319
|
for (let i = 0; i < keys.length - 1; i++) {
|
|
314
320
|
const k = keys[i];
|
|
315
|
-
if (k === "__proto__" || k === "constructor" || k === "prototype") {
|
|
316
|
-
return;
|
|
317
|
-
}
|
|
318
321
|
if (!current[k] || typeof current[k] !== "object") {
|
|
319
|
-
current[k] =
|
|
322
|
+
current[k] = /* @__PURE__ */ Object.create(null);
|
|
320
323
|
}
|
|
321
324
|
current = current[k];
|
|
322
325
|
}
|
|
323
326
|
const lastKey = keys[keys.length - 1];
|
|
324
|
-
|
|
325
|
-
current[lastKey] = value;
|
|
326
|
-
}
|
|
327
|
+
current[lastKey] = value;
|
|
327
328
|
this.invalidateCacheForLang(lang);
|
|
328
329
|
}
|
|
329
330
|
/**
|
|
@@ -332,17 +333,20 @@ var LocL = class _LocL {
|
|
|
332
333
|
* @param bundle - Object of translations to merge.
|
|
333
334
|
*/
|
|
334
335
|
addResources(lang, bundle) {
|
|
336
|
+
if (this.isUnsafeObjectKey(lang)) {
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
335
339
|
if (!this.resources[lang]) {
|
|
336
|
-
this.resources[lang] =
|
|
340
|
+
this.resources[lang] = /* @__PURE__ */ Object.create(null);
|
|
337
341
|
}
|
|
338
342
|
const deepMerge = (target, source) => {
|
|
339
343
|
for (const k of Object.keys(source)) {
|
|
340
|
-
if (k
|
|
344
|
+
if (this.isUnsafeObjectKey(k)) {
|
|
341
345
|
continue;
|
|
342
346
|
}
|
|
343
347
|
if (source[k] && typeof source[k] === "object" && !Array.isArray(source[k])) {
|
|
344
348
|
if (!target[k] || typeof target[k] !== "object") {
|
|
345
|
-
target[k] =
|
|
349
|
+
target[k] = /* @__PURE__ */ Object.create(null);
|
|
346
350
|
}
|
|
347
351
|
deepMerge(target[k], source[k]);
|
|
348
352
|
} else {
|
|
@@ -563,7 +567,7 @@ var LocL = class _LocL {
|
|
|
563
567
|
return void 0;
|
|
564
568
|
}
|
|
565
569
|
const keyTest = keysCopy.join(".");
|
|
566
|
-
if (
|
|
570
|
+
if (Object.prototype.hasOwnProperty.call(current, keyTest)) {
|
|
567
571
|
return current[keyTest];
|
|
568
572
|
}
|
|
569
573
|
if (!(key in current)) {
|
|
@@ -737,6 +741,9 @@ var LocL = class _LocL {
|
|
|
737
741
|
this.proxyCache.set(obj, proxy);
|
|
738
742
|
return proxy;
|
|
739
743
|
}
|
|
744
|
+
isUnsafeObjectKey(key) {
|
|
745
|
+
return key === "__proto__" || key === "constructor" || key === "prototype";
|
|
746
|
+
}
|
|
740
747
|
};
|
|
741
748
|
|
|
742
749
|
// src/index.ts
|
package/dist/index.mjs
CHANGED
|
@@ -277,25 +277,26 @@ var LocL = class _LocL {
|
|
|
277
277
|
* @param value - The translation value.
|
|
278
278
|
*/
|
|
279
279
|
addResource(lang, key, value) {
|
|
280
|
-
if (
|
|
281
|
-
|
|
280
|
+
if (this.isUnsafeObjectKey(lang)) {
|
|
281
|
+
return;
|
|
282
282
|
}
|
|
283
283
|
const keys = key.split(".");
|
|
284
|
+
if (keys.some((k) => this.isUnsafeObjectKey(k))) {
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
if (!this.resources[lang]) {
|
|
288
|
+
this.resources[lang] = /* @__PURE__ */ Object.create(null);
|
|
289
|
+
}
|
|
284
290
|
let current = this.resources[lang];
|
|
285
291
|
for (let i = 0; i < keys.length - 1; i++) {
|
|
286
292
|
const k = keys[i];
|
|
287
|
-
if (k === "__proto__" || k === "constructor" || k === "prototype") {
|
|
288
|
-
return;
|
|
289
|
-
}
|
|
290
293
|
if (!current[k] || typeof current[k] !== "object") {
|
|
291
|
-
current[k] =
|
|
294
|
+
current[k] = /* @__PURE__ */ Object.create(null);
|
|
292
295
|
}
|
|
293
296
|
current = current[k];
|
|
294
297
|
}
|
|
295
298
|
const lastKey = keys[keys.length - 1];
|
|
296
|
-
|
|
297
|
-
current[lastKey] = value;
|
|
298
|
-
}
|
|
299
|
+
current[lastKey] = value;
|
|
299
300
|
this.invalidateCacheForLang(lang);
|
|
300
301
|
}
|
|
301
302
|
/**
|
|
@@ -304,17 +305,20 @@ var LocL = class _LocL {
|
|
|
304
305
|
* @param bundle - Object of translations to merge.
|
|
305
306
|
*/
|
|
306
307
|
addResources(lang, bundle) {
|
|
308
|
+
if (this.isUnsafeObjectKey(lang)) {
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
307
311
|
if (!this.resources[lang]) {
|
|
308
|
-
this.resources[lang] =
|
|
312
|
+
this.resources[lang] = /* @__PURE__ */ Object.create(null);
|
|
309
313
|
}
|
|
310
314
|
const deepMerge = (target, source) => {
|
|
311
315
|
for (const k of Object.keys(source)) {
|
|
312
|
-
if (k
|
|
316
|
+
if (this.isUnsafeObjectKey(k)) {
|
|
313
317
|
continue;
|
|
314
318
|
}
|
|
315
319
|
if (source[k] && typeof source[k] === "object" && !Array.isArray(source[k])) {
|
|
316
320
|
if (!target[k] || typeof target[k] !== "object") {
|
|
317
|
-
target[k] =
|
|
321
|
+
target[k] = /* @__PURE__ */ Object.create(null);
|
|
318
322
|
}
|
|
319
323
|
deepMerge(target[k], source[k]);
|
|
320
324
|
} else {
|
|
@@ -535,7 +539,7 @@ var LocL = class _LocL {
|
|
|
535
539
|
return void 0;
|
|
536
540
|
}
|
|
537
541
|
const keyTest = keysCopy.join(".");
|
|
538
|
-
if (
|
|
542
|
+
if (Object.prototype.hasOwnProperty.call(current, keyTest)) {
|
|
539
543
|
return current[keyTest];
|
|
540
544
|
}
|
|
541
545
|
if (!(key in current)) {
|
|
@@ -709,6 +713,9 @@ var LocL = class _LocL {
|
|
|
709
713
|
this.proxyCache.set(obj, proxy);
|
|
710
714
|
return proxy;
|
|
711
715
|
}
|
|
716
|
+
isUnsafeObjectKey(key) {
|
|
717
|
+
return key === "__proto__" || key === "constructor" || key === "prototype";
|
|
718
|
+
}
|
|
712
719
|
};
|
|
713
720
|
|
|
714
721
|
// src/index.ts
|
package/dist/react.d.mts
CHANGED
|
@@ -1,28 +1,25 @@
|
|
|
1
1
|
import React, { ReactElement, ReactNode } from 'react';
|
|
2
|
-
import { S as ScopeType, N as NestedKeyOf, T as TranslationObjectFor,
|
|
2
|
+
import { S as ScopeType, N as NestedKeyOf, T as TranslationObjectFor, f as PluralKeys, e as IsEmptyParams, c as ParamsFor, d as PathValue, I as InterpolationOptions, a as LocL, g as Language, h as Scope } from './LocL-v4yNIiKt.mjs';
|
|
3
3
|
|
|
4
4
|
type TransKey<T extends Record<string, any> = DefaultResources, Fallback extends keyof T & string = DefaultFallback<T>, S extends ScopeType<T, Fallback> = undefined> = (NestedKeyOf<TranslationObjectFor<S, T, Fallback>> | PluralKeys<S, T, Fallback>) & string;
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
type TransValues<T extends Record<string, any>, Fallback extends keyof T & string, S extends ScopeType<T, Fallback>, K extends string> = IsEmptyParams<ParamsFor<PathValue<TranslationObjectFor<S, T, Fallback>, K>>> extends true ? InterpolationOptions | undefined : ParamsFor<PathValue<TranslationObjectFor<S, T, Fallback>, K>> & InterpolationOptions;
|
|
6
|
+
type TransProps<T extends Record<string, any> = DefaultResources, Fallback extends keyof T & string = DefaultFallback<T>, S extends ScopeType<T, Fallback> = undefined, K extends TransKey<T, Fallback, S> = TransKey<T, Fallback, S>> = {
|
|
7
|
+
/** Strictly typed translation key */
|
|
8
|
+
i18nKey: K;
|
|
9
|
+
values?: TransValues<T, Fallback, S, K>;
|
|
10
|
+
components?: Record<string, ReactElement | ((content: ReactNode) => ReactNode)>;
|
|
11
|
+
translator?: LocL<T, any, any, any, any>;
|
|
12
|
+
scope?: S;
|
|
13
|
+
fallback?: string;
|
|
14
|
+
} | {
|
|
15
|
+
/** Dynamic / fallback key allowed ONLY when fallback string is provided */
|
|
7
16
|
i18nKey: K | (string & {});
|
|
8
|
-
/** Values to interpolate into variable placeholders ({name}, {{name}}) */
|
|
9
17
|
values?: InterpolationOptions;
|
|
10
|
-
/**
|
|
11
|
-
* Component elements or functions to substitute for `<tag>content</tag>`
|
|
12
|
-
* @example
|
|
13
|
-
* components={{
|
|
14
|
-
* bold: <strong />,
|
|
15
|
-
* link: (content) => <a href="/terms">{content}</a>
|
|
16
|
-
* }}
|
|
17
|
-
*/
|
|
18
18
|
components?: Record<string, ReactElement | ((content: ReactNode) => ReactNode)>;
|
|
19
|
-
|
|
20
|
-
translator?: LocL<any, any, any, any, any>;
|
|
21
|
-
/** Optional namespace scope for the translation key */
|
|
19
|
+
translator?: LocL<T, any, any, any, any>;
|
|
22
20
|
scope?: S;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
21
|
+
fallback: string;
|
|
22
|
+
};
|
|
26
23
|
/**
|
|
27
24
|
* Renders translated text with rich React component interpolation without `dangerouslySetInnerHTML`.
|
|
28
25
|
* Subscribes reactively to language updates and supports strict type checking and autocompletion.
|
|
@@ -33,12 +30,12 @@ interface TransProps<T extends Record<string, any> = DefaultResources, Fallback
|
|
|
33
30
|
* values={{ name: "Alice" }}
|
|
34
31
|
* components={{
|
|
35
32
|
* bold: <strong />,
|
|
36
|
-
* link: <a href="/terms"
|
|
33
|
+
* link: (content) => <a href="/terms">{content}</a>
|
|
37
34
|
* }}
|
|
38
35
|
* />
|
|
39
36
|
* ```
|
|
40
37
|
*/
|
|
41
|
-
declare function Trans<T extends Record<string, any> = DefaultResources, Fallback extends keyof T & string = DefaultFallback<T>, S extends ScopeType<T, Fallback> = undefined, K extends
|
|
38
|
+
declare function Trans<T extends Record<string, any> = DefaultResources, Fallback extends keyof T & string = DefaultFallback<T>, S extends ScopeType<T, Fallback> = undefined, K extends TransKey<T, Fallback, S> = TransKey<T, Fallback, S>>(props: TransProps<T, Fallback, S, K>): ReactElement;
|
|
42
39
|
|
|
43
40
|
/**
|
|
44
41
|
* Global type registry for LocL React.
|
|
@@ -83,11 +80,10 @@ interface UseLocLResult<T extends Record<string, any> = DefaultResources, Fallba
|
|
|
83
80
|
}
|
|
84
81
|
interface UseTranslationResult<T extends Record<string, any> = DefaultResources, Fallback extends keyof T & string = DefaultFallback<T>, S extends ScopeType<T, Fallback> = undefined> extends UseLocLResult<T, Fallback, S> {
|
|
85
82
|
}
|
|
86
|
-
declare function useLocL<T extends Record<string, any> = DefaultResources, Fallback extends keyof T & string = DefaultFallback<T>, S extends ScopeType<T, Fallback> = undefined>(customTranslator?: LocL<any, any, any, any, any>): UseLocLResult<T, Fallback, S>;
|
|
87
|
-
declare function useTranslation<T extends Record<string, any> = DefaultResources, Fallback extends keyof T & string = DefaultFallback<T>>(scope?: undefined, customTranslator?: LocL<any, any, any, any, any>): UseTranslationResult<T, Fallback, undefined>;
|
|
88
|
-
declare function useTranslation<T extends Record<string, any> = DefaultResources, Fallback extends keyof T & string = DefaultFallback<T>, S extends ScopeType<T, Fallback> = ScopeType<T, Fallback>>(scope: S, customTranslator?: LocL<any, any, any, any, any>): UseTranslationResult<T, Fallback, S>;
|
|
83
|
+
declare function useLocL<T extends Record<string, any> = DefaultResources, Fallback extends keyof T & string = DefaultFallback<T>, S extends ScopeType<T, Fallback> = undefined>(customTranslator?: LocL<T, Fallback, S, any, any> | LocL<any, any, any, any, any>): UseLocLResult<T, Fallback, S>;
|
|
84
|
+
declare function useTranslation<T extends Record<string, any> = DefaultResources, Fallback extends keyof T & string = DefaultFallback<T>>(scope?: undefined, customTranslator?: LocL<T, Fallback, any, any, any> | LocL<any, any, any, any, any>): UseTranslationResult<T, Fallback, undefined>;
|
|
85
|
+
declare function useTranslation<T extends Record<string, any> = DefaultResources, Fallback extends keyof T & string = DefaultFallback<T>, S extends ScopeType<T, Fallback> = ScopeType<T, Fallback>>(scope: S, customTranslator?: LocL<T, Fallback, any, any, any> | LocL<any, any, any, any, any>): UseTranslationResult<T, Fallback, S>;
|
|
89
86
|
interface BoundLocLProviderProps<T extends Record<string, any>, Fallback extends keyof T & string> {
|
|
90
|
-
/** Optional override translator; defaults to the instance passed to `createLocLReact` */
|
|
91
87
|
translator?: LocL<any, any, any, any, any>;
|
|
92
88
|
children: ReactNode;
|
|
93
89
|
}
|
|
@@ -96,11 +92,13 @@ interface LocLReactSuite<T extends Record<string, any>, Fallback extends keyof T
|
|
|
96
92
|
LocLProvider: (props: BoundLocLProviderProps<T, Fallback>) => ReactElement;
|
|
97
93
|
useLocL: <S extends ScopeType<T, Fallback> = undefined>(customTranslator?: LocL<any, any, any, any, any>) => UseLocLResult<T, Fallback, S>;
|
|
98
94
|
useTranslation: {
|
|
95
|
+
(): UseTranslationResult<T, Fallback, undefined>;
|
|
96
|
+
<S extends Scope<T, Fallback>>(scope: S): UseTranslationResult<T, Fallback, S>;
|
|
97
|
+
<S extends Scope<T, Fallback>[]>(scope: S): UseTranslationResult<T, Fallback, S>;
|
|
99
98
|
(scope?: undefined, customTranslator?: LocL<any, any, any, any, any>): UseTranslationResult<T, Fallback, undefined>;
|
|
100
99
|
<S extends ScopeType<T, Fallback>>(scope: S, customTranslator?: LocL<any, any, any, any, any>): UseTranslationResult<T, Fallback, S>;
|
|
101
|
-
<S extends ScopeType<T, Fallback> = any>(scope?: S, customTranslator?: LocL<any, any, any, any, any>): UseTranslationResult<T, Fallback, S>;
|
|
102
100
|
};
|
|
103
|
-
Trans: <S extends ScopeType<T, Fallback> = undefined, K extends
|
|
101
|
+
Trans: <S extends ScopeType<T, Fallback> = undefined, K extends TransKey<T, Fallback, S> = TransKey<T, Fallback, S>>(props: TransProps<T, Fallback, S, K>) => ReactElement;
|
|
104
102
|
translator: LocL<T, Fallback, any, any, any>;
|
|
105
103
|
}
|
|
106
104
|
/**
|
|
@@ -117,4 +115,4 @@ interface LocLReactSuite<T extends Record<string, any>, Fallback extends keyof T
|
|
|
117
115
|
*/
|
|
118
116
|
declare function createLocLReact<T extends Record<string, any>, Fallback extends keyof T & string>(defaultTranslator: LocL<T, Fallback, any, any, any>): LocLReactSuite<T, Fallback>;
|
|
119
117
|
|
|
120
|
-
export { type BoundLocLProviderProps, type DefaultFallback, type DefaultResources, LocLContext, LocLProvider, type LocLProviderProps, type LocLReactSuite, type LocLRegister, Trans, type TransKey, type TransProps, type UseLocLResult, type UseTranslationResult, createLocLReact, useLocL, useTranslation };
|
|
118
|
+
export { type BoundLocLProviderProps, type DefaultFallback, type DefaultResources, LocLContext, LocLProvider, type LocLProviderProps, type LocLReactSuite, type LocLRegister, Trans, type TransKey, type TransProps, type TransValues, type UseLocLResult, type UseTranslationResult, createLocLReact, useLocL, useTranslation };
|
package/dist/react.d.ts
CHANGED
|
@@ -1,28 +1,25 @@
|
|
|
1
1
|
import React, { ReactElement, ReactNode } from 'react';
|
|
2
|
-
import { S as ScopeType, N as NestedKeyOf, T as TranslationObjectFor,
|
|
2
|
+
import { S as ScopeType, N as NestedKeyOf, T as TranslationObjectFor, f as PluralKeys, e as IsEmptyParams, c as ParamsFor, d as PathValue, I as InterpolationOptions, a as LocL, g as Language, h as Scope } from './LocL-v4yNIiKt.js';
|
|
3
3
|
|
|
4
4
|
type TransKey<T extends Record<string, any> = DefaultResources, Fallback extends keyof T & string = DefaultFallback<T>, S extends ScopeType<T, Fallback> = undefined> = (NestedKeyOf<TranslationObjectFor<S, T, Fallback>> | PluralKeys<S, T, Fallback>) & string;
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
type TransValues<T extends Record<string, any>, Fallback extends keyof T & string, S extends ScopeType<T, Fallback>, K extends string> = IsEmptyParams<ParamsFor<PathValue<TranslationObjectFor<S, T, Fallback>, K>>> extends true ? InterpolationOptions | undefined : ParamsFor<PathValue<TranslationObjectFor<S, T, Fallback>, K>> & InterpolationOptions;
|
|
6
|
+
type TransProps<T extends Record<string, any> = DefaultResources, Fallback extends keyof T & string = DefaultFallback<T>, S extends ScopeType<T, Fallback> = undefined, K extends TransKey<T, Fallback, S> = TransKey<T, Fallback, S>> = {
|
|
7
|
+
/** Strictly typed translation key */
|
|
8
|
+
i18nKey: K;
|
|
9
|
+
values?: TransValues<T, Fallback, S, K>;
|
|
10
|
+
components?: Record<string, ReactElement | ((content: ReactNode) => ReactNode)>;
|
|
11
|
+
translator?: LocL<T, any, any, any, any>;
|
|
12
|
+
scope?: S;
|
|
13
|
+
fallback?: string;
|
|
14
|
+
} | {
|
|
15
|
+
/** Dynamic / fallback key allowed ONLY when fallback string is provided */
|
|
7
16
|
i18nKey: K | (string & {});
|
|
8
|
-
/** Values to interpolate into variable placeholders ({name}, {{name}}) */
|
|
9
17
|
values?: InterpolationOptions;
|
|
10
|
-
/**
|
|
11
|
-
* Component elements or functions to substitute for `<tag>content</tag>`
|
|
12
|
-
* @example
|
|
13
|
-
* components={{
|
|
14
|
-
* bold: <strong />,
|
|
15
|
-
* link: (content) => <a href="/terms">{content}</a>
|
|
16
|
-
* }}
|
|
17
|
-
*/
|
|
18
18
|
components?: Record<string, ReactElement | ((content: ReactNode) => ReactNode)>;
|
|
19
|
-
|
|
20
|
-
translator?: LocL<any, any, any, any, any>;
|
|
21
|
-
/** Optional namespace scope for the translation key */
|
|
19
|
+
translator?: LocL<T, any, any, any, any>;
|
|
22
20
|
scope?: S;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
21
|
+
fallback: string;
|
|
22
|
+
};
|
|
26
23
|
/**
|
|
27
24
|
* Renders translated text with rich React component interpolation without `dangerouslySetInnerHTML`.
|
|
28
25
|
* Subscribes reactively to language updates and supports strict type checking and autocompletion.
|
|
@@ -33,12 +30,12 @@ interface TransProps<T extends Record<string, any> = DefaultResources, Fallback
|
|
|
33
30
|
* values={{ name: "Alice" }}
|
|
34
31
|
* components={{
|
|
35
32
|
* bold: <strong />,
|
|
36
|
-
* link: <a href="/terms"
|
|
33
|
+
* link: (content) => <a href="/terms">{content}</a>
|
|
37
34
|
* }}
|
|
38
35
|
* />
|
|
39
36
|
* ```
|
|
40
37
|
*/
|
|
41
|
-
declare function Trans<T extends Record<string, any> = DefaultResources, Fallback extends keyof T & string = DefaultFallback<T>, S extends ScopeType<T, Fallback> = undefined, K extends
|
|
38
|
+
declare function Trans<T extends Record<string, any> = DefaultResources, Fallback extends keyof T & string = DefaultFallback<T>, S extends ScopeType<T, Fallback> = undefined, K extends TransKey<T, Fallback, S> = TransKey<T, Fallback, S>>(props: TransProps<T, Fallback, S, K>): ReactElement;
|
|
42
39
|
|
|
43
40
|
/**
|
|
44
41
|
* Global type registry for LocL React.
|
|
@@ -83,11 +80,10 @@ interface UseLocLResult<T extends Record<string, any> = DefaultResources, Fallba
|
|
|
83
80
|
}
|
|
84
81
|
interface UseTranslationResult<T extends Record<string, any> = DefaultResources, Fallback extends keyof T & string = DefaultFallback<T>, S extends ScopeType<T, Fallback> = undefined> extends UseLocLResult<T, Fallback, S> {
|
|
85
82
|
}
|
|
86
|
-
declare function useLocL<T extends Record<string, any> = DefaultResources, Fallback extends keyof T & string = DefaultFallback<T>, S extends ScopeType<T, Fallback> = undefined>(customTranslator?: LocL<any, any, any, any, any>): UseLocLResult<T, Fallback, S>;
|
|
87
|
-
declare function useTranslation<T extends Record<string, any> = DefaultResources, Fallback extends keyof T & string = DefaultFallback<T>>(scope?: undefined, customTranslator?: LocL<any, any, any, any, any>): UseTranslationResult<T, Fallback, undefined>;
|
|
88
|
-
declare function useTranslation<T extends Record<string, any> = DefaultResources, Fallback extends keyof T & string = DefaultFallback<T>, S extends ScopeType<T, Fallback> = ScopeType<T, Fallback>>(scope: S, customTranslator?: LocL<any, any, any, any, any>): UseTranslationResult<T, Fallback, S>;
|
|
83
|
+
declare function useLocL<T extends Record<string, any> = DefaultResources, Fallback extends keyof T & string = DefaultFallback<T>, S extends ScopeType<T, Fallback> = undefined>(customTranslator?: LocL<T, Fallback, S, any, any> | LocL<any, any, any, any, any>): UseLocLResult<T, Fallback, S>;
|
|
84
|
+
declare function useTranslation<T extends Record<string, any> = DefaultResources, Fallback extends keyof T & string = DefaultFallback<T>>(scope?: undefined, customTranslator?: LocL<T, Fallback, any, any, any> | LocL<any, any, any, any, any>): UseTranslationResult<T, Fallback, undefined>;
|
|
85
|
+
declare function useTranslation<T extends Record<string, any> = DefaultResources, Fallback extends keyof T & string = DefaultFallback<T>, S extends ScopeType<T, Fallback> = ScopeType<T, Fallback>>(scope: S, customTranslator?: LocL<T, Fallback, any, any, any> | LocL<any, any, any, any, any>): UseTranslationResult<T, Fallback, S>;
|
|
89
86
|
interface BoundLocLProviderProps<T extends Record<string, any>, Fallback extends keyof T & string> {
|
|
90
|
-
/** Optional override translator; defaults to the instance passed to `createLocLReact` */
|
|
91
87
|
translator?: LocL<any, any, any, any, any>;
|
|
92
88
|
children: ReactNode;
|
|
93
89
|
}
|
|
@@ -96,11 +92,13 @@ interface LocLReactSuite<T extends Record<string, any>, Fallback extends keyof T
|
|
|
96
92
|
LocLProvider: (props: BoundLocLProviderProps<T, Fallback>) => ReactElement;
|
|
97
93
|
useLocL: <S extends ScopeType<T, Fallback> = undefined>(customTranslator?: LocL<any, any, any, any, any>) => UseLocLResult<T, Fallback, S>;
|
|
98
94
|
useTranslation: {
|
|
95
|
+
(): UseTranslationResult<T, Fallback, undefined>;
|
|
96
|
+
<S extends Scope<T, Fallback>>(scope: S): UseTranslationResult<T, Fallback, S>;
|
|
97
|
+
<S extends Scope<T, Fallback>[]>(scope: S): UseTranslationResult<T, Fallback, S>;
|
|
99
98
|
(scope?: undefined, customTranslator?: LocL<any, any, any, any, any>): UseTranslationResult<T, Fallback, undefined>;
|
|
100
99
|
<S extends ScopeType<T, Fallback>>(scope: S, customTranslator?: LocL<any, any, any, any, any>): UseTranslationResult<T, Fallback, S>;
|
|
101
|
-
<S extends ScopeType<T, Fallback> = any>(scope?: S, customTranslator?: LocL<any, any, any, any, any>): UseTranslationResult<T, Fallback, S>;
|
|
102
100
|
};
|
|
103
|
-
Trans: <S extends ScopeType<T, Fallback> = undefined, K extends
|
|
101
|
+
Trans: <S extends ScopeType<T, Fallback> = undefined, K extends TransKey<T, Fallback, S> = TransKey<T, Fallback, S>>(props: TransProps<T, Fallback, S, K>) => ReactElement;
|
|
104
102
|
translator: LocL<T, Fallback, any, any, any>;
|
|
105
103
|
}
|
|
106
104
|
/**
|
|
@@ -117,4 +115,4 @@ interface LocLReactSuite<T extends Record<string, any>, Fallback extends keyof T
|
|
|
117
115
|
*/
|
|
118
116
|
declare function createLocLReact<T extends Record<string, any>, Fallback extends keyof T & string>(defaultTranslator: LocL<T, Fallback, any, any, any>): LocLReactSuite<T, Fallback>;
|
|
119
117
|
|
|
120
|
-
export { type BoundLocLProviderProps, type DefaultFallback, type DefaultResources, LocLContext, LocLProvider, type LocLProviderProps, type LocLReactSuite, type LocLRegister, Trans, type TransKey, type TransProps, type UseLocLResult, type UseTranslationResult, createLocLReact, useLocL, useTranslation };
|
|
118
|
+
export { type BoundLocLProviderProps, type DefaultFallback, type DefaultResources, LocLContext, LocLProvider, type LocLProviderProps, type LocLReactSuite, type LocLRegister, Trans, type TransKey, type TransProps, type TransValues, type UseLocLResult, type UseTranslationResult, createLocLReact, useLocL, useTranslation };
|
package/dist/react.js
CHANGED
|
@@ -43,14 +43,15 @@ var import_react2 = require("react");
|
|
|
43
43
|
// src/react/Trans.tsx
|
|
44
44
|
var import_react = __toESM(require("react"));
|
|
45
45
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
46
|
-
function Trans({
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
46
|
+
function Trans(props) {
|
|
47
|
+
const {
|
|
48
|
+
i18nKey,
|
|
49
|
+
values,
|
|
50
|
+
components = {},
|
|
51
|
+
translator: customTranslator,
|
|
52
|
+
scope,
|
|
53
|
+
fallback
|
|
54
|
+
} = props;
|
|
54
55
|
const contextTranslator = (0, import_react.useContext)(LocLContext);
|
|
55
56
|
const activeTranslator = customTranslator ?? contextTranslator;
|
|
56
57
|
const getSnapshot = () => activeTranslator ? activeTranslator.getLanguage() : "";
|
package/dist/react.mjs
CHANGED
|
@@ -4,14 +4,15 @@ import { createContext, useContext as useContext2, useSyncExternalStore as useSy
|
|
|
4
4
|
// src/react/Trans.tsx
|
|
5
5
|
import React, { isValidElement, cloneElement, useContext, useMemo, useSyncExternalStore } from "react";
|
|
6
6
|
import { Fragment, jsx } from "react/jsx-runtime";
|
|
7
|
-
function Trans({
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
7
|
+
function Trans(props) {
|
|
8
|
+
const {
|
|
9
|
+
i18nKey,
|
|
10
|
+
values,
|
|
11
|
+
components = {},
|
|
12
|
+
translator: customTranslator,
|
|
13
|
+
scope,
|
|
14
|
+
fallback
|
|
15
|
+
} = props;
|
|
15
16
|
const contextTranslator = useContext(LocLContext);
|
|
16
17
|
const activeTranslator = customTranslator ?? contextTranslator;
|
|
17
18
|
const getSnapshot = () => activeTranslator ? activeTranslator.getLanguage() : "";
|
package/package.json
CHANGED