reactjs - react 国际 : async loading just one specific locale data in a Universal App

标签 reactjs internationalization webpack react-intl

我正在使用 React 制作一个多语言通用应用程序,但我很难找到处理区域设置数据的最佳方法。 该应用程序将提供 16 种语言版本,并且翻译的消息量非常大,因此我无法将所有消息加载到一个大 json 中(因为它在大多数 React-intl 示例中使用),而且我也无法将这些消息导入 webpack 生成的包中,我只需要按需加载用户语言消息。 当应用程序仅在客户端运行时我能够做到这一点,但我也需要它在服务器端运行。我使用express 进行服务器端渲染,使用webpack 进行捆绑。谁能帮忙找出解决这个问题的最佳方法吗?

最佳答案

我最近一直在做这样的事情,尽管我的项目中没有SSR。我发现将动态导入语法与 React 的 Suspense 组件配对似乎可以达到我的情况所需的结果。由于您也需要 SSR,因此您的情况可能会有所不同,但以下是我发现对我有用的内容的粗略概述:

// wrap this around your JSX in App.js:
<React.Suspense fallback={<SomeLoadingComponent />}>
  <AsyncIntlProvider>
    {/* app child components go here */}
  </AsyncIntlProvider>
</React.Suspense>

// the rest is in support of this
// can be placed in another file
// simply import AsyncIntlProvider in App.js

const messagesCache = {};

const AsyncIntlProvider = ({ children }) => {
  // replace with your app's locale getting logic
  // if based on something like useState, should kick off re-render and load new message bundle when locale changes
  const locale = getLocale();

  const messages = getMessages(locale);
  return (
    <IntlProvider locale={locale} messages={messages}>
      {children}
    </IntlProvider>
  );
};

function getMessages(locale) {
  if (messagesCache[locale]) {
    return messagesCache[locale];
  }
  // Suspense is based on ErrorBoundary
  // throwing a promise will cause <SomeLoadingComponent /> to render until the promise resolves
  throw loadMessages(locale);
}

async function loadMessages(locale) {
  // dynamic import syntax tells webpack to split this module into its own chunk
  const messages = await import('./path/to/${locale}.json`);
  messagesCache[locale] = messages;
  return messages;
}

Webpack 应该将每个语言环境 JSON 文件分割成自己的 block 。如果没有,则可能会在到达 webpack 之前将动态导入语法转换为不同的模块系统(require 等)。例如:如果使用 Typescript,tsconfig 需要 "module": "esnext" 来保留 import() 语法。如果使用 Babel,它也可能会尝试进行模块转译。

单个语言环境的 block 输出将如下所示:

(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[0],{

/***/ "./path/to/en-US.json":
/*!*************************************!*\
  !*** ./path/to/en-US.json ***!
  \*************************************/
/*! exports provided: message.id, default */
/***/ (function(module) {

eval("module.exports = JSON.parse(\"{\\\"message.id\\\":\\\"Localized message text\\\"}\");//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvbG9jYWxpemF0aW9uL2VuLVVTLmpzb24uanMiLCJzb3VyY2VzIjpbXSwibWFwcGluZ3MiOiIiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./path/to/en-US.json\n");

/***/ })

}]);

希望这有帮助。祝您的项目国际化好运! 😁

关于reactjs - react 国际 : async loading just one specific locale data in a Universal App,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39229381/

相关文章:

apache-flex - 国际化 Flex 应用程序的最佳实践?

javascript - 如何在旧版 Java Web 应用程序中捆绑 js/css

javascript - 将值传递给捆绑的 React JS 文件?

javascript - 动态添加字段到 Formik 表单

c# - 根据 Visual Studio 2013 中的资源文件设置按钮文本

javascript - React - 使用外部 URL 时未定义 Map 函数

grails - Grails 4.0.1-Spock单元测试用例由于空格而失败

javascript - 在生产环境中,Webpack 2.2.0.rc-0 将丑化/缩小vendor.js和manifest.js,但不会丑化/缩小bundle.js

javascript - react : How do I make child components rendered from an array update on parent change?

javascript - 导入第三方库es6