【问题标题】:How to create one page site with multi languages routes?如何创建具有多语言路线的一页网站?
【发布时间】:2021-03-24 23:12:47
【问题描述】:

我正在使用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 组件,因为没有与url 匹配的路由。有没有办法为 url 添加前缀并将所有内容重新路由到正确的组件?

【问题讨论】:

    标签: javascript reactjs graphql gatsby gatsby-plugin


    【解决方案1】:

    为什么你使用client-only 路由/将所有内容包装在&lt;Router&gt; 中?

    我不知道在您的方案中更改 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 中管理自定义,在这种情况下,它应该是该场景中的集合模板。

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

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

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

    如我所说,要使&lt;Link to="collection/1"&gt; 链接动态化,您应该进行页面查询,以获取正确的链接以从您的数据中构建自定义动态&lt;Link&gt;。

    一旦您安装了gatsby-plugin-intl 插件,您的所有页面都会自动添加前缀,但是,要使用&lt;Link&gt; 或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的值会随着你改变语言而自动设置。

    【讨论】:

    • 抱歉回复晚了,我的目标是创建一个单页应用程序,我遵循了这个教程:https://aravindballa.com/writings/gatsby-single-page-app/。所以一切都由index.js管理,但实际上url中的语言前缀没有处理...
    • 使用我提供的gatsby-plugin-intl 插件,然后使用锚链接。这将为所有页面添加基于包含/排除规则提供的语言的前缀。由于您只有一页,因此适合您。
    • 我已经使用 gatsby-plugin-intl 但是当我定义这样的链接时:&lt;Link to={/categories/${ctg.slug}}&gt;test&lt;/Link&gt; 我有这个:&lt;a href="/categories/archive"&gt;&lt;p class="bg-title--l text-white"&gt;archivio&lt;/p&gt;&lt;/a&gt; 但应该是 @987654352 @ 那为什么不加语言前缀呢?
    • 我已经添加了解释。基本上,您需要始终使用const { locale } = useIntl() 为所有链接添加前缀。因为它是一个钩子,所以这个值会随着您更改网站的语言而改变,因此您的所有链接都会继续工作。
    • 不,更改所有链接不是一个好习惯。在这种情况下,它对您使用 SPA 的用例很有用,但您需要使用这种方法手动更改它。当然,您可以创建一个解析和包装所有内容的函数以添加locale,但您需要开发它。
    猜你喜欢
    • 2013-06-14
    • 2016-07-31
    • 2018-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-26
    • 1970-01-01
    相关资源
    最近更新 更多