当前位置: 首页 > 面试题库 >

React / Redux和多语言(国际化)应用程序-体系结构

闻人举
2023-03-14
问题内容

我正在构建一个应用程序,它将需要提供多种语言和区域设置。

我的问题不是纯粹的技术问题,而是关于架构以及人们在生产中实际用来解决此问题的模式。我在那里找不到任何“食谱”,所以我转向了我最喜欢的问答网站:)

这是我的要求(它们实际上是“标准”):

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

这是我可以考虑的可能解决方案:

每个组件都独立处理翻译

这意味着每个组件在其旁边都有例如一组en.json,fr.json等文件以及翻译后的字符串。还有一个帮助程序功能,可帮助您根据所选语言从这些值中读取值。

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

每个组成部分都通过道具接收翻译

所以他们不知道当前的语言,他们只是拿一个字符串列表作为道具,恰好匹配当前的语言

  • 优点:由于这些字符串是“自上而下”的,因此可以将它们集中在某个位置
  • 缺点:现在每个组件都已绑定到翻译系统中,您不能只是重复使用一个组件,而是每次都需要指定正确的字符串

您绕过道具了一下,可能是使用 情境啄向下传递当前语言

  • 优点:几乎是透明的,无需始终通过道具传递当前语言和/或翻译
  • 缺点:使用起来很麻烦

如果您还有其他想法,请说!

你怎么做呢?


问题答案:

在尝试了很多解决方案之后,我认为我找到了一个很好的解决方案,并且应该是React 0.14的惯用解决方案(即,它不使用mixins,而是使用高阶组件)(
编辑 :当然,在React 15中也很好! )。

因此,这里是从底部开始的解决方案(各个组件):

组件

根据约定,您的组件唯一需要的是strings道具。它应该是一个包含Component所需的各种字符串的对象,但实际上它的形状取决于您。

它确实包含默认翻译,因此您可以在其他地方使用该组件而无需提供任何翻译(它可以使用默认语言(本例中为英语)开箱即用。

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早期版本的mixins)。

第一个参数是一个密钥,将用于在翻译文件中查找翻译(我在这里使用了组件的名称,但是可以是任何东西)。第二个(注意,该函数已进行咖喱化,以允许使用ES7装饰器)是组件本身的包装。

这是翻译组件的代码:

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()包裹,可以将其分隔开,从而允许其他希望strings按自己的意愿提供的人重用。

[Edit:31/03/2016]:我最近在一个Reactspective
Board(用于敏捷回顾)上工作,它是由React&Redux构建的,并且是多语言的。由于很多人在评论中要求提供真实的示例,因此它是:

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


 类似资料:
  • 我正在构建一个应用程序,它需要有多种语言和地区。 我的问题不是纯粹的技术问题,而是关于架构,以及人们在生产中实际使用的模式来解决这个问题。我在任何地方都找不到这方面的“食谱”,所以我转向我最喜欢的问答网站:) 以下是我的要求(它们实际上是“标准”): 用户可以选择语言(普通) 更改语言后,界面应自动转换为新的选定语言 我不太担心格式化数字、日期等。目前,我想要一个简单的解决方案,只翻译字符串 以下

  • 在这个例子中,我们将每个传递参数显示语言环境。 文件:I18NTester.java - 执行上面示例代码,得到以下输出结果 -

  • 问题内容: 在我当前的项目中,我们正在考虑逐步淘汰旧的表示层,并用更现代,更知名的东西代替它。由于各种原因,选择了JSP作为技术。可能与Apache Tiles结合使用。我也许应该提到,如果这很重要的话,我们将在后面使用Spring。 国际化是一项要求,特别是在以用户语言显示文本消息方面。令我感到惊讶的是,关于这方面的信息并不像我预期的那么多。 我发现的是JSTL 名称空间。特别是与一起使用。但是

  • 目录 4.1 编写适应国际化的应用程序 4.2 使用 POSIX.1 本地语言支持 (NLS) 的本地化消息 4.1 编写适应国际化的应用程序 为了使你的程序对于使用其他语言的用户更加有用, 我们希望你的程序应该国际化。 GNU的gcc编译器和GUI库比如QT或者GTK等通过对字符串的特殊处理来支持国际化。 生成一个支持国际化的程序非常容易。 它使得发布者很快的把你的程序移植成其他语言。 请参看详

  • 问题内容: 我从Google得知,国际化是使我的Web应用程序使用所有语言的过程。我想了解Unicode的国际化过程,所以我从这里到那里了解了Unicode 。 我能够了解Unicode,即如何将一个字符集设置为编码为字节,然后再将字节解码为字符集。但是我不知道如何进一步前进。我想学习如何比较字符串,还需要知道如何在Web应用程序中实现国际化。有什么建议吗?请指导我。 我的目标: 我的主要目标是开

  • 我目前正在开发一个PHP Web应用程序,需要有法语和英语版本。我环顾四周,发现Gettext()功能提供了最好的性能。 我生成了我的。使用命令创建pot文件 并成功地生成了一个。锅铲。我使用PoEdit生成消息。采购订单文件和创建的邮件。瞬间 以下是我的服务器文件: 我在php文件中设置了这样的语言环境: 但我只看到标签,没有看到翻译。。。我试着用'fr_fr'代替'fr_fr.UTF-8'和各