如何创建具有多语言路由的一页站点?

How to create one page site with multi languages routes?

我正在使用 Gatsby 并且我想使用多语言创建一个站点,到目前为止我已经定义了 pages/index.js 其中包含:

import React from "react"
import Layout from "../components/layout/layout"

import BGTState from "../context/bgt/bgtState"
import { Router } from "@reach/router"
import Home from "../components/pages/home"
import Collection from "../components/pages/collection"
import NotFound from "../components/pages/404"

const IndexPage = () => {
  return (
    <BGTState>
      <Layout>
        <Router>
          <Home path="/" />
          <Collection path="collection/:id" />
          <NotFound default />
        </Router>
      </Layout>
    </BGTState>
  )
}

export default IndexPage

并且我已将 gatsby-node.js 修改为:

// Implement the Gatsby API onCreatePage. This is
// called after every page is created.
exports.onCreatePage = async ({ page, actions }) => {
  const { createPage } = actions

  if (page.path === "/") {
    page.matchPath = "/*"
    createPage(page)
  }
}

每个请求都在 index.js 上转发,但是有一个问题。我正在使用添加到 url 动态前缀的插件 gatsby-plugin-intl,例如:http://localhost:3001/en/

如果我访问 http://localhost:3001/en/,则会显示 NotFound 组件,因为没有路由匹配 url。有没有办法为 url 添加前缀并将所有内容重新路由到正确的组件?

为什么要使用 client-only routes/wrapping <Router> 中的所有内容?

我不知道在您的场景中将 gatsby-node.js 更改为:

的目标是什么
// Implement the Gatsby API onCreatePage. This is
// called after every page is created.
exports.onCreatePage = async ({ page, actions }) => {
  const { createPage } = actions

  if (page.path === "/") {
    page.matchPath = "/*"
    createPage(page)
  }
}

如果您不使用仅客户端路由,您可以删除它们。

这是一个宽泛的问题,但只需定义您的语言和翻译文件即可。在你的 gatsby-config.js:

plugins: [
  {
    resolve: `gatsby-plugin-intl`,
    options: {
      // language JSON resource path
      path: `${__dirname}/src/intl`,
      // supported language
      languages: [`en`,`es`],
      // language file path
      defaultLanguage: `en`,
      // option to redirect to `/en` when connecting `/`
      redirect: true,
    },
  },
]

useIntl 挂钩将捕获内部请求,因此您只需要担心视图,忘记路由:

import React from "react"
import { useIntl, Link, FormattedMessage } from "gatsby-plugin-intl"

const IndexPage = () => {
  const intl = useIntl()
  return (
    <Layout>
      <SEO title={intl.formatMessage({ id: "title" })}/>
      <Link to="/page-2/">
       <FormattedMessage id="go_page2" />
      </Link>
    </Layout>
  )
}
export default IndexPage

您的 Collection 组件应该是一个页面,包裹在 /page 文件夹中,或者是一个具有特定 ID 的自定义集合。如果 page is dynamically created,您应该在 gatsby-node.js 中管理自定义项,在这种情况下,它应该是该场景中的集合模板。

到 link 页面之间,我建议使用 page-queries 来获取创建组件所需的数据。您的页面应如下所示:

const IndexPage = () => {
  return (
    <BGTState>
      <Layout>
        <Link to="/"> // home path
        <Link to="collection/1">
      </Layout>
    </BGTState>
  )
}

export default IndexPage

404 页面将由 Gatsby 自动处理,重定向所有错误请求(开发中将显示页面列表)。您的其他路由应使用内置的 <Link> 组件(从 React 的 @reach/router 扩展而来)进行管理。

要使 <Link to="collection/1"> link 动态化,您应该进行页面查询,如我所说,以获得正确的 link 来构建自定义动态 <Link>来自您的数据。

安装 gatsby-plugin-intl 插件后,所有页面都会自动添加前缀,但是,要使用 <Link>navigate 指向它们,您需要获取当前语言和前缀:

export const YourComponent = props => {
  const { locale } = useIntl(); // here you are getting the current language

  return <Link to={`${locale}/your/path`}>Your Link</Link>;
};

因为useIntl()是插件提供的自定义钩子,所以locale的值会在你更改语言时自动设置。