中文

学习如何在您的 Next.js 应用中实现无缝的国际化 (i18n),以触达全球受众。内容涵盖路由、内容翻译和最佳实践。

Next.js 国际化:构建面向全球受众的多语言应用

在当今这个互联互通的世界里,构建能够满足全球受众需求的应用不再是奢侈品,而是一种必需。Next.js,一个强大的 React 框架,为实现国际化 (i18n) 提供了强大的功能,让您能够创建多语言应用,为全球用户提供本地化的体验。本综合指南将引导您了解构建国际化 Next.js 应用的基本概念、技术和最佳实践。

理解国际化与本地化

在深入探讨 Next.js i18n 的具体细节之前,让我们先明确几个关键术语:

从本质上讲,i18n 是为您的应用程序进行本地化做准备。通过将依赖于语言的元素与核心代码分离,您可以更轻松地为不同市场对应用程序进行本地化。

为什么要在 Next.js 中实现国际化?

在您的 Next.js 应用中实现 i18n 会带来诸多好处:

Next.js 的 i18n 功能与配置

Next.js 通过其路由和内容管理功能为 i18n 提供了内置支持。以下是重要功能的分解说明:

1. 在 next.config.js 中配置 i18n

i18n 的核心配置位于 next.config.js 文件中。示例如下:


/** @type {import('next').NextConfig} */
const nextConfig = {
  i18n: {
    locales: ['en', 'es', 'fr'], // 支持的区域设置(语言代码)数组
    defaultLocale: 'en', // 要使用的默认区域设置
    localeDetection: true, // 启用/禁用基于浏览器设置的自动区域检测(可选)
    //  domains: [
    //  {
    //    domain: 'example.com',
    //    defaultLocale: 'en',
    //  },
    //  {
    //    domain: 'example.es',
    //    defaultLocale: 'es',
    //  },
    //  ],
  },
}

module.exports = nextConfig;

说明:

2. 使用区域设置前缀进行路由

Next.js 会自动为路由添加区域设置前缀。例如,如果您有一个位于 /about 的页面,并且区域设置为 'es'(西班牙语),那么 URL 将变为 /es/about。这使得页面的不同语言版本成为可能,并能让搜索引擎为每个区域设置索引内容。框架会为您处理重定向和路由。

3. 使用 useRouter 钩子

来自 next/routeruseRouter 钩子提供了对当前区域设置和其他路由信息的访问。


import { useRouter } from 'next/router';

function MyComponent() {
  const router = useRouter();
  const { locale, locales, defaultLocale } = router;

  return (
    

Current locale: {locale}

Available locales: {locales.join(', ')}

Default locale: {defaultLocale}

); } export default MyComponent;

router 对象提供了以下关键属性:

内容翻译策略

为 Next.js 应用配置好 i18n 后,您需要实施策略来翻译您的内容。以下是几种流行的方法:

1. 使用专门的翻译管理系统 (TMS)

对于拥有多种语言的大型项目,强烈建议使用 TMS。流行的选项包括:

优点:

2. 创建 JSON 翻译文件

对于较小的项目,使用 JSON 文件存储翻译是一种简单有效的方法。

目录结构示例:


/src
├── locales
│   ├── en.json
│   └── es.json
├── components
│   └── MyComponent.js
└── pages
    └── index.js

en.json 示例:


{
  "greeting": "Hello, world!",
  "welcomeMessage": "Welcome to our website."
}

es.json 示例:


{
  "greeting": "¡Hola, mundo!",
  "welcomeMessage": "Bienvenido a nuestro sitio web."
}

MyComponent.js 示例:


import { useRouter } from 'next/router';
import en from '../locales/en.json';
import es from '../locales/es.json';

function MyComponent() {
  const { locale } = useRouter();
  const t = locale === 'es' ? es : en;

  return (
    

{t.greeting}

{t.welcomeMessage}

); } export default MyComponent;

这种方法提供了灵活性,并且对于小型项目而言简单明了。通常易于更新和维护。

3. 使用翻译库

有几个 JavaScript 库可以简化您 React 组件内的内容翻译。

使用 next-i18next 的示例(安装:npm install next-i18next i18next react-i18next):

创建一个 i18n 配置文件(例如,在您的根目录中的 i18n.js):


// i18n.js
import { createServerSideHelpers } from 'next-i18next'
import { i18n } from './next-i18next.config'

export function initI18next(req, res, namespaces = ['common']) {
  const helpers = createServerSideHelpers(
    req, 
    res, 
    i18n, 
    namespaces
  )

  return helpers
}

export { appWithTranslation } from 'next-i18next'
export { i18n }

为 next-i18next 创建您的 Next.js 配置。


// next-i18next.config.js
const { i18n } = require('./next-i18next.config');

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  i18n: {
    defaultLocale: 'en',
    locales: ['en', 'es', 'fr'],
  },
  // 其他配置
}

module.exports = nextConfig

将配置和翻译导入添加到您的 _app.js 中:


import { appWithTranslation } from 'next-i18next';
import '../styles/globals.css';

function MyApp({ Component, pageProps }) {
  return ;
}

export default appWithTranslation(MyApp);

创建一个文件夹并用您的翻译区域设置文件填充它。


/public
└── locales
    ├── en
    │   └── common.json
    ├── es
    │   └── common.json
    └── fr
        └── common.json

en/common.json 示例:


{
  "greeting": "Hello, world!",
  "welcomeMessage": "Welcome to our website."
}

在组件中使用翻译:


import { useTranslation } from 'next-i18next';

function MyComponent() {
  const { t } = useTranslation('common');

  return (
    

{t('greeting')}

{t('welcomeMessage')}

); } export default MyComponent;

此示例使用 useTranslation 钩子根据当前区域设置检索翻译。

处理动态路由和静态站点生成 (SSG)

在处理动态路由(例如,博客文章、产品页面)和静态站点生成 (SSG) 时,国际化会变得更加复杂。

1. 动态路由(例如 /blog/[slug])

对于动态路由,您需要在构建时使用 getStaticPaths 为每个区域设置生成正确的路径。此函数返回一个 Next.js 应该预渲染的路径数组。


export async function getStaticPaths() {
  const paths = [];
  const locales = ['en', 'es', 'fr'];
  const posts = await fetchPosts(); // 获取博客文章数据

  posts.forEach(post => {
    locales.forEach(locale => {
      paths.push({
        params: {
          slug: post.slug,
        },
        locale,
      });
    });
  });

  return {
    paths,
    fallback: false, // 或者 'blocking' 如果你想显示加载状态
  };
}

export async function getStaticProps({ params, locale }) {
  const post = await getPostBySlug(params.slug, locale);

  return {
    props: {
      post,
    },
  };
}

说明:

2. 使用 getStaticProps 进行静态站点生成 (SSG)

getStaticProps 中,您可以根据 locale 参数获取翻译内容。


export async function getStaticProps({ params, locale }) {
  // 根据区域设置和参数获取内容
  const { post } = await getPostBySlug(params.slug, locale);

  return {
    props: {
      post,
    },
  };
}

getPostBySlug 函数应获取给定 slug 和区域设置的翻译内容,这些内容可以从您的翻译文件、数据库或 CMS 中检索。

3. 使用 getServerSideProps 进行服务器端渲染 (SSR)

对于需要在请求时获取的内容,请使用 getServerSideProps。如果内容频繁更改或为每个用户个性化,这将非常有用。


export async function getServerSideProps({ params, locale, req, res }) {
  // 根据区域设置和参数获取数据(例如,从数据库)
  const data = await fetchData(params.slug, locale);

  return {
    props: {
      data,
    },
  };
}

Next.js 国际化的最佳实践

遵循这些最佳实践将帮助您构建健壮、可维护且用户友好的多语言应用程序:

国际化网站的 SEO 注意事项

为您的国际化网站优化搜索引擎对于从世界各地吸引自然流量至关重要。以下是一些关键的 SEO 最佳实践:

示例:构建一个简单的多语言博客

让我们使用 Next.js 创建一个简化的多语言博客示例。这将更具体地说明如何应用上述概念。

1. 项目设置

创建一个新的 Next.js 项目:


npx create-next-app my-multi-lang-blog
cd my-multi-lang-blog

2. 配置 i18n (next.config.js)


/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  i18n: {
    locales: ['en', 'es', 'fr'],
    defaultLocale: 'en',
  },
}

module.exports = nextConfig

3. 创建翻译文件

在根目录中创建一个 locales 文件夹,并添加以下 JSON 文件:

locales/en.json:


{
  "title": "Welcome to My Blog",
  "postTitle": "My First Post",
  "postContent": "This is the content of my first blog post."
}

locales/es.json:


{
  "title": "Bienvenido a mi Blog",
  "postTitle": "Mi Primer Post",
  "postContent": "Este es el contenido de mi primer publicación de blog."
}

locales/fr.json:


{
  "title": "Bienvenue sur Mon Blog",
  "postTitle": "Mon Premier Article",
  "postContent": "Ceci est le contenu de mon premier article de blog."
}

4. 创建博客文章组件 (例如 components/BlogPost.js)


import { useRouter } from 'next/router';
import en from '../locales/en.json';
import es from '../locales/es.json';
import fr from '../locales/fr.json';

function BlogPost() {
  const router = useRouter();
  const { locale } = router;

  let translations;
  switch (locale) {
    case 'es':
      translations = es;
      break;
    case 'fr':
      translations = fr;
      break;
    default:
      translations = en;
  }

  return (
    

{translations.postTitle}

{translations.postContent}

); } export default BlogPost;

5. 创建索引页面 (pages/index.js)


import { useRouter } from 'next/router';
import BlogPost from '../components/BlogPost';
import en from '../locales/en.json';
import es from '../locales/es.json';
import fr from '../locales/fr.json';

function HomePage() {
  const router = useRouter();
  const { locale, locales } = router;

  let translations;
  switch (locale) {
    case 'es':
      translations = es;
      break;
    case 'fr':
      translations = fr;
      break;
    default:
      translations = en;
  }

  return (
    

{translations.title}

{locales.map((l) => ( {l.toUpperCase()} ))}
); } export default HomePage;

这个简化的示例展示了 Next.js 国际化的基本原则。您可以在此基本框架上进行扩展,以包含更复杂的功能,例如动态路由和与翻译管理系统的集成。可以考虑使用 Link 组件改进上面的链接,并添加适当的 locale 属性。

6. 运行应用程序

使用以下命令运行应用程序:


npm run dev

现在您可以在 http://localhost:3000(英语)、http://localhost:3000/es(西班牙语)和 http://localhost:3000/fr(法语)访问您的博客。您应该能看到标题和博客文章内容根据所选区域设置进行了翻译。

结论

Next.js 提供了一套全面的功能,用于在您的 Web 应用程序中实现国际化。通过遵循本指南中概述的原则和技术,您可以创建能够为全球用户提供本地化体验的多语言应用程序。请记住尽早规划您的 i18n 策略,选择适合您需求的正确翻译方法,并优先考虑用户体验。通过精心的规划和执行,您可以构建能与全球受众产生共鸣的应用程序,并开启新的增长机会。持续学习、跟上最新版本和最佳实践将确保您有效地利用您的工具和技术。

随着技术的发展,预计会出现更多先进的 i18n 功能。能够触达不同文化和语言群体的用户,仍将是全球应用程序开发人员的首要任务。因此,掌握 i18n 的基础知识是一项宝贵的技能,它将提升您在当今全球化开发领域中的价值。