使用 GraphQL 仅查询所选语言的降价页面
Using GraphQL to query only markdown pages of language selected
Gatsby/GraphQL 建立双语网站的新手。我的站点(导航栏、页脚、正文内容等)分别在 en
和 zh
json 文件中包含所有双语内容,并从 react-18next
调用 t
函数.但是,我的网站中有几个页面尚未 'internationalised' - 我的降价页面。目前,文件结构如下所示:
src
├── posts
│ └── positions
│ ├── en
│ │ ├── accounting-en.md
│ │ ├── socialmedia-en.md
│ │ └── swe-en.md
│ └── zh
│ ├── accounting-zh.md
│ ├── socialmedia-zh.md
│ └── swe-zh.md
其中 .md
文件使用 MDXRenderer
呈现到页面上,我只想加载 en
/zh
文件夹中的内容选择任一语言时。我想在 Netlify CMS 上编辑这些降价文件,所以这个 solution 和 react-markdown
不是我正在考虑的事情。
所以我想知道:如何将来自 i18n.language
的数据传递到 graphql 查询中?这是国际化降价页面的最佳方式吗?
编辑:
盖茨比-node.js
const { createFilePath } = require(`gatsby-source-filesystem`);
exports.onCreateNode = ({ node, actions, getNode }) => {
const { createNodeField } = actions
if (node.internal.type === `Mdx`) {
const value = createFilePath({ node, getNode })
createNodeField({
name: `slug`,
node,
value: `/posts${value}`,
language,
})
}
}
const path = require("path")
exports.createPages = async ({ graphql, actions, reporter }) => { // Create blog pages dynamically
const { createPage } = actions
const result = await graphql(`
query {
allMdx {
edges {
node {
id
fields {
slug
language
}
}
}
}
}
`)
if (result.errors) {
reporter.panicOnBuild(' ERROR: Loading "createPages" query')
}
// Create blog post pages.
const posts = result.data.allMdx.edges
posts.forEach(({ node }, index) => {
createPage({
path: node.fields.slug,
component: path.resolve(`./src/components/post-page-template.js`),
context: { id: node.id },
})
})
}
posts.js(呈现所有降价文件,但我希望只显示以 -en 或 -zh 结尾的降价文件,具体取决于已选择语言。我愿意更改此文件结构以支持更好的代码)
import React from "react";
import styled from "styled-components";
import { graphql, Link } from "gatsby";
import Navbar from "../components/Navbar.js";
import FooterContainer from "../containers/footer";
import { useTranslation } from "react-i18next";
import i18next from "i18next";
const Button = styled.button`
background-color: #ec1b2f;
border: none;
color: white;
padding: 10px 40px;
text-align: center;
text-decoration: none;
font-size: 16px;
border-radius: 10px;
`;
const Body = styled.body`
margin-left: 6%;
`;
const Divider = styled.hr`
margin-top: 20px;
line-height: 0;
border-top: 1px;
margin-left: 0px;
&:last-child {
margin-bottom: 30px;
}
`;
const Title = styled.h1`
font-family: "Arial";
color: #ec1b2f;
font-size: 25px;
font-weight: 400;
`;
// console.log('----')
// console.log(typeof i18next.language)// type string
// console.log(i18next.language) // output: i18next: languageChanged zh-Hant
const selectedLanguage = i18next.language // this doesn't work despite i18next.language being type string??
const selectedLangRegex = selectedLanguage.split(/languageChanged (.*)/gm)
export const query = (selectedLangRegex) => graphql`
query SITE_INDEX_QUERY {
site {
siteMetadata {
title
description
language
}
}
allMdx(
sort: {fields: [frontmatter___date], order: DESC},
filter: {frontmatter: {published: {eq: true}, language: {eq: selectedLangRegex}}} //trying to regex selectedLangRegex
){
nodes {
id
excerpt(pruneLength: 250)
frontmatter {
title
date(formatString: "DD MMM YYYY")
}
fields {
slug
}
}
}
}
`;
const Careers = ({ props, data }) => {
const { t } = useTranslation();
return (
<div>
<Navbar />
{data.allMdx.nodes.map(({ excerpt, frontmatter, fields }) => (
<Body>
<Title>{frontmatter.title}</Title>
<p>{frontmatter.date}</p>
<p>{excerpt}</p>
<Link to={fields.slug}>
<Button>{t("careers.apply_button")}</Button>
</Link>
<Divider />
</Body>
))}
<FooterContainer />
</div>
);
};
export default Careers;
so i was wondering: how can data from i18n.language
be passed into a
graphql query? is this the best way to internationalise markdown
pages?
当然可以。对我来说,将 GraphQL 变量传递给模板是最干净、最好的方法。这样,您可以添加后备语言(或将其留空)以选择尚未翻译的非国际化文件。
类似于:
const path = require("path")
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
const queryResults = await graphql(`
query getAllPosts {
allMarkdownRemark {
nodes {
slug
language #use relative/absolute path if needed
}
}
}
`)
const postTemplate = path.resolve(`src/templates/posts.js`)
queryResults.data.allProducts.nodes.forEach(node => {
createPage({
path: `/blog/${node.slug}`,
component: postTemplate,
context: {
slug: node.slug,
language: node.language || 'en' // the fallback
},
})
})
}
注意:在不知道您的 gatsby-node.js
看起来如何的情况下,您可能需要稍微调整一下查询以及 createPage
API。
这个想法是查询一个 language
字段,我假设它是每个 post 的一个字段。如果不是,您可以查询文件路径(相对或绝对),其名称中将包含 en
或 zh
变量。添加后备语言将强制您更改所有文件名以发送有效变量。
然后,在您的模板 (posts.js
) 中,您可以像使用 slug
一样使用 language
字段来过滤每个实体。
Gatsby/GraphQL 建立双语网站的新手。我的站点(导航栏、页脚、正文内容等)分别在 en
和 zh
json 文件中包含所有双语内容,并从 react-18next
调用 t
函数.但是,我的网站中有几个页面尚未 'internationalised' - 我的降价页面。目前,文件结构如下所示:
src
├── posts
│ └── positions
│ ├── en
│ │ ├── accounting-en.md
│ │ ├── socialmedia-en.md
│ │ └── swe-en.md
│ └── zh
│ ├── accounting-zh.md
│ ├── socialmedia-zh.md
│ └── swe-zh.md
其中 .md
文件使用 MDXRenderer
呈现到页面上,我只想加载 en
/zh
文件夹中的内容选择任一语言时。我想在 Netlify CMS 上编辑这些降价文件,所以这个 solution 和 react-markdown
不是我正在考虑的事情。
所以我想知道:如何将来自 i18n.language
的数据传递到 graphql 查询中?这是国际化降价页面的最佳方式吗?
编辑:
盖茨比-node.js
const { createFilePath } = require(`gatsby-source-filesystem`);
exports.onCreateNode = ({ node, actions, getNode }) => {
const { createNodeField } = actions
if (node.internal.type === `Mdx`) {
const value = createFilePath({ node, getNode })
createNodeField({
name: `slug`,
node,
value: `/posts${value}`,
language,
})
}
}
const path = require("path")
exports.createPages = async ({ graphql, actions, reporter }) => { // Create blog pages dynamically
const { createPage } = actions
const result = await graphql(`
query {
allMdx {
edges {
node {
id
fields {
slug
language
}
}
}
}
}
`)
if (result.errors) {
reporter.panicOnBuild(' ERROR: Loading "createPages" query')
}
// Create blog post pages.
const posts = result.data.allMdx.edges
posts.forEach(({ node }, index) => {
createPage({
path: node.fields.slug,
component: path.resolve(`./src/components/post-page-template.js`),
context: { id: node.id },
})
})
}
posts.js(呈现所有降价文件,但我希望只显示以 -en 或 -zh 结尾的降价文件,具体取决于已选择语言。我愿意更改此文件结构以支持更好的代码)
import React from "react";
import styled from "styled-components";
import { graphql, Link } from "gatsby";
import Navbar from "../components/Navbar.js";
import FooterContainer from "../containers/footer";
import { useTranslation } from "react-i18next";
import i18next from "i18next";
const Button = styled.button`
background-color: #ec1b2f;
border: none;
color: white;
padding: 10px 40px;
text-align: center;
text-decoration: none;
font-size: 16px;
border-radius: 10px;
`;
const Body = styled.body`
margin-left: 6%;
`;
const Divider = styled.hr`
margin-top: 20px;
line-height: 0;
border-top: 1px;
margin-left: 0px;
&:last-child {
margin-bottom: 30px;
}
`;
const Title = styled.h1`
font-family: "Arial";
color: #ec1b2f;
font-size: 25px;
font-weight: 400;
`;
// console.log('----')
// console.log(typeof i18next.language)// type string
// console.log(i18next.language) // output: i18next: languageChanged zh-Hant
const selectedLanguage = i18next.language // this doesn't work despite i18next.language being type string??
const selectedLangRegex = selectedLanguage.split(/languageChanged (.*)/gm)
export const query = (selectedLangRegex) => graphql`
query SITE_INDEX_QUERY {
site {
siteMetadata {
title
description
language
}
}
allMdx(
sort: {fields: [frontmatter___date], order: DESC},
filter: {frontmatter: {published: {eq: true}, language: {eq: selectedLangRegex}}} //trying to regex selectedLangRegex
){
nodes {
id
excerpt(pruneLength: 250)
frontmatter {
title
date(formatString: "DD MMM YYYY")
}
fields {
slug
}
}
}
}
`;
const Careers = ({ props, data }) => {
const { t } = useTranslation();
return (
<div>
<Navbar />
{data.allMdx.nodes.map(({ excerpt, frontmatter, fields }) => (
<Body>
<Title>{frontmatter.title}</Title>
<p>{frontmatter.date}</p>
<p>{excerpt}</p>
<Link to={fields.slug}>
<Button>{t("careers.apply_button")}</Button>
</Link>
<Divider />
</Body>
))}
<FooterContainer />
</div>
);
};
export default Careers;
so i was wondering: how can data from
i18n.language
be passed into a graphql query? is this the best way to internationalise markdown pages?
当然可以。对我来说,将 GraphQL 变量传递给模板是最干净、最好的方法。这样,您可以添加后备语言(或将其留空)以选择尚未翻译的非国际化文件。
类似于:
const path = require("path")
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
const queryResults = await graphql(`
query getAllPosts {
allMarkdownRemark {
nodes {
slug
language #use relative/absolute path if needed
}
}
}
`)
const postTemplate = path.resolve(`src/templates/posts.js`)
queryResults.data.allProducts.nodes.forEach(node => {
createPage({
path: `/blog/${node.slug}`,
component: postTemplate,
context: {
slug: node.slug,
language: node.language || 'en' // the fallback
},
})
})
}
注意:在不知道您的 gatsby-node.js
看起来如何的情况下,您可能需要稍微调整一下查询以及 createPage
API。
这个想法是查询一个 language
字段,我假设它是每个 post 的一个字段。如果不是,您可以查询文件路径(相对或绝对),其名称中将包含 en
或 zh
变量。添加后备语言将强制您更改所有文件名以发送有效变量。
然后,在您的模板 (posts.js
) 中,您可以像使用 slug
一样使用 language
字段来过滤每个实体。