UNPKG

react-i18next

Version:

Internationalization for react done right. Using the i18next i18n ecosystem.

317 lines (285 loc) 9.61 kB
import type { $Subtract, $Tuple } from './helpers.js'; import type { ReactOptions, i18n, Resource, FlatNamespace, Namespace, TypeOptions, TFunction, KeyPrefix, ParseKeys, TOptions, } from 'i18next'; import * as React from 'react'; import { Trans, TransProps, TransSelectorProps, ErrorCode, ErrorArgs, } from './TransWithoutContext.js'; export { initReactI18next } from './initReactI18next.js'; export const TransWithoutContext: typeof Trans; export { Trans, TransProps, TransSelectorProps, ErrorArgs, ErrorCode }; /** * Content declaration for IcuTrans component * Describes React components as type + props blueprints that will be rendered */ export interface IcuTransContentDeclaration { type: string | React.ComponentType<any>; props?: { children?: IcuTransContentDeclaration | IcuTransContentDeclaration[]; [key: string]: any; }; } /** * Props for IcuTransWithoutContext component (no React context) */ export type IcuTransWithoutContextProps< Key extends ParseKeys<Ns, TOpt, KPrefix> = string, Ns extends Namespace = _DefaultNamespace, KPrefix = undefined, TContext extends string | undefined = undefined, TOpt extends TOptions & { context?: TContext } = { context: TContext }, > = { /** The i18n key to look up the translation */ i18nKey: Key; /** The default translation in ICU format with numbered tags (e.g., "<0>Click here</0>") */ defaultTranslation: string; /** Declaration tree describing React components and their props */ content: IcuTransContentDeclaration[]; /** Optional namespace(s) for the translation */ ns?: Ns; /** Optional values for ICU variable interpolation */ values?: Record<string, any>; /** i18next instance. If not provided, uses global instance */ i18n?: i18n; /** Custom translation function */ t?: TFunction<Ns, KPrefix>; }; /** * Props for IcuTrans component (with React context support) */ export type IcuTransProps< Key extends ParseKeys<Ns, TOpt, KPrefix> = string, Ns extends Namespace = _DefaultNamespace, KPrefix = undefined, TContext extends string | undefined = undefined, TOpt extends TOptions & { context?: TContext } = { context: TContext }, > = IcuTransWithoutContextProps<Key, Ns, KPrefix, TContext, TOpt>; /** * IcuTrans component for rendering ICU MessageFormat translations * This is the context-aware version that works with I18nextProvider * * @example * ```tsx * // Type-safe usage with namespace * <IcuTrans<'welcome.message', 'common'> * i18nKey="welcome.message" * defaultTranslation="Welcome <0>friend</0>!" * content={[{ type: 'strong', props: {} }]} * /> * ``` */ export interface IcuTransComponent { < Key extends ParseKeys<Ns, TOpt, KPrefix> = string, Ns extends Namespace = _DefaultNamespace, KPrefix = undefined, TContext extends string | undefined = undefined, TOpt extends TOptions & { context?: TContext } = { context: TContext }, >( props: IcuTransProps<Key, Ns, KPrefix, TContext, TOpt>, ): React.ReactElement; } /** * IcuTransWithoutContext component for rendering ICU MessageFormat translations * This version does not use React context and requires explicit i18n instance * * @example * ```tsx * // Type-safe usage with namespace * <IcuTransWithoutContext<'welcome.message', 'common'> * i18nKey="welcome.message" * defaultTranslation="Welcome <0>back</0>!" * content={[{ type: 'strong', props: {} }]} * i18n={i18nInstance} * /> * ``` */ export interface IcuTransWithoutContextComponent { < Key extends ParseKeys<Ns, TOpt, KPrefix> = string, Ns extends Namespace = _DefaultNamespace, KPrefix = undefined, TContext extends string | undefined = undefined, TOpt extends TOptions & { context?: TContext } = { context: TContext }, >( props: IcuTransWithoutContextProps<Key, Ns, KPrefix, TContext, TOpt>, ): React.ReactElement; } export const IcuTrans: IcuTransComponent; export const IcuTransWithoutContext: IcuTransWithoutContextComponent; export function setDefaults(options: ReactOptions): void; export function getDefaults(): ReactOptions; export function setI18n(instance: i18n): void; export function getI18n(): i18n; 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; // } interface CustomInstanceExtensions { reportNamespaces?: ReportNamespaces; } } type ObjectOrNever = TypeOptions['allowObjectInHTMLChildren'] extends true ? Record<string, unknown> : never; type ReactI18NextChildren = React.ReactNode | ObjectOrNever; declare module 'react' { namespace JSX { interface IntrinsicAttributes { i18nIsDynamicList?: boolean; } } interface HTMLAttributes<T> { // This union is inspired by the typings for React.ReactNode. We do this to fix "This JSX tag's 'children' prop // expects a single child of type 'ReactI18NextChildren', but multiple children were provided": // https://github.com/DefinitelyTyped/DefinitelyTyped/blob/5a1e9f91ed0143adede394adb3f540e650455f71/types/react/index.d.ts#L268 children?: ReactI18NextChildren | Iterable<ReactI18NextChildren>; } } type _DefaultNamespace = TypeOptions['defaultNS']; export function useSSR(initialI18nStore: Resource, initialLanguage: string): void; // If the version is earlier than i18next v25.4.0, enableSelector does not exist in TypeOptions, so a conditional type is used to maintain type compatibility. type _EnableSelector = TypeOptions extends { enableSelector: infer U } ? U : false; export type UseTranslationOptions<KPrefix> = { i18n?: i18n; useSuspense?: boolean; keyPrefix?: KPrefix; bindI18n?: string | false; nsMode?: 'fallback' | 'default'; lng?: string; // other of these options might also work: https://github.com/i18next/i18next/blob/master/index.d.ts#L127 }; export type UseTranslationResponse<Ns extends Namespace, KPrefix> = [ t: TFunction<Ns, KPrefix>, i18n: i18n, ready: boolean, ] & { t: TFunction<Ns, KPrefix>; i18n: i18n; ready: boolean; }; // Workaround to make code completion to work when suggesting namespaces. // This is a typescript limitation when using generics with default values, // it'll be addressed in this issue: https://github.com/microsoft/TypeScript/issues/52516 export type FallbackNs<Ns> = Ns extends undefined ? _DefaultNamespace : Ns extends Namespace ? Ns : _DefaultNamespace; export const useTranslation: _EnableSelector extends true | 'optimize' ? UseTranslationSelector : UseTranslationLegacy; interface UseTranslationLegacy { < const Ns extends FlatNamespace | $Tuple<FlatNamespace> | undefined = undefined, const KPrefix extends KeyPrefix<FallbackNs<Ns>> = undefined, >( ns?: Ns, options?: UseTranslationOptions<KPrefix>, ): UseTranslationResponse<FallbackNs<Ns>, KPrefix>; } interface UseTranslationSelector { < const Ns extends FlatNamespace | $Tuple<FlatNamespace> | undefined = undefined, const KPrefix = undefined, >( ns?: Ns, options?: UseTranslationOptions<KPrefix>, ): UseTranslationResponse<FallbackNs<Ns>, KPrefix>; } // 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< Ns extends FlatNamespace | $Tuple<FlatNamespace> | undefined = undefined, KPrefix extends KeyPrefix<FallbackNs<Ns>> = undefined, > { t: TFunction<FallbackNs<Ns>, KPrefix>; i18n: i18n; tReady: boolean; } export interface WithTranslationProps { i18n?: i18n; useSuspense?: boolean; } export function withTranslation< Ns extends FlatNamespace | $Tuple<FlatNamespace> | undefined = undefined, KPrefix extends KeyPrefix<FallbackNs<Ns>> = undefined, >( ns?: Ns, options?: { withRef?: boolean; keyPrefix?: KPrefix; }, ): < C extends React.ComponentType<React.ComponentProps<any> & WithTranslationProps>, ResolvedProps = React.JSX.LibraryManagedAttributes< C, $Subtract<React.ComponentProps<C>, WithTranslationProps> >, >( component: C, ) => React.ComponentType<Omit<ResolvedProps, keyof WithTranslation<Ns>> & WithTranslationProps>; export interface I18nextProviderProps { children?: React.ReactNode; i18n: i18n; defaultNS?: string | string[]; } export const I18nextProvider: React.FunctionComponent<I18nextProviderProps>; export const I18nContext: React.Context<{ i18n: i18n }>; export interface TranslationProps< Ns extends FlatNamespace | $Tuple<FlatNamespace> | undefined = undefined, KPrefix extends KeyPrefix<FallbackNs<Ns>> = undefined, > { children: ( t: TFunction<FallbackNs<Ns>, KPrefix>, options: { i18n: i18n; lng: string; }, ready: boolean, ) => React.ReactNode; ns?: Ns; i18n?: i18n; useSuspense?: boolean; keyPrefix?: KPrefix; nsMode?: 'fallback' | 'default'; } export function Translation< Ns extends FlatNamespace | $Tuple<FlatNamespace> | undefined = undefined, KPrefix extends KeyPrefix<FallbackNs<Ns>> = undefined, >(props: TranslationProps<Ns, KPrefix>): any;