Im struggling to extend the function propperly. Im stuck with the error Cannot redeclare block-scoped variable t
. I`m not quite sure if declareing a module is the correct approach (im new to ts). I also played around with the idea of creating a wrapper for the t function to then use the wrapper and don't get the error of redeclartion. But I could not create a working example for that.
Suppresing the error // @ts-ignore results in that I get propper suggestions of valid keys from the json file but no validation if I type in a non existent one
I created a file i18n.d.ts which looks as following
import "react-i18next";
import deTranslation from 'src/translation/de-translation.json';
declare module 'i18next' {
type Translations<T = typeof deTranslation> = T;
type ConcatKeys<T, U> = T extends string ? `${T & string}.${U & string}` : never;
type NestedKeys<T> =
T extends object ? {
[K in keyof T]: K | ConcatKeys<K, NestedKeys<T[K]>>;
}[keyof T] :
string;
type TranslationKeys<T> = NestedKeys<T>;
interface TranslationFunction<T> {
<K extends TranslationKeys<T>>(key: K, nestedKeys?: string[]): string;
}
export const t: TranslationFunction<Translations>;
}
My goal is to be able to use it like this t('property.mortgage.mortgage_status')}
to get suggestions for the keys and validation if the key is not existing in de-translation.json file.
I came up with a possible solution.
Adding an I18n interface to the module declaration with the properties and methods used from i18n in the project. Then exporting it solves the issue. The t function now is typesafe and has the correct suggestions.
The drawback of this solution is that you have to manually add newly used functions to the interface.
interface I18n {
language: string;
changeLanguage: (lang: string) => Promise<void>;
use: (module: any) => I18n;
t: TranslationFunction<Translations>;
init: (options: any) => Promise<I18n>;
// Add other properties/methods you use from i18n
}
const i18n: I18n & {
t: TranslationFunction<Translations>;
};