@universal-i18n/core 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/dist/index.d.mts +347 -0
- package/dist/index.d.ts +347 -0
- package/dist/index.js +804 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +752 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +35 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
declare class TranslationError extends Error {
|
|
2
|
+
readonly sourceText?: string | undefined;
|
|
3
|
+
readonly targetLocale?: string | undefined;
|
|
4
|
+
readonly cause?: Error | undefined;
|
|
5
|
+
constructor(message: string, sourceText?: string | undefined, targetLocale?: string | undefined, cause?: Error | undefined);
|
|
6
|
+
}
|
|
7
|
+
declare class CacheError extends Error {
|
|
8
|
+
readonly backend?: string | undefined;
|
|
9
|
+
readonly cause?: Error | undefined;
|
|
10
|
+
constructor(message: string, backend?: string | undefined, cause?: Error | undefined);
|
|
11
|
+
}
|
|
12
|
+
declare class ConfigError extends Error {
|
|
13
|
+
constructor(message: string);
|
|
14
|
+
}
|
|
15
|
+
declare class RateLimitError extends Error {
|
|
16
|
+
readonly retryAfterMs?: number | undefined;
|
|
17
|
+
constructor(message: string, retryAfterMs?: number | undefined);
|
|
18
|
+
}
|
|
19
|
+
interface CacheEntry {
|
|
20
|
+
value: string;
|
|
21
|
+
translatedAt: string;
|
|
22
|
+
ttl?: number;
|
|
23
|
+
}
|
|
24
|
+
interface CacheStats {
|
|
25
|
+
totalEntries: number;
|
|
26
|
+
hitRate: number;
|
|
27
|
+
missRate: number;
|
|
28
|
+
hits: number;
|
|
29
|
+
misses: number;
|
|
30
|
+
sizeBytes?: number;
|
|
31
|
+
oldestEntry?: string;
|
|
32
|
+
newestEntry?: string;
|
|
33
|
+
}
|
|
34
|
+
interface ICache {
|
|
35
|
+
get(key: string): Promise<string | null>;
|
|
36
|
+
set(key: string, value: string, ttl?: number): Promise<void>;
|
|
37
|
+
delete(key: string): Promise<void>;
|
|
38
|
+
clear(pattern?: string): Promise<void>;
|
|
39
|
+
stats(): Promise<CacheStats>;
|
|
40
|
+
}
|
|
41
|
+
interface CacheConfig {
|
|
42
|
+
/** Cache backend type. Default: 'fs' */
|
|
43
|
+
backend: 'fs' | 'redis' | 'memory';
|
|
44
|
+
/** TTL in seconds. Default: 604800 (7 days) */
|
|
45
|
+
ttl?: number;
|
|
46
|
+
/** Filesystem cache directory. Default: '.cache/universal-i18n' */
|
|
47
|
+
fsDir?: string;
|
|
48
|
+
/** Redis connection URL */
|
|
49
|
+
redisUrl?: string;
|
|
50
|
+
/** Max entries for in-memory LRU cache. Default: 1000 */
|
|
51
|
+
memoryMaxEntries?: number;
|
|
52
|
+
/** Compress cached values with gzip. Default: false */
|
|
53
|
+
compression?: boolean;
|
|
54
|
+
}
|
|
55
|
+
type ProviderType = 'lingo.dev' | 'openai' | 'anthropic' | 'groq';
|
|
56
|
+
interface EngineConfig {
|
|
57
|
+
/** API key. Falls back to LINGODOTDEV_API_KEY env var */
|
|
58
|
+
apiKey?: string;
|
|
59
|
+
/** Source locale. Default: 'en' */
|
|
60
|
+
sourceLocale?: string;
|
|
61
|
+
/** Target locales to support */
|
|
62
|
+
targetLocales: string[];
|
|
63
|
+
/** Cache config */
|
|
64
|
+
cache?: CacheConfig;
|
|
65
|
+
/** Batch delay in ms before sending batched requests. Default: 50 */
|
|
66
|
+
batchDelayMs?: number;
|
|
67
|
+
/** Max retries on failure. Default: 3 */
|
|
68
|
+
maxRetries?: number;
|
|
69
|
+
/** Return original text on translation failure. Default: true */
|
|
70
|
+
fallbackOnError?: boolean;
|
|
71
|
+
/** Translation provider. Default: 'lingo.dev' */
|
|
72
|
+
provider?: ProviderType;
|
|
73
|
+
/** API key for non-lingo.dev providers */
|
|
74
|
+
providerApiKey?: string;
|
|
75
|
+
/** Model identifier for the chosen provider */
|
|
76
|
+
model?: string;
|
|
77
|
+
}
|
|
78
|
+
interface TranslateOpts {
|
|
79
|
+
/** Source locale */
|
|
80
|
+
sourceLocale: string;
|
|
81
|
+
/** Target locale */
|
|
82
|
+
targetLocale: string;
|
|
83
|
+
/** Additional context hint for the LLM */
|
|
84
|
+
context?: string;
|
|
85
|
+
/** Namespace used as cache key prefix */
|
|
86
|
+
namespace?: string;
|
|
87
|
+
}
|
|
88
|
+
interface BatchItem {
|
|
89
|
+
text: string;
|
|
90
|
+
id?: string;
|
|
91
|
+
}
|
|
92
|
+
interface BatchResult {
|
|
93
|
+
id?: string;
|
|
94
|
+
original: string;
|
|
95
|
+
translated: string;
|
|
96
|
+
cached: boolean;
|
|
97
|
+
}
|
|
98
|
+
interface GlossaryEntry {
|
|
99
|
+
[locale: string]: string;
|
|
100
|
+
}
|
|
101
|
+
interface BucketConfig {
|
|
102
|
+
include: string[];
|
|
103
|
+
}
|
|
104
|
+
interface UniversalI18nConfig {
|
|
105
|
+
/** Source locale. Default: 'en' */
|
|
106
|
+
sourceLocale: string;
|
|
107
|
+
/** Target locales */
|
|
108
|
+
targetLocales: string[];
|
|
109
|
+
/** Directory for locale JSON files. Default: './locales' */
|
|
110
|
+
localesDir?: string;
|
|
111
|
+
/** Cache configuration */
|
|
112
|
+
cache?: CacheConfig;
|
|
113
|
+
/** Translation provider config */
|
|
114
|
+
provider?: {
|
|
115
|
+
id: ProviderType;
|
|
116
|
+
apiKey?: string;
|
|
117
|
+
model?: string;
|
|
118
|
+
};
|
|
119
|
+
/** Brand glossary: terms that should never or always be translated a specific way */
|
|
120
|
+
glossary?: Record<string, GlossaryEntry>;
|
|
121
|
+
/** Namespace buckets mapping to lingo.dev buckets config */
|
|
122
|
+
buckets?: Record<string, BucketConfig>;
|
|
123
|
+
/** Lifecycle hooks */
|
|
124
|
+
hooks?: {
|
|
125
|
+
beforeTranslate?: (text: string, locale: string) => Promise<string>;
|
|
126
|
+
afterTranslate?: (text: string, locale: string) => Promise<string>;
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
130
|
+
interface Logger {
|
|
131
|
+
debug(message: string, ...args: unknown[]): void;
|
|
132
|
+
info(message: string, ...args: unknown[]): void;
|
|
133
|
+
warn(message: string, ...args: unknown[]): void;
|
|
134
|
+
error(message: string, ...args: unknown[]): void;
|
|
135
|
+
}
|
|
136
|
+
interface I18nMessages {
|
|
137
|
+
[locale: string]: Record<string, string | Record<string, unknown>>;
|
|
138
|
+
}
|
|
139
|
+
interface I18nContextValue {
|
|
140
|
+
locale: string;
|
|
141
|
+
setLocale: (locale: string) => void;
|
|
142
|
+
messages: I18nMessages;
|
|
143
|
+
t: (key: string, vars?: Record<string, string>) => string;
|
|
144
|
+
availableLocales: string[];
|
|
145
|
+
isLoading: boolean;
|
|
146
|
+
fallbackLocale?: string;
|
|
147
|
+
onMissingKey?: (key: string, locale: string) => void;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Core translation engine wrapping LingoDotDevEngine with:
|
|
152
|
+
* - Cache-first strategy
|
|
153
|
+
* - Request batching (configurable delay)
|
|
154
|
+
* - Automatic retry with exponential backoff
|
|
155
|
+
* - Graceful fallback on errors
|
|
156
|
+
*/
|
|
157
|
+
declare class UniversalI18nEngine {
|
|
158
|
+
private cache;
|
|
159
|
+
private logger;
|
|
160
|
+
private apiKey;
|
|
161
|
+
private sourceLocale;
|
|
162
|
+
private targetLocales;
|
|
163
|
+
private batchDelayMs;
|
|
164
|
+
private maxRetries;
|
|
165
|
+
private fallbackOnError;
|
|
166
|
+
private provider;
|
|
167
|
+
private providerApiKey?;
|
|
168
|
+
private model?;
|
|
169
|
+
private pendingBatch;
|
|
170
|
+
private batchTimer;
|
|
171
|
+
private sdkEngine;
|
|
172
|
+
constructor(config: EngineConfig);
|
|
173
|
+
/**
|
|
174
|
+
* Initialize the lingo.dev SDK engine lazily.
|
|
175
|
+
*/
|
|
176
|
+
private getSDKEngine;
|
|
177
|
+
/**
|
|
178
|
+
* Translate a single string with cache-first strategy.
|
|
179
|
+
*/
|
|
180
|
+
translate(text: string, opts: TranslateOpts): Promise<string>;
|
|
181
|
+
/**
|
|
182
|
+
* Translate a nested object (all string values) with cache.
|
|
183
|
+
*/
|
|
184
|
+
translateObject<T extends Record<string, unknown>>(obj: T, opts: TranslateOpts): Promise<T>;
|
|
185
|
+
/**
|
|
186
|
+
* Translate an HTML string.
|
|
187
|
+
*/
|
|
188
|
+
translateHTML(html: string, opts: TranslateOpts): Promise<string>;
|
|
189
|
+
/**
|
|
190
|
+
* Translate multiple items, leveraging batching and caching.
|
|
191
|
+
*/
|
|
192
|
+
translateBatch(items: BatchItem[], opts: TranslateOpts): Promise<BatchResult[]>;
|
|
193
|
+
/**
|
|
194
|
+
* Get current cache statistics.
|
|
195
|
+
*/
|
|
196
|
+
getCacheStats(): Promise<CacheStats>;
|
|
197
|
+
/**
|
|
198
|
+
* Clear the cache, optionally for a specific locale.
|
|
199
|
+
*/
|
|
200
|
+
clearCache(locale?: string): Promise<void>;
|
|
201
|
+
/**
|
|
202
|
+
* Pre-populate cache by translating all provided keys for specified locales.
|
|
203
|
+
*/
|
|
204
|
+
warmCache(keys: string[], locales: string[]): Promise<void>;
|
|
205
|
+
/**
|
|
206
|
+
* Translate with automatic retry and exponential backoff.
|
|
207
|
+
*/
|
|
208
|
+
private translateWithRetry;
|
|
209
|
+
/**
|
|
210
|
+
* Generic retry wrapper with exponential backoff.
|
|
211
|
+
*/
|
|
212
|
+
private callWithRetry;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* In-memory LRU cache with optional TTL support.
|
|
217
|
+
* Ideal for edge/serverless environments where filesystem isn't persistent.
|
|
218
|
+
*/
|
|
219
|
+
declare class MemoryCache implements ICache {
|
|
220
|
+
private cache;
|
|
221
|
+
private maxEntries;
|
|
222
|
+
private hits;
|
|
223
|
+
private misses;
|
|
224
|
+
constructor(maxEntries?: number);
|
|
225
|
+
get(key: string): Promise<string | null>;
|
|
226
|
+
set(key: string, value: string, ttl?: number): Promise<void>;
|
|
227
|
+
delete(key: string): Promise<void>;
|
|
228
|
+
clear(pattern?: string): Promise<void>;
|
|
229
|
+
stats(): Promise<CacheStats>;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Filesystem-based cache that stores translations as JSON files.
|
|
234
|
+
* Uses atomic writes (write to .tmp then rename) for safety.
|
|
235
|
+
* Cache structure: {fsDir}/{namespace}.json
|
|
236
|
+
*/
|
|
237
|
+
declare class FileSystemCache implements ICache {
|
|
238
|
+
private dir;
|
|
239
|
+
private hits;
|
|
240
|
+
private misses;
|
|
241
|
+
private defaultTtl;
|
|
242
|
+
constructor(dir?: string, defaultTtl?: number);
|
|
243
|
+
private ensureDir;
|
|
244
|
+
private getFilePath;
|
|
245
|
+
private readCacheFile;
|
|
246
|
+
private writeCacheFile;
|
|
247
|
+
get(key: string): Promise<string | null>;
|
|
248
|
+
set(key: string, value: string, ttl?: number): Promise<void>;
|
|
249
|
+
delete(key: string): Promise<void>;
|
|
250
|
+
clear(pattern?: string): Promise<void>;
|
|
251
|
+
private clearDirectory;
|
|
252
|
+
stats(): Promise<CacheStats>;
|
|
253
|
+
private scanDirectory;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Redis-based cache using ioredis.
|
|
258
|
+
* ioredis is a peer dependency — this module gracefully handles missing imports.
|
|
259
|
+
*
|
|
260
|
+
* Uses HSET/HGET with key pattern: ui18n:{srcLocale}:{tgtLocale}:{namespace}:{hash}
|
|
261
|
+
* TTL via EXPIRE on individual keys.
|
|
262
|
+
*/
|
|
263
|
+
declare class RedisCache implements ICache {
|
|
264
|
+
private client;
|
|
265
|
+
private defaultTtl;
|
|
266
|
+
private hits;
|
|
267
|
+
private misses;
|
|
268
|
+
private connected;
|
|
269
|
+
constructor(redisUrl?: string, defaultTtl?: number);
|
|
270
|
+
private initClient;
|
|
271
|
+
private loadRedis;
|
|
272
|
+
get(key: string): Promise<string | null>;
|
|
273
|
+
set(key: string, value: string, ttl?: number): Promise<void>;
|
|
274
|
+
delete(key: string): Promise<void>;
|
|
275
|
+
clear(pattern?: string): Promise<void>;
|
|
276
|
+
stats(): Promise<CacheStats>;
|
|
277
|
+
disconnect(): Promise<void>;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Factory function to create a cache instance based on configuration.
|
|
282
|
+
*/
|
|
283
|
+
declare function createCache(config?: CacheConfig): ICache;
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Generate a cache key from translation parameters.
|
|
287
|
+
* Format: ui18n:{sourceLocale}:{targetLocale}:{namespace}:{sha256(sourceText)}
|
|
288
|
+
*/
|
|
289
|
+
declare function generateCacheKey(sourceLocale: string, targetLocale: string, namespace: string, sourceText: string): string;
|
|
290
|
+
/**
|
|
291
|
+
* Compute a SHA-256 hash of a string, returning a hex digest.
|
|
292
|
+
*/
|
|
293
|
+
declare function sha256(text: string): string;
|
|
294
|
+
/**
|
|
295
|
+
* Create a pluggable logger respecting UI18N_LOG_LEVEL env var.
|
|
296
|
+
*/
|
|
297
|
+
declare function createLogger(level?: LogLevel): Logger;
|
|
298
|
+
/**
|
|
299
|
+
* Flatten a nested object into dot-notation keys.
|
|
300
|
+
* { a: { b: 'c' } } => { 'a.b': 'c' }
|
|
301
|
+
*/
|
|
302
|
+
declare function flattenObject(obj: Record<string, unknown>, prefix?: string): Record<string, string>;
|
|
303
|
+
/**
|
|
304
|
+
* Unflatten dot-notation keys back into a nested object.
|
|
305
|
+
* { 'a.b': 'c' } => { a: { b: 'c' } }
|
|
306
|
+
*/
|
|
307
|
+
declare function unflattenObject(obj: Record<string, string>): Record<string, unknown>;
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Create a new translation engine instance.
|
|
311
|
+
*
|
|
312
|
+
* @example
|
|
313
|
+
* ```ts
|
|
314
|
+
* import { createEngine } from '@universal-i18n/core'
|
|
315
|
+
*
|
|
316
|
+
* const engine = createEngine({
|
|
317
|
+
* apiKey: process.env.LINGODOTDEV_API_KEY,
|
|
318
|
+
* sourceLocale: 'en',
|
|
319
|
+
* targetLocales: ['es', 'fr'],
|
|
320
|
+
* cache: { backend: 'fs' }
|
|
321
|
+
* })
|
|
322
|
+
*
|
|
323
|
+
* const translated = await engine.translate('Hello', {
|
|
324
|
+
* sourceLocale: 'en',
|
|
325
|
+
* targetLocale: 'es'
|
|
326
|
+
* })
|
|
327
|
+
* ```
|
|
328
|
+
*/
|
|
329
|
+
declare function createEngine(config: EngineConfig): UniversalI18nEngine;
|
|
330
|
+
/**
|
|
331
|
+
* Define a universal-i18n configuration object with type safety.
|
|
332
|
+
*
|
|
333
|
+
* @example
|
|
334
|
+
* ```ts
|
|
335
|
+
* // i18n.config.ts
|
|
336
|
+
* import { defineConfig } from '@universal-i18n/core'
|
|
337
|
+
*
|
|
338
|
+
* export default defineConfig({
|
|
339
|
+
* sourceLocale: 'en',
|
|
340
|
+
* targetLocales: ['es', 'fr', 'de'],
|
|
341
|
+
* cache: { backend: 'fs', ttl: 604800 }
|
|
342
|
+
* })
|
|
343
|
+
* ```
|
|
344
|
+
*/
|
|
345
|
+
declare function defineConfig(config: UniversalI18nConfig): UniversalI18nConfig;
|
|
346
|
+
|
|
347
|
+
export { type BatchItem, type BatchResult, type BucketConfig, type CacheConfig, type CacheEntry, CacheError, type CacheStats, ConfigError, type EngineConfig, FileSystemCache, type GlossaryEntry, type I18nContextValue, type I18nMessages, type ICache, type LogLevel, type Logger, MemoryCache, type ProviderType, RateLimitError, RedisCache, type TranslateOpts, TranslationError, type UniversalI18nConfig, UniversalI18nEngine, createCache, createEngine, createLogger, defineConfig, flattenObject, generateCacheKey, sha256, unflattenObject };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
declare class TranslationError extends Error {
|
|
2
|
+
readonly sourceText?: string | undefined;
|
|
3
|
+
readonly targetLocale?: string | undefined;
|
|
4
|
+
readonly cause?: Error | undefined;
|
|
5
|
+
constructor(message: string, sourceText?: string | undefined, targetLocale?: string | undefined, cause?: Error | undefined);
|
|
6
|
+
}
|
|
7
|
+
declare class CacheError extends Error {
|
|
8
|
+
readonly backend?: string | undefined;
|
|
9
|
+
readonly cause?: Error | undefined;
|
|
10
|
+
constructor(message: string, backend?: string | undefined, cause?: Error | undefined);
|
|
11
|
+
}
|
|
12
|
+
declare class ConfigError extends Error {
|
|
13
|
+
constructor(message: string);
|
|
14
|
+
}
|
|
15
|
+
declare class RateLimitError extends Error {
|
|
16
|
+
readonly retryAfterMs?: number | undefined;
|
|
17
|
+
constructor(message: string, retryAfterMs?: number | undefined);
|
|
18
|
+
}
|
|
19
|
+
interface CacheEntry {
|
|
20
|
+
value: string;
|
|
21
|
+
translatedAt: string;
|
|
22
|
+
ttl?: number;
|
|
23
|
+
}
|
|
24
|
+
interface CacheStats {
|
|
25
|
+
totalEntries: number;
|
|
26
|
+
hitRate: number;
|
|
27
|
+
missRate: number;
|
|
28
|
+
hits: number;
|
|
29
|
+
misses: number;
|
|
30
|
+
sizeBytes?: number;
|
|
31
|
+
oldestEntry?: string;
|
|
32
|
+
newestEntry?: string;
|
|
33
|
+
}
|
|
34
|
+
interface ICache {
|
|
35
|
+
get(key: string): Promise<string | null>;
|
|
36
|
+
set(key: string, value: string, ttl?: number): Promise<void>;
|
|
37
|
+
delete(key: string): Promise<void>;
|
|
38
|
+
clear(pattern?: string): Promise<void>;
|
|
39
|
+
stats(): Promise<CacheStats>;
|
|
40
|
+
}
|
|
41
|
+
interface CacheConfig {
|
|
42
|
+
/** Cache backend type. Default: 'fs' */
|
|
43
|
+
backend: 'fs' | 'redis' | 'memory';
|
|
44
|
+
/** TTL in seconds. Default: 604800 (7 days) */
|
|
45
|
+
ttl?: number;
|
|
46
|
+
/** Filesystem cache directory. Default: '.cache/universal-i18n' */
|
|
47
|
+
fsDir?: string;
|
|
48
|
+
/** Redis connection URL */
|
|
49
|
+
redisUrl?: string;
|
|
50
|
+
/** Max entries for in-memory LRU cache. Default: 1000 */
|
|
51
|
+
memoryMaxEntries?: number;
|
|
52
|
+
/** Compress cached values with gzip. Default: false */
|
|
53
|
+
compression?: boolean;
|
|
54
|
+
}
|
|
55
|
+
type ProviderType = 'lingo.dev' | 'openai' | 'anthropic' | 'groq';
|
|
56
|
+
interface EngineConfig {
|
|
57
|
+
/** API key. Falls back to LINGODOTDEV_API_KEY env var */
|
|
58
|
+
apiKey?: string;
|
|
59
|
+
/** Source locale. Default: 'en' */
|
|
60
|
+
sourceLocale?: string;
|
|
61
|
+
/** Target locales to support */
|
|
62
|
+
targetLocales: string[];
|
|
63
|
+
/** Cache config */
|
|
64
|
+
cache?: CacheConfig;
|
|
65
|
+
/** Batch delay in ms before sending batched requests. Default: 50 */
|
|
66
|
+
batchDelayMs?: number;
|
|
67
|
+
/** Max retries on failure. Default: 3 */
|
|
68
|
+
maxRetries?: number;
|
|
69
|
+
/** Return original text on translation failure. Default: true */
|
|
70
|
+
fallbackOnError?: boolean;
|
|
71
|
+
/** Translation provider. Default: 'lingo.dev' */
|
|
72
|
+
provider?: ProviderType;
|
|
73
|
+
/** API key for non-lingo.dev providers */
|
|
74
|
+
providerApiKey?: string;
|
|
75
|
+
/** Model identifier for the chosen provider */
|
|
76
|
+
model?: string;
|
|
77
|
+
}
|
|
78
|
+
interface TranslateOpts {
|
|
79
|
+
/** Source locale */
|
|
80
|
+
sourceLocale: string;
|
|
81
|
+
/** Target locale */
|
|
82
|
+
targetLocale: string;
|
|
83
|
+
/** Additional context hint for the LLM */
|
|
84
|
+
context?: string;
|
|
85
|
+
/** Namespace used as cache key prefix */
|
|
86
|
+
namespace?: string;
|
|
87
|
+
}
|
|
88
|
+
interface BatchItem {
|
|
89
|
+
text: string;
|
|
90
|
+
id?: string;
|
|
91
|
+
}
|
|
92
|
+
interface BatchResult {
|
|
93
|
+
id?: string;
|
|
94
|
+
original: string;
|
|
95
|
+
translated: string;
|
|
96
|
+
cached: boolean;
|
|
97
|
+
}
|
|
98
|
+
interface GlossaryEntry {
|
|
99
|
+
[locale: string]: string;
|
|
100
|
+
}
|
|
101
|
+
interface BucketConfig {
|
|
102
|
+
include: string[];
|
|
103
|
+
}
|
|
104
|
+
interface UniversalI18nConfig {
|
|
105
|
+
/** Source locale. Default: 'en' */
|
|
106
|
+
sourceLocale: string;
|
|
107
|
+
/** Target locales */
|
|
108
|
+
targetLocales: string[];
|
|
109
|
+
/** Directory for locale JSON files. Default: './locales' */
|
|
110
|
+
localesDir?: string;
|
|
111
|
+
/** Cache configuration */
|
|
112
|
+
cache?: CacheConfig;
|
|
113
|
+
/** Translation provider config */
|
|
114
|
+
provider?: {
|
|
115
|
+
id: ProviderType;
|
|
116
|
+
apiKey?: string;
|
|
117
|
+
model?: string;
|
|
118
|
+
};
|
|
119
|
+
/** Brand glossary: terms that should never or always be translated a specific way */
|
|
120
|
+
glossary?: Record<string, GlossaryEntry>;
|
|
121
|
+
/** Namespace buckets mapping to lingo.dev buckets config */
|
|
122
|
+
buckets?: Record<string, BucketConfig>;
|
|
123
|
+
/** Lifecycle hooks */
|
|
124
|
+
hooks?: {
|
|
125
|
+
beforeTranslate?: (text: string, locale: string) => Promise<string>;
|
|
126
|
+
afterTranslate?: (text: string, locale: string) => Promise<string>;
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
130
|
+
interface Logger {
|
|
131
|
+
debug(message: string, ...args: unknown[]): void;
|
|
132
|
+
info(message: string, ...args: unknown[]): void;
|
|
133
|
+
warn(message: string, ...args: unknown[]): void;
|
|
134
|
+
error(message: string, ...args: unknown[]): void;
|
|
135
|
+
}
|
|
136
|
+
interface I18nMessages {
|
|
137
|
+
[locale: string]: Record<string, string | Record<string, unknown>>;
|
|
138
|
+
}
|
|
139
|
+
interface I18nContextValue {
|
|
140
|
+
locale: string;
|
|
141
|
+
setLocale: (locale: string) => void;
|
|
142
|
+
messages: I18nMessages;
|
|
143
|
+
t: (key: string, vars?: Record<string, string>) => string;
|
|
144
|
+
availableLocales: string[];
|
|
145
|
+
isLoading: boolean;
|
|
146
|
+
fallbackLocale?: string;
|
|
147
|
+
onMissingKey?: (key: string, locale: string) => void;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Core translation engine wrapping LingoDotDevEngine with:
|
|
152
|
+
* - Cache-first strategy
|
|
153
|
+
* - Request batching (configurable delay)
|
|
154
|
+
* - Automatic retry with exponential backoff
|
|
155
|
+
* - Graceful fallback on errors
|
|
156
|
+
*/
|
|
157
|
+
declare class UniversalI18nEngine {
|
|
158
|
+
private cache;
|
|
159
|
+
private logger;
|
|
160
|
+
private apiKey;
|
|
161
|
+
private sourceLocale;
|
|
162
|
+
private targetLocales;
|
|
163
|
+
private batchDelayMs;
|
|
164
|
+
private maxRetries;
|
|
165
|
+
private fallbackOnError;
|
|
166
|
+
private provider;
|
|
167
|
+
private providerApiKey?;
|
|
168
|
+
private model?;
|
|
169
|
+
private pendingBatch;
|
|
170
|
+
private batchTimer;
|
|
171
|
+
private sdkEngine;
|
|
172
|
+
constructor(config: EngineConfig);
|
|
173
|
+
/**
|
|
174
|
+
* Initialize the lingo.dev SDK engine lazily.
|
|
175
|
+
*/
|
|
176
|
+
private getSDKEngine;
|
|
177
|
+
/**
|
|
178
|
+
* Translate a single string with cache-first strategy.
|
|
179
|
+
*/
|
|
180
|
+
translate(text: string, opts: TranslateOpts): Promise<string>;
|
|
181
|
+
/**
|
|
182
|
+
* Translate a nested object (all string values) with cache.
|
|
183
|
+
*/
|
|
184
|
+
translateObject<T extends Record<string, unknown>>(obj: T, opts: TranslateOpts): Promise<T>;
|
|
185
|
+
/**
|
|
186
|
+
* Translate an HTML string.
|
|
187
|
+
*/
|
|
188
|
+
translateHTML(html: string, opts: TranslateOpts): Promise<string>;
|
|
189
|
+
/**
|
|
190
|
+
* Translate multiple items, leveraging batching and caching.
|
|
191
|
+
*/
|
|
192
|
+
translateBatch(items: BatchItem[], opts: TranslateOpts): Promise<BatchResult[]>;
|
|
193
|
+
/**
|
|
194
|
+
* Get current cache statistics.
|
|
195
|
+
*/
|
|
196
|
+
getCacheStats(): Promise<CacheStats>;
|
|
197
|
+
/**
|
|
198
|
+
* Clear the cache, optionally for a specific locale.
|
|
199
|
+
*/
|
|
200
|
+
clearCache(locale?: string): Promise<void>;
|
|
201
|
+
/**
|
|
202
|
+
* Pre-populate cache by translating all provided keys for specified locales.
|
|
203
|
+
*/
|
|
204
|
+
warmCache(keys: string[], locales: string[]): Promise<void>;
|
|
205
|
+
/**
|
|
206
|
+
* Translate with automatic retry and exponential backoff.
|
|
207
|
+
*/
|
|
208
|
+
private translateWithRetry;
|
|
209
|
+
/**
|
|
210
|
+
* Generic retry wrapper with exponential backoff.
|
|
211
|
+
*/
|
|
212
|
+
private callWithRetry;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* In-memory LRU cache with optional TTL support.
|
|
217
|
+
* Ideal for edge/serverless environments where filesystem isn't persistent.
|
|
218
|
+
*/
|
|
219
|
+
declare class MemoryCache implements ICache {
|
|
220
|
+
private cache;
|
|
221
|
+
private maxEntries;
|
|
222
|
+
private hits;
|
|
223
|
+
private misses;
|
|
224
|
+
constructor(maxEntries?: number);
|
|
225
|
+
get(key: string): Promise<string | null>;
|
|
226
|
+
set(key: string, value: string, ttl?: number): Promise<void>;
|
|
227
|
+
delete(key: string): Promise<void>;
|
|
228
|
+
clear(pattern?: string): Promise<void>;
|
|
229
|
+
stats(): Promise<CacheStats>;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Filesystem-based cache that stores translations as JSON files.
|
|
234
|
+
* Uses atomic writes (write to .tmp then rename) for safety.
|
|
235
|
+
* Cache structure: {fsDir}/{namespace}.json
|
|
236
|
+
*/
|
|
237
|
+
declare class FileSystemCache implements ICache {
|
|
238
|
+
private dir;
|
|
239
|
+
private hits;
|
|
240
|
+
private misses;
|
|
241
|
+
private defaultTtl;
|
|
242
|
+
constructor(dir?: string, defaultTtl?: number);
|
|
243
|
+
private ensureDir;
|
|
244
|
+
private getFilePath;
|
|
245
|
+
private readCacheFile;
|
|
246
|
+
private writeCacheFile;
|
|
247
|
+
get(key: string): Promise<string | null>;
|
|
248
|
+
set(key: string, value: string, ttl?: number): Promise<void>;
|
|
249
|
+
delete(key: string): Promise<void>;
|
|
250
|
+
clear(pattern?: string): Promise<void>;
|
|
251
|
+
private clearDirectory;
|
|
252
|
+
stats(): Promise<CacheStats>;
|
|
253
|
+
private scanDirectory;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Redis-based cache using ioredis.
|
|
258
|
+
* ioredis is a peer dependency — this module gracefully handles missing imports.
|
|
259
|
+
*
|
|
260
|
+
* Uses HSET/HGET with key pattern: ui18n:{srcLocale}:{tgtLocale}:{namespace}:{hash}
|
|
261
|
+
* TTL via EXPIRE on individual keys.
|
|
262
|
+
*/
|
|
263
|
+
declare class RedisCache implements ICache {
|
|
264
|
+
private client;
|
|
265
|
+
private defaultTtl;
|
|
266
|
+
private hits;
|
|
267
|
+
private misses;
|
|
268
|
+
private connected;
|
|
269
|
+
constructor(redisUrl?: string, defaultTtl?: number);
|
|
270
|
+
private initClient;
|
|
271
|
+
private loadRedis;
|
|
272
|
+
get(key: string): Promise<string | null>;
|
|
273
|
+
set(key: string, value: string, ttl?: number): Promise<void>;
|
|
274
|
+
delete(key: string): Promise<void>;
|
|
275
|
+
clear(pattern?: string): Promise<void>;
|
|
276
|
+
stats(): Promise<CacheStats>;
|
|
277
|
+
disconnect(): Promise<void>;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Factory function to create a cache instance based on configuration.
|
|
282
|
+
*/
|
|
283
|
+
declare function createCache(config?: CacheConfig): ICache;
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Generate a cache key from translation parameters.
|
|
287
|
+
* Format: ui18n:{sourceLocale}:{targetLocale}:{namespace}:{sha256(sourceText)}
|
|
288
|
+
*/
|
|
289
|
+
declare function generateCacheKey(sourceLocale: string, targetLocale: string, namespace: string, sourceText: string): string;
|
|
290
|
+
/**
|
|
291
|
+
* Compute a SHA-256 hash of a string, returning a hex digest.
|
|
292
|
+
*/
|
|
293
|
+
declare function sha256(text: string): string;
|
|
294
|
+
/**
|
|
295
|
+
* Create a pluggable logger respecting UI18N_LOG_LEVEL env var.
|
|
296
|
+
*/
|
|
297
|
+
declare function createLogger(level?: LogLevel): Logger;
|
|
298
|
+
/**
|
|
299
|
+
* Flatten a nested object into dot-notation keys.
|
|
300
|
+
* { a: { b: 'c' } } => { 'a.b': 'c' }
|
|
301
|
+
*/
|
|
302
|
+
declare function flattenObject(obj: Record<string, unknown>, prefix?: string): Record<string, string>;
|
|
303
|
+
/**
|
|
304
|
+
* Unflatten dot-notation keys back into a nested object.
|
|
305
|
+
* { 'a.b': 'c' } => { a: { b: 'c' } }
|
|
306
|
+
*/
|
|
307
|
+
declare function unflattenObject(obj: Record<string, string>): Record<string, unknown>;
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Create a new translation engine instance.
|
|
311
|
+
*
|
|
312
|
+
* @example
|
|
313
|
+
* ```ts
|
|
314
|
+
* import { createEngine } from '@universal-i18n/core'
|
|
315
|
+
*
|
|
316
|
+
* const engine = createEngine({
|
|
317
|
+
* apiKey: process.env.LINGODOTDEV_API_KEY,
|
|
318
|
+
* sourceLocale: 'en',
|
|
319
|
+
* targetLocales: ['es', 'fr'],
|
|
320
|
+
* cache: { backend: 'fs' }
|
|
321
|
+
* })
|
|
322
|
+
*
|
|
323
|
+
* const translated = await engine.translate('Hello', {
|
|
324
|
+
* sourceLocale: 'en',
|
|
325
|
+
* targetLocale: 'es'
|
|
326
|
+
* })
|
|
327
|
+
* ```
|
|
328
|
+
*/
|
|
329
|
+
declare function createEngine(config: EngineConfig): UniversalI18nEngine;
|
|
330
|
+
/**
|
|
331
|
+
* Define a universal-i18n configuration object with type safety.
|
|
332
|
+
*
|
|
333
|
+
* @example
|
|
334
|
+
* ```ts
|
|
335
|
+
* // i18n.config.ts
|
|
336
|
+
* import { defineConfig } from '@universal-i18n/core'
|
|
337
|
+
*
|
|
338
|
+
* export default defineConfig({
|
|
339
|
+
* sourceLocale: 'en',
|
|
340
|
+
* targetLocales: ['es', 'fr', 'de'],
|
|
341
|
+
* cache: { backend: 'fs', ttl: 604800 }
|
|
342
|
+
* })
|
|
343
|
+
* ```
|
|
344
|
+
*/
|
|
345
|
+
declare function defineConfig(config: UniversalI18nConfig): UniversalI18nConfig;
|
|
346
|
+
|
|
347
|
+
export { type BatchItem, type BatchResult, type BucketConfig, type CacheConfig, type CacheEntry, CacheError, type CacheStats, ConfigError, type EngineConfig, FileSystemCache, type GlossaryEntry, type I18nContextValue, type I18nMessages, type ICache, type LogLevel, type Logger, MemoryCache, type ProviderType, RateLimitError, RedisCache, type TranslateOpts, TranslationError, type UniversalI18nConfig, UniversalI18nEngine, createCache, createEngine, createLogger, defineConfig, flattenObject, generateCacheKey, sha256, unflattenObject };
|