返回博客

Storybook 中的国际化 (I18n)

如何在 Storybook 中对组件进行国际化

loading
Shaun Evening
@Integrayshaun
最后更新

在一个应用程序中支持多种语言很棘手。有些语言单词较长,会导致意外的文本溢出。有些语言在不同地区有不同的语言环境——比如英式英语和美式英语。还有一些是从右到左阅读的,这会改变整个页面布局。

面向全球用户的应用程序需要国际化(i18n),即将应用程序针对不同地区进行“本地化”的做法。但国际化 UI 很繁琐。你必须在开发过程中通过手动切换语言偏好来验证应用程序的每种状态在每种支持的语言环境下的情况。

使用 Storybook,你可以将任意语言环境传递给组件,而无需更改浏览器偏好设置,并且只需单击一下即可切换语言环境。本指南将向你展示具体方法。

➕ 在 Storybook 中暴露 i18next 翻译
🎁 使用 i18next Provider 包装 stories
🔘 在工具栏中添加语言环境切换器
👈 添加从右到左的语言支持

我们将构建什么

大多数开发者使用 i18next,这是一个流行的 JavaScript 库,它允许应用程序为每种支持的语言环境定义单独的文件。它会检测用户的语言偏好和地区,并且只加载检测到的语言环境。

语言环境不是作为输入传递给组件,而是通过上下文全局共享。我们将使用 i18next 扩展 Storybook,在工具栏中添加一个语言环境切换器,用于选择与组件共享的语言环境。

请参考 i18next-react GitHub 仓库中的代码示例 进行操作。

Switching locale between English, German, and Arabic in Storybook

前提条件

在我们开始之前,请确保你有一个使用 i18next-react 且已设置 Storybook 6.0 或更新版本的正常运行的 React 应用程序。如果你需要设置这些资源的帮助,我在下面列出了一些建议。

或者如果你喜欢视频,请观看 Chantastic 关于向你的 React 应用添加 i18next 的精彩视频。

1. 向 Storybook 暴露 i18next

为了让你的翻译在 stories 中可用,你需要首先将 i18next 实例暴露给 Storybook。下面是一个在我的 React 应用中使用的 ./src/i18n.js 文件中的 i18next 实例示例。

// src/i18n.js

import i18n from 'i18next';
import Backend from 'i18next-http-backend';
import LanguageDetector from 'i18next-browser-languagedetector';
 
i18n
 .use(Backend) // lazy loads translations from /public/locales
 .use(LanguageDetector) // detect user language
 .init({
   fallbackLng: 'en',
   debug: true,
   interpolation: {
     escapeValue: false,
   },
 });
 
export default i18n;

要将此实例暴露给 Storybook,我们可以将其导入到 ./.storybook/preview.js 文件中,Storybook 在其中保存共享的 story 配置。

// .storybook/preview.js
import i18n from '../src/i18n';

2. 使用 i18next provider 包装你的 stories

既然 Storybook 可以访问 i18next,我们需要将其与我们的 stories 共享。为此,我们将创建一个装饰器来包装我们的 stories。

// .storybook/preview.js
import React, { Suspense } from "react";
import { I18nextProvider } from "react-i18next";
import i18n from '../src/i18n';
 
// Wrap your stories in the I18nextProvider component
const withI18next = (Story) => {
 return (
   // This catches the suspense from components not yet ready (still loading translations)
   // Alternative: set useSuspense to false on i18next.options.react when initializing i18next
   <Suspense fallback={<div>loading translations...</div>}>
     <I18nextProvider i18n={i18n}>
       <Story />
     </I18nextProvider>
   </Suspense>
 );
};
 
// export decorators for storybook to wrap your stories in
export const decorators = [withI18next];

太棒了!我们的 stories 正式可以访问我们的翻译了。如果我们更改 ./src/i18n.js 中定义的 lng,你会看到你的 stories 以新语言重新加载。

Manually changing the locale from English to French

3. 添加语言环境切换器

硬编码语言环境很烦人,对查看你部署的 Storybook 的任何人都没有帮助,所以让我们在 Storybook 工具栏中添加一个语言环境切换器。如果你想了解更多关于切换器的信息,请查阅 Yann Braga 关于添加主题切换器的文章。

为此,我们可以在 .storybook/preview.js 中声明一个名为 locale 的全局变量,并将其分配给一个可供选择的支持语言列表。

// .storybook/preview.js

/* Snipped for brevity */
 
// Create a global variable called locale in storybook
// and add a menu in the toolbar to change your locale
export const globalTypes = {
 locale: {
   name: 'Locale',
   description: 'Internationalization locale',
   toolbar: {
     icon: 'globe',
     items: [
       { value: 'en', title: 'English' },
       { value: 'de', title: 'Deutsch' },
     ],
     showName: true,
   },
 },
};

回过头看 Storybook,我们现在可以看到工具栏中添加了一个“语言环境”切换器,其中包含我们刚刚设置的选项。

The locale switcher in the Storybook toolbar

现在让我们更新我们的装饰器,以便在选择新语言时更改我们的语言环境。

// .storybook/preview.js

/* Snipped for brevity */

const withI18next = (Story, context) => {
 const { locale } = context.globals;
 
 // When the locale global changes
 // Set the new locale in i18n
 useEffect(() => {
   i18n.changeLanguage(locale);
 }, [locale]);
 
 return (
   <Suspense fallback={<div>loading translations...</div>}>
     <I18nextProvider i18n={i18n}>
       <Story />
     </I18nextProvider>
   </Suspense>
 );
};

瞧!一个由 i18next-react 提供支持的、功能齐全的 stories 语言环境切换器!

Switching between English and German using the locale switcher

4. 设置文档方向

有些语言不是像英语那样从左到右阅读的。例如,阿拉伯语是从右到左阅读的。HTML 使用 dir 属性内置支持这一点。

首先,让我们通过在 globalTypes 的 items 数组中添加一个对象,将阿拉伯语添加为我们的语言环境切换器中的一个选项。

// .storybook/preview.js

/* Snipped for brevity */
 
// Create a global variable called locale in storybook
// and add a menu in the toolbar to change your locale
export const globalTypes = {
 locale: {
   name: 'Locale',
   description: 'Internationalization locale',
   toolbar: {
     icon: 'globe',
     items: [
       { value: 'en', title: 'English' },
       { value: 'de', title: 'Deutsch' },
       { value: 'ar', title: 'عربي' },
     ],
     showName: true,
   },
 },
};

使用 i18next 的 dir(lng) 函数和 languageChanged 事件,我们可以为选定的语言环境设置文档方向。

// .storybook/preview.js
 
/* Snipped for brevity */
 
// When The language changes, set the document direction
i18n.on('languageChanged', (locale) => {
 const direction = i18n.dir(locale);
 document.dir = direction;
});

现在,当我们将 storybook 设置为阿拉伯语时,文档方向会设置为 “rtl” 🎉

Switching between English, German, and Arabic with the locale switcher

总结

在 Storybook 中添加语言环境切换器可以让你检查带有更长字符串甚至是从右到左的语言(如阿拉伯语)的组件。

如果你想参考我的 DIY 实现,请查看 i18next-react 的 Storybook 示例。但是,如果你希望有人帮你处理这个问题,请查看 Stevensack 出色的 storybook-react-i18next 插件。

想要更多指南?

我们想听听你的意见!

你喜欢这个指南吗?你还想看到 Storybook 的哪些其他集成指南?

@storybookjs 上发推文或通过 Storybook Discord 服务器与我们联系!我们迫不及待想见到你 🤩

加入 Storybook 邮件列表

获取最新新闻、更新和发布信息

7,180开发者,还在增加

我们正在招聘!

加入 Storybook 和 Chromatic 背后的团队。构建被成千上万开发者用于生产环境的工具。远程优先。

查看职位

热门文章

Storybook 中的 Material UI

利用 Storybook 最大化使用 Material UI 的三个技巧
loading
Shaun Evening

Storybook 对 Vite 的一流支持

Storybook 7.0 带来了许多 Vite 改进:预打包以提高速度,零配置设置,无需 Webpack,以及更小的安装体积。
loading
Ian VanSchooten

社区展示 #3

新主页、视频教程以及面向游戏开发的 Storybook
loading
Varun Vachhar
加入社区
7,180开发者,还在增加
为什么为什么选择 Storybook组件驱动的 UI
文档指南教程更新日志遥测
社区插件参与贡献博客
展示探索项目组件词汇表
开源软件
Storybook - Storybook 中文

特别感谢 Netlify CircleCI