Micro View of Allium

Micro View of Allium

Jeango

Jeango 2/4/2021, 2:40:07 PM

👉 i18n-routing 国际化路由

配置区域信息:

// 👉 /next.config.js 配置脚本
module.exports = {
  i18n: {
    // These are all the locales you want to support in
    // your application
    locales: ['en-US', 'fr', 'nl-NL'],
    // This is the default locale you want to be used when visiting
    // a non-locale prefixed path e.g. `/hello`
    defaultLocale: 'en-US',
    // This is a list of locale domains and the default locale they
    // should handle (these are only required when setting up domain routing)

    // The automatic locale detection can be disabled with:
    localeDetection: false,

    domains: [
      {
        domain: 'example.com',
        defaultLocale: 'en-US',
      },
      {
        domain: 'example.nl',
        defaultLocale: 'nl-NL',
      },
      {
        domain: 'example.fr',
        defaultLocale: 'fr',
      },
    ],
  },
}

Next.js 10 项目的国际化调整分为两块:翻译,与路由,支持两种最常见的路由策略:子路径路由,与域路由。对于这两种策略,都需要先在 Next.js 配置中指定语言环境。

  • Sub-path Routing 子路由将区域信息放在 URL 路径中,在 locales 指定想要支持的所有语言区域,在defaultLocale指定默认的语言区域。
  • Domain Routing 域名路由

大部分 React 都提供翻译完成的应用程序,但却很少为您提供自动路由处理方案,而且通常只使用一种渲染策略。考虑到这一现实,在 Next.js 10 中发布对国际化路由以及语言检测的内置支持。

内置的国际化路由功能支持 Next.js 的混合策略,您可以在静态生成与服务器渲染之间自由做出选择。

Locales 代表的是 UTS 语言环境标识符,属于一种用于定义语言环境的标准化格式。通常,Locale 标识符由语言、区域与脚本组成,各元素之间使用破折号分隔language - area - script,其中的区域与脚本属于可选项。

例如:

  • en-US - 在美国使用的英语
  • nl-NL - 在荷兰使用的荷兰语
  • nl - 无特定使用区域的荷兰语

以上给定的区域信息配置中,有三种语言,其中法语 fr 没有指定区域信息,对于 pages/blog.js 页面来说,有效的访问地址可以是以下三个:

  • /blog
  • /fr/blog
  • /nl-nl/blog

对于默认语言区域,defaultLocale的值不会在地址中前缀。

域路由意味着您将语言环境与顶级域名映射起来,例如,example.nl 可映射至 nl 语言环境,example.com 则映射至 en 语言环境。对于 pages/blog.js 页面,以下的域路由有效:

  • example.com/blog
  • example.fr/blog
  • example.nl/blog
  • example.nl/nl-BE/blog

Next.js 10 进行语言检测,在 / 路由上提供基于 Accept-Language 标头的内置语言检测功能,目前所有现代浏览器均支持此项检测。配置的语言环境将与 Accept-Language 标头相匹配,而后根据预设策略进行重新定向。

通过 Next.js Router 访问语言区域信息,useRouter() 勾子函数返回的实例包含:

  • locale 当前活动的区域语言;
  • locales 已配置的区域语言;
  • defaultLocale 已配置的默认区域语言;

当进行静态预渲染时,页面的 getStaticProps() 或者 getServerSideProps() 方法可以从参数中获取。

通过 next/linknext/router 组件可以实现在各种语言间切换,在 Link 中指定 locale

import Link from 'next/link'

export default function IndexPage(props) {
  return (
    <Link href="/another" locale="fr">
      <a>To /fr/another</a>
    </Link>
  )
}

或者直接使用 next/router 方法切换,将区域语言信息设置到路由中:

import { useRouter } from 'next/router'

export default function IndexPage(props) {
  const router = useRouter()

  return (
    <div
      onClick={() => {
        router.push('/another', '/another', { locale: 'fr' })
      }}
    >
      to /fr/another
    </div>
  )
}

再如,直接写入 href 属性:

import Link from 'next/link'

export default function IndexPage(props) {
  return (
    <Link href="/fr/another" locale={false}>
      <a>To /fr/another</a>
    </Link>
  )
}

对于非动态页面 Non-dynamic getStaticProps Pages,只需要一个页面就可以对应已配置的各种语言,如果不想要对某种语言进行预渲染,可以返回 notFound:

export async function getStaticProps({ locale }) {
  // Call an external API endpoint to get posts.
  // You can use any data fetching library
  const res = await fetch(`https://.../posts?locale=${locale}`)
  const posts = await res.json()

  if (posts.length === 0) {
    return {
      notFound: true,
    }
  }

  // By returning { props: posts }, the Blog component
  // will receive `posts` as a prop at build time
  return {
    props: {
      posts,
    },
  }
}

对于动态页面 Dynamic getStaticProps Pages,需要渲染对应语言的页面,就要在返回的路径列表中设置 locale 参数。

// pages/blog/[slug].js
export const getStaticPaths = ({ locales }) => {
  return {
    paths: [
      { params: { slug: 'post-1' }, locale: 'en-US' },
      { params: { slug: 'post-1' }, locale: 'fr' },
    ],
    fallback: true,
  }
}

搜索引擎优化 Next.js 能够感知用户所访问页面的语言类别,因此会自动将 lang 属性添加至标签当中。

但 Next.js 无法识别出页面的变体,因此需要由您使用 next/head 添加 hreflang 元标签。关于 hreflang 元标签的更多详细信息,请参阅 谷歌 Webmasters 说明文档。

Next.js 还将提供更多国际化选项 国际化路由只是 Next.js 一系列国际化功能中的一种,旨在降低项目国际化与本地化的实现难度。国际化路由能够与大部分 React 国际化库相集成。