Comments (13)
I got a simple solution for using the changeLocale call.
Just add intl context like the plugin when you create pages from your MDX files
Here are my codes(gatsby-node.js) based on #47
const { createFilePath } = require("gatsby-source-filesystem")
const path = require("path")
const languages = ["en", "ko"] // plugin options
function flattenMessages(nestedMessages, prefix = "") {
return Object.keys(nestedMessages).reduce((messages, key) => {
let value = nestedMessages[key]
let prefixedKey = prefix ? `${prefix}.${key}` : key
if (typeof value === "string") {
messages[prefixedKey] = value
} else {
Object.assign(messages, flattenMessages(value, prefixedKey))
}
return messages
}, {})
}
const basicPages = new Map()
// Programmatically create the pages for browsing blog posts (Create Page!)
exports.createPages = async ({ graphql, actions, reporter }) => {
const { createPage } = actions
const getMessages = (path, language) => {
try {
// TODO load yaml here
const messages = require(`${path}/${language}.json`)
return flattenMessages(messages)
} catch (error) {
if (error.code === "MODULE_NOT_FOUND") {
process.env.NODE_ENV !== "test" &&
console.error(
`[gatsby-plugin-intl] couldn't find file "${path}/${language}.json"`
)
}
throw error
}
}
/**
* Basic Contents
*/
const resultsBasic = await graphql(`
query {
allMdx(
sort: { fields: [frontmatter___order], order: ASC }
filter: { frontmatter: { type: { eq: "basic" } } }
) {
edges {
node {
id
excerpt(pruneLength: 250)
frontmatter {
title
author
lang
}
fields {
slug
}
}
}
}
}
`)
// Handle errors
if (resultsBasic.errors) {
reporter.panicOnBuild(`🚨 Error while running GraphQL(resultsBasic) query.`)
return
}
console.log("resultsBasic", resultsBasic)
// you'll call `createPage` for each result
resultsBasic.data.allMdx.edges.forEach(({ node }, index) => {
let slug = node.fields.slug
basicPages.set(`${slug}`, {})
createPage({
path: slug,
// This component will wrap our MDX content
component: path.resolve(`./src/templates/blog-post-layout.js`),
context: {
id: node.id,
slug: slug,
prev: index - 1,
next: index + 1,
type: "basic",
// ADD INITL CONTEXT AT HERE
intl: {
language: node.frontmatter.lang,
languages,
messages: getMessages("./src/intl/", node.frontmatter.lang),
routed: true,
originalPath: slug.substr(3), // remove front /en or /ko strings
redirect: false,
},
},
})
})
}
// Create Slug!
exports.onCreateNode = async ({
node,
actions,
getNode,
store,
cache,
createNodeId,
}) => {
const { createNodeField, createNode } = actions
if (node.internal.type === "Mdx") {
const value = createFilePath({ node, getNode })
const newSlug =
"/" + node.frontmatter.lang + "/clone-apple-music/basic" + value
createNodeField({
// Individual MDX node
node,
// Name of the field you are adding
name: "slug",
// Generated value based on filepath with "blog" prefix
value: newSlug,
})
}
}
// remove duplicated init pages
exports.onCreatePage = async ({ page, actions }) => {
const { createPage, deletePage } = actions
// console.log('page.context.type', page.context.type)
const isBasicPage = page.context.type === "basic"
const hasInvalidBlogPath = !basicPages.has(page.path)
// If page is a blog page but has the wrong path
if (isBasicPage && hasInvalidBlogPath) {
deletePage(page)
}
}
from gatsby-plugin-intl.
I've found out a blog from Hiddentao that setup multilingual blog using this plugin with markdown.
It's ok with .md but I want to try with mdx files using gatsby-mdx. Taking the above blog and this doc as references, It seems doesn't work out with <MDXRenderer>
(haven't try it with <MDXProvider>
but that way is kinda hacky) and the process to setup this is cumbersome.
I ended up using using-i18n in the official example without any i18n library and works well with mdx file (in my case).
I still like the approach that react-intl
provides. Hope this plugin can further support creating pages with md/mdx.
from gatsby-plugin-intl.
@sn3h Hey. Look at issue #47, it's already solved :)
from gatsby-plugin-intl.
@sn3h No, it will not work with translated slug.
from gatsby-plugin-intl.
thinking about this more.. Let's say I have blog entry
`
- slug: 'test'
- localization:
- en:
- title: 'Hello'
- de:
- title: 'Guten tag'
`
- title: 'Guten tag'
- en:
then en.json and de.json and some blog.js template (using this plugin with [en, de] as languages)... If blog.js has query depending on language variable
data (filter: localization: { eq: $intl.language} }), would this plugin generate /en/blog/test and /de/blog/test correctly? Because we know the current language..
kind of brainstorming, but I hope something like this works. If I find some solution for this, I will let you know ;)
from gatsby-plugin-intl.
hmmmm...how would you go about changing this example around to support regular mdx files, rather than content coming from a cms @ruucm? It's a bit hard for me to follow :-(
The multi language mdx content is in a folder structure in the project as follows:
src
- content
- - news /* folder of the category type, due to multiple folders of content types */
- - - hipster /* name of the article for the folder */
- - - - index.en.mdx /* or index-en.mdx or anything else that works */
- - - - index.vi.mdx /* or index-vi.mdx or anything else that works */
current node file with some of my guesses as to what should be different:
const { createFilePath } = require("gatsby-source-filesystem")
const path = require("path")
const languages = ["en", "vi"] // plugin options
function flattenMessages(nestedMessages, prefix = "") {
return Object.keys(nestedMessages).reduce((messages, key) => {
let value = nestedMessages[key]
let prefixedKey = prefix ? `${prefix}.${key}` : key
if (typeof value === "string") {
messages[prefixedKey] = value
} else {
Object.assign(messages, flattenMessages(value, prefixedKey))
}
return messages
}, {})
}
const basicPages = new Map()
// Programmatically create the pages for browsing blog posts (Create Page!)
exports.createPages = async ({ graphql, actions, reporter }) => {
const { createPage } = actions
const getMessages = (path, language) => {
try {
// TODO load yaml here
const messages = require(`${path}/${language}.json`)
return flattenMessages(messages)
} catch (error) {
if (error.code === "MODULE_NOT_FOUND") {
process.env.NODE_ENV !== "test" &&
console.error(
`[gatsby-plugin-intl] couldn't find file "${path}/${language}.json"`
)
}
throw error
}
}
/**
* News Content
*/
const news = await graphql(`
query {
allMdx(
sort: { order: DESC, fields: [frontmatter___date] }
filter: { frontmatter: { category: { eq: "news" } } }
)
{
edges {
node {
id
excerpt(pruneLength: 100)
frontmatter {
title
author
language
}
fields {
slug
}
}
}
}
}
`)
// Handle errors
if (news.errors) {
reporter.panicOnBuild(`🚨 Error while running GraphQL(news) query.`)
return
}
console.log("news", news)
// you'll call `createPage` for each result
news.data.allMdx.edges.forEach(({ node }, index) => {
let slug = node.fields.slug
basicPages.set(`${slug}`, {})
createPage({
path: slug,
// This component will wrap our MDX content
component: path.resolve(`./src/templates/article.js`),
context: {
id: node.id,
slug: slug,
prev: index - 1,
next: index + 1,
category: "news",
// ADD INITL CONTEXT AT HERE
intl: {
language: node.frontmatter.language,
languages,
messages: getMessages("./src/intl/", node.frontmatter.language),
routed: true,
originalPath: slug.substr(3), // remove front /en or /vi strings
redirect: false,
},
},
})
})
}
// Create Slug!
exports.onCreateNode = async ({
node,
actions,
getNode,
store,
cache,
createNodeId,
}) => {
const { createNodeField, createNode } = actions
if (node.internal.type === "Mdx") {
const value = createFilePath({ node, getNode })
const newSlug =
"/" + node.frontmatter.language + "/" + value
createNodeField({
// Individual MDX node
node,
// Name of the field you are adding
name: "slug",
// Generated value based on filepath with "news" prefix
value: newSlug,
})
}
}
// remove duplicated init pages
exports.onCreatePage = async ({ page, actions }) => {
const { createPage, deletePage } = actions
// console.log('page.context.type', page.context.type)
const isBasicPage = page.context.type === "basic"
const hasInvalidBlogPath = !basicPages.has(page.path)
// If page is a blog page but has the wrong path
if (isBasicPage && hasInvalidBlogPath) {
deletePage(page)
}
}
...and from this I'm getting double posts for each language in the blog posts page, and then I'm getting whacky urls like this for each post, which is not working, obviously:
http://localhost:8000/en/en/hipster/index.en/
...soooooooo, yeah...
...no idea what I'm doing...
...just shooting at bugs in the desert at night over here...
from gatsby-plugin-intl.
Thanks for the hot tip @ruucm! That did the trick for me 😄
from gatsby-plugin-intl.
oh nice, i'll check it out :-)
from gatsby-plugin-intl.
@rchrdnsh You can use react-intl with MDX in the same way as with JSX.
If you want to generate pages programmatically, and keep separate files for different languages, you should not rely on this plugin i think. It's different task.
@darekaze If I understand correctly all page translations are sent to the client. Not perfect solution for me. I personally did this by passing correct data into the context of the page that was already generated by gatsby-plugin-intl
. Also found out some bug (#43) on the way :)
from gatsby-plugin-intl.
If I understand you correctly, you need to transform parts of any data format, which go something like this:
- slug : 'blogPost'
- en
- title
- text
- es
- title
- text
into 2 pages. /en/blogPost and /es/blogPost, each using adequate subtree of data.. if you tell Gatsby to create pages for each language, this plugin creates another language mutations for each of them, so you would have to intercept and delete them in the gatsby-node. Something like
onCreatePage ...
if(page.url.contains('/en/de/')) deletePage(page)
I just thought that up, want to try it in few days, but might not work. I am still beginner at this :)
from gatsby-plugin-intl.
@angrypie thank you, but will it work with changeLocale call?
from gatsby-plugin-intl.
Hi @darekaze,
I checked out the official 'using-i18n' example and mostly everything looks good, except for the language switcher at the top, which takes the user back to the homepage of the other language, rather than staying on the current page, which is a biiiiiiiiiiiiiiiiiiiiig UI/UX no-no. Trying to figure out how to make a switcher that stays on the same page using that example, but I don't really know how to go about it.
If you have any thoughts, I'm all ears.
from gatsby-plugin-intl.
Is there any real solution to avoid the duplicates??
http://localhost:8000/en/en/SLUG/index.en/
http://localhost:8000/es/es/SLUG/index.es/
Thanks :)
from gatsby-plugin-intl.
Related Issues (20)
- Updated json needs clear cache in order to show changes on the page HOT 2
- Sitemap problems HOT 4
- redirect option creates problems with routers HOT 1
- Getting Error: Cannot find react-intl/locale-data/hk in Safari HOT 1
- Updating locales requires cleaning .cache HOT 2
- Distinguish between default display/redirect language and default messages language
- Is this project abandoned? HOT 8
- Fork and link this repo? HOT 1
- Styling a specific language HOT 1
- gatsby-plugin-intl is not compatible with your gatsby version 3 HOT 2
- How to use with Storybook? HOT 3
- Problem when using gatsby-plugin-transition-link and gatsby-plugin-intl. HOT 1
- Best practice for translate keywords ( react helmet ) & alt image description HOT 1
- ngeLoc
- Load component inside `wrapPageElement` fails HOT 1
- Is this plugin going to be updated to supported gatsby version 4.x.x? HOT 7
- Dynamic translation keys from json are not extracted
- How do I use this together with slices? HOT 1
- Wrong import of @formatjs locale-data
- All locale data included in bundle HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from gatsby-plugin-intl.