Как создать одностраничный сайт с многоязычными маршрутами?

Я использую 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 позволяет создавать собственные серверные приложения с использованием платформы Node.js.


1
962
1

Ответ:

Решено

Почему вы используете клиентские маршруты/обертываете все внутри <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, или пользовательской коллекцией с определенным идентификатором. Если эта страница создается динамически, вы должны управлять настройками в своей 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, перенаправляя все неправильные запросы (в разработке будет показан список страниц). Ваша другая маршрутизация должна управляться с помощью встроенного компонента <Link> (расширенного от @reach/router из React).

Чтобы сделать ссылку <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 будет автоматически устанавливаться при смене языка.