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

示例

相关推荐
百思可瑞教育7 分钟前
Vue中使用keep-alive实现页面前进刷新、后退缓存的完整方案
前端·javascript·vue.js·缓存·uni-app·北京百思可瑞教育
yinuo12 分钟前
Uni-App跨端实战:APP的WebView与H5通信全流程解析(03)
前端
yinuo15 分钟前
Uni-App跨端实战:支付宝小程序WebView与H5通信全流程解析(02)
前端
GISer_Jing1 小时前
sqb&ks二面(准备)
前端·javascript·面试
谢尔登1 小时前
【Webpack】模块联邦
前端·webpack·node.js
Bottle4142 小时前
深入探究 React Fiber(译文)
前端
汤姆Tom2 小时前
JavaScript Proxy 对象详解与应用
前端·javascript
xiaopengbc2 小时前
在 React 中如何使用 useMemo 和 useCallback 优化性能?
前端·javascript·react.js
GISer_Jing2 小时前
React 18 过渡更新:并发渲染的艺术
前端·javascript·react.js
全栈技术负责人2 小时前
前端网络性能优化实践:从 HTTP 请求到 HTTPS 与 HTTP/2 升级
前端·网络·http