使用 GraphQL 仅查询所选语言的降价页面

Using GraphQL to query only markdown pages of language selected

Gatsby/GraphQL 建立双语网站的新手。我的站点(导航栏、页脚、正文内容等)分别在 enzh 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 上编辑这些降价文件,所以这个 solutionreact-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 的一个字段。如果不是,您可以查询文件路径(相对或绝对),其名称中将包含 enzh 变量。添加后备语言将强制您更改所有文件名以发送有效变量。

然后,在您的模板 (posts.js) 中,您可以像使用 slug 一样使用 language 字段来过滤每个实体。