通用基础项目

    5. I18N 项目设置

    会员专享 · 非会员仅可阅读 30% 的正文。

    发布时间
    May 17, 2025
    阅读时间
    4 min read
    作者
    Felix
    访问
    会员专享
    这是预览内容

    非会员仅可阅读 30% 的正文。

    在上一章中,我们讲到了部署,把核心的项目骨架完成了。那么这一章我们就直接讲18n,很少有人直接在前面的部分讲18n,但我把18n的顺序提到前面的排序主要是出于下面的这些考虑:

    1. 项目的页面索引数量翻倍,添加来自小语种的曝光。 2. 在一开始做这件事的话,不用担心后续的I18N的内容覆盖率,在后期会让这个改造工程量特别的大。 3. 整个最简AI项目,追求的是以最快的方式生成闭环项目,而I18N自带的配置化JSON结构以Key填充内容的方式,更适合AI去填充。

    I18N基础设置

    那么就开始我们的项目I18N基础搭建把,这一节的版本是 github tag v2.01,基础部分都是看文档,所以不会过多的赘述。

    项目基础配置

    依赖下载和目录配置文档(https://next-intl.dev/docs/getting-started/app-router/with-i18n-routing) ,主要作用是,配置项目的i18n布局/页面、跳转、路由中间件、翻译文件。

    app/[locale]/about/page.tsx是客户端组件的用法,app/[locale]/page.tsx是服务端路线的用法。

    Ts和Eslint设置

    项目的Typescript文档项目的Eslint文档。主要作用是用于项目的 Ts语法提示以及 Eslint 限制必须覆盖,效果如下:

    Eslint报错

    Ts语法提示

    I18N路由与检测

    这一节的版本是 github tag v2.02

    处理路由前缀

    intl中,默认的前缀模式是Always,但这个行为不符合SEO的实践,需要在 en 语言(默认语言)时去掉路由后缀,同时保留其他语言的路由后缀。

    在 next-intl 中,localePrefix 有几个选项:

    - always: 总是显示语言前缀 - never: 从不显示语言前缀 - as-needed: 只为非默认语言显示前缀

    localePrefixalways 改为 as-needed,这样默认语言 en 就不会显示在 URL 中,而其他语言如 zh 会保留前缀。

    import { defineRouting } from 'next-intl/routing'
    
    export const routing = defineRouting({
      locales: ['en', 'zh'],
      defaultLocale: 'en',
      localePrefix: 'as-needed'
    })
    ```
    
    这样修改后,英文页面的 URL 将是 `/about`,中文页面的 URL 将是 `/zh/about`。
    
    ### 路由检测机制
    
    Next-intl自己有一套检测机制,可以根据多种因素自动确定用户的首选语言。默认情况下,会按照以下优先级顺序检测语言:
    
    1. URL 路径中的语言前缀(例如 `/zh/about`)
    2. Cookie 中保存的之前检测到的语言偏好
    3. 浏览器的 `accept-language` 请求头
    4. 如果以上都无法匹配,则使用 `defaultLocale` 设置的默认语言
    
    用户第一次访问网站时会根据浏览器语言自动跳转到相应语言版本,后续访问则会记住他们的语言偏好。
    
    #### 工作流示例
    
    1. 用户请求 `/` 路径,系统根据 `accept-language` 头部匹配到 `en` 语言
    2. 用户被重定向到 `/` (因为我们设置了 `localePrefix: 'as-needed'` 且 `en` 是默认语言)
    3. 应用渲染 `<Link locale="zh" href="/">切换到中文</Link>` 允许用户切换到中文
    4. 用户点击链接后,发起对 `/zh` 的请求
    5. 中间件会添加一个 cookie 来记住用户对中文的偏好
    6. 用户稍后再次请求 `/`,中间件会根据 cookie 重定向到 `/zh`
    
    #### 语言匹配算法
    
    Next-intl 使用 `@formatjs/intl-localematcher` 的"最佳匹配"算法来确定最合适的语言。
    
    简单来说,这个算法能更智能地理解用户想要的语言,即使没有完全匹配的选项。
    
    例如,如果您的应用支持 `en` 和 `zh` 这两种语言,而用户浏览器发送的 `accept-language` 头是 `en-GB`:
    
    - "查找"算法会逐步移除用户 `accept-language` 头中的子标签,直到找到匹配项。在这种情况下,它找不到匹配项,因此会使用默认语言。
    - "最佳匹配"算法会比较用户的 `accept-language` 头与可用语言之间的距离,同时考虑区域信息。因此,"最佳匹配"算法能够将 `en` 匹配为最佳匹配语言。
    
    想象一下这个场景:你的网站支持英语(`en`)和简体中文(`zh`),英国的用户访问你的网站,他的浏览器设置为英式英语(`en-GB`),传统的"查找"算法会说:"我找不到英式英语,所以我将使用默认语言"。而"最佳匹配"算法会说:"虽然没有英式英语,但英语和英式英语很接近,所以我会选择英语而不是默认的中文"。
    
    ## 常用语言代码最佳实践
    
    当我们理解了语言匹配后,我写了一个常用语言最佳实践配置示例:
    
    ```typescript
    import { defineRouting } from 'next-intl/routing'
    
    export const locales = [
      {
        code: 'en',
        name: 'English',
        dir: 'ltr'
      },
      {
        code: 'zh',
        name: '中文',
        dir: 'ltr'
      },
      {
        code: 'ja',
        name: '日本語',
        dir: 'ltr'
      },
      {
        code: 'ko',
        name: '한국어',
        dir: 'ltr'
      },
      {
        code: 'es',
        name: 'Español',
        dir: 'ltr'
      },
    会员专享

    订阅后解锁完整文章

    支持创作、解锁全文,未来更新也会第一时间送达。

    评论

    加入讨论

    0 条评论
    登录后评论

    还没有评论,来占个沙发吧。