如何在连接的组件中使用 react-i18next

23

我希望能够在我的react-redux连接组件中使用react-i18next,但不确定该如何操作。

为了展示一个连接组件的例子,我已经简化了我的代码:

import React from 'react';
import {connect} from 'react-redux';
import {userSelectors} from "./userSelectors";

interface IConnectedProps {
    activeUserName: string | undefined;
}
export class LandingPageComponent extends React.Component<IConnectedProps> {
    public render(): JSX.Element {
        return (
            <React.Suspense fallback={<Spinner/>}>
                <React.Fragment>
                    <div>
                    ... a bunch of controls using translated text
                    </div>
                    <div>{activeUserName}</div>
                </React.Fragment>
            </React.Suspense>
        );
    }
}

const mapStateToProps = (state: ICoreRootState) : IConnectedProps => ({
    activeUserName: userSelectors.getDisplayName(state),
});

export const LandingPage = connect(mapStateToProps)(LandingPageComponent);

安装的软件包版本:
react version: 16.8.4 
react-redux version: 5.1.1 
react-i18next version: 10.6.0

我将尝试:

1)使用以下withTranslation、WithTranslation时,出现以下错误:

export class LandingPageComponent extends React.Component<IConnectedProps & WithTranslation> {...}
export const LandingPage = connect(mapStateToProps)(withTranslation()(LandingPageComponent));

错误:

The above error occurred in the <withI18nextTranslation(LandingPageComponent)> component:
    in withI18nextTranslation(LandingPageComponent) (created by Connect(withI18nextTranslation(LandingPageComponent)))
    in Connect(withI18nextTranslation(LandingPageComponent))
    in Route
    in t
    in Connect(t) (at App.tsx:49)
    in Switch (at App.tsx:45)
    in App (at src/index.tsx:14)
    in Router (created by ConnectedRouter)
    in ConnectedRouter (created by Connect(ConnectedRouter))
    in Connect(ConnectedRouter) (at src/index.tsx:13)
    in Provider (at src/index.tsx:12)

2) 当我使用withTranslation和WithTranslation时,会出现以下错误:

export class LandingPageComponent extends React.Component<IConnectedProps & WithTranslation> {...}
export const LandingPage = withTranslation()(connect(mapStateToProps)(LandingPageComponent));

错误:

index.js:1446 The above error occurred in the <withI18nextTranslation(Connect(LandingPageComponent))> component:
    in withI18nextTranslation(Connect(LandingPageComponent))
    in Route
    in t
    in Connect(t) (at App.tsx:49)
    in Switch (at App.tsx:45)
    in App (at src/index.tsx:14)
    in Router (created by ConnectedRouter)
    in ConnectedRouter (created by Connect(ConnectedRouter))
    in Connect(ConnectedRouter) (at src/index.tsx:13)
    in Provider (at src/index.tsx:12)

3) 由于 hook 不能在类中使用,因此我无法使用 useTranslation。

我还尝试了以下方法:

... a bunch of imports
interface ILogoutButtonProps {
    userName?: string;
}
interface IConnectedHandlers {
    readonly logout: any;
    readonly push: any;
}
class InnerLogoutComponent extends React.Component<IButtonProps & IConnectedHandlers & ILogoutButtonProps & WithTranslation, {}> {

    public render() {
        const {userName, onClick, logout: Logout, push: Push, ...buttonProps} = this.props;
        const logoutText = this.props.i18n.t(StringNames.logout);
        const buttonText = userName ? logoutText + " " + userName : logoutText;
        return (
            <Button {...buttonProps} text={buttonText} onClick={this.handleClick}/>
        );
    }

    private handleClick = (event: React.MouseEvent<HTMLElement>) : void => {
        this.props.logout()
            .then(() => this.props.push(LoginPaths.verifyUser));
    }
}
const InnerLogoutTranslatedComponent = withTranslation()(InnerLogoutComponent);

class LogoutComponentInternal extends React.Component<IButtonProps & IConnectedHandlers & ILogoutButtonProps, {}> {
    public render () {
        return (
            <InnerLogoutTranslatedComponent {...this.props}/>
        );
    }
}
export const LogoutComponent = connect(null,{logout, push})(LogoutComponentInternal);

但是我遇到了以下错误:
Hooks can only be called inside the body of a function component. 

Thank you in advance...


2
你还没有分享实际的错误信息,这只是错误堆栈跟踪信息。 - Shubham Khatri
5个回答

5
在我们的项目中,我们成功地利用了这个:
import { compose } from 'redux';
import { withNamespaces } from 'react-i18next';
import { connect } from 'react-redux';
...
export default compose(withNamespaces('translation'), connect(mapStateToProps))(ComponentName);

通过使用mapStateToProps,我们将连接到Redux并获得translations


4

我正在使用RazzleJS中的SSR技术,目前情况良好。我将connectwithTranslation连接在一起,方法如下:

export default connect(mapStateToProps,mapDispatchToProps)(withTranslation()(Component));

1
这对我有效:

export default withTranslation()(connect(mapStateToProps, mapDispatchToProps)(Component));

0

0

我实际上有些困难,无法确定您在HOC中包装组件的顺序。在我目前工作的项目中,我们像这样包装:withNamespaces(connect(withStyles(component))),这非常有效(withNamespaces本质上与withTranslations相同)。当我们尝试连接一个翻译组件时,我们遇到了问题,您可能正在经历同样的问题。因此,以下是我们的做法:

您有一个“普通”的组件,如下所示:

type InjectedProps = StateProps & ExternalProps & MyComponentsTranslations
export class MyComponent extends React.Component<InjectedProps> {
    ...
} 

(注意:使用函数式组件的过程完全相同)
您可以使用以下代码连接组件:const MyConnectedComponent = connect(mapStateToProps, mapDispatchToProps)(MyComponent) 最后,执行
import {WithNamespaces, withNamespaces} from "react-i18next"
export const LocalizedMyComponent = withNamespaces()(
  ({t,...rest}): WithNamepsaces) => (
    <MyConnectedComponent translations={{ put translations here }} {...rest} />
  )
)

现在,诀窍在于我们定义了一个 interface MyComponentsTranslations {},在其中放置所有所需的翻译或翻译函数(在复数情况下)。
MyComponentsTranslations 添加到 InjectedProps 中,以使它们在原始组件中可用。
您始终可以简单地将 i18n 的 t 函数注入到您的组件中,但在我的当前项目中,我们决定这样做更加清晰:
  • 明确命名组件所需的翻译
  • 由于原始组件和连接的组件都不依赖于 t 函数,因此它们很容易进行测试
如果这对您有用,请告诉我。
另外,为了使整个过程更加优雅,您可以使用以下帮助程序:
export interface Translations<T> {
  translations: T
}

export const createTranslations = <T>(translations: T): Translations<T> => ({
  translations,
})

这允许您进行设置

type InjectedProps = StateProps & Translations<MyComponentTranslations>

并且在 withNamespace 高阶组件中:

<MyConnectedComponent {...createTranslations<MyComponentTranslations>({ put translations here })} {...rest} />

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接