使用 i18next 创建 React 应用程序 - 从 json 文件加载翻译

Create react app with i18next - load translations from json file

我正在尝试使用多种语言配置我的 React 应用程序。为此,我使用 i18next 进行反应。我的配置文件是:

i18n.ts

import i18next from 'i18next';
import { initReactI18next } from 'react-i18next';
import XHR from 'i18next-xhr-backend';

const backendOptions = {
    loadPath: '/locales/{{lng}}.json',
    crossDomain: true,
};

i18next
    .use(initReactI18next)
    .use(XHR)
    .init({
        backend: backendOptions,
        debug: true,
        lng: 'en_GB',
        fallbackLng: false,
        react: {
            wait: true
        }
    });

export default i18next;

我的翻译在(示例路径)public/locales/en_GB.json

在我的 index.tsx 中,我使用 import './i18n';

导入配置

我的实际组件的用法如下所示:

tab-bar.tsx

interface TabBarInterface {
    value: number;
}

class TabBar extends React.Component<WithTranslation, TabBarInterface> {

    public tabs: Array<boolean | string>;

    constructor(props: any) {
        super(props);
        const { t } = this.props;
        this.state = { value: 0, isExModeAvailable: true };

        this.tabs = [
            t('SID_RHMI_BYOD_INFO'),
            t('SID_RHMI_BYOD_MEDIA'),
            t('SID_RHMI_BYOD_CLIMATE')
        ].filter(Boolean);
    }

    handleChange = (event: ChangeEvent<{}>, value: number) => {
        this.setState({ value });
    };

    handleChangeIndex = (value: number) => {
        this.setState({ value });
    };

    render() {
        const { classes } = this.props;
        const { value } = this.state;

        return (
            <div className={classes.root}>
                <AppBar className={classes.appBar} position="relative">
                    <Tabs value={value} indicatorColor="primary" textColor="primary"
                          classes={{
                              scrollButtons: classes.scrollBtn,
                              flexContainer: classes.tabsContainer
                          }} onChange={this.handleChange}>
                        {
                            this.tabs.map((label, key) =>
                                <Tab className={classes.tab} label={label} key={key}/>)
                        }

                    </Tabs>
                </AppBar>
                <SwipeableViews index={value} onChangeIndex={this.handleChangeIndex}>
                    <JourneyInfo/>
                    <div>Item Two</div>
                    <div>Item Three</div>
                    <div>Item Four</div>
                </SwipeableViews>
            </div>
        );
    }
}

export default (withTranslation()(TabBar));

我还可以看到翻译文件已成功加载,但 cra 抛出此错误:

index.js:1437 The above error occurred in the <withI18nextTranslation(TabBar)> component:
    in withI18nextTranslation(TabBar) (created by WithStyles(withI18nextTranslation(TabBar)))
    in WithStyles(withI18nextTranslation(TabBar)) (at app.tsx:11)
    in div (at app.tsx:10)
    in ThemeProvider (at app.tsx:9)
    in App (at src/index.tsx:7)
...
Consider adding an error boundary to your tree to customize error handling behavior.

...
Add a <Suspense fallback=...> component higher in the tree to provide a loading indicator or placeholder to display.
    in withI18nextTranslation(TabBar) (created by WithStyles(withI18nextTranslation(TabBar)))
  ...  
logger.js:21 i18next::backendConnector: loaded namespace translation for language en_GB {SID_TITLE: "Bring Your Own Device", SID_TITLE_REMOTE_CONTROL: "Remote Control", SID_RHMI_BYOD_BANNER: "Controlling of vehicle functions active.", SID_RHMI_BYOD_BANNER_DETAIL: "Connected Command activated on {{device name}}. No…n control vehicle functions as playback or sound.", SID_RHMI_BYOD_CID_REMOVE_PERMISSION: "You can manage the permissions for Connected Comma… the menu "Communication" under "Mobile devices".", …}
logger.js:21 i18next: languageChanged en_GB
logger.js:21 i18next: initialized {debug: true, initImmediate: true, ns: Array(1), defaultNS: Array(1), fallbackLng: false, …}

由于 i18next-xhr-backend-插件通过 xhr 请求异步加载 json 文件。视图已加载,而请求中的数据尚未加载完毕。解决方案:

import i18n from './i18n';
import './index.scss';
import React from 'react';
import ReactDOM from 'react-dom';
import App from './modules/app/app/app';

i18n.init().then(
    () => ReactDOM.render(<App />, document.getElementById('root'))
);