i18next 25.8.20 → 25.9.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/esm/package.json +1 -1
- package/jsr.json +1 -1
- package/package.json +1 -1
- package/typescript/t.d.ts +124 -10
package/dist/esm/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"type":"module","version":"25.
|
|
1
|
+
{"type":"module","version":"25.9.0"}
|
package/jsr.json
CHANGED
package/package.json
CHANGED
package/typescript/t.d.ts
CHANGED
|
@@ -234,6 +234,27 @@ export type KeyWithContext<Key, TOpt extends TOptions> = TOpt['context'] extends
|
|
|
234
234
|
? `${Key & string}${_ContextSeparator}${TOpt['context']}`
|
|
235
235
|
: Key;
|
|
236
236
|
|
|
237
|
+
export type ContextOfKey<
|
|
238
|
+
Key extends string,
|
|
239
|
+
Ns extends Namespace = DefaultNamespace,
|
|
240
|
+
TOpt extends TOptions = {},
|
|
241
|
+
KPrefix = undefined,
|
|
242
|
+
Keys extends $Dictionary = KeysByTOptions<TOpt>,
|
|
243
|
+
ActualNS extends Namespace = NsByTOptions<Ns, TOpt>,
|
|
244
|
+
ActualKeys =
|
|
245
|
+
| ParseKeysByKeyPrefix<Keys[$FirstNamespace<ActualNS>], KPrefix>
|
|
246
|
+
| ParseKeysByNamespaces<ActualNS, Keys>
|
|
247
|
+
| ParseKeysByFallbackNs<Keys>,
|
|
248
|
+
> = $IsResourcesDefined extends true
|
|
249
|
+
? Key extends ActualKeys
|
|
250
|
+
? string
|
|
251
|
+
: ActualKeys extends
|
|
252
|
+
| `${Key}${_ContextSeparator}${infer Context}${_PluralSeparator}${PluralSuffix}`
|
|
253
|
+
| `${Key}${_ContextSeparator}${infer Context}`
|
|
254
|
+
? Context
|
|
255
|
+
: never
|
|
256
|
+
: string;
|
|
257
|
+
|
|
237
258
|
// helper that maps the configured fallbackNS value to the matching resources slice
|
|
238
259
|
type FallbackResourcesOf<FallbackNS, R> = FallbackNS extends readonly (infer FN)[]
|
|
239
260
|
? R[FN & keyof R]
|
|
@@ -337,7 +358,12 @@ interface TFunctionStrict<
|
|
|
337
358
|
Ret extends TFunctionReturn<Ns, AppendKeyPrefix<Key, EffectiveKPrefix<KPrefix, TOpt>>, TOpt>,
|
|
338
359
|
>(
|
|
339
360
|
key: Key | Key[],
|
|
340
|
-
options?: TOpt &
|
|
361
|
+
options?: TOpt &
|
|
362
|
+
InterpolationMap<Ret> & {
|
|
363
|
+
context?: Key extends string
|
|
364
|
+
? ContextOfKey<Key, Ns, TOpt, EffectiveKPrefix<KPrefix, TOpt>>
|
|
365
|
+
: never;
|
|
366
|
+
},
|
|
341
367
|
): TFunctionReturnOptionalDetails<TFunctionProcessReturnValue<$NoInfer<Ret>, never>, TOpt>;
|
|
342
368
|
<
|
|
343
369
|
const Key extends ParseKeys<Ns, TOpt, EffectiveKPrefix<KPrefix, TOpt>> | TemplateStringsArray,
|
|
@@ -346,7 +372,12 @@ interface TFunctionStrict<
|
|
|
346
372
|
>(
|
|
347
373
|
key: Key | Key[],
|
|
348
374
|
defaultValue: string,
|
|
349
|
-
options?: TOpt &
|
|
375
|
+
options?: TOpt &
|
|
376
|
+
InterpolationMap<Ret> & {
|
|
377
|
+
context?: Key extends string
|
|
378
|
+
? ContextOfKey<Key, Ns, TOpt, EffectiveKPrefix<KPrefix, TOpt>>
|
|
379
|
+
: never;
|
|
380
|
+
},
|
|
350
381
|
): TFunctionReturnOptionalDetails<TFunctionProcessReturnValue<$NoInfer<Ret>, never>, TOpt>;
|
|
351
382
|
}
|
|
352
383
|
|
|
@@ -358,7 +389,17 @@ interface TFunctionNonStrict<
|
|
|
358
389
|
const Key extends ParseKeys<Ns, TOpt, EffectiveKPrefix<KPrefix, TOpt>> | TemplateStringsArray,
|
|
359
390
|
const TOpt extends TOptions,
|
|
360
391
|
Ret extends TFunctionReturn<Ns, AppendKeyPrefix<Key, EffectiveKPrefix<KPrefix, TOpt>>, TOpt>,
|
|
361
|
-
const ActualOptions extends TOpt
|
|
392
|
+
const ActualOptions extends Omit<TOpt, 'context'> &
|
|
393
|
+
InterpolationMap<Ret> & {
|
|
394
|
+
context?: Key extends string
|
|
395
|
+
? ContextOfKey<Key, Ns, TOpt, EffectiveKPrefix<KPrefix, TOpt>>
|
|
396
|
+
: never;
|
|
397
|
+
} = TOpt &
|
|
398
|
+
InterpolationMap<Ret> & {
|
|
399
|
+
context?: Key extends string
|
|
400
|
+
? ContextOfKey<Key, Ns, TOpt, EffectiveKPrefix<KPrefix, TOpt>>
|
|
401
|
+
: never;
|
|
402
|
+
},
|
|
362
403
|
DefaultValue extends string = never,
|
|
363
404
|
>(
|
|
364
405
|
...args:
|
|
@@ -388,9 +429,23 @@ export type KeyPrefix<Ns extends Namespace> = ResourceKeys<true>[$FirstNamespace
|
|
|
388
429
|
/// ↆ selector ↆ ///
|
|
389
430
|
/// ////////////// ///
|
|
390
431
|
|
|
432
|
+
declare const $PluralBrand: unique symbol;
|
|
433
|
+
/** Marks a value as coming from a plural-form key, requiring `count` in the selector options. */
|
|
434
|
+
type PluralValue<T extends string> = T & { readonly [$PluralBrand]: typeof $PluralBrand };
|
|
435
|
+
/** Recursively strips the {@link PluralValue} brand from a type (handles nested objects for `returnObjects`). */
|
|
436
|
+
type DeepUnwrapPlural<T> =
|
|
437
|
+
T extends PluralValue<infer U>
|
|
438
|
+
? U
|
|
439
|
+
: T extends readonly any[]
|
|
440
|
+
? { [I in keyof T]: DeepUnwrapPlural<T[I]> }
|
|
441
|
+
: T extends object
|
|
442
|
+
? { [K in keyof T]: DeepUnwrapPlural<T[K]> }
|
|
443
|
+
: T;
|
|
444
|
+
|
|
391
445
|
type NsArg<Ns extends Namespace> = Ns[number] | readonly Ns[number][];
|
|
392
446
|
|
|
393
447
|
interface TFunctionSelector<Ns extends Namespace, KPrefix, Source> extends Branded<Ns> {
|
|
448
|
+
// ── Selector(s) with explicit `ns` ───────────────────────────────────────────
|
|
394
449
|
<
|
|
395
450
|
Target extends ConstrainTarget<Opts>,
|
|
396
451
|
const NewNs extends NsArg<Ns> & Namespace,
|
|
@@ -403,16 +458,72 @@ interface TFunctionSelector<Ns extends Namespace, KPrefix, Source> extends Brand
|
|
|
403
458
|
options: Opts & InterpolationMap<Target> & { ns: NewNs },
|
|
404
459
|
): SelectorReturn<Target, Opts>;
|
|
405
460
|
|
|
461
|
+
// ── Array of selectors with default `ns` ─────────────────────────────────────
|
|
462
|
+
// Captures the selector tuple as `const Fns` so TypeScript preserves each
|
|
463
|
+
// element's exact return type. The union of return types is then extracted
|
|
464
|
+
// via a distributive `infer`, which correctly handles mixed PluralValue<T> and
|
|
465
|
+
// plain-string callbacks that would otherwise cause TypeScript to "lock in" the
|
|
466
|
+
// type from the first element.
|
|
467
|
+
<
|
|
468
|
+
const Fns extends readonly ((src: Select<Source, Opts['context']>) => string | object)[],
|
|
469
|
+
const Opts extends SelectorOptions<Ns[number]> = SelectorOptions<Ns[number]>,
|
|
470
|
+
>(
|
|
471
|
+
selectors: Fns,
|
|
472
|
+
options?: Opts &
|
|
473
|
+
InterpolationMap<
|
|
474
|
+
DeepUnwrapPlural<Fns[number] extends (...args: any[]) => infer R ? R : never>
|
|
475
|
+
>,
|
|
476
|
+
): SelectorReturn<Fns[number] extends (...args: any[]) => infer R ? R : never, Opts>;
|
|
477
|
+
|
|
478
|
+
// ── Single selector with context — bypasses count enforcement ────────────────
|
|
479
|
+
// When `context` is present in options, `Target` is derived from the
|
|
480
|
+
// context-filtered source (third mapped type of FilterKeys), which does NOT
|
|
481
|
+
// apply the PluralValue brand. A separate overload avoids the circular
|
|
482
|
+
// inference that would otherwise occur when `Opts['context']` sits inside the
|
|
483
|
+
// conditional rest tuple of the overload below.
|
|
406
484
|
<
|
|
407
485
|
Target extends ConstrainTarget<Opts>,
|
|
408
486
|
const NewNs extends NsArg<Ns> = Ns[number],
|
|
409
|
-
const Opts extends SelectorOptions<NewNs> = SelectorOptions<NewNs
|
|
487
|
+
const Opts extends SelectorOptions<NewNs> & { context: string } = SelectorOptions<NewNs> & {
|
|
488
|
+
context: string;
|
|
489
|
+
},
|
|
410
490
|
>(
|
|
411
|
-
selector:
|
|
412
|
-
|
|
413
|
-
| readonly SelectorFn<Source, ApplyTarget<Target, Opts>, Opts>[],
|
|
414
|
-
options?: Opts & InterpolationMap<Target>,
|
|
491
|
+
selector: SelectorFn<Source, ApplyTarget<Target, Opts>, Opts>,
|
|
492
|
+
options: Opts & InterpolationMap<Target>,
|
|
415
493
|
): SelectorReturn<Target, Opts>;
|
|
494
|
+
|
|
495
|
+
// ── Single selector with defaultValue — preserves literal type of DV ────────
|
|
496
|
+
// `const Opts` loses literal precision for `defaultValue` when inferred
|
|
497
|
+
// through a conditional rest tuple (TypeScript limitation). This dedicated
|
|
498
|
+
// overload captures `DV` from a regular (non-conditional) parameter position,
|
|
499
|
+
// preserving its literal type. Count enforcement for plural keys is achieved
|
|
500
|
+
// via a conditional intersection on the options parameter.
|
|
501
|
+
<
|
|
502
|
+
const Fn extends (src: Select<Source, undefined>) => ConstrainTarget<Opts>,
|
|
503
|
+
const DV extends string,
|
|
504
|
+
const Opts extends SelectorOptions<Ns[number]> = SelectorOptions<Ns[number]>,
|
|
505
|
+
>(
|
|
506
|
+
selector: Fn,
|
|
507
|
+
options: Opts & { defaultValue: DV } & (ReturnType<Fn> extends PluralValue<string>
|
|
508
|
+
? { count: number }
|
|
509
|
+
: {}) &
|
|
510
|
+
InterpolationMap<DeepUnwrapPlural<ReturnType<Fn>>>,
|
|
511
|
+
): SelectorReturn<ReturnType<Fn>, Opts, DV>;
|
|
512
|
+
|
|
513
|
+
// ── Single selector without context — enforces count for plural keys ──────────
|
|
514
|
+
// Uses `const Fn` to capture the selector's exact return type independently of
|
|
515
|
+
// `Opts`, breaking the circular dependency between `Target` inference and the
|
|
516
|
+
// conditional rest tuple. `ReturnType<Fn>` drives both the plural check and
|
|
517
|
+
// the return type; `Opts` is inferred later from the resolved rest args.
|
|
518
|
+
<
|
|
519
|
+
const Fn extends (src: Select<Source, undefined>) => ConstrainTarget<Opts>,
|
|
520
|
+
const Opts extends SelectorOptions<Ns[number]> = SelectorOptions<Ns[number]>,
|
|
521
|
+
>(
|
|
522
|
+
selector: Fn,
|
|
523
|
+
...args: ReturnType<Fn> extends PluralValue<string>
|
|
524
|
+
? [options: Opts & { count: number } & InterpolationMap<DeepUnwrapPlural<ReturnType<Fn>>>]
|
|
525
|
+
: [options?: Opts & InterpolationMap<ReturnType<Fn>>]
|
|
526
|
+
): SelectorReturn<ReturnType<Fn>, Opts>;
|
|
416
527
|
}
|
|
417
528
|
|
|
418
529
|
interface SelectorOptions<Ns = Namespace>
|
|
@@ -423,8 +534,9 @@ interface SelectorOptions<Ns = Namespace>
|
|
|
423
534
|
type SelectorReturn<
|
|
424
535
|
Target,
|
|
425
536
|
Opts extends { defaultValue?: unknown; returnObjects?: boolean },
|
|
537
|
+
DV = Opts['defaultValue'],
|
|
426
538
|
> = $IsResourcesDefined extends true
|
|
427
|
-
? TFunctionReturnOptionalDetails<ProcessReturnValue<Target
|
|
539
|
+
? TFunctionReturnOptionalDetails<ProcessReturnValue<DeepUnwrapPlural<Target>, DV>, Opts>
|
|
428
540
|
: DefaultTReturn<Opts>;
|
|
429
541
|
|
|
430
542
|
interface SelectorFn<Source, Target, Opts extends SelectorOptions<unknown>> {
|
|
@@ -501,7 +613,9 @@ type FilterKeys<T, Context> = never | T extends readonly any[]
|
|
|
501
613
|
| `${infer Prefix}${_PluralSeparator}${PluralSuffix}`
|
|
502
614
|
| `${infer Prefix}${_PluralSeparator}ordinal${_PluralSeparator}${PluralSuffix}`
|
|
503
615
|
? Prefix
|
|
504
|
-
: never]: T[K] extends object
|
|
616
|
+
: never]: T[K] extends object
|
|
617
|
+
? FilterKeys<T[K], Context>
|
|
618
|
+
: PluralValue<T[K] & string>;
|
|
505
619
|
} & {
|
|
506
620
|
[K in keyof T as T[K] extends object
|
|
507
621
|
? never
|