样例参考:
https://github.dev/isaachinman/next-i18next/tree/master/examples/simple

翻译你的 NextJs 应用程序的最简单方法。

如果你在生产中使用 next-i18next,请考虑用你认为合适的金额赞助该软件包。

这是什么?

虽然 NextJs 直接提供了国际化的路由,但它并不处理任何翻译内容的管理,或实际的翻译功能本身。NextJs 所做的只是保持您的地域和 URL 的同步。

作为补充,next-i18next 提供了其余的功能 — 翻译内容的管理,以及翻译你的 React 组件的组件 / 钩子 — 同时完全支持 SSG/SSR、多命名空间、代码分割等。

next-i18next 在后台使用 i18next 和 react-i18next,而 next-i18next 的用户只需要将他们的翻译内容作为 JSON 文件,而不必担心其他问题。

这里有一个现场演示。这个演示应用程序是一个简单的例子 — 仅此而已。

为什么选择 next-i18next?

易于设置,易于使用:设置只需要几个步骤,配置也很简单。

没有其他要求:next-i18next 简化了你的 NextJs 应用程序的国际化,没有额外的依赖性。

生产就绪:next-i18next 支持将翻译和配置选项作为道具传入页面,并支持 SSG/SSR。

它是如何工作的?

你的 next-i18next.config.js 文件将为 next-i18next 提供配置。配置之后,appWithTranslation 允许我们通过钩子在我们的组件中使用 t(翻译)功能。

然后我们将 serverSideTranslation 添加到我们的页面级组件中的 getStaticProps 或 getServerSideProps(取决于你的情况)。

现在,我们的 NextJs 应用程序是完全可翻译的了。

设置

1. 安装

你还需要安装 react 和 next。

2. 翻译内容

默认情况下,next-i18next 希望你的翻译内容是这样组织的。

  1. .
  2. └── public
  3. └── locales
  4. ├── en
  5. | └── common.json
  6. └── de
  7. └── common.json

这个结构也可以在简单的例子中看到。

如果你想以自定义的方式来组织你的翻译 / 命名空间,你需要将修改后的 localePath 和 localeStructure 值传入初始化配置。

3. 项目设置

首先,在你的项目根部创建一个 next-i18next.config.js 文件。嵌套的 i18n 对象的语法直接来自 NextJs。

这将告诉 next-i18next 你的 defaultLocale 和其他语言是什么,以便它可以在服务器上预装翻译。

next-i18next.config.js

  1. module.exports = {
  2. i18n: {
  3. defaultLocale: 'en',
  4. locales: ['en', 'de'],
  5. },
  6. };

现在,创建或修改你的 next.config.js 文件,将 i18n 对象传入你的 next.config.js 文件,以启用本地化的 URL 路由。

[next.config.js](https://nextjs.org/docs/api-reference/next.config.js/introduction)

  1. const { i18n } = require('./next-i18next.config');
  2. module.exports = {
  3. i18n,
  4. };

next-i18next 输出了三个函数,你需要用它们来翻译你的项目。

appWithTranslation

这是一个包装你的_app 的 HOC。

  1. import { appWithTranslation } from 'next-i18next';
  2. const MyApp = ({ Component, pageProps }) => <Component {...pageProps} />;
  3. export default appWithTranslation(MyApp);

appWithTranslation HOC 主要负责添加一个 I18nextProvider。

serverSideTranslations

这是一个异步函数,你需要通过 getStaticProps 或 getServerSideProps(取决于你的使用情况)在你的页面级组件中加入。

  1. import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
  2. export async function getStaticProps({ locale }) {
  3. return {
  4. props: {
  5. ...(await serverSideTranslations(locale, ['common', 'footer'])),
  6. // Will be passed to the page component as props
  7. },
  8. };
  9. }

请注意,serverSideTranslations 必须从 next-i18next/serverSideTranslations 导入 — 这是一个单独的模块,包含 NodeJs 特定的代码。

另外,注意 serverSideTranslations 与 getInitialProps 不兼容,因为它只能在服务器环境下执行,而 getInitialProps 是在客户端在页面间导航时调用。

serverSideTranslations HOC 主要负责将翻译和配置选项作为道具传入页面 — 你需要将其添加到任何有翻译的页面。

useTranslation

这是一个钩子,你将实际用来做翻译本身。useTranslation 钩子来自 react-i18next,但也可以直接从 next-i18next 导入。

  1. import { useTranslation } from 'next-i18next';
  2. export const Footer = () => {
  3. const { t } = useTranslation('footer');
  4. return (
  5. <footer>
  6. <p>{t('description')}</p>
  7. </footer>
  8. );
  9. };

4. 声明命名空间的依赖性

默认情况下,next-i18next 会在每次初始请求时将你的所有命名空间下发到客户端。对于内容较少的小型应用程序来说,这可能是一个合适的方法,但很多应用程序将受益于基于路由的命名空间的分割。

要做到这一点,你可以将每个页面所需的命名空间数组传递给 serverSideTranslations。你可以在 examples/simple/pages/index.js 中看到这种方法。传入一个所需命名空间的空数组将不发送任何命名空间。

注意:useTranslation 为你使用它的组件提供命名空间。然而,serverSideTranslations 为整个 React 树提供总的可用命名空间,属于页面级别。两者都是必需的。

5. 高级配置

传递其他配置选项

如果你需要修改更多的高级配置选项,你可以通过 next-i18next.config.js 传递它们。比如说。

  1. const path = require('path');
  2. module.exports = {
  3. i18n: {
  4. defaultLocale: 'en',
  5. locales: ['en', 'de'],
  6. },
  7. localePath: path.resolve('./my/custom/path'),
  8. };

不可序列化的配置

一些 i18next 插件(你可以传入 config.use)是不可序列化的,因为它们包含函数和其他 JavaScript 原语。

如果你的用例比较高级,你可能会遇到这种情况。你会看到 NextJs 抛出一个错误,比如。

  1. Error: Error serializing `._nextI18Next.userConfig.use[0].process` returned from `getStaticProps` in "/my-page".
  2. Reason: `function` cannot be serialized as JSON. Please only return JSON serializable data types.

要解决这个问题,你需要将 config.serializeConfig 设置为 false,并手动将你的配置传入 appWithTranslation。

  1. import { appWithTranslation } from 'next-i18next';
  2. import nextI18NextConfig from '../next-i18next.config.js';
  3. const MyApp = ({ Component, pageProps }) => <Component {...pageProps} />;
  4. export default appWithTranslation(MyApp, nextI18NextConfig);
  1. import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
  2. import nextI18NextConfig from '../next-i18next.config.js';
  3. export const getStaticProps = async ({ locale }) => ({
  4. props: {
  5. ...(await serverSideTranslations(
  6. locale,
  7. ['common', 'footer'],
  8. nextI18NextConfig
  9. )),
  10. },
  11. });

在开发中重新加载资源

因为资源在服务器启动时被加载一次,所以在开发中对翻译 JSON 文件所做的任何修改都不会被加载,直到服务器重新启动。

在生产中,这往往不是一个问题,但在开发中,你可能希望看到你的翻译 JSON 文件的更新,而不必每次都重新启动你的开发服务器。要做到这一点,请将 reloadOnPrerender 配置选项设置为 true。

这个选项将在 serverSideTranslations 被调用时(在 getStaticProps 或 getServerSideProps 中)重新加载你的翻译。如果你在 getServerSideProps 中使用 serverSideTranslations,建议在生产环境中禁用 reloadOnPrerender,以避免在每次调用服务器时重新加载资源。

选项

Options

Key Default value
defaultNS ‘common’
localeExtension ‘json’
localePath ‘./public/locales’
localeStructure ‘{{lng}}/{{ns}}’
reloadOnPrerender false
serializeConfig true
strictMode true
use (for plugins) []
键值 默认值
默认 NS '普通'。
localeExtension 'json'。
localePath './public/locales'
定位结构(localeStructure '{{lng}}/{{ns}}'
渲染时重新加载 错误
序列化配置(serializeConfig true
严格模式 true
使用 (对于插件) []

所有其他的 i18next 选项也可以被传入。

客户端动态加载命名空间

在一些用例中,你可能想动态加载翻译文件,而不需要使用 serverSideTranslations。这对于你不希望拖慢页面的懒惰加载的组件特别有用。

这可以通过使用 addResourceBundle 轻松实现。

  1. import { i18n } from 'next-i18next'
  2. const Component = () => {
  3. const { locale } = useRouter()
  4. useEffect(() => {
  5. i18n.addResourceBundle(locale, '<namespace name>')
  6. }, [])
  7. }

迁移到 V8

要从以前的版本迁移到第 8 版,请查看 v8 - 迁移指南。

注释

Vercel 和 Netlify

一些无服务器 PaaS 可能无法定位你的翻译路径,需要额外配置。如果你在使用 serverSideTranslations 时遇到文件系统问题,可以将 config.localePath 设置为使用 path.resolve。这里可以找到一个例子。

Docker

对于 Docker 部署,注意如果你使用 Next.js 文档中的 Dockerfile,不要忘记将 next.config.js 和 next-i18next.config.js 复制到 Docker 镜像中。

  1. COPY --from=builder /app/next.config.js ./next.config.js
  2. COPY --from=builder /app/next-i18next.config.js ./next-i18next.config.js

异步的 i18next 后端

如果你选择使用不同于内置 i18next-fs-backend 的 i18next 后端,你需要确保翻译资源在你调用 t 函数之前已经加载。由于 React suspense 还不支持 SSR,这可以通过 2 种不同的方式解决。

1)预装命名空间。

设置 ns 选项,就像这个例子中一样。这样做将确保所有翻译资源在初始化时被加载。

2)检查就绪标志。

如果你不能或不想提供 ns 数组,对 t 函数的调用将导致命名空间被即时加载。这意味着你需要通过检查 ready === true 或 props.tReady === true 来处理 “未就绪” 状态。不这样做会导致在翻译加载之前渲染你的翻译,这将导致 “保存丢失” 被调用,尽管翻译实际存在(只是还没有加载)。这可以通过 useTranslation 钩子或 withTranslation HOC 来实现。

https://github.com/isaachinman/next-i18next