使用i18next搭建Gatsby多语言页面时如何减少重复查询定义
问题原因
你之前两种方案失效的核心原因是Gatsby的GraphQL页面查询是构建阶段静态提取的,只会识别当前文件内直接通过graphql模板字符串声明、且直接导出的查询内容,不会解析导入的外部变量、也不会执行函数来获取查询定义,因此编译阶段无法识别到有效查询。
方案1:使用GraphQL片段复用逻辑(侵入性最小)
这是改动最小的复用方案,仅需一次修改所有页面的查询定义,后续维护只需更新片段即可:
- 新建片段定义文件
src/fragments/locale.js,写入核心查询逻辑:
import { graphql } from "gatsby" export const LocaleQueryFragment = graphql` fragment LocaleQueryData on Query { locales: allLocale(filter: { language: { eq: $language } }) { edges { node { ns data language } } } } `
Gatsby会自动全局识别所有定义的GraphQL片段,无需额外引入。
2. 所有页面的查询简化为以下代码,无需重复写查询逻辑:
import { graphql } from "gatsby" export const languageQuery = graphql` query($language: String!) { ...LocaleQueryData } ` 后续如果需要修改查询逻辑,仅修改片段文件即可,无需逐一调整页面代码。 ## 方案2:构建阶段统一注入数据(彻底消除页面重复代码) 如果希望完全不在页面写任何查询代码,可以通过`gatsby-node.js`的`createPage`钩子统一查询后注入页面上下文: 1. 移除所有页面中定义的`languageQuery`导出 2. 在项目根目录的`gatsby-node.js`中添加如下逻辑: ```js exports.createPages = async ({ graphql, actions }) => { const { createPage } = actions // 统一查询全量翻译资源 const localeRes = await graphql(` query { allLocale { edges { node { ns data language } } } } `) // 按语言分组整理数据 const localeMap = {} localeRes.data.allLocale.edges.forEach(({ node }) => { if (!localeMap[node.language]) localeMap[node.language] = [] localeMap[node.language].push(node) }) // 原有创建页面的逻辑 // 这里替换为你自己的页面遍历逻辑 const yourPageList = [/* 你的页面配置 */] yourPageList.forEach(page => { createPage({ path: page.path, component: page.componentPath, context: { // 原有上下文参数 language: page.lang, // 注入对应语言的翻译资源 locales: localeMap[page.lang] } }) }) }
- 页面组件直接从
props.pageContext.locales获取翻译数据即可,无需单独声明查询。
注意事项
如果使用方案2,需要确认gatsby-plugin-react-i18next的配置中没有开启强制页面查询的相关选项,避免和注入的上下文数据冲突。
内容的提问来源于stack exchange,提问作者seedBoot
相关产品推荐
相关产品推荐

