intor-translator 1.0.8 → 1.0.11

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.cts CHANGED
@@ -161,7 +161,7 @@ type LocaleNamespaceMessages = Record<Locale, NamespaceMessages>;
161
161
  * type Result = UnionLocaleMessages<typeof messages>;
162
162
  * // Result: { auth: { login: "Login" } } | { auth: { logout: "登出" } }
163
163
  */
164
- type UnionLocaleMessages<M extends LocaleNamespaceMessages> = M[LocaleKey<M>];
164
+ type UnionLocaleMessages<M> = M[StrictLocaleKey<M>];
165
165
 
166
166
  /**
167
167
  * Extracts the locale keys from the messages object as string literals.
@@ -173,7 +173,28 @@ type UnionLocaleMessages<M extends LocaleNamespaceMessages> = M[LocaleKey<M>];
173
173
  * }>;
174
174
  * // Locales is "en" | "zh-TW"
175
175
  */
176
- type LocaleKey<M extends LocaleNamespaceMessages> = keyof M & string;
176
+ type StrictLocaleKey<M> = keyof M & string;
177
+ /**
178
+ * Extracts locale keys only when M is a valid messages object.
179
+ *
180
+ * When M is a concrete `LocaleNamespaceMessages`, the locale key
181
+ * will be inferred as a union of its top-level keys like `"en" | "zh-TW"`.
182
+ * Otherwise, falls back to a generic `string`.
183
+ *
184
+ * This helps retain intellisense when `messages` is provided,
185
+ * but avoids TypeScript errors when M is left as `unknown`.
186
+ *
187
+ * @example
188
+ * type Locales = LocaleKey<{
189
+ * en: {};
190
+ * fr: {};
191
+ * }>;
192
+ * // → "en" | "fr"
193
+ *
194
+ * type Fallback = LocaleKey<unknown>;
195
+ * // → string
196
+ */
197
+ type LocaleKey<M = unknown> = M extends LocaleNamespaceMessages ? StrictLocaleKey<M> : string;
177
198
  /**
178
199
  * A map that defines fallback locales for each base locale.
179
200
  *
@@ -242,7 +263,7 @@ type LeafKeys<M, D extends number = DefaultDepth> = [D] extends [never] ? never
242
263
  * @example
243
264
  * UnionLocaleLeafKeys<{ en: { a: { b: "x" } }, zh: { a: { c: "y" } } }> → "a.b" | "a.c"
244
265
  */
245
- type UnionLocaleLeafKeys<M extends LocaleNamespaceMessages, D extends number = DefaultDepth> = UnionLocaleMessages<M> extends NamespaceMessages ? LeafKeys<UnionLocaleMessages<M>, D> : never;
266
+ type UnionLocaleLeafKeys<M, D extends number = DefaultDepth> = UnionLocaleMessages<M> extends NamespaceMessages ? LeafKeys<UnionLocaleMessages<M>, D> : never;
246
267
  /**
247
268
  * Resolves the type at a dot-separated key in a nested object.
248
269
  *
@@ -261,15 +282,13 @@ type ResolvePathType<T, P extends string> = P extends `${infer Head}.${infer Tai
261
282
  * };
262
283
  * ScopedLeafKeys<Messages, "auth.login"> → "success" | "failed"
263
284
  */
264
- type ScopedLeafKeys<M extends LocaleNamespaceMessages, K extends string, D extends number = DefaultDepth> = UnionLocaleMessages<M> extends infer ResolvedLocaleMessages ? ResolvedLocaleMessages extends object ? LeafKeys<ResolvePathType<ResolvedLocaleMessages, K>, D> : never : never;
285
+ type ScopedLeafKeys<M, K extends string, D extends number = DefaultDepth> = UnionLocaleMessages<M> extends infer ResolvedLocaleMessages ? ResolvedLocaleMessages extends object ? LeafKeys<ResolvePathType<ResolvedLocaleMessages, K>, D> : never : never;
265
286
  /**
266
287
  * Infer valid key type from locale messages.
267
288
  *
268
289
  * If `M` is not passed or empty, fallback to `string`.
269
290
  */
270
- type InferTranslatorKey<M extends LocaleNamespaceMessages> = [
271
- M
272
- ] extends [never] ? string : UnionLocaleLeafKeys<M>;
291
+ type InferTranslatorKey<M> = M extends LocaleNamespaceMessages ? UnionLocaleLeafKeys<M> : string;
273
292
 
274
293
  /**
275
294
  * A ref object holding all localized messages by locale.
@@ -282,7 +301,7 @@ type InferTranslatorKey<M extends LocaleNamespaceMessages> = [
282
301
  * }
283
302
  * };
284
303
  */
285
- type MessagesRef<M extends LocaleNamespaceMessages> = {
304
+ type MessagesRef<M> = {
286
305
  current?: Readonly<M>;
287
306
  };
288
307
  /**
@@ -293,7 +312,7 @@ type MessagesRef<M extends LocaleNamespaceMessages> = {
293
312
  * current: "en"
294
313
  * };
295
314
  */
296
- type LocaleRef<M extends LocaleNamespaceMessages> = {
315
+ type LocaleRef<M> = {
297
316
  current?: LocaleKey<M>;
298
317
  };
299
318
  /**
@@ -309,8 +328,8 @@ type IsLoadingRef = {
309
328
  };
310
329
 
311
330
  /** Config options for translation behavior. */
312
- type TranslateConfig = {
313
- fallbackLocales?: FallbackLocalesMap;
331
+ type TranslateConfig<M> = {
332
+ fallbackLocales?: FallbackLocalesMap<LocaleKey<M>>;
314
333
  loadingMessage?: string;
315
334
  placeholder?: string;
316
335
  handlers?: TranslateHandlers;
@@ -344,12 +363,12 @@ type TranslateContext = {
344
363
  replacements?: Replacement | RichReplacement;
345
364
  };
346
365
 
347
- interface BaseTranslatorOptions<M extends LocaleNamespaceMessages> {
366
+ interface BaseTranslatorOptions<M = unknown> {
348
367
  messages?: Readonly<M>;
349
368
  locale?: LocaleKey<M>;
350
369
  }
351
370
 
352
- declare class BaseTranslator<M extends LocaleNamespaceMessages = never> {
371
+ declare class BaseTranslator<M = unknown> {
353
372
  protected messagesRef: MessagesRef<M>;
354
373
  protected localeRef: LocaleRef<M>;
355
374
  constructor(options?: BaseTranslatorOptions<M>);
@@ -370,10 +389,10 @@ declare class BaseTranslator<M extends LocaleNamespaceMessages = never> {
370
389
  hasKey: (key: InferTranslatorKey<M>, targetLocale?: LocaleKey<M>) => boolean;
371
390
  }
372
391
 
373
- interface CoreTranslatorOptions<M extends LocaleNamespaceMessages> extends BaseTranslatorOptions<M>, TranslateConfig {
392
+ interface CoreTranslatorOptions<M> extends BaseTranslatorOptions<M>, TranslateConfig<M> {
374
393
  }
375
394
 
376
- declare class CoreTranslator<M extends LocaleNamespaceMessages = never> extends BaseTranslator<M> {
395
+ declare class CoreTranslator<M = unknown> extends BaseTranslator<M> {
377
396
  protected options: CoreTranslatorOptions<M>;
378
397
  protected isLoadingRef: IsLoadingRef;
379
398
  constructor(options?: CoreTranslatorOptions<M>);
@@ -384,16 +403,16 @@ declare class CoreTranslator<M extends LocaleNamespaceMessages = never> extends
384
403
  t: <Result = string>(key: InferTranslatorKey<M>, replacements?: Replacement | RichReplacement) => Result;
385
404
  }
386
405
 
387
- declare class ScopeTranslator<M extends LocaleNamespaceMessages = never> extends CoreTranslator<M> {
406
+ declare class ScopeTranslator<M = unknown> extends CoreTranslator<M> {
388
407
  constructor(options?: CoreTranslatorOptions<M>);
389
408
  scoped<K extends NodeKeys<UnionLocaleMessages<M>> & string>(preKey: K): {
390
- hasKey: (key?: ScopedLeafKeys<M, K> & string, targetLocale?: string) => boolean;
409
+ hasKey: (key?: ScopedLeafKeys<M, K> & string, targetLocale?: LocaleKey<M>) => boolean;
391
410
  t: (key?: ScopedLeafKeys<M, K> & string, replacements?: Replacement | RichReplacement) => string;
392
411
  };
393
412
  scoped(): {
394
- hasKey: (key?: UnionLocaleLeafKeys<M> & string, targetLocale?: string) => boolean;
395
- t: (key?: UnionLocaleLeafKeys<M> & string, replacements?: Replacement | RichReplacement) => string;
413
+ hasKey: (key?: InferTranslatorKey<M> & string, targetLocale?: LocaleKey<M>) => boolean;
414
+ t: (key?: InferTranslatorKey<M> & string, replacements?: Replacement | RichReplacement) => string;
396
415
  };
397
416
  }
398
417
 
399
- export { type FallbackLocalesMap, type FormatMessage, type IsLoadingRef, type LeafKeys, type Locale, type LocaleKey, type LocaleNamespaceMessages, type LocaleRef, type Message, type MessageRecord, type MessagesRef, type Namespace, type NamespaceMessages, type NestedMessage, type NodeKeys, type OnLoading, type OnMissing, type Replacement, type RichReplacement, type ScopedLeafKeys, type TranslateConfig, type TranslateContext, type TranslateHandlers, ScopeTranslator as Translator, type UnionLocaleLeafKeys, type UnionLocaleMessages };
418
+ export { type FallbackLocalesMap, type FormatMessage, type IsLoadingRef, type LeafKeys, type Locale, type LocaleKey, type LocaleNamespaceMessages, type LocaleRef, type Message, type MessageRecord, type MessagesRef, type Namespace, type NamespaceMessages, type NestedMessage, type NodeKeys, type OnLoading, type OnMissing, type Replacement, type RichReplacement, type ScopedLeafKeys, type StrictLocaleKey, type TranslateConfig, type TranslateContext, type TranslateHandlers, ScopeTranslator as Translator, type UnionLocaleLeafKeys, type UnionLocaleMessages };
package/dist/index.d.ts CHANGED
@@ -161,7 +161,7 @@ type LocaleNamespaceMessages = Record<Locale, NamespaceMessages>;
161
161
  * type Result = UnionLocaleMessages<typeof messages>;
162
162
  * // Result: { auth: { login: "Login" } } | { auth: { logout: "登出" } }
163
163
  */
164
- type UnionLocaleMessages<M extends LocaleNamespaceMessages> = M[LocaleKey<M>];
164
+ type UnionLocaleMessages<M> = M[StrictLocaleKey<M>];
165
165
 
166
166
  /**
167
167
  * Extracts the locale keys from the messages object as string literals.
@@ -173,7 +173,28 @@ type UnionLocaleMessages<M extends LocaleNamespaceMessages> = M[LocaleKey<M>];
173
173
  * }>;
174
174
  * // Locales is "en" | "zh-TW"
175
175
  */
176
- type LocaleKey<M extends LocaleNamespaceMessages> = keyof M & string;
176
+ type StrictLocaleKey<M> = keyof M & string;
177
+ /**
178
+ * Extracts locale keys only when M is a valid messages object.
179
+ *
180
+ * When M is a concrete `LocaleNamespaceMessages`, the locale key
181
+ * will be inferred as a union of its top-level keys like `"en" | "zh-TW"`.
182
+ * Otherwise, falls back to a generic `string`.
183
+ *
184
+ * This helps retain intellisense when `messages` is provided,
185
+ * but avoids TypeScript errors when M is left as `unknown`.
186
+ *
187
+ * @example
188
+ * type Locales = LocaleKey<{
189
+ * en: {};
190
+ * fr: {};
191
+ * }>;
192
+ * // → "en" | "fr"
193
+ *
194
+ * type Fallback = LocaleKey<unknown>;
195
+ * // → string
196
+ */
197
+ type LocaleKey<M = unknown> = M extends LocaleNamespaceMessages ? StrictLocaleKey<M> : string;
177
198
  /**
178
199
  * A map that defines fallback locales for each base locale.
179
200
  *
@@ -242,7 +263,7 @@ type LeafKeys<M, D extends number = DefaultDepth> = [D] extends [never] ? never
242
263
  * @example
243
264
  * UnionLocaleLeafKeys<{ en: { a: { b: "x" } }, zh: { a: { c: "y" } } }> → "a.b" | "a.c"
244
265
  */
245
- type UnionLocaleLeafKeys<M extends LocaleNamespaceMessages, D extends number = DefaultDepth> = UnionLocaleMessages<M> extends NamespaceMessages ? LeafKeys<UnionLocaleMessages<M>, D> : never;
266
+ type UnionLocaleLeafKeys<M, D extends number = DefaultDepth> = UnionLocaleMessages<M> extends NamespaceMessages ? LeafKeys<UnionLocaleMessages<M>, D> : never;
246
267
  /**
247
268
  * Resolves the type at a dot-separated key in a nested object.
248
269
  *
@@ -261,15 +282,13 @@ type ResolvePathType<T, P extends string> = P extends `${infer Head}.${infer Tai
261
282
  * };
262
283
  * ScopedLeafKeys<Messages, "auth.login"> → "success" | "failed"
263
284
  */
264
- type ScopedLeafKeys<M extends LocaleNamespaceMessages, K extends string, D extends number = DefaultDepth> = UnionLocaleMessages<M> extends infer ResolvedLocaleMessages ? ResolvedLocaleMessages extends object ? LeafKeys<ResolvePathType<ResolvedLocaleMessages, K>, D> : never : never;
285
+ type ScopedLeafKeys<M, K extends string, D extends number = DefaultDepth> = UnionLocaleMessages<M> extends infer ResolvedLocaleMessages ? ResolvedLocaleMessages extends object ? LeafKeys<ResolvePathType<ResolvedLocaleMessages, K>, D> : never : never;
265
286
  /**
266
287
  * Infer valid key type from locale messages.
267
288
  *
268
289
  * If `M` is not passed or empty, fallback to `string`.
269
290
  */
270
- type InferTranslatorKey<M extends LocaleNamespaceMessages> = [
271
- M
272
- ] extends [never] ? string : UnionLocaleLeafKeys<M>;
291
+ type InferTranslatorKey<M> = M extends LocaleNamespaceMessages ? UnionLocaleLeafKeys<M> : string;
273
292
 
274
293
  /**
275
294
  * A ref object holding all localized messages by locale.
@@ -282,7 +301,7 @@ type InferTranslatorKey<M extends LocaleNamespaceMessages> = [
282
301
  * }
283
302
  * };
284
303
  */
285
- type MessagesRef<M extends LocaleNamespaceMessages> = {
304
+ type MessagesRef<M> = {
286
305
  current?: Readonly<M>;
287
306
  };
288
307
  /**
@@ -293,7 +312,7 @@ type MessagesRef<M extends LocaleNamespaceMessages> = {
293
312
  * current: "en"
294
313
  * };
295
314
  */
296
- type LocaleRef<M extends LocaleNamespaceMessages> = {
315
+ type LocaleRef<M> = {
297
316
  current?: LocaleKey<M>;
298
317
  };
299
318
  /**
@@ -309,8 +328,8 @@ type IsLoadingRef = {
309
328
  };
310
329
 
311
330
  /** Config options for translation behavior. */
312
- type TranslateConfig = {
313
- fallbackLocales?: FallbackLocalesMap;
331
+ type TranslateConfig<M> = {
332
+ fallbackLocales?: FallbackLocalesMap<LocaleKey<M>>;
314
333
  loadingMessage?: string;
315
334
  placeholder?: string;
316
335
  handlers?: TranslateHandlers;
@@ -344,12 +363,12 @@ type TranslateContext = {
344
363
  replacements?: Replacement | RichReplacement;
345
364
  };
346
365
 
347
- interface BaseTranslatorOptions<M extends LocaleNamespaceMessages> {
366
+ interface BaseTranslatorOptions<M = unknown> {
348
367
  messages?: Readonly<M>;
349
368
  locale?: LocaleKey<M>;
350
369
  }
351
370
 
352
- declare class BaseTranslator<M extends LocaleNamespaceMessages = never> {
371
+ declare class BaseTranslator<M = unknown> {
353
372
  protected messagesRef: MessagesRef<M>;
354
373
  protected localeRef: LocaleRef<M>;
355
374
  constructor(options?: BaseTranslatorOptions<M>);
@@ -370,10 +389,10 @@ declare class BaseTranslator<M extends LocaleNamespaceMessages = never> {
370
389
  hasKey: (key: InferTranslatorKey<M>, targetLocale?: LocaleKey<M>) => boolean;
371
390
  }
372
391
 
373
- interface CoreTranslatorOptions<M extends LocaleNamespaceMessages> extends BaseTranslatorOptions<M>, TranslateConfig {
392
+ interface CoreTranslatorOptions<M> extends BaseTranslatorOptions<M>, TranslateConfig<M> {
374
393
  }
375
394
 
376
- declare class CoreTranslator<M extends LocaleNamespaceMessages = never> extends BaseTranslator<M> {
395
+ declare class CoreTranslator<M = unknown> extends BaseTranslator<M> {
377
396
  protected options: CoreTranslatorOptions<M>;
378
397
  protected isLoadingRef: IsLoadingRef;
379
398
  constructor(options?: CoreTranslatorOptions<M>);
@@ -384,16 +403,16 @@ declare class CoreTranslator<M extends LocaleNamespaceMessages = never> extends
384
403
  t: <Result = string>(key: InferTranslatorKey<M>, replacements?: Replacement | RichReplacement) => Result;
385
404
  }
386
405
 
387
- declare class ScopeTranslator<M extends LocaleNamespaceMessages = never> extends CoreTranslator<M> {
406
+ declare class ScopeTranslator<M = unknown> extends CoreTranslator<M> {
388
407
  constructor(options?: CoreTranslatorOptions<M>);
389
408
  scoped<K extends NodeKeys<UnionLocaleMessages<M>> & string>(preKey: K): {
390
- hasKey: (key?: ScopedLeafKeys<M, K> & string, targetLocale?: string) => boolean;
409
+ hasKey: (key?: ScopedLeafKeys<M, K> & string, targetLocale?: LocaleKey<M>) => boolean;
391
410
  t: (key?: ScopedLeafKeys<M, K> & string, replacements?: Replacement | RichReplacement) => string;
392
411
  };
393
412
  scoped(): {
394
- hasKey: (key?: UnionLocaleLeafKeys<M> & string, targetLocale?: string) => boolean;
395
- t: (key?: UnionLocaleLeafKeys<M> & string, replacements?: Replacement | RichReplacement) => string;
413
+ hasKey: (key?: InferTranslatorKey<M> & string, targetLocale?: LocaleKey<M>) => boolean;
414
+ t: (key?: InferTranslatorKey<M> & string, replacements?: Replacement | RichReplacement) => string;
396
415
  };
397
416
  }
398
417
 
399
- export { type FallbackLocalesMap, type FormatMessage, type IsLoadingRef, type LeafKeys, type Locale, type LocaleKey, type LocaleNamespaceMessages, type LocaleRef, type Message, type MessageRecord, type MessagesRef, type Namespace, type NamespaceMessages, type NestedMessage, type NodeKeys, type OnLoading, type OnMissing, type Replacement, type RichReplacement, type ScopedLeafKeys, type TranslateConfig, type TranslateContext, type TranslateHandlers, ScopeTranslator as Translator, type UnionLocaleLeafKeys, type UnionLocaleMessages };
418
+ export { type FallbackLocalesMap, type FormatMessage, type IsLoadingRef, type LeafKeys, type Locale, type LocaleKey, type LocaleNamespaceMessages, type LocaleRef, type Message, type MessageRecord, type MessagesRef, type Namespace, type NamespaceMessages, type NestedMessage, type NodeKeys, type OnLoading, type OnMissing, type Replacement, type RichReplacement, type ScopedLeafKeys, type StrictLocaleKey, type TranslateConfig, type TranslateContext, type TranslateHandlers, ScopeTranslator as Translator, type UnionLocaleLeafKeys, type UnionLocaleMessages };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "intor-translator",
3
- "version": "1.0.8",
3
+ "version": "1.0.11",
4
4
  "description": "A type safe translator that knows what to say and how to handle the rest. Supports custom messages, rich replacements, and async loading.",
5
5
  "author": "Yiming Liao",
6
6
  "license": "MIT",