如何创建具有多语言路由的一页站点?
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
的值会在你更改语言时自动设置。
我正在使用 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
的值会在你更改语言时自动设置。