react 国际化_React的国际化

慕皓君
2023-12-01

react 国际化

by Preethi Kasireddy

通过Preethi Kasireddy

React的国际化 (Internationalization in React)

Internationalization is a big problem. If you want your application to make a worldwide impact, you have to deal with language barriers.

国际化是一个大问题。 如果您希望您的应用程序对全球产生影响,则必须应对语言障碍。

Unfortunately, the road from “Your funds will arrive by July 7th” to “Vos fonds arriveront le 7 Juillet” is far from simple.

不幸的是,从“您的资金将在7月7日到达”到“ Vos fonds抵达7 Juillet”的路途并非一帆风顺。

Before your application can succeed outside the English-speaking world, you’ll have to adapt all your strings, dates, and numbers to the conventions of different cultures.

在您的应用程序在英语国家以外的地区获得成功之前,您必须使所有字符串,日期和数字适应不同文化的惯例。

Developers call this practice internationalization (which is often abbreviated to “i18n,” because there are 18 letters between the ‘I’ and the ’n’ in the word Internationalization.)

开发商称这种做法国际 (通常缩写为“ 国际化 ”,因为有“ ”和“ ”字 nternationalizatio N的18个字母。)

One reason we overlook internationalization is simply because it’s hard to get right. Every language has different rules and conventions. Adapting to these rules and conventions takes time and effort.

我们忽略国际化的原因之一仅仅是因为很难做到正确。 每种语言都有不同的规则和约定。 适应这些规则和约定需要花费时间和精力。

解决方案:React Intl (The solution: React Intl)

But internationalization doesn’t have to be hard, thanks to a new React library. React Intl is an open-source project from Yahoo, and part of Format.js, a collection of JavaScript libraries for internationalization that builds on Javascript’s built-in Intl API.

但是,由于有了新的React库,国际化并不难。 React Intl是Yahoo的一个开源项目,它是Format.js的一部分, Format.js是基于Javascript的内置Intl API构建的国际化JavaScript库的集合。

The React Intl library makes internalization in React straightforward, with off-the-shelf components and an API that can handle everything from formatting strings, dates, and numbers, to pluralization.

React Intl库提供了现成的组件和一个API,可以处理React中的内部化,该API可以处理从格式化字符串,日期和数字到复数的所有内容。

Let’s give it a walk-through.

让我们来看一下。

核心概念 (Core concepts)

Here are the core concepts you’ll need under your belt to get the most out of React Intl:

要充分利用React Intl,您需要掌握以下核心概念:

JavaScript的国际化API (JavaScript’s Internationalization API)

JavaScript has an Internationalization API specification which defines the Intl object as a standard built-in global object.

JavaScript具有国际化API规范,该规范将Intl对象定义为标准的内置全局对象。

React Intl essentially uses and builds on this API. As long as the browser supports these APIs, React Intl will continue to work its magic.

React Intl本质上使用并以此API为基础。 只要浏览器支持这些API,React Intl就会继续发挥其魔力。

Note: the only browser that doesn’t currently support these APIs is Safari. We’ll use a polyfill to overcome this in the sample project below.

注意:Safari当前是唯一不支持这些API的浏览器。 在下面的示例项目中,我们将使用polyfill来克服这一问题。

模块捆绑器 (Module bundlers)

React Intl distributes its package via ES6, CommonJS, and UMD modules. Hence, it works really well with bundlers like Webpack, Browserify and Rollup.

React Intl通过ES6,CommonJS和UMD模块分发其软件包。 因此,它与Webpack,Browserify和Rollup等捆绑程序一起使用时效果很好。

In the sample project, we’ll be using Webpack as our module bundler.

在示例项目中,我们将使用Webpack作为模块捆绑器。

If you don’t plan to use a module bundler to load React Intl into your application, I recommend the documentation for more information on other approaches (e.g. via Node.js).

如果您不打算使用模块捆绑程序将React Intl加载到您的应用程序中,那么我建议您使用该文档以获取有关其他方法的更多信息(例如,通过Node.js)。

加载区域设置数据 (Loading Locale data)

React Intl relies on this locale data to support plural and relative-time formatting. Locale data defines the following for each specific locale:

React Intl依赖于此语言环境数据来支持复数和相对时间格式。 语言环境数据为每个特定语言环境定义了以下内容:

  • Locale-specific patterns for formatting and parsing dates, times, time zones, numbers and currency values

    特定于语言环境的模式,用于格式化和解析日期,时间,时区,数字和货币值
  • Translations for names of currencies, eras, months, weekdays, etc.

    货币名称,时代,月份,工作日等的翻译。
  • Language and script information (plural cases, characters used, gender of lists, capitalization, writing direction, etc.)

    语言和文字信息(多种情况,使用的字符,列表的性别,大小写,书写方向等)
  • Country information (currency, calendar preference, week conventions, telephone codes, etc.)

    国家信息(货币,日历首选项,星期惯例,电话代码等)

If you’re using Browserify, Webpack or Rollup to bundle React Intl for the browser, it will only contain locale data for basic English by default. The rest of the locale data is not included in the main library. So in this sample project we’ll cover how to import the locale data per language you choose to support in your app.

如果您使用Browserify,Webpack或Rollup为浏览器捆绑React Intl,则默认情况下,它将仅包含基本英语的语言环境数据。 其余的语言环境数据包含在主库中。 因此,在此示例项目中,我们将介绍如何在您选择的应用程序中支持的每种语言下导入语言环境数据。

Keep in mind that if you’re using React Intl via Node.js, all locale data will be loaded into memory, so you can skip this step.

请记住,如果您通过Node.js使用React Intl,则所有语言环境数据都会加载到内存中,因此您可以跳过此步骤。

使用React Components与API格式化数据 (Formatting Data using React Components vs. the API)

The library provides two ways to format strings, numbers, and dates: React components or an API.

该库提供了两种格式化字符串,数字和日期的格式: React 组件API

React Component:

React组件:

API:

API:

I take the first approach whenever possible, using declarative idiomatic-React components to format data over the imperative API.

我会尽可能采用第一种方法,即使用声明性的惯用React组件通过命令式API格式化数据。

The benefit of this approach is that it lets us a) compose components with other components, b) allows for rich text and string formatting, c) provides prop type warnings for formatting options, and d) implements shouldComponentUpdate to avoid costly formatting operations.

这种方法的好处是,它使我们可以:a)与其他组件组成组件,b)允许使用富文本格式和字符串格式,c)为格式选项提供属性类型警告,d)实现shouldComponentUpdate以避免昂贵的格式化操作。

Of course, there are times when your only choice is to use the API (For example: passing a string as a prop, a name attribute of an HTML element, etc.), so it still comes in handy.

当然,有时候您唯一的选择就是使用API​​(例如:将字符串作为道具传递,HTML元素的name属性等),因此它仍然派上用场。

样例项目 (Sample project)

The best way to learn is to see a live example. For this post, I made a simple React project which consists of a main header component, a subheader component, and a few widget components, each with their own headers and body.

最好的学习方法是看一个生动的例子。 在本文中,我制作了一个简单的React项目 ,该项目由一个主要的标头组件,一个子标头组件和一些小部件组成,每个都有自己的标头和正文。

First, we’ll walk through the process of setting up React Intl. Then we’ll use the components and API to convert strings, numbers, and dates used within the components.

首先,我们将逐步完成设置React Intl的过程。 然后,我们将使用组件和API来转换组件中使用的字符串,数字和日期。

配置 (Setting up)

Let’s assume we have an existing React application that we’re working from. First, you’ll need to install the React Intl package:

假设我们有一个正在使用的现有React应用程序。 首先,您需要安装React Intl软件包:

Next, we’ll need to install the babel plugin for React Intl:

接下来,我们需要为React Intl安装babel插件:

To actually have the babel plugin do its magic, we need to set up our .babelrc file to include this plugin. Here’s what my .babelrc looks like with the react-intl plugin added to it (lines 6–11):

为了使babel插件真正发挥作用,我们需要设置.babelrc文件以包含此插件。 这是添加了react-intl插件后的.babelrc的样子(第6-11行):

What this babel plugin does is it extract all the string messages in your application that are defined using either defineMessages, <FormattedMessage>;, or <FormattedHTMLMessage>.

这个babel插件的作用是提取应用程序中所有使用defineMessages<FormattedMessa ge> ;或<FormattedHTM LMessage>定义的字符串消息。

(Note that defineMessages, <FormattedMessage>, and <FormattedHTMLMessage> are all named exports of the React Intl package).

(请注意, defineMessages<FormattedMessa ge> 和<FormattedHTM LMessage>都是React Intl包的命名导出)。

Once extracted, it generates JSON files which contain the string messages and places them in the directory you defined in the messagesDir path above.

提取后,它将生成包含字符串消息的JSON文件,并将其放置在您在上面messagesDir路径中定义的目录中。

加载数据中 (Loading data)

Next, let’s load the appropriate locale data for the languages that we need to support.

接下来,让我们为需要支持的语言加载适当的语言环境数据。

As I mentioned above, if you’re bundling for the browser using Webpack, Browserify or Rollup, React Intl comes English-only by default. So we have to add the other locale data manually.

如前所述,如果您使用Webpack,Browserify或Rollup捆绑浏览器,则默认情况下React Intl仅提供英语。 因此,我们必须手动添加其他语言环境数据。

In the root component file, we add the locale data using the addLocaleData API. The data will then be passed the contents of the locale data module, which will then be registered in its locale data registry.

在根组件文件中,我们使用addLocaleData API添加语言环境数据。 然后将数据传递给区域数据模块的内容,然后将其注册在其区域数据注册表中。

For this sample project, I’m going to assume we’re supporting 4 languages: English, Spanish, French and Italian.

对于此示例项目,我将假设我们支持4种语言:英语,西班牙语,法语和意大利语。

Note: If your app supports a lot more, the recommended approach to adding locale data is to dynamically load the locale data based on the current user’s language. Read the React Intl docs for more info on this approach.

注意 :如果您的应用程序支持更多,则推荐的添加区域设置数据的方法是根据当前用户的语言动态加载区域设置数据。 请阅读React Intl文档以获取有关此方法的更多信息。

在您的React应用程序中创建i18n上下文 (Create the i18n context in your React application)

So far, we’ve installed the React Intl package, set up our .babelrc plugin, and loaded the appropriate locale data.

到目前为止,我们已经安装了React Intl软件包,设置了.babelrc插件,并加载了适当的语言环境数据。

One final step is to create an i18n context for all our React components so that the current user’s locale and translated message (based on the user’s locale) can be loaded into the React Intl Components that you define in your app.

最后一步是为我们所有的React组件创建一个i18n上下文,以便可以将当前用户的语言环境和翻译后的消息(基于用户的语言环境)加载到您在应用中定义的React Intl组件中。

To do this, we first define the messages to pass to IntlProvider based on the user’s locale (see lines 18–26 below). Then we wrap the root React component with IntlProvider, which is a named export provided by React-Intl (see lines 31–33):

为此,我们首先根据用户的区域设置定义要传递给IntlProvider的消息(请参见下面的第18-26行)。 然后,使用IntlProvider包装根React组件该组件是 由React-Intl提供的命名导出(请参阅第31-33行):

In this setup, we’re assuming that our translated data will live in build/locales/data.json and that the data is grouped by language, like so:

在此设置中,我们假设翻译后的数据将位于build / locales / data.json中 ,并且该数据按语言分组,如下所示:

构建脚本进行翻译 (Build a script for translating)

Now that we have the configuration all done, let’s take a look at how we can build a simple script that will grab all the strings that babel extracts for us into multiple JSON files, and combine them into one file.

现在我们已经完成了配置,让我们看一下如何构建一个简单的脚本,该脚本将babel为我们提取的所有字符串捕获到多个JSON文件中,并将它们组合为一个文件。

The point of this script is to accumulate all the English strings so that we can then upload these strings to a translation service, have them be translated into the different languages we support, and then place the results into the build/locales/data.json file we used above. Once there, the IntlProvider component can finally load them into our root component.

该脚本的重点是累积所有英语字符串,以便我们可以随后将这些字符串上载到翻译服务,将它们翻译成我们支持的其他语言,然后将结果放入build / locales / data.json中。我们上面使用的文件。 到达那里之后, IntlProvider组件最终可以将它们加载到我们的根组件中。

Since we don’t need to actually do the translations in this post, we’ll skip this step and just build a script that puts everything in one file. Just remember to loop in a translation service provider in real-world applications :)

由于我们实际上不需要翻译本文,因此我们将跳过此步骤,只构建一个将所有内容放入一个文件的脚本。 只需记住在实际应用中循环使用翻译服务提供商即可:)

All credit goes to the React Intl library authors for generating this script below:

所有功劳归功于React Intl库作者在下面生成此脚本的方式:

使用React Intl转换日期,数字和字符串的步骤 (Steps to convert dates, numbers and strings with React Intl)

Okay — we’re finally ready to do some formatting!

好的-我们终于可以进行格式化了!

The sample app is a simple layout with a header, subheader, and widgets, each of which contains strings, numbers, and/or a dates:

示例应用程序是一个简单的布局,其中包含headersubheader小部件 ,每个小部件都包含字符串,数字和/或日期:

Nothing sophisticated, but it’s enough to get us started.

没什么复杂的,但是足以让我们开始。

First, we’ll look at the header which says: “Welcome to your dashboard, Preethi!”

首先,我们看一下标题为: “欢迎使用仪表板,Preethi!”

To convert this, we’ll use the FormattedMessage component:

要进行转换,我们将使用FormattedMessage组件:

The FormattedMessage component has props that correspond something called a “Message Descriptor” in React Intl. The Message Descriptor is the format used to define default messages/strings, and is useful for providing the data necessary for having the strings/messages translated. It contains the following properties:

FormattedMessage组件具有对应于React Intl中称为“ Message Descriptor ”的道具。 消息描述符是用于定义默认消息/字符串的格式,对于提供转换字符串/消息所需的数据很有用。 它包含以下属性:

  • id: A unique, stable identifier for the message

    id :消息的唯一,稳定的标识符

  • description: Context for the translator about how it’s used in the UI (optional)

    description :翻译器在UI中的使用方式上下文(可选)

  • defaultMessage: The default message (in English)

    defaultMessage :默认消息(英文)

The id prop must be unique for every message defined in your app. What’s awesome is that the defaultMessage can be passed data from the props, as is the case in name above. (Note that the values that are passed as data won’t get translated — they’re simply inserted into the final translated string as-is.)

ID道具对于您应用中定义的每条消息都必须是唯一的。 很棒的是,可以从props传递数据到defaultMessage ,就像上面的名字一样 。 (请注意,作为数据传递的值将不会被翻译,它们只是按原样插入最终的翻译字符串中。)

副标题 (SubHeader)

Next, let’s look at the Subheader, which is slightly more involved:

接下来,让我们看一下Subheader,它稍微复杂一些:

The ability to compose components within other components (i.e. have Formatted* items within another Formatted* item) is a powerful feature of React Intl.

其他组件中撰写组件的能力(即已经格式化另一个格式化 *项中*项目)是发生React国际强大的功能。

You can see in the above example that unreadCount is a FormattedNumber, and notifications is a FormattedPlural, and that both are values passed into FormattedMessages’s defaultMessage. Beautiful!

在上面的示例中,您可以看到unreadCountFormattedNumber通知FormattedPlural ,并且两者都是传递到FormattedMessagesdefaultMessage中的值。 美丽!

Another slick feature is FormattedRelative, which will render the formatted relative time:

另一个巧妙的功能是FormattedRelative ,它将呈现格式化的相对时间:

Once translated and formatted, it will read: “You last logged in 4 hours ago!” (Or however long ago lastLogin was.)

翻译和格式化后,它将显示为: “您上次登录是4小时前!” (或者很久以前,lastLogin是。)

传递格式化的字符串作为组件 (Passing formatted strings as components)

In the above two snippets, we saw how to use the Formatted* Components to define strings, numbers, dates, and pluralization.

在以上两个片段中,我们了解了如何使用Formatted * Components定义字符串,数字,日期和复数形式。

However, there are plenty of instances where it’s necessary to pass formatted strings as props or use formatted strings to name an HTML component. The FormattedMessage component doesn’t well work in cases like this.

但是,在很多情况下,有必要将格式字符串作为prop传递或使用格式字符串命名HTML组件。 在这种情况下, FormattedMessage组件不能很好地工作。

Luckily, React Intl’s defineMessages API lets us imperatively define all of a component’s strings, then pass them as props to the component.

幸运的是,React Intl的defineMessages API使我们能够命令性地定义组件的所有字符串,然后将它们作为prop传递给组件。

Let’s try this approach for the widget headers and body. First, we use defineMessages to define our strings:

让我们为小部件标题和正文尝试这种方法。 首先,我们使用defineMessages定义字符串:

Then, assuming we have a Widget component that expects header and body props, we can continue like so:

然后,假设我们有一个需要标题和正文道具的Widget组件,我们可以像这样继续:

One thing you might have noticed in the first widget is that we can also pass data to the strings defined in defineMessages. Here, we passed the current formatted date as the value date. Pretty neat, huh?

您可能在第一个小部件中注意到的一件事是,我们还可以将数据传递到defineMessages中定义的字符串。 在这里,我们将当前的格式化日期作为值date传递。 很整洁吧?

The API also works well for formatting numbers, dates, times, relative times, and pluralization (check out their docs for more on this)

该API还可以很好地用于格式化数字,日期,时间,相对时间和复数形式(有关更多信息,请查看其文档 )

如何使其在Safari中工作 (How to make it work in Safari)

Now that we’re almost done, I’ll throw one last curve ball at you:

现在我们快完成了,我将向您扔最后一个曲线球:

The current setup will not work for Safari browsers :(

当前设置不适用于Safari浏览器:(

As mentioned above, this is because Safari does not currently have native support for Javascript’s Internationalization API.

如上所述,这是因为Safari当前不支持Javascript的Internationalization API。

Fortunately, there’s still a way to make this work for Safari users. What we need to do is use the Intl polyfill. There are a few different ways to load this in. Let’s continue using Webpack, for the sake of example:

幸运的是,仍然有一种方法可以使Safari用户正常工作。 我们需要做的是使用Intl polyfill 。 有几种不同的加载方法。为了举例,让我们继续使用Webpack:

First, we install the intl package from npm:

首先,我们从npm安装intl软件包:

Next, we’ll write a simple if-statement to only load the polyfill if there is no native browser support for Intl (see lines 30–57). This is to avoid loading the library and all the locale data into your app when not needed.

接下来,我们将编写一个简单的if语句,仅在不支持Intl的本机浏览器时才加载polyfill(请参阅第30-57行)。 这是为了避免在不需要时将库和所有语言环境数据加载到您的应用程序中。

As you can see, the first thing to check is if the intl global is not available on window. If not, then we load the intl polyfill and associated locale data and then render the component. Otherwise, we simply render the component.

如您所见,首先要检查的是intl全局窗口是否不可用。 如果不是,则加载intl polyfill和关联的语言环境数据,然后渲染组件。 否则,我们仅渲染组件。

And at last, here’s our pre-translated app (still in English of course). I’ll leave you with the final step, which is finding a translation provider and getting these strings translated!

最后,这是我们的预翻译应用程序(当然仍然是英语)。 我将为您提供最后一步,这是找到翻译提供商并翻译这些字符串!

其他提示 (Other tips)

I hope this post is enough to start turning your spazzy React application into one that’s amicable to other cultures and languages.

我希望这篇文章足以使您出色的React应用程序变成适合其他文化和语言的应用程序。

Before I sign off, here are a few other tips to consider when internationalizing your app:

在我退出之前,这里是一些国际化您的应用程序时要考虑的其他提示:

  • Flexible components: Build your components such that they are flexible and allow for text expansion and shrinkage. Some languages can expand much larger or shrink much smaller than English. If you don’t account for this, your layout can look unbearable after translation.

    灵活的组件:构建组件时应使其灵活,并允许文本扩展和缩小。 有些语言可以比英语大得多或小很多。 如果您不考虑这一点,那么在翻译后您的布局可能看起来难以忍受。

  • Appropriate font size: Use a font size that will work well with all the languages you support. Some languages, like Japanese and Chinese, need larger font sizes.

    适当的字体大小:使用适合您支持的所有语言的字体大小。 某些语言(例如日语和中文)需要更大的字体。

  • UTF-8: Use UTF-8 everywhere. This includes in your HTML, server-side language, database, etc. Unlike other encodings, UTF-8 encoding handles almost all languages really well.

    UTF-8 :到处都使用UTF-8。 这包括HTML,服务器端语言,数据库等。与其他编码不同,UTF-8编码几乎可以很好地处理所有语言。

  • No text in images: Avoid using text in images because translating text in graphics is extremely difficult, and not worth the pain.

    图像中没有文本:避免在图像中使用文本,因为在图形中翻译文本非常困难,也不值得付出痛苦。

  • Don’t split your strings: For example, if you have “Your funds will arrive by July 7th,” avoid splitting strings like “Your funds will arrive by” and “July 7th”. The combination might only work in English due to word order variations in other languages.

    不要分割字符串:例如,如果您有“您的资金将在7月7日到达”的信息,请避免分割字符串,例如“您的资金将在7月7日到达”和“ 7月7日”。 由于其他语言的字序变化,该组合可能仅适用于英语。

结论 (Conclusion)

As always, feel free to comment with suggestions and questions. I’d love to hear it :)

与往常一样,请随时提出建议和问题。 我很想听听:)

All the code for the sample application can be found on github here: https://github.com/iam-peekay/inbox-react-intl

该示例应用程序的所有代码都可以在github上找到: https : //github.com/iam-peekay/inbox-react-intl

翻译自: https://www.freecodecamp.org/news/internationalization-in-react-7264738274a0/

react 国际化

 类似资料: