6月1日 02:22
How to use i18next in TypeScript projects?
Basic Type Definitions
Install Type Definitions
bashnpm install --save-dev @types/i18next # for react-i18next npm install --save-dev @types/react-i18next
Define Translation Resource Types
typescriptinterface TranslationResources { en: { translation: EnTranslation; }; zh: { translation: ZhTranslation; }; } interface EnTranslation { welcome: string; greeting: string; user: { name: string; profile: string; }; } interface ZhTranslation { welcome: string; greeting: string; user: { name: string; profile: string; }; }
Using useTranslation Hook
Basic Usage
typescriptimport { useTranslation } from 'react-i18next'; function MyComponent() { const { t } = useTranslation(); return <h1>{t('welcome')}</h1>; }
Specify Namespace
typescriptfunction MyComponent() { const { t } = useTranslation('common'); return <button>{t('save')}</button>; }
Type-safe Translation Keys
typescript// define translation key types type TranslationKeys = 'welcome' | 'greeting' | 'user.name'; function useTypedTranslation() { const { t } = useTranslation(); return { t: (key: TranslationKeys, options?: any) => t(key, options) }; } function MyComponent() { const { t } = useTypedTranslation(); return <h1>{t('welcome')}</h1>; }
Creating Type-safe Translation Functions
Using Generics
typescriptimport i18next from 'i18next'; type TranslationFunction<T> = (key: keyof T, options?: any) => string; function createTypedTranslation<T>(ns: string): TranslationFunction<T> { return (key: keyof T, options?: any) => { return i18next.t(`${ns}:${String(key)}`, options); }; } // usage interface CommonTranslations { save: string; cancel: string; delete: string; } const tCommon = createTypedTranslation<CommonTranslations>('common'); function MyComponent() { return ( <div> <button>{tCommon('save')}</button> <button>{tCommon('cancel')}</button> </div> ); }
Using i18next-resources-to-ts
Generate Type Definitions
bashnpm install --save-dev i18next-resources-to-ts
javascript// scripts/generate-types.js const { generateTypes } = require('i18next-resources-to-ts'); const fs = require('fs'); generateTypes('./locales', { indent: 2, sort: true, lineEnding: 'lf' }).then(types => { fs.writeFileSync('./src/types/i18n.d.ts', types); console.log('Types generated successfully'); });
Add Script in package.json
json{ "scripts": { "generate:i18n-types": "node scripts/generate-types.js" } }
Interpolation Type Safety
typescriptinterface GreetingOptions { name: string; title?: string; } function useGreeting() { const { t } = useTranslation(); return (options: GreetingOptions) => { return t('greeting', options); }; } function MyComponent() { const greet = useGreeting(); return ( <div> {greet({ name: 'John' })} {greet({ name: 'Jane', title: 'Dr.' })} </div> ); }
Pluralization Types
typescriptinterface PluralOptions { count: number; item: string; } function usePlural() { const { t } = useTranslation(); return (options: PluralOptions) => { return t('item_count', options); }; } function MyComponent() { const plural = usePlural(); return ( <div> {plural({ count: 1, item: 'apple' })} {plural({ count: 5, item: 'apple' })} </div> ); }
Context Types
typescripttype Context = 'male' | 'female' | 'other'; interface ContextOptions { context: Context; name: string; } function useContextTranslation() { const { t } = useTranslation(); return (options: ContextOptions) => { return t('friend', options); }; } function MyComponent() { const tFriend = useContextTranslation(); return ( <div> {tFriend({ context: 'male', name: 'John' })} {tFriend({ context: 'female', name: 'Jane' })} </div> ); }
Namespace Types
typescriptinterface Namespaces { common: CommonTranslations; errors: ErrorTranslations; user: UserTranslations; } function useNamespacedTranslation<K extends keyof Namespaces>( namespace: K ) { const { t } = useTranslation(namespace); return { t: (key: keyof Namespaces[K], options?: any) => t(key, options) }; } function MyComponent() { const { t: tCommon } = useNamespacedTranslation('common'); const { t: tErrors } = useNamespacedTranslation('errors'); return ( <div> <button>{tCommon('save')}</button> <p>{tErrors('notFound')}</p> </div> ); }
Trans Component Types
typescriptimport { Trans } from 'react-i18next'; interface TransProps { i18nKey: string; values?: Record<string, string | number>; components?: Record<string, React.ReactNode>; } function TypedTrans({ i18nKey, values, components }: TransProps) { return ( <Trans i18nKey={i18nKey} values={values} components={components} /> ); } function MyComponent() { return ( <TypedTrans i18nKey="user.greeting" values={{ name: 'John' }} components={{ strong: <strong /> }} /> ); }
Best Practices
- Generate Types: Use tools to automatically generate translation resource types
- Strict Mode: Enable TypeScript strict mode
- Namespaces: Use namespaces to organize translations
- Type Guards: Use type guards to ensure type safety
- Continuous Integration: Generate and check types in CI/CD
- Documentation: Document type definitions and usage
- Testing: Write type tests to ensure type correctness