首页 > 解决方案 > 如何创建具有多语言路线的一页网站?

问题描述

我正在使用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,但存在问题。我正在使用gatsby-plugin-intl向 url 添加动态前缀的插件,例如:http://localhost:3001/en/

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

标签: javascriptreactjsgraphqlgatsbygatsby-plugin

解决方案


为什么您使用仅限客户端的路由/将所有内容包装在<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 的自定义集合。如果该页面是动态创建的,您应该管理您的自定义gatsby-node.js,并且在这种情况下,它应该是该场景中的集合模板。

要在页面之间链接,我建议使用页面查询来获取创建组件所需的数据。您的页面应如下所示:

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

export default IndexPage

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

如我所说,要使链接动态化<Link to="collection/1">,您应该进行页面查询,以获取正确的链接以<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更改语言时会自动设置 的值。


推荐阅读