这可能是最好的NextJs国际化方案,没有之一

最近VoerkaI18n新出了3.0版本,功能更加强大易用,针对NextJs提供了全方面的适配,这可能是最好的NextJs国际化方案,没有之一。

VoerkaI18nNextjs应用的国际化解决方案提供了一个全新的解决方案!

Nextjs应用引入国际化需要引入以下插件:

  • @voerkai18n/nextjs

    Nextjs插件 ,提供访问当前语言切换语言自动更新等功能。

使用方法

第1步:安装依赖

首先安装@voerkai18n/cli到全局.

::: code-group

bash 复制代码
npm install -g @voerkai18n/cli
bash 复制代码
yarn global add @voerkai18n/cli
bash 复制代码
pnpm  add -g @voerkai18n/cli

:::

第2步:初始化

接着VoerkaI18n init初始化工程。

bash 复制代码
> voerkai18n init

初始化完成后,会创建一个语言工作目录,默认位置是src/languages。文件夹结构如下:
myapp //i src //i languages messages/ paragraphs/ translates/ // 提取需要翻译的内容 messages/ // 提取的需要翻译的内容 paragraphs/ // 提取的需要翻译的段落 prompts/ // 执行AI翻译的相关提示词 api.json // API接口 component.tsx // 翻译组件 server.ts //! 服务端入口 client.ts //! 客户端入口 index.ts //! 客户端入口文件 settings.json // 配置文件 storage.ts // 存储管理 loader.ts // 加载器 transform.ts // 翻译变换 formatters.json // 格式化器配置 package.json //i index.ts //i

React应用不同的是,Nextjs应用需要提供服务端入口客户端入口

第3步:启用Nextjs支持

接下需要voerkai18n apply来启用Nextjs支持。

bash 复制代码
> voerkai18n apply

执行voerkai18n apply命令后,选择Nextjs后,会执行以下操作:

  • 安装@voerkai18n/nextjs
  • 更新languages的相关文件,主要是server.tsclient.ts

:::warning 提示 也可以手动安装@voerkai18n/nextjs,并更新languages的相关文件。见下文手工配置。 :::

第4步:配置应用

不同于其他Nextjs国际化方案,VoerkaI18n不需配置相应的中间件配置,只需要客户端配置相应的组件即可。

修改app/layout.tsx文件,引入VoerkaI18nNextjsProvider

tsx 复制代码
import { VoerkaI18nNextjsProvider } from "@/languages/client";
// .....
export default function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) {
  return (
    <html lang="en">
      <body  >
        <VoerkaI18nNextjsProvider fallback={<div>loading language...</div>}>
          {children} 
        </VoerkaI18nNextjsProvider>
      </body>
    </html>
  );
}

第5步:翻译内容

Nextjs应用组件包括服务端组件客户端组件两部分,需要导入不同的组件。

  • 服务端组件
tsx 复制代码
import { Translate } from "@/languages/server";

export default async function Server() {
    return (<div>
        <Translate message="服务端组件"/> 
    </div>)
}
  • 客户端组件
tsx 复制代码
import { Translate } from "@/languages/client";

export default async function Client() {
    return (<div>
        <Translate message="客户端组件"/> 
    </div>)
}

第6步:切换语言

引入useVoerkaI18n来实现切换语言的功能。

tsx 复制代码
'use client'  
import React from 'react'; 
import { useVoerkaI18n } from "@voerkai18n/nextjs/client";
import classNames from 'classnames'

const LanguageBar: React.FC = () => {
  const { activeLanguage, changeLanguage, languages } = useVoerkaI18n();
  return (
    <div className="flex md:order-2 flex-row justify-items-center align-middle">
      { languages.map((lang) => {
        return (<button 
          key={lang.name} 
          onClick={() => changeLanguage(lang.name) } 
          className={ lang.name === activeLanguage ? 'active' : ''}
        >{lang.name}</button>)
      })}
    </div>
  )
}

useVoerkaI18n返回值:

ts 复制代码
{
    scope          : VoerkaI18nScope
    manager        : VoerkaI18nManager
    activeLanguage : string
    defaultLanguage: string
    languages      : VoerkaI18nLanguage
    changeLanguage : (language:string)=>Promise<string>,
    t              : VoerkaI18nTranslate
};

:::warning 提示 useVoerkaI18n运行在客户端。 :::

指南

手动配置

voerkai18n apply负责自动配置Nextjs应用支持,也可以手动配置.

  • 编辑languages/client.{ts|js}文件
ts 复制代码
'use client'
import { 
    createClientTranslateComponent,
    ReactTranslateComponentType 
}  from "@voerkai18n/nextjs/client"
import { VoerkaI18nScope, VoerkaI18nTranslateProps } from '@voerkai18n/runtime';
import formatters from "@voerkai18n/formatters" 
import storage  from "./storage"
import idMap from "./messages/idMap.json"
import paragraphs from "./paragraphs"
import settings from "./settings.json"
import defaultMessages from "./messages/zh-CN"    
  
const component = createClientTranslateComponent() 
 
const messages = { 
    'zh-CN'    : defaultMessages,
    'en-US'    : ()=>import("./messages/en-US"),
    'ja-JP'    : ()=>import("./messages/ja-JP"),
}


export const i18nScope = new VoerkaI18nScope<ReactTranslateComponentType>({    
    id: "nextjs_client",                                // 当前作用域的id
    idMap,                                              // 消息id映射列表    
    injectLangAttr:false,                               // 不注入lang属性
    formatters,                                         // 格式化器
    storage,                                            // 语言配置存储器
    messages,                                           // 语言包 
    paragraphs,                                         // 段落
    component,                                          // 翻译组件
    ...settings
}) 

export const t = i18nScope.t
export const Translate = i18nScope.Translate as React.FC<VoerkaI18nTranslateProps>
export { VoerkaI18nNextjsProvider } from "@voerkai18n/nextjs/client"
  • 编辑languages/server.{ts|js}文件
ts 复制代码
import {                       
    createServerTranslateComponent,
    ReactServerTranslateComponentType 
}  from "@voerkai18n/nextjs/server"
import { VoerkaI18nScope, VoerkaI18nTranslateProps } from '@voerkai18n/runtime';
import formatters from "@voerkai18n/formatters"
import storage  from "./storage"
import idMap from "./messages/idMap.json"
import paragraphs from "./paragraphs"
import settings from "./settings.json"
import zhCNMessages from "./messages/zh-CN"    
import enUSMessages from "./messages/en-US";
import jaJPMessages from "./messages/ja-JP";
  
const component = createServerTranslateComponent() 

const messages = { 
    'zh-CN'    : zhCNMessages,
    'en-US'    : enUSMessages,
    'ja-JP'    : jaJPMessages
}


export const i18nScope = new VoerkaI18nScope<ReactServerTranslateComponentType>({    
    id: "nextjs_server",                   // 当前作用域的id    
    injectLangAttr:false,                  // 不注入lang属性
    idMap,                                 // 消息id映射列表
    formatters,                            // 格式化器
    storage,                               // 语言配置存储器
    messages,                              // 语言包 
    paragraphs,
    component,                             // 翻译组件
    ...settings
}) 



export const t = i18nScope.t
export const Translate = i18nScope.Translate as React.FC<VoerkaI18nTranslateProps>

React

@voerkai18n/nextjs依赖于@voerkai18n/react,并且导出了@voerkai18n/react的所有API。

详见@voerkai18n/react文档。

常见问题

  • 如何处理hydration错误问题?

Nextjs应用经常出现以下错误:

shell 复制代码
A tree hydrated but some attributes of the server rendered 
HTML didn't match the client properties. This won't be patched up. 
This can happen if a SSR-ed Client Component used:

- A server/client branch `if (typeof window !== 'undefined')`.
- Variable input such as `Date.now()` or `Math.random()` which changes each time it's called.
- Date formatting in a user's locale which doesn't match the server.
- External changing data without sending a snapshot of it along with the HTML.
- Invalid HTML tag nesting.

这是Nextjs的常见的问题,开发者需要充分了解Nextjshydration机制。

相关问题可以参考Nextjs文档以及这里

:::warning 提示

  • 有时chrome相关插件也会导致hydration错误,因为某些插件可能会在DOM中注入内容而导致hydrated错误。
  • VoerkaI18n默认会在body注入lang属性,可能会导致hydration error,因此需要在settings.json中设置injectLangAttrtrue。 :::

示例

相关推荐
Mintopia12 分钟前
像素的进化史诗:计算机图形学与屏幕的千年之恋
前端·javascript·计算机图形学
Mintopia15 分钟前
Three.js 中三角形到四边形的顶点变换:一场几何的华丽变身
前端·javascript·three.js
归于尽29 分钟前
async/await 从入门到精通,解锁异步编程的优雅密码
前端·javascript
陈随易30 分钟前
Kimi k2不行?一个小技巧,大幅提高一次成型的概率
前端·后端·程序员
猩猩程序员36 分钟前
Rust 动态类型与类型反射详解
前端
杨进军38 分钟前
React 实现节点删除
前端·react.js·前端框架
yanlele1 小时前
【实践篇】【01】我用做了一个插件, 点击复制, 获取当前文章为 Markdown 文档
前端·javascript·浏览器
爱编程的喵1 小时前
React useContext 深度解析:告别组件间通信的噩梦
前端·react.js
望获linux2 小时前
【实时Linux实战系列】多核同步与锁相(Clock Sync)技术
linux·前端·javascript·chrome·操作系统·嵌入式软件·软件
魂祈梦2 小时前
rsbuild的环境变量
前端