静态构建的nextjs项目整合i18n多语言翻译

27天前

#nextjs

1

前言

  • 最近有一个项目,需要在保证页面功能的情况下,还要保证网站的seo友好。鉴于这种情况,我选择了nextjs框架,并使用其静态导出功能,在保证seo友好的同时,还不需要相对应的后端服务器。
  • 然而,在实际搭框架的过程中,我发现现有的多语言插件,很多对静态导出模式+ssg模式的支持并不友好,不得不花更多时间来找解决方案。

问题

  • 现有主流多语言库对静态导出与ssg功能支持度不高,尤其是nextjs官方支持的国际化路由首先就不支持静态导出模式
  • 很多多语言库对app路由支持不佳,使用app路由配置起来会很麻烦
  • 需要对ssg模式友好,最终要能构建出seo友好的网站

开发环境

  • "next": "15.1.2" 使用app路由,并在next.config.ts配置文件中,配置了静态导出的模式,该模式可以构建出无需后端服务器的静态html文件。
  • 使用typescript语言

解决方案

  • 最终我是选择了next-intl这个库来做多语言功能,原因有如下几点
    • 配置简单
    • 对静态导出模式友好
    • 对app路由支持友好
  • 既然选好了插件,接下来便是配置
  • 安装,使用pnpm i next-intl安装该插件
  • 修改next.config.ts配置文件
import type { NextConfig } from "next";
import createNextIntlPlugin from 'next-intl/plugin';
 
const withNextIntl = createNextIntlPlugin();
 
const nextConfig: NextConfig = {
  /* config options here */
  output: 'export',
};

export default withNextIntl(nextConfig);

  • 在根目录下,创建i18n/request.ts文件
import {getRequestConfig} from 'next-intl/server';
 
export default getRequestConfig(async () => {
  // This typically corresponds to the `[locale]` segment.
  const locale = 'pt'
  return {
    locale,
    messages: (await import(`../locales/${locale}.json`)).default
  };
});
  • 该文件的作用是在此读取cookie或者请求的header,来自行选择加载的多语言文件
  • 接下来,在根目录下,创建/locales/文件夹,在这个文件夹里放置多语言文件
  • 示例,创建en.json文件
{
  "HomePage": {
    "title": "It's a title",
    "desc": "it's a desc",
}
  • 最后,在项目代码中使用该插件,我是这么用的
  • 在page.js文件中,引入该插件提供的provider,并注入en.json这个语言文件的内容
import { NextIntlClientProvider } from 'next-intl';
import enLanguage from "@/locales/en.json";
import Main from "./Main"
import Link from 'next/link';

export default function Home() {
  return (
    <NextIntlClientProvider messages={enLanguage}>
      <Main></Main>
    </NextIntlClientProvider>
  );
}
  • 如此,我们便可以在这个page组件内部及其子组件中使用该插件了,如上,我在/en路径下的page文件,引入了en.json文件,代表这个页面使用英文
  • 具体使用如下
import { useTranslations } from 'next-intl';

export default function HeaderSection() {
  const t = useTranslations('HomePage');
  return (
    <div className="text-center mb-12">
      <div className="inline-flex items-center gap-2 mb-4">
        <div className="w-8 h-8 rounded-full bg-[#009c3b]" />
        <h1 className="text-4xl font-bold">{t('title')}</h1>
        <div className="w-8 h-8 rounded-full bg-[#ffdf00]" />
      </div>
      <p className="text-muted-foreground text-lg">
        {t('desc')}
      </p>
    </div>
  );
}
  • 就这样,一个配置简单,适合小型项目的多语言功能便整合完毕

参考文章

  • https://dev.to/ikramdeveloper/i18n-with-nextjs-output-export-1pbc