这可能是最好的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。 :::

示例

相关推荐
烂蜻蜓几秒前
深入理解 Vue 3 项目结构与运行机制
前端·javascript·vue.js
han_hanker1 小时前
一个普通的vue权限管理方案-菜单权限控制
前端·javascript·vue.js
老大白菜2 小时前
lunar是一款无第三方依赖的公历 python调用
前端·python
混血哲谈4 小时前
如何使用webpack预加载 CSS 中定义的资源和预加载 CSS 文件
前端·css·webpack
浪遏6 小时前
我的远程实习(二) | git 持续更新版
前端
智商不在服务器6 小时前
XSS 绕过分析:一次循环与两次循环的区别
前端·xss
MonkeyKing_sunyuhua6 小时前
npm WARN EBADENGINE required: { node: ‘>=14‘ }
前端·npm·node.js
Hi-Jimmy7 小时前
【VolView】纯前端实现CT三维重建-CBCT
前端·架构·volview·cbct
janthinasnail7 小时前
编写一个简单的chrome截图扩展
前端·chrome
拉不动的猪7 小时前
刷刷题40(vue中计算属性不能异步,如何实现异步)
前端·javascript·vue.js