问题描述
上下文
我有一个Gatsby项目,我在这里使用gatsby-source-filesystem从整个站点内的YAML文件中获取内容,但这不是一个大问题(最多四页,没有博客)。
为什么要使用YAML?
选择YAML是基于以下事实:客户端不希望在其后方拥有CMS,而是要编辑文件。而且由于无法告诉人们编辑其内容的人员是否具有编程背景等知识,因此我们所有人都同意,YAML格式“容易”且“简单”,可以向团队解释,以便在完成后接管。 还需要支持以葡萄牙语(应为默认语言)和英语开头的语言。稍后,他们将决定是否需要添加其他语言。
问题
我已经修改了一些教程,并浏览了Gatsby插件目录,以获取i18n and intl支持,它们是react-i18next和react-intl这些插件背后的大多数依赖关系。实际上,有一个非常具体的名为gatsby-plugin-yaml-i18n的声音听起来像是该项目的正确选择,但是它的文档记录很差,而且在github上的文件中查看时,我真的无法理解其背后的含义,这意味着难以实现。
i18n
i18n方法的问题在于我们还真的不知道默认文本是什么,这意味着首页内容将来可能会更改,因此翻译其内容可能会成为问题。
我们知道,需要的是在我们的代码中指出每个实例的位置,以便盖茨比在构建时使用每种语言的选项(如果有任何意义的话)。
可能的解决方案(?)
总而言之,我认为最好的方法是为区域设置单独的文件,并根据用户是否切换为语言来获取其内容-如果使用默认值 示例:
./src
|- content
| |- homepage.pt-br.yaml
| |- homepage.en-us.yaml
|- template
| |- homepage.js
两个文件的结构都相似,因此编辑者可以读取两个文件并将它们中的文本关联起来。像这样:
# homepage.pt-br.yaml
titulo: "titulo principal"
texto: "texto corrido"
...
# homepage.en-us.yaml
titulo: "main header"
texto: "text fill"
尽管我不确定是否可以仅使用gatsby-source-filesystem从我的简单配置中获取它。这个想法来自以前的经验,在该经验中,我们使用了Contentful CMS,它在graphql查询中为每个节点和数组结果分别获取了区域设置。我不记得是怎么回事
完成,但类似<h1>{['pt-BR'].title</h1>
之类的东西。然后,我必须配置gatsby-node.js来基于我们所使用的语言创建上下文,设置默认值,使用适当的子句构建页面等。因此,每个页面都将调用适当的lang,并且用户可以选择它是通过开关来实现的。
我不确定从哪里开始。过去,我曾经使用过createResolvers API来处理同一个Contenful无法处理的节点,但是我不确定是否可以用它来为每种语言构建节点。
有正确的方法吗?为此我会阅读任何文档吗? 如果这个问题看起来太“不合适”,我感到抱歉。我正在努力更深入地学习React和Gatsby。
任何评论,建议和问题将不胜感激。
解决方法
我在以前的i18n Gatsby项目中使用了类似的设置,在该项目中,我们还使用文件名来分隔不同的语言(即ToList
,ToListAsync
)。
1。为每个内容文件创建一个元字段
例如,查询 async eventListener() {Notifications.events().registerNotificationOpened(async (notification: Notification,completion: () => void,action: NotificationActionResponse) => {
await this.setInititalScreen(notification.payload)
// console.log("Notification opened by device user",notification.payload);
// console.log(`Notification opened with an action identifier: ${action.identifier} and response text: ${action.text}`);
completion();
});}
将显示类似main.en.md
对于您的情况,可以在main.ko.md
或main.en.md
中执行此操作,获取yaml的父File节点,然后检查它是否包含语言字符串。我们是在{ _meta: { lang: 'en' },title: 'hello',...}
可用之前完成此操作的,因此我们在onSourceNode中使用了createSchemaCustomization
。
2。以编程方式在页面和模板上调用onSourceNode
我们有一系列已知语言
createSchemaCustomization
对于createNodeField
文件夹中的页面,我们使用createPage
将语言添加到上下文和url:
['en','ko','ja'].forEach(lang => {
createPage({
// result in url such as 'site.com/ko/main'
path: path.join('/',lang,slug),component: componentPath,context: { lang,otherContext }
})
})
3。按模板中的语言字段查询数据:
src/pages
4。使前端导航正常工作
这是最混乱的部分,我们在其中创建语言的React上下文,用它包装根,然后编写一个环绕onCreatePages
的自定义Link组件,以确保站点中的所有链接都指向同一个语言部分。
另一件事是存储用户语言选择,然后在页面加载时重定向(如果用户位于网站的“错误”语言部分)。
在实践中,我们的解决方案也稍微复杂一点,因为我们在单独的文件(exports.onCreatePages = ({ page,actions }) => {
const { createPage,deletePage } = actions
if (!page.componentPath.includes('src/pages')) {
return
}
languages.forEach(lang => {
createPage({
...page,path: path.join('/',page.path),context: { lang }
})
})
deletePage(page)
}
中有包含i18n数据的页面,并且在同一文件中具有该信息的页面。
我们还希望有一个很好的默认URL(query SomePage($lang: String!) {
myPage( _meta: { lang: { eq: $lang } } ) {
/* stuff */
}
}
),因此我们的GatsbyLink
逻辑也考虑到了这一点。
这绝对是一团糟-我们在早期的盖茨比2.0(Gatsby 2.0)中做到了这一点,当时没有很好的i18n解决方案,否则我肯定会首先寻找替代方案。
,// this code can be used to create your Gatsby JS site multilingual as well as you can pass id or data which you require to send as a parameter. to make this code works create a page name colors in your pages directory and this is now you can access your single page with multiple urls.
// http://localhost:8001/en-us/color/984 => for en-us language
// http://localhost:8000/en-ca/colour/987 => for en-ca language
// http://localhost:8000/fr-ca/couleur/987 => for fr-ca language
const path = require(`path`);
// language locales
const locales = ["en-us","en-ca","fr-ca"];
// names of pages in different locales
const colorPageNames = ["color","colour","couleur"];
// this method will automatically execute on every page creation
exports.onCreatePage = ({ page,actions }) => {
// destruct createPage and deletePage methods from actions
const { createPage,deletePage } = actions;
// Grab the keys of locales and map over them
colorPageNames.map((pagename,index) => {
// condition to match page path
if (page.path.match(/^\/color/)) {
// first delete the incoming page that was automatically created by Gatsby. if path is matched
deletePage(page);
// use the values defined in "locales" to construct the path
const localizedPath = `${locales[index]}/${pagename}`;
// match the url format of page
page.matchPath = `/${locales[index]}/${pagename}/:id`;
// call a function createPage to construcut new pages with multiple routes
return createPage({
// pass on everything from the original page
...page,// path use to create path for the new page
path: localizedPath,// pass in the locale and pagename as context to every page
context: {
locale: `${locales[index]}`,pagename: `${pagename}`,},});
}
});
};