@zucker-framework/i18n 1.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.
- package/LICENSE +201 -0
- package/NOTICE +22 -0
- package/THIRD_PARTY_NOTICES +4 -0
- package/dist/index.d.mts +282 -0
- package/dist/index.d.ts +282 -0
- package/dist/index.js +677 -0
- package/dist/index.mjs +636 -0
- package/package.json +40 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import { NestInterceptor, ExecutionContext, CallHandler, Type, DynamicModule, InjectionToken, OptionalFactoryDependency } from '@nestjs/common';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
import { BusinessException } from '@zucker-framework/core';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* MessageSource — i18n message resolution interface.
|
|
7
|
+
*/
|
|
8
|
+
interface MessageSource {
|
|
9
|
+
getMessage(code: string, args?: unknown[], defaultMessage?: string, locale?: string): string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* FileMessageSource — loads messages from JSON files.
|
|
13
|
+
*
|
|
14
|
+
* Expected file structure: {basePath}/{locale}.json
|
|
15
|
+
* JSON format: flat key-value pairs, e.g. { "error.notFound": "Resource not found" }
|
|
16
|
+
*
|
|
17
|
+
* Supports message interpolation with positional args: "Hello {0}, welcome to {1}"
|
|
18
|
+
*/
|
|
19
|
+
declare class FileMessageSource implements MessageSource {
|
|
20
|
+
private readonly basePath;
|
|
21
|
+
private readonly logger;
|
|
22
|
+
private readonly messages;
|
|
23
|
+
private readonly defaultLocale;
|
|
24
|
+
constructor(basePath: string, options?: {
|
|
25
|
+
defaultLocale?: string;
|
|
26
|
+
});
|
|
27
|
+
getMessage(code: string, args?: unknown[], defaultMessage?: string, locale?: string): string;
|
|
28
|
+
private loadLocale;
|
|
29
|
+
private flatten;
|
|
30
|
+
private interpolate;
|
|
31
|
+
clearCache(): void;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* CompositeMessageSource — aggregates multiple message sources.
|
|
35
|
+
* Checks sources in order, returns the first match.
|
|
36
|
+
*/
|
|
37
|
+
declare class CompositeMessageSource implements MessageSource {
|
|
38
|
+
private readonly sources;
|
|
39
|
+
constructor(sources: MessageSource[]);
|
|
40
|
+
getMessage(code: string, args?: unknown[], defaultMessage?: string, locale?: string): string;
|
|
41
|
+
addSource(source: MessageSource): void;
|
|
42
|
+
/**
|
|
43
|
+
* Add multiple sources at once.
|
|
44
|
+
*/
|
|
45
|
+
addSources(sources: MessageSource[]): void;
|
|
46
|
+
/**
|
|
47
|
+
* Get the number of registered sources.
|
|
48
|
+
*/
|
|
49
|
+
getSourceCount(): number;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* LocaleContext -- uses AsyncLocalStorage to bind the current locale
|
|
54
|
+
* to the execution context (request scope).
|
|
55
|
+
*/
|
|
56
|
+
declare class LocaleContext {
|
|
57
|
+
private static defaultLocale;
|
|
58
|
+
static setDefault(locale: string): void;
|
|
59
|
+
static getCurrent(): string;
|
|
60
|
+
static run<T>(locale: string, fn: () => T): T;
|
|
61
|
+
static runAsync<T>(locale: string, fn: () => Promise<T>): Promise<T>;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* NestJS interceptor that sets the locale from the Accept-Language header.
|
|
65
|
+
*/
|
|
66
|
+
declare class LocaleInterceptor implements NestInterceptor {
|
|
67
|
+
private readonly supportedLocales;
|
|
68
|
+
private readonly defaultLocale;
|
|
69
|
+
constructor(options?: {
|
|
70
|
+
supportedLocales?: string[];
|
|
71
|
+
defaultLocale?: string;
|
|
72
|
+
});
|
|
73
|
+
intercept(context: ExecutionContext, next: CallHandler): Observable<unknown>;
|
|
74
|
+
private parseLocale;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* I18nException — an exception whose message is resolved via i18n at response time.
|
|
79
|
+
*
|
|
80
|
+
* Stores a message code and interpolation args. The actual i18n resolution
|
|
81
|
+
* happens when getMessage() is called (typically in an exception filter).
|
|
82
|
+
*/
|
|
83
|
+
declare class I18nException extends BusinessException {
|
|
84
|
+
readonly i18nCode: string;
|
|
85
|
+
readonly i18nArgs: unknown[];
|
|
86
|
+
constructor(code: string, args?: unknown[], fallbackMessage?: string);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* I18nSpec — supports nested i18n parameter resolution.
|
|
91
|
+
*
|
|
92
|
+
* Allows i18n message codes whose arguments themselves need i18n resolution.
|
|
93
|
+
*
|
|
94
|
+
* Reference: jetlinks I18nSpec
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```ts
|
|
98
|
+
* const spec = I18nSpec.of('message.scene.term.full_name', 'Property: {0}/{1}',
|
|
99
|
+
* 'Temperature',
|
|
100
|
+
* I18nSpec.of('message.property.recent', 'Current Value'),
|
|
101
|
+
* );
|
|
102
|
+
* const resolved = spec.resolve(messageSource);
|
|
103
|
+
* // => "Property: Temperature/Current Value" (or localized)
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
declare class I18nSpec {
|
|
107
|
+
/** i18n message code; if empty, defaultMessage is returned as-is */
|
|
108
|
+
code?: string;
|
|
109
|
+
/** Fallback message when code is not found or not provided */
|
|
110
|
+
defaultMessage?: string;
|
|
111
|
+
/** Nested i18n-aware arguments */
|
|
112
|
+
args: I18nSpec[];
|
|
113
|
+
constructor(code?: string, defaultMessage?: string, args?: I18nSpec[]);
|
|
114
|
+
/**
|
|
115
|
+
* Create an I18nSpec with optional nested args.
|
|
116
|
+
* Args can be strings (treated as plain defaults) or I18nSpec instances.
|
|
117
|
+
*/
|
|
118
|
+
static of(code: string, defaultMessage?: string, ...args: Array<string | I18nSpec>): I18nSpec;
|
|
119
|
+
/**
|
|
120
|
+
* Add a nested i18n argument.
|
|
121
|
+
*/
|
|
122
|
+
withArg(code: string, defaultMessage?: string, ...args: Array<string | I18nSpec>): this;
|
|
123
|
+
/**
|
|
124
|
+
* Add an existing I18nSpec as a nested argument.
|
|
125
|
+
*/
|
|
126
|
+
withArgSpec(spec: I18nSpec): this;
|
|
127
|
+
/**
|
|
128
|
+
* Resolve this spec to a final message using the given MessageSource.
|
|
129
|
+
* Recursively resolves nested args first.
|
|
130
|
+
*/
|
|
131
|
+
resolve(messageSource: MessageSource, locale?: string): string;
|
|
132
|
+
/**
|
|
133
|
+
* Create a shallow copy of this spec.
|
|
134
|
+
*/
|
|
135
|
+
copy(): I18nSpec;
|
|
136
|
+
private resolveMessage;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Format a message template with positional or named parameters.
|
|
141
|
+
*
|
|
142
|
+
* Supports positional arguments `{0}, {1}` and named arguments `{name}, {count}`.
|
|
143
|
+
*
|
|
144
|
+
* @example formatMessage('Hello {0}, you have {1} messages', ['Alice', 5])
|
|
145
|
+
* @example formatMessage('Hello {name}, you have {count} messages', { name: 'Alice', count: 5 })
|
|
146
|
+
*/
|
|
147
|
+
declare function formatMessage(template: string, params: unknown[] | Record<string, unknown>): string;
|
|
148
|
+
/**
|
|
149
|
+
* Simple plural selection (ICU MessageFormat style).
|
|
150
|
+
*
|
|
151
|
+
* Chooses among `zero`, `one` and `other` forms based on `count`.
|
|
152
|
+
* The selected form is then interpolated with `{count}` replaced by the actual
|
|
153
|
+
* number (formatted according to `locale` when provided).
|
|
154
|
+
*
|
|
155
|
+
* @example pluralize(0, { zero: '没有消息', one: '1 条消息', other: '{count} 条消息' })
|
|
156
|
+
* @example pluralize(5, { zero: '没有消息', one: '1 条消息', other: '{count} 条消息' })
|
|
157
|
+
*/
|
|
158
|
+
declare function pluralize(count: number, forms: {
|
|
159
|
+
zero?: string;
|
|
160
|
+
one?: string;
|
|
161
|
+
other: string;
|
|
162
|
+
}, locale?: string): string;
|
|
163
|
+
/**
|
|
164
|
+
* Format a date using `Intl.DateTimeFormat`.
|
|
165
|
+
*
|
|
166
|
+
* @param date Date instance or epoch-milliseconds timestamp
|
|
167
|
+
* @param style Predefined date style — `'short'`, `'medium'` (default),
|
|
168
|
+
* `'long'` or `'full'`
|
|
169
|
+
* @param locale BCP-47 locale tag; defaults to the current context locale
|
|
170
|
+
*/
|
|
171
|
+
declare function formatDate(date: Date | number, style?: 'short' | 'medium' | 'long' | 'full', locale?: string): string;
|
|
172
|
+
/**
|
|
173
|
+
* Format a number using `Intl.NumberFormat`.
|
|
174
|
+
*
|
|
175
|
+
* @param value The numeric value
|
|
176
|
+
* @param style `'decimal'` (default), `'currency'` or `'percent'`
|
|
177
|
+
* @param options Additional options — currently only `currency` (ISO 4217 code,
|
|
178
|
+
* required when `style` is `'currency'`)
|
|
179
|
+
* @param locale BCP-47 locale tag; defaults to the current context locale
|
|
180
|
+
*/
|
|
181
|
+
declare function formatNumber(value: number, style?: 'decimal' | 'currency' | 'percent', options?: {
|
|
182
|
+
currency?: string;
|
|
183
|
+
}, locale?: string): string;
|
|
184
|
+
/**
|
|
185
|
+
* Format a date as a human-friendly relative time string
|
|
186
|
+
* (e.g. "3 hours ago", "in 2 days") using `Intl.RelativeTimeFormat`.
|
|
187
|
+
*
|
|
188
|
+
* @param date Date instance or epoch-milliseconds timestamp
|
|
189
|
+
* @param locale BCP-47 locale tag; defaults to the current context locale
|
|
190
|
+
*/
|
|
191
|
+
declare function formatRelativeTime(date: Date | number, locale?: string): string;
|
|
192
|
+
/**
|
|
193
|
+
* LocaleUtils — static utility for i18n message resolution.
|
|
194
|
+
*
|
|
195
|
+
* Provides convenient methods for resolving messages using the current locale
|
|
196
|
+
* context and a configured MessageSource.
|
|
197
|
+
*/
|
|
198
|
+
declare class LocaleUtils {
|
|
199
|
+
private static messageSource;
|
|
200
|
+
/**
|
|
201
|
+
* Set the global message source used by resolve helpers.
|
|
202
|
+
*/
|
|
203
|
+
static setMessageSource(source: MessageSource): void;
|
|
204
|
+
/**
|
|
205
|
+
* Get the currently configured global message source.
|
|
206
|
+
*/
|
|
207
|
+
static getMessageSource(): MessageSource | null;
|
|
208
|
+
/**
|
|
209
|
+
* Resolve a message using the current locale context.
|
|
210
|
+
*/
|
|
211
|
+
static resolveMessage(code: string, ...args: unknown[]): string;
|
|
212
|
+
/**
|
|
213
|
+
* Resolve a message with a default fallback using the current locale context.
|
|
214
|
+
*/
|
|
215
|
+
static resolveMessageWithDefault(code: string, defaultMessage: string, ...args: unknown[]): string;
|
|
216
|
+
/**
|
|
217
|
+
* Resolve a message using a specific MessageSource and the current locale.
|
|
218
|
+
*/
|
|
219
|
+
static resolveMessageFrom(source: MessageSource, code: string, defaultMessage?: string, ...args: unknown[]): string;
|
|
220
|
+
/**
|
|
221
|
+
* Resolve a message using a specific locale (ignoring the context locale).
|
|
222
|
+
*/
|
|
223
|
+
static resolveMessageForLocale(code: string, locale: string, defaultMessage?: string, ...args: unknown[]): string;
|
|
224
|
+
/**
|
|
225
|
+
* Execute a function within a specific locale context.
|
|
226
|
+
*/
|
|
227
|
+
static doWith<T>(locale: string, fn: () => T): T;
|
|
228
|
+
/**
|
|
229
|
+
* Execute an async function within a specific locale context.
|
|
230
|
+
*/
|
|
231
|
+
static doWithAsync<T>(locale: string, fn: () => Promise<T>): Promise<T>;
|
|
232
|
+
/**
|
|
233
|
+
* Get the current locale.
|
|
234
|
+
*/
|
|
235
|
+
static current(): string;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* @I18n(code) -- marks a field/property for i18n text resolution.
|
|
240
|
+
*
|
|
241
|
+
* When applied, the field value is treated as an i18n message code
|
|
242
|
+
* that should be resolved through the MessageSource at display time.
|
|
243
|
+
*/
|
|
244
|
+
declare function I18n(code: string): PropertyDecorator;
|
|
245
|
+
/**
|
|
246
|
+
* Get the i18n code associated with a property.
|
|
247
|
+
*/
|
|
248
|
+
declare function getI18nCode(target: object, propertyKey: string | symbol): string | undefined;
|
|
249
|
+
/**
|
|
250
|
+
* Check if a property has an i18n code.
|
|
251
|
+
*/
|
|
252
|
+
declare function hasI18n(target: object, propertyKey: string | symbol): boolean;
|
|
253
|
+
|
|
254
|
+
declare const MESSAGE_SOURCE = "MESSAGE_SOURCE";
|
|
255
|
+
interface I18nModuleOptions {
|
|
256
|
+
/** Path to message files directory */
|
|
257
|
+
basePath?: string;
|
|
258
|
+
/** Default locale */
|
|
259
|
+
defaultLocale?: string;
|
|
260
|
+
/** Supported locales */
|
|
261
|
+
supportedLocales?: string[];
|
|
262
|
+
/** Additional message sources */
|
|
263
|
+
messageSources?: MessageSource[];
|
|
264
|
+
}
|
|
265
|
+
interface I18nModuleAsyncOptions {
|
|
266
|
+
imports?: Array<Type | DynamicModule>;
|
|
267
|
+
useFactory?: (...args: unknown[]) => I18nModuleOptions | Promise<I18nModuleOptions>;
|
|
268
|
+
useClass?: Type<I18nModuleOptionsFactory>;
|
|
269
|
+
useExisting?: Type<I18nModuleOptionsFactory>;
|
|
270
|
+
inject?: Array<InjectionToken | OptionalFactoryDependency>;
|
|
271
|
+
}
|
|
272
|
+
interface I18nModuleOptionsFactory {
|
|
273
|
+
createI18nOptions(): I18nModuleOptions | Promise<I18nModuleOptions>;
|
|
274
|
+
}
|
|
275
|
+
declare class ZuckerI18nModule {
|
|
276
|
+
static forRoot(options?: I18nModuleOptions): DynamicModule;
|
|
277
|
+
static forRootAsync(options: I18nModuleAsyncOptions): DynamicModule;
|
|
278
|
+
private static buildProviders;
|
|
279
|
+
private static createAsyncProviders;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
export { CompositeMessageSource, FileMessageSource, I18n, I18nException, type I18nModuleAsyncOptions, type I18nModuleOptions, type I18nModuleOptionsFactory, I18nSpec, LocaleContext, LocaleInterceptor, LocaleUtils, MESSAGE_SOURCE, type MessageSource, ZuckerI18nModule, formatDate, formatMessage, formatNumber, formatRelativeTime, getI18nCode, hasI18n, pluralize };
|