i18next 21.10.0 → 22.0.1

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.
@@ -1 +1 @@
1
- {"type":"module","version":"21.10.0"}
1
+ {"type":"module","version":"22.0.1"}
package/index.d.ts CHANGED
@@ -1,21 +1,126 @@
1
- type Omit<T, K> = Pick<T, Exclude<keyof T, K>>;
1
+ // Helpers
2
2
  type MergeBy<T, K> = Omit<T, keyof K> & K;
3
+ type StringMap = { [key: string]: any };
4
+ type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void
5
+ ? I
6
+ : never;
7
+ type LastOf<T> = UnionToIntersection<T extends any ? () => T : never> extends () => infer R
8
+ ? R
9
+ : never;
3
10
 
4
- export interface FallbackLngObjList {
5
- [language: string]: readonly string[];
6
- }
11
+ /**
12
+ * This interface can be augmented by users to add types to `i18next` default TypeOptions.
13
+ */
14
+ export interface CustomTypeOptions {}
7
15
 
8
- export type FallbackLng =
9
- | string
10
- | readonly string[]
11
- | FallbackLngObjList
12
- | ((code: string) => string | readonly string[] | FallbackLngObjList);
16
+ /**
17
+ * This interface can be augmented by users to add types to `i18next` default PluginOptions.
18
+ *
19
+ * Usage:
20
+ * ```ts
21
+ * // react-i18next.d.ts
22
+ * import 'react-i18next';
23
+ * declare module 'react-i18next' {
24
+ * interface CustomTypeOptions {
25
+ * defaultNS: 'custom';
26
+ * returnNull: false;
27
+ * returnEmptyString: false;
28
+ * nsSeparator: ':';
29
+ * keySeparator: '.';
30
+ * jsonFormat: 'v4';
31
+ * allowObjectInHTMLChildren: false;
32
+ * resources: {
33
+ * custom: {
34
+ * foo: 'foo';
35
+ * };
36
+ * };
37
+ * }
38
+ * }
39
+ * ```
40
+ */
41
+ export interface CustomPluginOptions {}
42
+
43
+ export type TypeOptions = MergeBy<
44
+ {
45
+ /**
46
+ * Allows null values as valid translation
47
+ */
48
+ returnNull: true;
13
49
 
14
- export type FormatFunction = (
50
+ /**
51
+ * Allows empty string as valid translation
52
+ */
53
+ returnEmptyString: true;
54
+
55
+ /**
56
+ * Char to separate keys
57
+ */
58
+ keySeparator: '.';
59
+
60
+ /**
61
+ * Char to split namespace from key
62
+ */
63
+ nsSeparator: ':';
64
+
65
+ /**
66
+ * Default namespace used if not passed to translation function
67
+ */
68
+ defaultNS: 'translation';
69
+
70
+ /**
71
+ * Json Format Version - V4 allows plural suffixes
72
+ */
73
+ jsonFormat: 'v4';
74
+
75
+ /**
76
+ * Resources to initialize with
77
+ */
78
+ resources: object;
79
+
80
+ /**
81
+ * Flag that allows HTML elements to receive objects. This is only useful for React applications
82
+ * where you pass objects to HTML elements so they can be replaced to their respective interpolation
83
+ * values (mostly with Trans component)
84
+ */
85
+ allowObjectInHTMLChildren: false;
86
+ },
87
+ CustomTypeOptions
88
+ >;
89
+
90
+ export type PluginOptions = MergeBy<
91
+ {
92
+ /**
93
+ * Options for language detection - check documentation of plugin
94
+ * @default undefined
95
+ */
96
+ detection?: object;
97
+
98
+ /**
99
+ * Options for backend - check documentation of plugin
100
+ * @default undefined
101
+ */
102
+ backend?: object;
103
+
104
+ /**
105
+ * Options for cache layer - check documentation of plugin
106
+ * @default undefined
107
+ */
108
+ cache?: object;
109
+
110
+ /**
111
+ * Options for i18n message format - check documentation of plugin
112
+ * @default undefined
113
+ */
114
+ i18nFormat?: object;
115
+ },
116
+ CustomPluginOptions
117
+ >;
118
+
119
+ type FormatFunction = (
15
120
  value: any,
16
121
  format?: string,
17
122
  lng?: string,
18
- options?: InterpolationOptions & { [key: string]: any },
123
+ options?: InterpolationOptions & StringMap,
19
124
  ) => string;
20
125
 
21
126
  export interface InterpolationOptions {
@@ -124,6 +229,16 @@ export interface InterpolationOptions {
124
229
  skipOnVariables?: boolean;
125
230
  }
126
231
 
232
+ export interface FallbackLngObjList {
233
+ [language: string]: readonly string[];
234
+ }
235
+
236
+ export type FallbackLng =
237
+ | string
238
+ | readonly string[]
239
+ | FallbackLngObjList
240
+ | ((code: string) => string | readonly string[] | FallbackLngObjList);
241
+
127
242
  export interface ReactOptions {
128
243
  /**
129
244
  * Set it to fallback to let passed namespaces to translated hoc act as fallbacks
@@ -191,38 +306,7 @@ export interface ReactOptions {
191
306
  unescape?(str: string): string;
192
307
  }
193
308
 
194
- /**
195
- * This interface can be augmented by users to add types to `i18next` default PluginOptions.
196
- */
197
- export interface PluginOptions {}
198
-
199
- interface DefaultPluginOptions {
200
- /**
201
- * Options for language detection - check documentation of plugin
202
- * @default undefined
203
- */
204
- detection?: object;
205
-
206
- /**
207
- * Options for backend - check documentation of plugin
208
- * @default undefined
209
- */
210
- backend?: object;
211
-
212
- /**
213
- * Options for cache layer - check documentation of plugin
214
- * @default undefined
215
- */
216
- cache?: object;
217
-
218
- /**
219
- * Options for i18n message format - check documentation of plugin
220
- * @default undefined
221
- */
222
- i18nFormat?: object;
223
- }
224
-
225
- export interface InitOptions extends MergeBy<DefaultPluginOptions, PluginOptions> {
309
+ export interface InitOptions extends PluginOptions {
226
310
  /**
227
311
  * Logs info level to console output. Helps finding issues with loading not working.
228
312
  * @default false
@@ -627,37 +711,87 @@ export interface TOptionsBase {
627
711
  interpolation?: InterpolationOptions;
628
712
  }
629
713
 
630
- /**
631
- * indexer that is open to any value
632
- */
633
- export type StringMap = { [key: string]: any };
634
-
635
714
  /**
636
715
  * Options that allow open ended values for interpolation unless type is provided.
637
716
  */
638
717
  export type TOptions<TInterpolationMap extends object = StringMap> = TOptionsBase &
639
718
  TInterpolationMap;
640
719
 
641
- export type Callback = (error: any, t: TFunction) => void;
642
-
643
- /**
644
- * Uses similar args as the t function and returns true if a key exists.
645
- */
646
- export interface ExistsFunction<
647
- TKeys extends string = string,
648
- TInterpolationMap extends object = StringMap,
649
- > {
650
- (key: TKeys | TKeys[], options?: TOptions<TInterpolationMap>): boolean;
651
- }
652
-
653
- export interface WithT {
720
+ type FallbackOrNS<F, T = keyof Resources> = [T] extends [never] ? F : T;
721
+
722
+ type Resources = TypeOptions['resources'];
723
+ type DefaultNamespace = TypeOptions['defaultNS'];
724
+
725
+ export type Namespace<T = FallbackOrNS<string>> = T | T[];
726
+
727
+ type PluralSuffix = 'zero' | 'one' | 'two' | 'few' | 'many' | 'other';
728
+
729
+ type WithOrWithoutPlural<K> = TypeOptions['jsonFormat'] extends 'v4'
730
+ ? K extends `${infer B}_${PluralSuffix}`
731
+ ? B | K
732
+ : K
733
+ : K;
734
+
735
+ // Normalize single namespace
736
+ export type KeysWithSeparator<K1, K2, S extends string = TypeOptions['keySeparator']> = `${K1 &
737
+ string}${S}${K2 & string}`;
738
+ type KeysWithSeparator2<K1, K2> = KeysWithSeparator<K1, Exclude<K2, keyof any[]>>;
739
+ type Normalize2<T, K = keyof T> = K extends keyof T
740
+ ? T[K] extends StringMap
741
+ ? T[K] extends readonly any[]
742
+ ?
743
+ | KeysWithSeparator2<K, WithOrWithoutPlural<keyof T[K]>>
744
+ | KeysWithSeparator2<K, Normalize2<T[K]>>
745
+ :
746
+ | KeysWithSeparator<K, WithOrWithoutPlural<keyof T[K]>>
747
+ | KeysWithSeparator<K, Normalize2<T[K]>>
748
+ : never
749
+ : never;
750
+ type Normalize<T> = WithOrWithoutPlural<keyof T> | Normalize2<T>;
751
+
752
+ // Normalize multiple namespaces
753
+ type KeyWithNSSeparator<N, K, S extends string = TypeOptions['nsSeparator']> = `${N &
754
+ string}${S}${K & string}`;
755
+ type NormalizeMulti<T, U extends keyof T, L = LastOf<U>> = L extends U
756
+ ? KeyWithNSSeparator<L, Normalize<T[L]>> | NormalizeMulti<T, Exclude<U, L>>
757
+ : never;
758
+
759
+ // Normalize single namespace with key prefix
760
+ type NormalizeWithKeyPrefix<
761
+ T,
762
+ K,
763
+ S extends string = TypeOptions['keySeparator'],
764
+ > = K extends `${infer K1}${S}${infer K2}`
765
+ ? K1 extends keyof T
766
+ ? NormalizeWithKeyPrefix<T[K1], K2>
767
+ : never
768
+ : K extends keyof T
769
+ ? T[K] extends string
770
+ ? never
771
+ : Normalize<T[K]>
772
+ : never;
773
+
774
+ export type KeyPrefix<N extends Namespace> =
775
+ | (N extends keyof Resources ? Normalize<Resources[N]> : string)
776
+ | undefined;
777
+
778
+ export type TFuncKey<
779
+ N extends Namespace = DefaultNamespace,
780
+ TKPrefix = undefined,
781
+ T = Resources,
782
+ > = N extends (keyof T)[] | Readonly<(keyof T)[]>
783
+ ? NormalizeMulti<T, N[number]>
784
+ : N extends keyof T
785
+ ? TKPrefix extends undefined
786
+ ? Normalize<T[N]>
787
+ : NormalizeWithKeyPrefix<T[N], TKPrefix>
788
+ : string;
789
+
790
+ export interface WithT<N extends Namespace = DefaultNamespace> {
654
791
  // Expose parameterized t in the i18next interface hierarchy
655
- t: TFunction;
792
+ t: TFunction<N>;
656
793
  }
657
794
 
658
- /**
659
- * Object returned from t() function when passed returnDetails: true option.
660
- */
661
795
  export type TFunctionDetailedResult<T = string> = {
662
796
  /**
663
797
  * The plain used key
@@ -680,65 +814,107 @@ export type TFunctionDetailedResult<T = string> = {
680
814
  */
681
815
  usedNS: string;
682
816
  };
683
- export type TFunctionResult =
817
+
818
+ type TypeOptionsFallback<TranslationValue, Option, MatchingValue> = Option extends false
819
+ ? TranslationValue extends MatchingValue
820
+ ? string
821
+ : TranslationValue
822
+ : TranslationValue;
823
+
824
+ /**
825
+ * Checks if user has enabled `returnEmptyString` and `returnNull` options to retrieve correct values.
826
+ */
827
+ interface CustomTypeParameters {
828
+ returnNull?: boolean;
829
+ returnEmptyString?: boolean;
830
+ }
831
+ export type NormalizeByTypeOptions<
832
+ TranslationValue,
833
+ Options extends CustomTypeParameters = TypeOptions,
834
+ R = TypeOptionsFallback<TranslationValue, Options['returnEmptyString'], ''>,
835
+ > = TypeOptionsFallback<R, Options['returnNull'], null>;
836
+
837
+ type StringIfPlural<T> = TypeOptions['jsonFormat'] extends 'v4'
838
+ ? T extends `${string}_${PluralSuffix}`
839
+ ? string
840
+ : never
841
+ : never;
842
+
843
+ export type NormalizeReturn<
844
+ T,
845
+ V,
846
+ S extends string | false = TypeOptions['keySeparator'],
847
+ > = V extends keyof T
848
+ ? NormalizeByTypeOptions<T[V]>
849
+ : S extends false
850
+ ? V
851
+ : V extends `${infer K}${S}${infer R}`
852
+ ? K extends keyof T
853
+ ? NormalizeReturn<T[K], R>
854
+ : never
855
+ : StringIfPlural<keyof T>;
856
+
857
+ type NormalizeMultiReturn<T, V> = V extends `${infer N}:${infer R}`
858
+ ? N extends keyof T
859
+ ? NormalizeReturn<T[N], R>
860
+ : never
861
+ : never;
862
+
863
+ export type DefaultTFuncReturn =
684
864
  | string
685
865
  | object
686
866
  | TFunctionDetailedResult
687
867
  | Array<string | object>
688
868
  | undefined
689
869
  | null;
690
- export type TFunctionKeys = string | TemplateStringsArray;
691
- export interface TFunction {
692
- // basic usage
693
- <
694
- TResult extends TFunctionResult = string,
695
- TKeys extends TFunctionKeys = string,
696
- TInterpolationMap extends object = StringMap,
697
- >(
698
- key: TKeys | TKeys[],
699
- ): TResult;
870
+
871
+ export type TFuncReturn<
872
+ N,
873
+ TKeys,
874
+ TDefaultResult,
875
+ TKPrefix = undefined,
876
+ T = Resources,
877
+ > = N extends (keyof T)[]
878
+ ? NormalizeMultiReturn<T, TKeys>
879
+ : N extends keyof T
880
+ ? TKPrefix extends undefined
881
+ ? NormalizeReturn<T[N], TKeys>
882
+ : NormalizeReturn<T[N], KeysWithSeparator<TKPrefix, TKeys>>
883
+ : TDefaultResult;
884
+
885
+ export interface TFunction<N extends Namespace = DefaultNamespace, TKPrefix = undefined> {
700
886
  <
701
- TResult extends TFunctionResult = TFunctionDetailedResult<object>,
702
- TKeys extends TFunctionKeys = string,
887
+ TKeys extends TFuncKey<N, TKPrefix> | TemplateStringsArray extends infer A ? A : never,
888
+ TDefaultResult extends DefaultTFuncReturn,
703
889
  TInterpolationMap extends object = StringMap,
704
890
  >(
705
891
  key: TKeys | TKeys[],
706
- options?: TOptions<TInterpolationMap> & { returnDetails: true; returnObjects: true },
707
- ): TResult;
892
+ ): TFuncReturn<N, TKeys, TDefaultResult, TKPrefix>;
708
893
  <
709
- TResult extends TFunctionResult = TFunctionDetailedResult,
710
- TKeys extends TFunctionKeys = string,
894
+ TKeys extends TFuncKey<N, TKPrefix> | TemplateStringsArray extends infer A ? A : never,
895
+ TDefaultResult extends DefaultTFuncReturn,
711
896
  TInterpolationMap extends object = StringMap,
712
897
  >(
713
898
  key: TKeys | TKeys[],
714
899
  options?: TOptions<TInterpolationMap> & { returnDetails: true },
715
- ): TResult;
900
+ ): TFunctionDetailedResult<TFuncReturn<N, TKeys, TDefaultResult, TKPrefix>>;
716
901
  <
717
- TResult extends TFunctionResult = object,
718
- TKeys extends TFunctionKeys = string,
902
+ TKeys extends TFuncKey<N, TKPrefix> | TemplateStringsArray extends infer A ? A : never,
903
+ TDefaultResult extends DefaultTFuncReturn,
719
904
  TInterpolationMap extends object = StringMap,
720
905
  >(
721
906
  key: TKeys | TKeys[],
722
- options?: TOptions<TInterpolationMap> & { returnObjects: true },
723
- ): TResult;
907
+ options?: TOptions<TInterpolationMap>,
908
+ ): TFuncReturn<N, TKeys, TDefaultResult, TKPrefix>;
724
909
  <
725
- TResult extends TFunctionResult = string,
726
- TKeys extends TFunctionKeys = string,
727
- TInterpolationMap extends object = StringMap,
728
- >(
729
- key: TKeys | TKeys[],
730
- options?: TOptions<TInterpolationMap> | string,
731
- ): TResult;
732
- // overloaded usage
733
- <
734
- TResult extends TFunctionResult = string,
735
- TKeys extends TFunctionKeys = string,
910
+ TKeys extends TFuncKey<N, TKPrefix> | TemplateStringsArray extends infer A ? A : never,
911
+ TDefaultResult extends DefaultTFuncReturn,
736
912
  TInterpolationMap extends object = StringMap,
737
913
  >(
738
914
  key: TKeys | TKeys[],
739
915
  defaultValue?: string,
740
916
  options?: TOptions<TInterpolationMap> | string,
741
- ): TResult;
917
+ ): TFuncReturn<N, TKeys, TDefaultResult, TKPrefix>;
742
918
  }
743
919
 
744
920
  export interface Resource {
@@ -920,14 +1096,25 @@ export interface Modules {
920
1096
  export interface Newable<T> {
921
1097
  new (...args: any[]): T;
922
1098
  }
923
-
924
1099
  export interface NewableModule<T extends Module> extends Newable<T> {
925
1100
  type: T['type'];
926
1101
  }
927
1102
 
1103
+ type Callback = (error: any, t: TFunction) => void;
1104
+
1105
+ /**
1106
+ * Uses similar args as the t function and returns true if a key exists.
1107
+ */
1108
+ export interface ExistsFunction<
1109
+ TKeys extends string = string,
1110
+ TInterpolationMap extends object = StringMap,
1111
+ > {
1112
+ (key: TKeys | TKeys[], options?: TOptions<TInterpolationMap>): boolean;
1113
+ }
1114
+
928
1115
  export interface i18n {
929
1116
  // Expose parameterized t in the i18next interface hierarchy
930
- t: TFunction;
1117
+ t: TFunction<FallbackOrNS<string>[]>;
931
1118
 
932
1119
  /**
933
1120
  * The default of the i18next module is an i18next instance ready to be initialized by calling init.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "i18next",
3
- "version": "21.10.0",
3
+ "version": "22.0.1",
4
4
  "description": "i18next internationalization framework",
5
5
  "main": "./dist/cjs/i18next.js",
6
6
  "module": "./dist/esm/i18next.js",
@@ -98,15 +98,16 @@
98
98
  "rollup-plugin-terser": "^4.0.4",
99
99
  "sinon": "11.1.2",
100
100
  "tslint": "^5.12.1",
101
- "typescript": "^3.6.4",
101
+ "typescript": "^4.7.4",
102
102
  "watchify": "3.9.0"
103
103
  },
104
104
  "scripts": {
105
- "pretest": "npm run test:typescript && npm run test:typescript:noninterop",
105
+ "pretest": "npm run test:typescript && npm run test:typescript:customtypes && npm run test:typescript:noninterop",
106
106
  "test": "npm run test:new && npm run test:compat",
107
107
  "test:new": "karma start karma.conf.js --singleRun",
108
108
  "test:compat": "karma start karma.backward.conf.js --singleRun",
109
109
  "test:typescript": "tslint --project tsconfig.json",
110
+ "test:typescript:customtypes": "tslint --project test/typescript/custom-types/tsconfig.json",
110
111
  "test:typescript:noninterop": "tslint --project tsconfig.nonEsModuleInterop.json",
111
112
  "tdd": "karma start karma.conf.js",
112
113
  "tdd:compat": "karma start karma.backward.conf.js",