乐闻世界logo
搜索文章和话题

How to use i18next in TypeScript projects?

2月18日 22:07

Basic Type Definitions

Install Type Definitions

bash
npm install --save-dev @types/i18next # for react-i18next npm install --save-dev @types/react-i18next

Define Translation Resource Types

typescript
interface 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

typescript
import { useTranslation } from 'react-i18next'; function MyComponent() { const { t } = useTranslation(); return <h1>{t('welcome')}</h1>; }

Specify Namespace

typescript
function 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

typescript
import 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

bash
npm 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

typescript
interface 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

typescript
interface 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

typescript
type 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

typescript
interface 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

typescript
import { 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

  1. Generate Types: Use tools to automatically generate translation resource types
  2. Strict Mode: Enable TypeScript strict mode
  3. Namespaces: Use namespaces to organize translations
  4. Type Guards: Use type guards to ensure type safety
  5. Continuous Integration: Generate and check types in CI/CD
  6. Documentation: Document type definitions and usage
  7. Testing: Write type tests to ensure type correctness
标签:i18next