ngx-kit 8.5.0 → 9.0.0

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.
@@ -0,0 +1,213 @@
1
+ import * as i0 from '@angular/core';
2
+ import { InjectionToken, Type, PipeTransform, Signal, EnvironmentProviders } from '@angular/core';
3
+ import { Observable } from 'rxjs';
4
+ import { CanActivateChildFn } from '@angular/router';
5
+
6
+ /** A (possibly nested) translation file as returned by the server. */
7
+ interface Dictionary {
8
+ [key: string]: string | number | boolean | null | Dictionary | Array<unknown>;
9
+ }
10
+ type Params = Record<string, unknown>;
11
+ type TranslateFn = (key: string, params?: Params) => string;
12
+ type MissingHandler = (key: string, lang: string) => string;
13
+ type Transpiler = (value: string, params: Params | undefined, lang: string) => string;
14
+ interface I18nLoader {
15
+ /** `scope === undefined` means the global file. */
16
+ load(lang: string, scope?: string): Observable<Dictionary> | Promise<Dictionary>;
17
+ }
18
+ declare class I18nConfig {
19
+ /** All supported languages. */
20
+ langs: string[];
21
+ defaultLang: string;
22
+ /** Looked up (in order) when a key is empty/missing in the active language. */
23
+ fallbackLangs?: string[];
24
+ /** Default `'key'` (returns the key itself). */
25
+ missing?: 'key' | 'empty' | MissingHandler;
26
+ /** Log each missing key once. Default: `isDevMode()`. */
27
+ warnMissing?: boolean;
28
+ /** Replace the default `{{ name }}` interpolation (ICU, plurals, ...). */
29
+ transpile?: Transpiler;
30
+ /** Custom loader class (must be `@Injectable({providedIn:'root'})` or constructible without args). Default: HTTP. */
31
+ loader?: Type<I18nLoader>;
32
+ /** Default HTTP loader: base URL. Default `'/i18n'` -> `/i18n/fa`, `/i18n/setting/fa`. */
33
+ baseUrl?: string;
34
+ /** Default HTTP loader: file extension appended to the URL, e.g. `'.json'`. Default `'.json'`. */
35
+ fileExtension?: string;
36
+ /** Default HTTP loader: full control over the URL. */
37
+ url?: (lang: string, scope?: string) => string;
38
+ /** Retries per failed request. Default `1`. */
39
+ retries?: number;
40
+ /** localStorage key used to remember the language. `null` disables. Default `'lazy-i18n.lang'`. */
41
+ storageKey?: string | null;
42
+ /** Pick the initial language from `navigator.languages` when nothing is stored. Default `false`. */
43
+ detectBrowserLang?: boolean;
44
+ /** Keep `<html lang dir>` in sync. Default `true`. */
45
+ manageDocument?: boolean;
46
+ }
47
+ declare const I18N_CONFIG: InjectionToken<I18nConfig>;
48
+ declare const I18N_LOADER: InjectionToken<I18nLoader>;
49
+
50
+ /**
51
+ * `{{ 'orders.title' | tr }}` / `{{ 'hello' | tr: { name } }}`
52
+ *
53
+ * Impure on purpose (it must follow signals), but memoised: when key, params and the
54
+ * service revision are unchanged it returns the cached string in O(1) with no lookup.
55
+ */
56
+ declare class TrPipe implements PipeTransform {
57
+ private readonly svc;
58
+ private k?;
59
+ private p?;
60
+ private rev;
61
+ private out;
62
+ transform(key: string | null | undefined, params?: Params): string;
63
+ static ɵfac: i0.ɵɵFactoryDeclaration<TrPipe, never>;
64
+ static ɵpipe: i0.ɵɵPipeDeclaration<TrPipe, "tr", true>;
65
+ }
66
+
67
+ interface TrContext {
68
+ $implicit: TranslateFn;
69
+ t: TranslateFn;
70
+ lang: Signal<string>;
71
+ }
72
+ /**
73
+ * Structural directive. The view is created ONCE; `t` reads signals, so only the bindings that use it update.
74
+ *
75
+ * <ng-container *tr="let t; prefix: 'orders'">
76
+ * <h1>{{ t('title') }}</h1> <!-- orders.title -->
77
+ * </ng-container>
78
+ */
79
+ declare class TrDirective {
80
+ private readonly tpl;
81
+ private readonly vcr;
82
+ private readonly svc;
83
+ private readonly prefix;
84
+ /** `prefix: 'orders'` in the microsyntax. */
85
+ set trPrefix(v: string | undefined);
86
+ static ngTemplateContextGuard(_dir: TrDirective, _ctx: unknown): _ctx is TrContext;
87
+ constructor();
88
+ static ɵfac: i0.ɵɵFactoryDeclaration<TrDirective, never>;
89
+ static ɵdir: i0.ɵɵDirectiveDeclaration<TrDirective, "[tr],[translate]", never, { "trPrefix": { "alias": "trPrefix"; "required": false; }; }, {}, never, never, true, never>;
90
+ }
91
+ /**
92
+ * Attribute directive.
93
+ * <span trKey="orders.title"></span>
94
+ * <input trKey="form.name" trAttr="placeholder" />
95
+ * <p trKey="hello" [trParams]="{ name: user.name }"></p>
96
+ */
97
+ declare class TrKeyDirective {
98
+ private readonly key;
99
+ private readonly params;
100
+ private readonly attr;
101
+ private readonly prefix;
102
+ set trKey(v: string | undefined);
103
+ set trParams(v: Params | undefined);
104
+ set trAttr(v: string | undefined);
105
+ set trPrefix(v: string | undefined);
106
+ constructor();
107
+ static ɵfac: i0.ɵɵFactoryDeclaration<TrKeyDirective, never>;
108
+ static ɵdir: i0.ɵɵDirectiveDeclaration<TrKeyDirective, "[trKey]", never, { "trKey": { "alias": "trKey"; "required": false; }; "trParams": { "alias": "trParams"; "required": false; }; "trAttr": { "alias": "trAttr"; "required": false; }; "trPrefix": { "alias": "trPrefix"; "required": false; }; }, {}, never, never, true, never>;
109
+ }
110
+
111
+ /** Flatten a nested dictionary into `target` (dot-separated keys). Non-string leaves are stringified. */
112
+ declare function flatten(dict: Dictionary, target?: Map<string, string>, onConflict?: (key: string) => void, prefix?: string): Map<string, string>;
113
+ /** `Hello {{ name }}` + `{name:'Ali'}` -> `Hello Ali`. Unknown placeholders are left untouched. */
114
+ declare function interpolate(text: string, params?: Params): string;
115
+ /** Identity function the extractor recognises: `const k = marker('orders.title')`. */
116
+ declare function marker<T extends string>(key: T): T;
117
+
118
+ /** Default loader: GET `{baseUrl}/{lang}` and `{baseUrl}/{scope}/{lang}`. Goes through your HttpClient interceptors. */
119
+ declare class HttpI18nLoader implements I18nLoader {
120
+ private readonly http;
121
+ private readonly cfg;
122
+ load(lang: string, scope?: string): Observable<Dictionary>;
123
+ static ɵfac: i0.ɵɵFactoryDeclaration<HttpI18nLoader, never>;
124
+ static ɵprov: i0.ɵɵInjectableDeclaration<HttpI18nLoader>;
125
+ }
126
+
127
+ declare class I18nService {
128
+ private readonly cfg;
129
+ private readonly loader;
130
+ private readonly doc;
131
+ private readonly _lang;
132
+ private readonly _rev;
133
+ /** Active language (reactive). */
134
+ readonly lang: Signal<string>;
135
+ /** Bumps whenever the active language or any dictionary changes. */
136
+ readonly revision: Signal<number>;
137
+ readonly dir: Signal<"rtl" | "ltr">;
138
+ readonly langs: readonly string[];
139
+ private readonly fallbacks;
140
+ private readonly warn;
141
+ private readonly dicts;
142
+ private readonly loaded;
143
+ private readonly inflight;
144
+ private readonly scopes;
145
+ private readonly pending;
146
+ private readonly warned;
147
+ private useToken;
148
+ /** Translate. Reads signals, so it is reactive inside `computed`, `effect` and templates. */
149
+ t(key: string, params?: Params): string;
150
+ /** Same as `t`, but never creates a reactive dependency. */
151
+ instant(key: string, params?: Params): string;
152
+ /** `computed` signal for one key. `params` may be a function reading other signals. */
153
+ select(key: string, params?: Params | (() => Params)): Signal<string>;
154
+ /** True when the key has a non-empty value in the active language or a fallback. */
155
+ has(key: string): boolean;
156
+ /** Returns every key below `prefix` as a nested object (values are raw, not interpolated). */
157
+ getObject(prefix: string): Dictionary;
158
+ private lookup;
159
+ private resolve;
160
+ private onMissing;
161
+ /**
162
+ * Load global + all registered scopes (and fallback languages) for `lang`, THEN activate it.
163
+ * Nothing renders half-translated and no "missing" flash occurs.
164
+ */
165
+ use(lang: string): Promise<void>;
166
+ /** Download a language without activating it. */
167
+ preload(lang: string): Promise<void>;
168
+ /** Language to start with: stored > browser (opt-in) > default. */
169
+ detectInitialLang(): string;
170
+ /** Register a scope and start loading it for the active language. Idempotent. Used by `provideI18nScope`. */
171
+ registerScope(scope: string): void;
172
+ /** Resolves once every scope registered so far is available. Never rejects. */
173
+ whenReady(): Promise<void>;
174
+ /** Manually set translations (tests, SSR transfer state, ...). */
175
+ setTranslation(lang: string, dict: Dictionary, merge?: boolean): void;
176
+ private merge;
177
+ private fetch;
178
+ private loadLang;
179
+ private isComplete;
180
+ private storageKey;
181
+ private persist;
182
+ private applyDocument;
183
+ static ɵfac: i0.ɵɵFactoryDeclaration<I18nService, never>;
184
+ static ɵprov: i0.ɵɵInjectableDeclaration<I18nService>;
185
+ }
186
+
187
+ /**
188
+ * ```ts
189
+ * provideHttpClient(),
190
+ * provideI18n({ langs: ['fa', 'en'], defaultLang: 'fa', fallbackLangs: ['en'] })
191
+ * ```
192
+ * The global dictionary of the initial language is loaded before the app starts.
193
+ */
194
+ declare function provideI18n(config: I18nConfig): EnvironmentProviders;
195
+
196
+ /**
197
+ * Put in `route.providers`. Runs when the route injector is created (before guards),
198
+ * so loading starts as early as possible. Child routes need nothing.
199
+ */
200
+ declare function provideI18nScope(scope: string | string[]): EnvironmentProviders;
201
+ /** Put ONCE on the root path-less route: `canActivateChild: [i18nReadyGuard]`. Waits for every registered scope. */
202
+ declare const i18nReadyGuard: CanActivateChildFn;
203
+
204
+ /** `readonly title = translateSignal('orders.title')` (injection context) */
205
+ declare function translateSignal(key: string, params?: Params | (() => Params)): Signal<string>;
206
+ /** `const t = injectT(); computed(() => t('a.b'))` — reactive translate function. */
207
+ declare function injectT(): TranslateFn;
208
+
209
+ /** `imports: [TR]` brings the pipe and both directives into a standalone component. */
210
+ declare const TR: readonly [typeof TrPipe, typeof TrDirective, typeof TrKeyDirective];
211
+
212
+ export { HttpI18nLoader, I18N_CONFIG, I18N_LOADER, I18nConfig, I18nService, TR, TrDirective, TrKeyDirective, TrPipe, flatten, i18nReadyGuard, injectT, interpolate, marker, provideI18n, provideI18nScope, translateSignal };
213
+ export type { Dictionary, I18nLoader, MissingHandler, Params, TrContext, TranslateFn, Transpiler };