@fukict/i18n 0.1.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Fukict Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/I18n.d.ts ADDED
@@ -0,0 +1,112 @@
1
+ /**
2
+ * @fukict/i18n - I18n Class
3
+ *
4
+ * Core i18n class implementation
5
+ */
6
+ import type { I18nInstance, I18nListener, I18nOptions, Unsubscribe } from './types';
7
+ /**
8
+ * I18n class
9
+ */
10
+ export declare class I18n<Messages extends Record<string, any>> implements I18nInstance<Messages> {
11
+ /**
12
+ * Current locale
13
+ */
14
+ private currentLocale;
15
+ /**
16
+ * Translation messages
17
+ */
18
+ private messages;
19
+ /**
20
+ * Configuration options
21
+ */
22
+ private options;
23
+ /**
24
+ * Subscribers
25
+ */
26
+ private listeners;
27
+ /**
28
+ * Loading locales (track loading state)
29
+ */
30
+ private loadingLocales;
31
+ /**
32
+ * Loaded locales (track loaded state)
33
+ */
34
+ private loadedLocales;
35
+ /**
36
+ * Translation cache
37
+ */
38
+ private translationCache;
39
+ /**
40
+ * Constructor
41
+ */
42
+ constructor(options: I18nOptions<Messages>);
43
+ /**
44
+ * Get current locale
45
+ */
46
+ get locale(): string;
47
+ /**
48
+ * Translate text
49
+ */
50
+ t(key: string, params?: Record<string, string | number>): string;
51
+ /**
52
+ * Internal translate function
53
+ */
54
+ private translate;
55
+ /**
56
+ * Get text by key from locale
57
+ */
58
+ private getTextByKey;
59
+ /**
60
+ * Get plural form based on count
61
+ */
62
+ private getPluralForm;
63
+ /**
64
+ * Interpolate variables in text
65
+ */
66
+ private interpolate;
67
+ /**
68
+ * Handle missing translation
69
+ */
70
+ private handleMissing;
71
+ /**
72
+ * Change locale
73
+ */
74
+ changeLocale(locale: string): Promise<void>;
75
+ /**
76
+ * Wait for locale to finish loading
77
+ */
78
+ private waitForLocale;
79
+ /**
80
+ * Subscribe to locale changes
81
+ */
82
+ subscribe(listener: I18nListener): Unsubscribe;
83
+ /**
84
+ * Notify all subscribers
85
+ */
86
+ private notify;
87
+ /**
88
+ * Get current locale messages
89
+ */
90
+ getMessages(): Messages[keyof Messages];
91
+ /**
92
+ * Get available locales
93
+ */
94
+ getAvailableLocales(): string[];
95
+ /**
96
+ * Add messages for a locale
97
+ */
98
+ addMessages(locale: string, messages: Messages[keyof Messages]): void;
99
+ /**
100
+ * Format number
101
+ */
102
+ n(value: number, options?: Intl.NumberFormatOptions): string;
103
+ /**
104
+ * Format date
105
+ */
106
+ d(value: Date | number, options?: Intl.DateTimeFormatOptions): string;
107
+ /**
108
+ * Format relative time
109
+ */
110
+ rt(value: number, unit: Intl.RelativeTimeFormatUnit): string;
111
+ }
112
+ //# sourceMappingURL=I18n.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"I18n.d.ts","sourceRoot":"","sources":["../src/I18n.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EACV,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,WAAW,EACZ,MAAM,SAAS,CAAC;AAEjB;;GAEG;AACH,qBAAa,IAAI,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CACpD,YAAW,YAAY,CAAC,QAAQ,CAAC;IAEjC;;OAEG;IACH,OAAO,CAAC,aAAa,CAAS;IAE9B;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAW;IAE3B;;OAEG;IACH,OAAO,CAAC,OAAO,CAAwB;IAEvC;;OAEG;IACH,OAAO,CAAC,SAAS,CAAgC;IAEjD;;OAEG;IACH,OAAO,CAAC,cAAc,CAAqB;IAE3C;;OAEG;IACH,OAAO,CAAC,aAAa,CAAqB;IAE1C;;OAEG;IACH,OAAO,CAAC,gBAAgB,CAA6B;IAErD;;OAEG;gBACS,OAAO,EAAE,WAAW,CAAC,QAAQ,CAAC;IAW1C;;OAEG;IACH,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED;;OAEG;IACH,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GAAG,MAAM;IAgBhE;;OAEG;IACH,OAAO,CAAC,SAAS;IAiCjB;;OAEG;IACH,OAAO,CAAC,YAAY;IA4BpB;;OAEG;IACH,OAAO,CAAC,aAAa;IAsBrB;;OAEG;IACH,OAAO,CAAC,WAAW;IASnB;;OAEG;IACH,OAAO,CAAC,aAAa;IAkBrB;;OAEG;IACG,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAyCjD;;OAEG;YACW,aAAa;IAa3B;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,YAAY,GAAG,WAAW;IAQ9C;;OAEG;IACH,OAAO,CAAC,MAAM;IAUd;;OAEG;IACH,WAAW,IAAI,QAAQ,CAAC,MAAM,QAAQ,CAAC;IAKvC;;OAEG;IACH,mBAAmB,IAAI,MAAM,EAAE;IAI/B;;OAEG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,MAAM,QAAQ,CAAC,GAAG,IAAI;IAQrE;;OAEG;IACH,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,mBAAmB,GAAG,MAAM;IAI5D;;OAEG;IACH,CAAC,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,qBAAqB,GAAG,MAAM;IAIrE;;OAEG;IACH,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,sBAAsB,GAAG,MAAM;CAG7D"}
package/dist/I18n.js ADDED
@@ -0,0 +1,278 @@
1
+ /**
2
+ * I18n class
3
+ */
4
+ export class I18n {
5
+ /**
6
+ * Current locale
7
+ */
8
+ currentLocale;
9
+ /**
10
+ * Translation messages
11
+ */
12
+ messages;
13
+ /**
14
+ * Configuration options
15
+ */
16
+ options;
17
+ /**
18
+ * Subscribers
19
+ */
20
+ listeners = new Set();
21
+ /**
22
+ * Loading locales (track loading state)
23
+ */
24
+ loadingLocales = new Set();
25
+ /**
26
+ * Loaded locales (track loaded state)
27
+ */
28
+ loadedLocales = new Set();
29
+ /**
30
+ * Translation cache
31
+ */
32
+ translationCache = new Map();
33
+ /**
34
+ * Constructor
35
+ */
36
+ constructor(options) {
37
+ this.options = options;
38
+ this.currentLocale = options.locale || options.defaultLocale;
39
+ this.messages = options.messages;
40
+ // Mark initially provided locales as loaded
41
+ for (const locale of Object.keys(options.messages)) {
42
+ this.loadedLocales.add(locale);
43
+ }
44
+ }
45
+ /**
46
+ * Get current locale
47
+ */
48
+ get locale() {
49
+ return this.currentLocale;
50
+ }
51
+ /**
52
+ * Translate text
53
+ */
54
+ t(key, params) {
55
+ // Check cache
56
+ const cacheKey = `${this.currentLocale}:${key}:${JSON.stringify(params || {})}`;
57
+ if (this.translationCache.has(cacheKey)) {
58
+ return this.translationCache.get(cacheKey);
59
+ }
60
+ // Get translation
61
+ const result = this.translate(key, params);
62
+ // Cache result
63
+ this.translationCache.set(cacheKey, result);
64
+ return result;
65
+ }
66
+ /**
67
+ * Internal translate function
68
+ */
69
+ translate(key, params) {
70
+ // Try current locale
71
+ let text = this.getTextByKey(key, this.currentLocale);
72
+ // Try fallback locale
73
+ if (text === undefined && this.options.fallbackLocale) {
74
+ text = this.getTextByKey(key, this.options.fallbackLocale);
75
+ }
76
+ // Handle missing translation
77
+ if (text === undefined) {
78
+ return this.handleMissing(key, this.currentLocale);
79
+ }
80
+ // Handle plural forms
81
+ if (params && 'count' in params && typeof text === 'object') {
82
+ text = this.getPluralForm(text, params.count);
83
+ }
84
+ // Handle interpolation
85
+ if (params && typeof text === 'string') {
86
+ text = this.interpolate(text, params);
87
+ }
88
+ return text;
89
+ }
90
+ /**
91
+ * Get text by key from locale
92
+ */
93
+ getTextByKey(key, locale) {
94
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
95
+ const messages = this.messages[locale];
96
+ if (!messages)
97
+ return undefined;
98
+ // Support dot notation: 'user.name'
99
+ const keys = key.split('.');
100
+ let current = messages;
101
+ for (const k of keys) {
102
+ if (current &&
103
+ typeof current === 'object' &&
104
+ k in current &&
105
+ current !== null) {
106
+ current = current[k];
107
+ }
108
+ else {
109
+ return undefined;
110
+ }
111
+ }
112
+ return current;
113
+ }
114
+ /**
115
+ * Get plural form based on count
116
+ */
117
+ getPluralForm(pluralObj, count) {
118
+ // Use Intl.PluralRules to determine plural category
119
+ const rules = new Intl.PluralRules(this.currentLocale);
120
+ const category = rules.select(count);
121
+ // Try to get the plural form
122
+ if (category in pluralObj) {
123
+ return pluralObj[category];
124
+ }
125
+ // Fallback to 'other'
126
+ if ('other' in pluralObj) {
127
+ return pluralObj.other;
128
+ }
129
+ // Return empty if no match
130
+ return '';
131
+ }
132
+ /**
133
+ * Interpolate variables in text
134
+ */
135
+ interpolate(text, params) {
136
+ return text.replace(/\{(\w+)\}/g, (match, key) => {
137
+ return key in params ? String(params[key]) : match;
138
+ });
139
+ }
140
+ /**
141
+ * Handle missing translation
142
+ */
143
+ handleMissing(key, locale) {
144
+ const handler = this.options.missingHandler;
145
+ if (typeof handler === 'function') {
146
+ return handler(key, locale);
147
+ }
148
+ if (handler === 'fallback' && this.options.fallbackLocale) {
149
+ const fallbackText = this.getTextByKey(key, this.options.fallbackLocale);
150
+ if (fallbackText !== undefined && typeof fallbackText === 'string') {
151
+ return fallbackText;
152
+ }
153
+ }
154
+ // Default: return key
155
+ return key;
156
+ }
157
+ /**
158
+ * Change locale
159
+ */
160
+ async changeLocale(locale) {
161
+ // Already current locale
162
+ if (locale === this.currentLocale) {
163
+ return;
164
+ }
165
+ // If already loaded, just switch
166
+ if (this.loadedLocales.has(locale)) {
167
+ this.currentLocale = locale;
168
+ this.notify();
169
+ return;
170
+ }
171
+ // If loading, wait for it
172
+ if (this.loadingLocales.has(locale)) {
173
+ await this.waitForLocale(locale);
174
+ return;
175
+ }
176
+ // Load new locale
177
+ if (this.options.loadMessages) {
178
+ this.loadingLocales.add(locale);
179
+ try {
180
+ const messages = await this.options.loadMessages(locale);
181
+ this.addMessages(locale, messages);
182
+ this.loadedLocales.add(locale);
183
+ this.currentLocale = locale;
184
+ this.notify();
185
+ }
186
+ catch (error) {
187
+ console.error(`Failed to load locale ${locale}:`, error);
188
+ throw error;
189
+ }
190
+ finally {
191
+ this.loadingLocales.delete(locale);
192
+ }
193
+ }
194
+ else {
195
+ // No lazy loading, just switch (might have missing translations)
196
+ this.currentLocale = locale;
197
+ this.notify();
198
+ }
199
+ }
200
+ /**
201
+ * Wait for locale to finish loading
202
+ */
203
+ async waitForLocale(locale) {
204
+ return new Promise(resolve => {
205
+ const check = () => {
206
+ if (!this.loadingLocales.has(locale)) {
207
+ resolve();
208
+ }
209
+ else {
210
+ setTimeout(check, 50);
211
+ }
212
+ };
213
+ check();
214
+ });
215
+ }
216
+ /**
217
+ * Subscribe to locale changes
218
+ */
219
+ subscribe(listener) {
220
+ this.listeners.add(listener);
221
+ return () => {
222
+ this.listeners.delete(listener);
223
+ };
224
+ }
225
+ /**
226
+ * Notify all subscribers
227
+ */
228
+ notify() {
229
+ // Clear cache on locale change
230
+ this.translationCache.clear();
231
+ // Notify subscribers
232
+ this.listeners.forEach(listener => {
233
+ listener();
234
+ });
235
+ }
236
+ /**
237
+ * Get current locale messages
238
+ */
239
+ getMessages() {
240
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
241
+ return this.messages[this.currentLocale];
242
+ }
243
+ /**
244
+ * Get available locales
245
+ */
246
+ getAvailableLocales() {
247
+ return Object.keys(this.messages);
248
+ }
249
+ /**
250
+ * Add messages for a locale
251
+ */
252
+ addMessages(locale, messages) {
253
+ this.messages = {
254
+ ...this.messages,
255
+ [locale]: messages,
256
+ };
257
+ this.loadedLocales.add(locale);
258
+ }
259
+ /**
260
+ * Format number
261
+ */
262
+ n(value, options) {
263
+ return new Intl.NumberFormat(this.currentLocale, options).format(value);
264
+ }
265
+ /**
266
+ * Format date
267
+ */
268
+ d(value, options) {
269
+ return new Intl.DateTimeFormat(this.currentLocale, options).format(value);
270
+ }
271
+ /**
272
+ * Format relative time
273
+ */
274
+ rt(value, unit) {
275
+ return new Intl.RelativeTimeFormat(this.currentLocale).format(value, unit);
276
+ }
277
+ }
278
+ //# sourceMappingURL=I18n.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"I18n.js","sourceRoot":"","sources":["../src/I18n.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { I18nInstance, I18nOptions } from './types';
2
+ /**
3
+ * Create i18n instance
4
+ *
5
+ * @example
6
+ * ```typescript
7
+ * const i18n = createI18n({
8
+ * defaultLocale: 'en',
9
+ * messages: {
10
+ * en: { hello: 'Hello' },
11
+ * zh: { hello: '你好' },
12
+ * },
13
+ * });
14
+ * ```
15
+ */
16
+ export declare function createI18n<Messages extends Record<string, any>>(options: I18nOptions<Messages>): I18nInstance<Messages>;
17
+ //# sourceMappingURL=createI18n.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createI18n.d.ts","sourceRoot":"","sources":["../src/createI18n.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEzD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC7D,OAAO,EAAE,WAAW,CAAC,QAAQ,CAAC,GAC7B,YAAY,CAAC,QAAQ,CAAC,CAExB"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @fukict/i18n - createI18n
3
+ *
4
+ * Factory function to create i18n instance
5
+ */
6
+ import { I18n } from './I18n';
7
+ /**
8
+ * Create i18n instance
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * const i18n = createI18n({
13
+ * defaultLocale: 'en',
14
+ * messages: {
15
+ * en: { hello: 'Hello' },
16
+ * zh: { hello: '你好' },
17
+ * },
18
+ * });
19
+ * ```
20
+ */
21
+ export function createI18n(options) {
22
+ return new I18n(options);
23
+ }
24
+ //# sourceMappingURL=createI18n.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createI18n.js","sourceRoot":"","sources":["../src/createI18n.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAG9B;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,UAAU,CACxB,OAA8B;IAE9B,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @fukict/i18n
3
+ *
4
+ * Type-safe internationalization library for Fukict framework
5
+ */
6
+ import { METADATA } from './metadata.js';
7
+ export { METADATA };
8
+ export declare const VERSION: "0.1.0";
9
+ export { I18n } from './I18n';
10
+ export { createI18n } from './createI18n';
11
+ export type { I18nInstance, I18nListener, I18nOptions, KeyPath, TranslationKey, Unsubscribe, } from './types';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,EAAE,QAAQ,EAAE,CAAC;AAEpB,eAAO,MAAM,OAAO,SAAmB,CAAC;AAExC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EACV,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,OAAO,EACP,cAAc,EACd,WAAW,GACZ,MAAM,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @fukict/i18n
3
+ *
4
+ * Type-safe internationalization library for Fukict framework
5
+ */
6
+ // Package metadata
7
+ import { METADATA } from './metadata.js';
8
+ export { METADATA };
9
+ export const VERSION = METADATA.version;
10
+ export { I18n } from './I18n';
11
+ export { createI18n } from './createI18n';
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,mBAAmB;AACnB,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,EAAE,QAAQ,EAAE,CAAC;AAEpB,MAAM,CAAC,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;AAExC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Package metadata
3
+ * Auto-generated by extract-metadata.ts - DO NOT EDIT MANUALLY
4
+ */
5
+ export declare const METADATA: {
6
+ readonly name: "@fukict/i18n";
7
+ readonly version: "0.1.0";
8
+ readonly description: "Type-safe internationalization library for Fukict framework";
9
+ readonly author: "Fukict Team";
10
+ readonly license: "MIT";
11
+ readonly homepage: "";
12
+ readonly repository: "https://github.com/fukict/fukict.git";
13
+ };
14
+ //# sourceMappingURL=metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,QAAQ;;;;;;;;CAQX,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Package metadata
3
+ * Auto-generated by extract-metadata.ts - DO NOT EDIT MANUALLY
4
+ */
5
+ export const METADATA = {
6
+ name: '@fukict/i18n',
7
+ version: '0.1.0',
8
+ description: 'Type-safe internationalization library for Fukict framework',
9
+ author: 'Fukict Team',
10
+ license: 'MIT',
11
+ homepage: '',
12
+ repository: 'https://github.com/fukict/fukict.git',
13
+ };
14
+ //# sourceMappingURL=metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata.js","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,IAAI,EAAE,cAAc;IACpB,OAAO,EAAE,OAAO;IAChB,WAAW,EAAE,6DAA6D;IAC1E,MAAM,EAAE,aAAa;IACrB,OAAO,EAAE,KAAK;IACd,QAAQ,EAAE,EAAE;IACZ,UAAU,EAAE,sCAAsC;CAC1C,CAAC"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * @fukict/i18n - Types
3
+ *
4
+ * Type definitions for i18n library
5
+ */
6
+ /**
7
+ * Listener function type
8
+ */
9
+ export type I18nListener = () => void;
10
+ /**
11
+ * Unsubscribe function type
12
+ */
13
+ export type Unsubscribe = () => void;
14
+ /**
15
+ * Recursively extract key paths from nested object
16
+ */
17
+ export type KeyPath<T, Prefix extends string = ''> = T extends object ? {
18
+ [K in keyof T & string]: T[K] extends string ? Prefix extends '' ? K : `${Prefix}.${K}` : KeyPath<T[K], Prefix extends '' ? K : `${Prefix}.${K}`>;
19
+ }[keyof T & string] : never;
20
+ /**
21
+ * Extract translation key type from messages
22
+ */
23
+ export type TranslationKey<Messages> = Messages extends Record<string, infer Msg> ? KeyPath<Msg> : never;
24
+ /**
25
+ * I18n configuration options
26
+ */
27
+ export interface I18nOptions<Messages extends Record<string, any>> {
28
+ /**
29
+ * Default locale
30
+ */
31
+ defaultLocale: string;
32
+ /**
33
+ * Current locale (optional, defaults to defaultLocale)
34
+ */
35
+ locale?: string;
36
+ /**
37
+ * Translation messages
38
+ */
39
+ messages: Messages;
40
+ /**
41
+ * Missing translation handler
42
+ * - 'key': return the key itself (default)
43
+ * - 'fallback': use fallbackLocale
44
+ * - function: custom handler
45
+ */
46
+ missingHandler?: 'key' | 'fallback' | ((key: string, locale: string) => string);
47
+ /**
48
+ * Fallback locale (when translation is missing)
49
+ */
50
+ fallbackLocale?: string;
51
+ /**
52
+ * Lazy load messages function
53
+ */
54
+ loadMessages?: (locale: string) => Promise<Messages[keyof Messages]>;
55
+ }
56
+ /**
57
+ * I18n instance interface
58
+ */
59
+ export interface I18nInstance<Messages extends Record<string, any>> {
60
+ /**
61
+ * Current locale (readonly)
62
+ */
63
+ readonly locale: string;
64
+ /**
65
+ * Translate text
66
+ */
67
+ t(key: string, params?: Record<string, any>): string;
68
+ /**
69
+ * Change locale
70
+ */
71
+ changeLocale(locale: string): Promise<void>;
72
+ /**
73
+ * Subscribe to locale changes
74
+ */
75
+ subscribe(listener: I18nListener): Unsubscribe;
76
+ /**
77
+ * Get current locale messages
78
+ */
79
+ getMessages(): Messages[keyof Messages];
80
+ /**
81
+ * Get available locales
82
+ */
83
+ getAvailableLocales(): string[];
84
+ /**
85
+ * Add messages for a locale
86
+ */
87
+ addMessages(locale: string, messages: Messages[keyof Messages]): void;
88
+ /**
89
+ * Format number
90
+ */
91
+ n(value: number, options?: Intl.NumberFormatOptions): string;
92
+ /**
93
+ * Format date
94
+ */
95
+ d(value: Date | number, options?: Intl.DateTimeFormatOptions): string;
96
+ /**
97
+ * Format relative time
98
+ */
99
+ rt(value: number, unit: Intl.RelativeTimeFormatUnit): string;
100
+ }
101
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC;AAEtC;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC;AAErC;;GAEG;AACH,MAAM,MAAM,OAAO,CAAC,CAAC,EAAE,MAAM,SAAS,MAAM,GAAG,EAAE,IAAI,CAAC,SAAS,MAAM,GACjE;KACG,CAAC,IAAI,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,GACxC,MAAM,SAAS,EAAE,GACf,CAAC,GACD,GAAG,MAAM,IAAI,CAAC,EAAE,GAClB,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,SAAS,EAAE,GAAG,CAAC,GAAG,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC;CAC5D,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,GACnB,KAAK,CAAC;AAEV;;GAEG;AACH,MAAM,MAAM,cAAc,CAAC,QAAQ,IACjC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAEpE;;GAEG;AACH,MAAM,WAAW,WAAW,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAC/D;;OAEG;IACH,aAAa,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,QAAQ,EAAE,QAAQ,CAAC;IAEnB;;;;;OAKG;IACH,cAAc,CAAC,EACX,KAAK,GACL,UAAU,GACV,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC;IAE9C;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,MAAM,QAAQ,CAAC,CAAC,CAAC;CACtE;AAED;;GAEG;AACH,MAAM,WAAW,YAAY,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAChE;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC;IAErD;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5C;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,YAAY,GAAG,WAAW,CAAC;IAE/C;;OAEG;IACH,WAAW,IAAI,QAAQ,CAAC,MAAM,QAAQ,CAAC,CAAC;IAExC;;OAEG;IACH,mBAAmB,IAAI,MAAM,EAAE,CAAC;IAEhC;;OAEG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,MAAM,QAAQ,CAAC,GAAG,IAAI,CAAC;IAEtE;;OAEG;IACH,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,mBAAmB,GAAG,MAAM,CAAC;IAE7D;;OAEG;IACH,CAAC,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,qBAAqB,GAAG,MAAM,CAAC;IAEtE;;OAEG;IACH,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,sBAAsB,GAAG,MAAM,CAAC;CAC9D"}
package/dist/types.js ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @fukict/i18n - Types
3
+ *
4
+ * Type definitions for i18n library
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@fukict/i18n",
3
+ "version": "0.1.0",
4
+ "description": "Type-safe internationalization library for Fukict framework",
5
+ "keywords": [
6
+ "fukict",
7
+ "i18n",
8
+ "internationalization",
9
+ "localization",
10
+ "translation",
11
+ "reactive"
12
+ ],
13
+ "bugs": {
14
+ "url": "https://github.com/fukict/fukict/issues"
15
+ },
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "https://github.com/fukict/fukict.git",
19
+ "directory": "packages/i18n"
20
+ },
21
+ "license": "MIT",
22
+ "author": "Fukict Team",
23
+ "sideEffects": false,
24
+ "type": "module",
25
+ "exports": {
26
+ ".": {
27
+ "types": "./dist/index.d.ts",
28
+ "browser": "./dist/index.js",
29
+ "default": "./dist/index.js"
30
+ }
31
+ },
32
+ "main": "./dist/index.js",
33
+ "module": "./dist/index.js",
34
+ "types": "./dist/index.d.ts",
35
+ "files": [
36
+ "dist",
37
+ "README.md"
38
+ ],
39
+ "devDependencies": {
40
+ "typescript": "^5.6.3"
41
+ },
42
+ "engines": {
43
+ "node": ">=16.0.0"
44
+ },
45
+ "scripts": {
46
+ "build": "tsx ../../scripts/build-package.ts --pkg-name i18n --no-watch",
47
+ "dev": "tsx ../../scripts/build-package.ts --pkg-name i18n --watch",
48
+ "lint": "tsc --noEmit",
49
+ "typecheck": "tsc --noEmit"
50
+ }
51
+ }