import { catalogs , DEFAULT_LOCALE , ICatalog , ILocale , TODO_IMPLEMENTATION_MSG , } from "i18n/catalog" ; import { ENGLISH } from "i18n/english" ; import React from "react" ; import ENV from "tools/client-env" ; /** ===========================================================================
 * Types & Config
 * ============================================================================
 */ export type tFn = ( ... text : ENGLISH ) => ReadonlyArray < JSX . Element > ; export type tFnString = ( ... text : ENGLISH ) => string ; export type tReturnType = ReadonlyArray < JSX . Element > | string ; export interface TranslateMethodProps { t : tFn ; tString : tFnString ; } interface I18nTranslateProps extends TranslateMethodProps { locale : ILocale ; } export interface I18nProps { i18n : I18nTranslateProps ; setLocale : ( locale : ILocale ) => void ; } /** ===========================================================================
 * Utils
 * ============================================================================
 */ /**
 * Get a catalog given a locale if it exists, otherwise return the default
 * locale.
 */ export const getCatalogFromLocale = ( locale ) : ICatalog => { if ( locale in catalogs ) { return catalogs [ locale ] . catalog ; } return catalogs [ DEFAULT_LOCALE ] . catalog ; } ; const INTERPOLATION_PATTERN = new RegExp ( /\{\{(.*?)\}\}/g ) ; /**
 * Helper to parse the i18n input.
 */ const parseCatalogInput = ( input , catalog ) => { const [ t , ... rest ] = input ; const variables = rest [ 0 ] ; if ( ! ( t in catalog ) ) { if ( ENV . DEVELOPMENT ) { throw new Error ( `No match for i18n text input: ${ t }` ) ; } else { /**
             * NOTE: In production allow fallback to the English key! This is
             * to allow us to more quickly ship updates to the app text content,
             * but will result in "broken" internationalized versions of the
             * app.
             */ const text = t . split ( INTERPOLATION_PATTERN ) ; return { text , variables , } ; } } const value = catalog [ t ] ; if ( value === TODO_IMPLEMENTATION_MSG ) { /**
         * This shouldn't happen but if it does just fallback to the original
         * English string value.
         */ const text = t . split ( INTERPOLATION_PATTERN ) ; return { text , variables } ; } else { const text = value . split ( INTERPOLATION_PATTERN ) ; return { text , variables } ; } } ; /**
 * This methods returns a translation method given a locale which interpolates
 * translations values for text internationalization.
 */ export const createTranslationMethodFromLocale = ( catalog ) => ( ... input ) : ReadonlyArray < JSX . Element > => { const { text , variables } = parseCatalogInput ( input , catalog ) ; return text . filter ( Boolean ) . map ( ( match , index ) => { let interpolated ; if ( variables && match in variables ) { interpolated = variables [ match as keyof ENGLISH [ 1 ] ] ; } else { interpolated = match ; } return < span key = { index } > { interpolated } < /span>; } ) ; } ; /**
 * The same method as above but this method explicitly returns a string. This
 * is to make it easier to use the i18n-utils for components where the
 * translated text must be a string value. This method will throw an error
 * if it receives a dynamic non-string value for an interpolated variable.
 */ export const createStringTranslationMethodFromLocale = ( catalog ) => ( ... input ) : string => { const { text , variables } = parseCatalogInput ( input , catalog ) ; return text . filter ( Boolean ) . map ( ( match ) => { let interpolated ; if ( variables && match in variables ) { interpolated = variables [ match as keyof ENGLISH [ 1 ] ] ; } else { interpolated = match ; } if ( typeof interpolated !== "string" ) { throw new Error ( `Trying to interpolate non-string value in tString function, value: ${ interpolated }` ) ; } return interpolated ; } ) . reduce ( ( str , itr ) => str + itr , "" ) ; } ; /**
 * Helper to wrap some text string in bold attributes.
 */ export const bold = ( s ) : JSX . Element => < b > { s } < /b>;