You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					399 lines
				
				11 KiB
			
		
		
			
		
	
	
					399 lines
				
				11 KiB
			| 
											3 years ago
										 | import i18next, { | ||
|  |   ReactOptions, | ||
|  |   i18n, | ||
|  |   ThirdPartyModule, | ||
|  |   Resource, | ||
|  |   TOptions, | ||
|  |   StringMap, | ||
|  |   TFunctionResult, | ||
|  | } from 'i18next'; | ||
|  | import * as React from 'react'; | ||
|  | 
 | ||
|  | type Subtract<T extends K, K> = Omit<T, keyof K>; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Due to a limitation/bug on typescript 4.1 (https://github.com/microsoft/TypeScript/issues/41406), we added
 | ||
|  |  * "extends infer A ? A : never" in a few places to suppress the error "Type instantiation is excessively deep and possibly infinite." | ||
|  |  * on cases where users have more than 22 namespaces. Once the issue is fixed, we can remove all instances of the workaround used. | ||
|  |  * | ||
|  |  * Reference of the bug reported: https://github.com/i18next/react-i18next/issues/1222
 | ||
|  |  */ | ||
|  | 
 | ||
|  | /** | ||
|  |  * This interface can be augmented by users to add types to `react-i18next` default resources. | ||
|  |  * | ||
|  |  * @deprecated use the `resources` key of `CustomTypeOptions` instead | ||
|  |  */ | ||
|  | export interface Resources {} | ||
|  | /** | ||
|  |  * This interface can be augmented by users to add types to `react-i18next`. It accepts a `defaultNS`, `resources`, `returnNull` and `returnEmptyString` properties. | ||
|  |  * | ||
|  |  * Usage: | ||
|  |  * ```ts
 | ||
|  |  * // react-i18next.d.ts
 | ||
|  |  * import 'react-i18next'; | ||
|  |  * declare module 'react-i18next' { | ||
|  |  *   interface CustomTypeOptions { | ||
|  |  *     defaultNS: 'custom'; | ||
|  |  *     returnNull: false; | ||
|  |  *     returnEmptyString: false; | ||
|  |  *     nsSeparator: ':'; | ||
|  |  *     keySeparator: '.'; | ||
|  |  *     jsonFormat: 'v4'; | ||
|  |  *     allowObjectInHTMLChildren: false; | ||
|  |  *     resources: { | ||
|  |  *       custom: { | ||
|  |  *         foo: 'foo'; | ||
|  |  *       }; | ||
|  |  *     }; | ||
|  |  *   } | ||
|  |  * } | ||
|  |  * ```
 | ||
|  |  */ | ||
|  | export interface CustomTypeOptions {} | ||
|  | 
 | ||
|  | type MergeBy<T, K> = Omit<T, keyof K> & K; | ||
|  | 
 | ||
|  | type TypeOptions = MergeBy< | ||
|  |   { | ||
|  |     returnNull: true; | ||
|  |     returnEmptyString: true; | ||
|  |     keySeparator: '.'; | ||
|  |     nsSeparator: ':'; | ||
|  |     defaultNS: 'translation'; | ||
|  |     jsonFormat: 'v4'; | ||
|  |     resources: Resources; | ||
|  |     allowObjectInHTMLChildren: false; | ||
|  |   }, | ||
|  |   CustomTypeOptions | ||
|  | >; | ||
|  | 
 | ||
|  | type DefaultResources = TypeOptions['resources']; | ||
|  | type DefaultNamespace<T = TypeOptions['defaultNS']> = T extends Fallback<string> ? T : string; | ||
|  | 
 | ||
|  | type Fallback<F, T = keyof DefaultResources> = [T] extends [never] ? F : T; | ||
|  | 
 | ||
|  | export type Namespace<F = Fallback<string>> = F | F[]; | ||
|  | 
 | ||
|  | export function setDefaults(options: ReactOptions): void; | ||
|  | export function getDefaults(): ReactOptions; | ||
|  | export function setI18n(instance: i18n): void; | ||
|  | export function getI18n(): i18n; | ||
|  | export const initReactI18next: ThirdPartyModule; | ||
|  | export function composeInitialProps(ForComponent: any): (ctx: unknown) => Promise<any>; | ||
|  | export function getInitialProps(): { | ||
|  |   initialI18nStore: { | ||
|  |     [ns: string]: {}; | ||
|  |   }; | ||
|  |   initialLanguage: string; | ||
|  | }; | ||
|  | 
 | ||
|  | export interface ReportNamespaces { | ||
|  |   addUsedNamespaces(namespaces: Namespace[]): void; | ||
|  |   getUsedNamespaces(): string[]; | ||
|  | } | ||
|  | 
 | ||
|  | declare module 'i18next' { | ||
|  |   interface i18n { | ||
|  |     reportNamespaces: ReportNamespaces; | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | type ObjectOrNever = TypeOptions['allowObjectInHTMLChildren'] extends true | ||
|  |   ? Record<string, unknown> | ||
|  |   : never; | ||
|  | 
 | ||
|  | type ReactI18NextChild = React.ReactNode | ObjectOrNever; | ||
|  | 
 | ||
|  | declare module 'react' { | ||
|  |   interface HTMLAttributes<T> { | ||
|  |     children?: ReactI18NextChild | Iterable<ReactI18NextChild>; | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | type PluralSuffix = 'zero' | 'one' | 'two' | 'few' | 'many' | 'other'; | ||
|  | 
 | ||
|  | type WithOrWithoutPlural<K> = TypeOptions['jsonFormat'] extends 'v4' | ||
|  |   ? K extends `${infer B}_${PluralSuffix}` | ||
|  |     ? B | K | ||
|  |     : K | ||
|  |   : K; | ||
|  | 
 | ||
|  | // Normalize single namespace
 | ||
|  | export type KeysWithSeparator<K1, K2, S extends string = TypeOptions['keySeparator']> = `${K1 & | ||
|  |   string}${S}${K2 & string}`;
 | ||
|  | type KeysWithSeparator2<K1, K2> = KeysWithSeparator<K1, Exclude<K2, keyof any[]>>; | ||
|  | type Normalize2<T, K = keyof T> = K extends keyof T | ||
|  |   ? T[K] extends Record<string, any> | ||
|  |     ? T[K] extends readonly any[] | ||
|  |       ? | ||
|  |           | KeysWithSeparator2<K, WithOrWithoutPlural<keyof T[K]>> | ||
|  |           | KeysWithSeparator2<K, Normalize2<T[K]>> | ||
|  |       : | ||
|  |           | KeysWithSeparator<K, WithOrWithoutPlural<keyof T[K]>> | ||
|  |           | KeysWithSeparator<K, Normalize2<T[K]>> | ||
|  |     : never | ||
|  |   : never; | ||
|  | type Normalize<T> = WithOrWithoutPlural<keyof T> | Normalize2<T>; | ||
|  | 
 | ||
|  | // Normalize multiple namespaces
 | ||
|  | type KeyWithNSSeparator<N, K, S extends string = TypeOptions['nsSeparator']> = `${N & | ||
|  |   string}${S}${K & string}`;
 | ||
|  | type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void | ||
|  |   ? I | ||
|  |   : never; | ||
|  | type LastOf<T> = UnionToIntersection<T extends any ? () => T : never> extends () => infer R | ||
|  |   ? R | ||
|  |   : never; | ||
|  | type NormalizeMulti<T, U extends keyof T, L = LastOf<U>> = L extends U | ||
|  |   ? KeyWithNSSeparator<L, Normalize<T[L]>> | NormalizeMulti<T, Exclude<U, L>> | ||
|  |   : never; | ||
|  | 
 | ||
|  | interface CustomTypeParameters { | ||
|  |   returnNull?: boolean; | ||
|  |   returnEmptyString?: boolean; | ||
|  | } | ||
|  | 
 | ||
|  | type TypeOptionsFallback<TranslationValue, Option, MatchingValue> = Option extends false | ||
|  |   ? TranslationValue extends MatchingValue | ||
|  |     ? string | ||
|  |     : TranslationValue | ||
|  |   : TranslationValue; | ||
|  | 
 | ||
|  | /** | ||
|  |  * Checks if user has enabled `returnEmptyString` and `returnNull` options to retrieve correct values. | ||
|  |  */ | ||
|  | export type NormalizeByTypeOptions< | ||
|  |   TranslationValue, | ||
|  |   Options extends CustomTypeParameters = TypeOptions, | ||
|  |   R = TypeOptionsFallback<TranslationValue, Options['returnEmptyString'], ''> | ||
|  | > = TypeOptionsFallback<R, Options['returnNull'], null>; | ||
|  | 
 | ||
|  | type StringIfPlural<T> = TypeOptions['jsonFormat'] extends 'v4' | ||
|  |   ? T extends `${string}_${PluralSuffix}` | ||
|  |     ? string | ||
|  |     : never | ||
|  |   : never; | ||
|  | 
 | ||
|  | type NormalizeReturn< | ||
|  |   T, | ||
|  |   V, | ||
|  |   S extends string | false = TypeOptions['keySeparator'] | ||
|  | > = V extends keyof T | ||
|  |   ? NormalizeByTypeOptions<T[V]> | ||
|  |   : S extends false | ||
|  |   ? V | ||
|  |   : V extends `${infer K}${S}${infer R}` | ||
|  |   ? K extends keyof T | ||
|  |     ? NormalizeReturn<T[K], R> | ||
|  |     : never | ||
|  |   : StringIfPlural<keyof T>; | ||
|  | 
 | ||
|  | type NormalizeMultiReturn<T, V> = V extends `${infer N}:${infer R}` | ||
|  |   ? N extends keyof T | ||
|  |     ? NormalizeReturn<T[N], R> | ||
|  |     : never | ||
|  |   : never; | ||
|  | 
 | ||
|  | type NormalizeWithKeyPrefix< | ||
|  |   T, | ||
|  |   K, | ||
|  |   S extends string = TypeOptions['keySeparator'] | ||
|  | > = K extends `${infer K1}${S}${infer K2}` | ||
|  |   ? K1 extends keyof T | ||
|  |     ? NormalizeWithKeyPrefix<T[K1], K2> | ||
|  |     : never | ||
|  |   : K extends keyof T | ||
|  |   ? T[K] extends string | ||
|  |     ? never | ||
|  |     : Normalize<T[K]> | ||
|  |   : never; | ||
|  | 
 | ||
|  | type KeyPrefix<N extends Namespace> = | ||
|  |   | (N extends keyof DefaultResources ? Normalize<DefaultResources[N]> : string) | ||
|  |   | undefined; | ||
|  | 
 | ||
|  | export type TFuncKey< | ||
|  |   N extends Namespace = DefaultNamespace, | ||
|  |   TKPrefix = undefined, | ||
|  |   T = DefaultResources | ||
|  | > = N extends (keyof T)[] | Readonly<(keyof T)[]> | ||
|  |   ? NormalizeMulti<T, N[number]> | ||
|  |   : N extends keyof T | ||
|  |   ? TKPrefix extends undefined | ||
|  |     ? Normalize<T[N]> | ||
|  |     : NormalizeWithKeyPrefix<T[N], TKPrefix> | ||
|  |   : string; | ||
|  | 
 | ||
|  | export type TFuncReturn< | ||
|  |   N, | ||
|  |   TKeys, | ||
|  |   TDefaultResult, | ||
|  |   TKPrefix = undefined, | ||
|  |   T = DefaultResources | ||
|  | > = N extends (keyof T)[] | ||
|  |   ? NormalizeMultiReturn<T, TKeys> | ||
|  |   : N extends keyof T | ||
|  |   ? TKPrefix extends undefined | ||
|  |     ? NormalizeReturn<T[N], TKeys> | ||
|  |     : NormalizeReturn<T[N], KeysWithSeparator<TKPrefix, TKeys>> | ||
|  |   : Fallback<TDefaultResult>; | ||
|  | 
 | ||
|  | export interface TFunction<N extends Namespace = DefaultNamespace, TKPrefix = undefined> { | ||
|  |   < | ||
|  |     TKeys extends TFuncKey<N, TKPrefix> | TemplateStringsArray extends infer A ? A : never, | ||
|  |     TDefaultResult extends TFunctionResult | React.ReactNode = string, | ||
|  |     TInterpolationMap extends object = StringMap | ||
|  |   >( | ||
|  |     key: TKeys | TKeys[], | ||
|  |     options?: TOptions<TInterpolationMap> | string, | ||
|  |   ): TFuncReturn<N, TKeys, TDefaultResult, TKPrefix>; | ||
|  |   < | ||
|  |     TKeys extends TFuncKey<N, TKPrefix> | TemplateStringsArray extends infer A ? A : never, | ||
|  |     TDefaultResult extends TFunctionResult | React.ReactNode = string, | ||
|  |     TInterpolationMap extends object = StringMap | ||
|  |   >( | ||
|  |     key: TKeys | TKeys[], | ||
|  |     defaultValue?: string, | ||
|  |     options?: TOptions<TInterpolationMap> | string, | ||
|  |   ): TFuncReturn<N, TKeys, TDefaultResult, TKPrefix>; | ||
|  | } | ||
|  | 
 | ||
|  | type TransChild = React.ReactNode | Record<string, unknown>; | ||
|  | export type TransProps< | ||
|  |   K extends TFuncKey<N, TKPrefix> extends infer A ? A : never, | ||
|  |   N extends Namespace = DefaultNamespace, | ||
|  |   TKPrefix = undefined, | ||
|  |   E = React.HTMLProps<HTMLDivElement> | ||
|  | > = E & { | ||
|  |   children?: TransChild | TransChild[]; | ||
|  |   components?: readonly React.ReactElement[] | { readonly [tagName: string]: React.ReactElement }; | ||
|  |   count?: number; | ||
|  |   context?: string; | ||
|  |   defaults?: string; | ||
|  |   i18n?: i18n; | ||
|  |   i18nKey?: K | K[]; | ||
|  |   ns?: N; | ||
|  |   parent?: string | React.ComponentType<any> | null; // used in React.createElement if not null
 | ||
|  |   tOptions?: {}; | ||
|  |   values?: {}; | ||
|  |   shouldUnescape?: boolean; | ||
|  |   t?: TFunction<N, TKPrefix>; | ||
|  | }; | ||
|  | 
 | ||
|  | export function Trans< | ||
|  |   K extends TFuncKey<N, TKPrefix> extends infer A ? A : never, | ||
|  |   N extends Namespace = DefaultNamespace, | ||
|  |   TKPrefix extends KeyPrefix<N> = undefined, | ||
|  |   E = React.HTMLProps<HTMLDivElement> | ||
|  | >(props: TransProps<K, N, TKPrefix, E>): React.ReactElement; | ||
|  | 
 | ||
|  | export function useSSR(initialI18nStore: Resource, initialLanguage: string): void; | ||
|  | 
 | ||
|  | export interface UseTranslationOptions<TKPrefix = undefined> { | ||
|  |   i18n?: i18n; | ||
|  |   useSuspense?: boolean; | ||
|  |   keyPrefix?: TKPrefix; | ||
|  |   bindI18n?: string | false; | ||
|  |   nsMode?: 'fallback' | 'default'; | ||
|  | } | ||
|  | 
 | ||
|  | export type UseTranslationResponse<N extends Namespace, TKPrefix = undefined> = [ | ||
|  |   TFunction<N, TKPrefix>, | ||
|  |   i18n, | ||
|  |   boolean, | ||
|  | ] & { | ||
|  |   t: TFunction<N, TKPrefix>; | ||
|  |   i18n: i18n; | ||
|  |   ready: boolean; | ||
|  | }; | ||
|  | 
 | ||
|  | export function useTranslation< | ||
|  |   N extends Namespace = DefaultNamespace, | ||
|  |   TKPrefix extends KeyPrefix<N> = undefined | ||
|  | >( | ||
|  |   ns?: N | Readonly<N>, | ||
|  |   options?: UseTranslationOptions<TKPrefix>, | ||
|  | ): UseTranslationResponse<N, TKPrefix>; | ||
|  | 
 | ||
|  | // Need to see usage to improve this
 | ||
|  | export function withSSR(): <Props>( | ||
|  |   WrappedComponent: React.ComponentType<Props>, | ||
|  | ) => { | ||
|  |   ({ | ||
|  |     initialI18nStore, | ||
|  |     initialLanguage, | ||
|  |     ...rest | ||
|  |   }: { | ||
|  |     initialI18nStore: Resource; | ||
|  |     initialLanguage: string; | ||
|  |   } & Props): React.FunctionComponentElement<Props>; | ||
|  |   getInitialProps: (ctx: unknown) => Promise<any>; | ||
|  | }; | ||
|  | 
 | ||
|  | export interface WithTranslation< | ||
|  |   N extends Namespace = DefaultNamespace, | ||
|  |   TKPrefix extends KeyPrefix<N> = undefined | ||
|  | > { | ||
|  |   t: TFunction<N, TKPrefix>; | ||
|  |   i18n: i18n; | ||
|  |   tReady: boolean; | ||
|  | } | ||
|  | 
 | ||
|  | export interface WithTranslationProps { | ||
|  |   i18n?: i18n; | ||
|  |   useSuspense?: boolean; | ||
|  | } | ||
|  | 
 | ||
|  | export function withTranslation< | ||
|  |   N extends Namespace = DefaultNamespace, | ||
|  |   TKPrefix extends KeyPrefix<N> = undefined | ||
|  | >( | ||
|  |   ns?: N, | ||
|  |   options?: { | ||
|  |     withRef?: boolean; | ||
|  |     keyPrefix?: TKPrefix; | ||
|  |   }, | ||
|  | ): < | ||
|  |   C extends React.ComponentType<React.ComponentProps<any> & WithTranslationProps>, | ||
|  |   ResolvedProps = JSX.LibraryManagedAttributes< | ||
|  |     C, | ||
|  |     Subtract<React.ComponentProps<C>, WithTranslationProps> | ||
|  |   > | ||
|  | >( | ||
|  |   component: C, | ||
|  | ) => React.ComponentType<Omit<ResolvedProps, keyof WithTranslation<N>> & WithTranslationProps>; | ||
|  | 
 | ||
|  | export interface I18nextProviderProps { | ||
|  |   children?: React.ReactNode; | ||
|  |   i18n: i18n; | ||
|  |   defaultNS?: string; | ||
|  | } | ||
|  | 
 | ||
|  | export const I18nextProvider: React.FunctionComponent<I18nextProviderProps>; | ||
|  | export const I18nContext: React.Context<{ i18n: i18n }>; | ||
|  | 
 | ||
|  | export interface TranslationProps< | ||
|  |   N extends Namespace = DefaultNamespace, | ||
|  |   TKPrefix extends KeyPrefix<N> = undefined | ||
|  | > { | ||
|  |   children: ( | ||
|  |     t: TFunction<N, TKPrefix>, | ||
|  |     options: { | ||
|  |       i18n: i18n; | ||
|  |       lng: string; | ||
|  |     }, | ||
|  |     ready: boolean, | ||
|  |   ) => React.ReactNode; | ||
|  |   ns?: N; | ||
|  |   i18n?: i18n; | ||
|  |   useSuspense?: boolean; | ||
|  |   keyPrefix?: TKPrefix; | ||
|  |   nsMode?: 'fallback' | 'default'; | ||
|  | } | ||
|  | 
 | ||
|  | export function Translation< | ||
|  |   N extends Namespace = DefaultNamespace, | ||
|  |   TKPrefix extends KeyPrefix<N> = undefined | ||
|  | >(props: TranslationProps<N, TKPrefix>): any; |