【问题标题】:Using GraphQL to query only markdown pages of language selected使用 GraphQL 仅查询所选语言的降价页面
【发布时间】:2021-07-19 11:40:35
【问题描述】:

Gatsby/GraphQL 新手构建双语网站。我的网站(导航栏、页脚、正文内容等)分别在enzh json 文件中包含所有双语内容,并从react-18next 调用t 函数。然而,我的网站中有几个页面还没有被“国际化”——我的降价页面。目前,文件结构如下:

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 文件夹中的内容。我想让这些 Markdown 文件在 Netlify CMS 上可编辑,所以这 solutionreact-markdown 不是我正在考虑的事情。

所以我想知道:i18n.language 中的数据如何传递到 graphql 查询中?这是国际化降价页面的最佳方式吗?

编辑:

gatsby-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;

【问题讨论】:

    标签: graphql internationalization gatsby netlify


    【解决方案1】:

    所以我想知道:如何将来自 i18n.language 的数据传递到 图形查询?这是国际化降价的最佳方式吗 页面?

    是的,当然。对我来说,将 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 字段,我假设它是每个帖子的一个字段。如果不是,您可以查询文件路径(相对或绝对),其名称中将包含enzh 变量。添加后备语言将强制您更改所有文件名以发送有效变量。

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

    【讨论】:

    • 谢谢!这真的很有帮助。查询language 字段是一个非常优雅的解决方案——但是,我在将语言作为字段添加到我的frontmatter 并将i18next.language 的输出传递给posts.js 中的查询时遇到了问题。我已经编辑了我的帖子以包含我的gatsby-node.jsposts.js,你认为你可以看一下吗?
    • 还有,node.slugnode.language 是从图书馆调用的吗?
    • sluglanguage 来自 MDX 的前端。您应该在那里添加新字段
    • 我已经设法让它工作了,但是字符串插值不起作用(afaik,数据是在运行时获取的,但查询+页面是在构建时编译的)-我将i18next.language 传递给onCreatePage API 并为每种语言创建了一个 en/zh 页面。这是您的想法还是有更优雅的解决方案?
    • 这正是我的意思。避免构建时间会迫使您调整 Gatsby 的默认行为,所以对我来说,这是迄今为止最优雅的解决方案。
    猜你喜欢
    • 2020-07-10
    • 2018-06-14
    • 2019-06-14
    • 1970-01-01
    • 2014-01-15
    • 2020-09-21
    • 1970-01-01
    • 2021-07-16
    • 1970-01-01
    相关资源
    最近更新 更多