React/Redux和多语言(国际化)应用程序 – 架构

前端之家收集整理的这篇文章主要介绍了React/Redux和多语言(国际化)应用程序 – 架构前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在构建一个应用程序,需要有多种语言和区域设置。

我的问题不是纯粹的技术,而是关于建筑,以及人们实际在生产中使用的模式来解决这个问题。
我找不到任何地方任何“食谱”,所以我转向我最喜欢的Q / A网站:)

这里是我的要求(他们真的是“标准”):

>用户可以选择语言(平凡)
>更改语言后,界面应自动翻译为新的所选语言
>我不是太担心格式化数字,日期等,在这一刻,我想要一个简单的解决方案,只是翻译字符串

下面是我可以想到的可能的解决方案:

每个组件单独处理翻译

这意味着每个组件都有例如一组en.json,fr.json等文件以及翻译的字符串。以及帮助函数,帮助读取取决于所选语言的值。

> Pro:更尊重React的理念,每个组件都是“独立”
>缺点:您无法将所有翻译集中在文件中(例如要让其他人添加新语言)
>缺点:你仍然需要传递当前语言作为道具,在每个血腥的组件和他们的孩子

每个组件通过道具接收翻译

所以他们不知道当前的语言,他们只是把字符串列表作为道具,碰巧匹配当前语言

> Pro:因为那些字符串来自“顶部”,所以它们可以集中在某个地方
>缺点:每个组件现在绑定到翻译系统,你不能只是重复使用,你需要每次指定正确的字符串

你绕过道具有点,可能使用context东西传递当前语言

> Pro:它大部分是透明的,不必通过道具通过当前语言和/或翻译所有的时间
>缺点:使用看起来很麻烦

如果你有其他想法,请说!

你怎么做呢?

在尝试了相当多的解决方案后,我想我发现一个工作良好,应该是React 0.14的一个惯用的解决方案(即它不使用mixins,但高阶组件)(编辑:也完全精细React 15当然! )。

所以这里的解决方案,从底部开始(单个组件):

组件

你的组件唯一需要的(按照惯例),是一个字符串道具。
它应该是一个包含你的组件需要的各种字符串的对象,但真正的形状是由你决定的。

它包含默认翻译,所以你可以使用其他地方的组件,而不需要提供任何翻译(它将使用默认语言,在这个例子中的英语框)

import { default as React,PropTypes } from 'react';
import translate from './translate';

class MyComponent extends React.Component {
    render() {

        return (
             <div>
                { this.props.strings.someTranslatedText }
             </div>
        );
    }
}

MyComponent.propTypes = {
    strings: PropTypes.object
};

MyComponent.defaultProps = {
     strings: {
         someTranslatedText: 'Hello World'
    }
};

export default translate('MyComponent')(MyComponent);

高阶组件

在上一个片段中,您可能已经在最后一行注意到了这一点:
translate(‘MyComponent’)(MyComponent)

在这种情况下,translate是一个高阶组件,它包装你的组件,并提供一些额外的功能(这个结构取代了以前的React版本的混合)。

第一个参数是一个键,用于查找翻译文件中的翻译(我在这里使用了组件的名称,但它可以是任何东西)。第二个(注意函数是curryed,允许ES7装饰器)是组件自身要包装。

这里是translate组件的代码

import { default as React } from 'react';
import en from '../i18n/en';
import fr from '../i18n/fr';

const languages = {
    en,fr
};

export default function translate(key) {
    return Component => {
        class TranslationComponent extends React.Component {
            render() {
                console.log('current language: ',this.context.currentLanguage);
                var strings = languages[this.context.currentLanguage][key];
                return <Component {...this.props} {...this.state} strings={strings} />;
            }
        }

        TranslationComponent.contextTypes = {
            currentLanguage: React.PropTypes.string
        };

        return TranslationComponent;
    };
}

这不是魔术:它只是从上下文中读取当前语言(并且上下文不会在整个代码库中流出,只是在这个包装器中使用),然后从加载的文件获取相关的字符串对象。这个逻辑在这个例子中是相当朴素的,可以按照你想要的方式做。

重要的是,它从上下文中获取当前语言,并将其转换为字符串,给定所提供的键。

在层次结构的最顶端

在根组件上,您只需要从当前状态设置当前语言。以下示例使用Redux作为Flux类实现,但它可以很容易地使用任何其他框架/模式/库进行转换。

import { default as React,PropTypes } from 'react';
import Menu from '../components/Menu';
import { connect } from 'react-redux';
import { changeLanguage } from '../state/lang';

class App extends React.Component {
    render() {
        return (
            <div>
                <Menu onLanguageChange={this.props.changeLanguage}/>
                <div className="">
                    {this.props.children}
                </div>

            </div>

        );
    }

    getChildContext() {
        return {
            currentLanguage: this.props.currentLanguage
        };
    }
}

App.propTypes = {
    children: PropTypes.object.isrequired,};

App.childContextTypes = {
    currentLanguage: PropTypes.string.isrequired
};

function select(state){
    return {user: state.auth.user,currentLanguage: state.lang.current};
}

function mapDispatchToProps(dispatch){
    return {
        changeLanguage: (lang) => dispatch(changeLanguage(lang))
    };
}

export default connect(select,mapDispatchToProps)(App);

并完成,翻译文件

翻译文件

// en.js
export default {
    MyComponent: {
        someTranslatedText: 'Hello World'
    },SomeOtherComponent: {
        foo: 'bar'
    }
};

// fr.js
export default {
    MyComponent: {
        someTranslatedText: 'Salut le monde'
    },SomeOtherComponent: {
        foo: 'bar mais en français'
    }
};

你们有什么感想?

我认为是解决所有的问题,我试图避免在我的问题:翻译逻辑不会泄漏所有的源代码,它是相当孤立,允许重复使用组件没有它。

例如,MyComponent不需要被translate()包装,并且可以是单独的,允许任何想要以自己的意思提供字符串的人重用它。

[编辑:31/03/2016]:我最近在一个回顾董事会(敏捷回顾),用React& Redux,并且是多语言的。
由于很多人在评论中要求一个现实生活的例子,这里是:

你可以在这里找到代码https://github.com/antoinejaussoin/retro-board/tree/master

猜你在找的React相关文章