There is a guide to do i18n right way: often you need to set alternate URLs for the same page. Right now there are just 3 attributes for URL, which can be overwritten: 'url', 'changefreq' and 'priority', proof.
I think it should be something like an argument of createPage() function with the name like 'alternates':
createPage({
path: '/example/english/',
component: path.resolve('src/templates/index.js'),
context: {
...
},
alternates: [
{
url: '/example/deutsch/',
hrefLang: 'de'
}
]
})
The motivation is an ability to generate internationalized sitemaps in the future.
I wish this was already possible :)
Btw, small typo in the issue name: atrubute -> attribute.
+1
alternates could be stuffed in context? I'm trying to wrap my head around some universal i18n solution for gatsby as well, would be nice to have it as dynamic as possible to allow for different methods like subdomain and directory based routes
Heya! 👋
For those stumbling across this issue looking to internationalize a sitemap of their own, I do have a bit of good news 😄gatsby-plugin-sitemap actually does support internationalized sitemaps. It just takes a little bit of extra code.
Let's say your website is https://sitemaps.com and your Spanish version is https://sitemaps.com/es, you will want to add the links property with an array of three alternative links: English, Spanish, and a default for a fall-back in case the page hasn't been translated to the user's preferred language just yet.
Here's how that works:
// In your gatsby-config.js
siteMetadata: {
siteUrl: `https://sitemaps.com`,
},
plugins: [
{
resolve: `gatsby-plugin-sitemap`,
options: {
query: `
{
site {
siteMetadata {
siteUrl
}
}
allSitePage {
edges {
node {
path
}
}
}
}`,
serialize: ({ site, allSitePage }) => allSitePage.edges
.map(edge => {
return {
url: site.siteMetadata.siteUrl + path, // https://sitemaps.com/page-path
changefreq: 'daily',
priority: 0.7,
links: [
// https://sitemaps.com/page-path
{ lang: 'en', url: site.siteMetadata.siteUrl + path },
// https://sitemaps.com/es/page-path
{ lang: 'es', url: `${site.siteMetadata.siteUrl}/es${path}` },
// The default in case page for user's language is not localized.
{ lang: 'x-default', url: site.siteMetadata.siteUrl + path }
]
};
})
}
}
]
With this good news, I bring a slight round of bad news 🤷♂️ This will cause most web-viewers to not be able to pretty print the sitemap anymore. For an in-depth reason as to why, check out How to indicate alternate languages pages?. The sitemap is still a valid sitemap, however.
Could this be generalized and made a bit more dynamic? I'd say so. Just wanted to put it out there that it is possible with the current state-of-affairs 💙
Hiya!
This issue has gone quiet. Spooky quiet. 👻
We get a lot of issues, so we currently close issues after 30 days of inactivity. It’s been at least 20 days since the last update here.
If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!
Thanks for being a part of the Gatsby community! 💪💜
Hey again!
It’s been 30 days since anything happened on this issue, so our friendly neighborhood robot (that’s me!) is going to close it.
Please keep in mind that I’m only a robot, so if I’ve closed this issue in error, I’m HUMAN_EMOTION_SORRY. Please feel free to reopen this issue or create a new one if you need anything else.
Thanks again for being part of the Gatsby community!
Heya! 👋
For those stumbling across this issue looking to internationalize a sitemap of their own, I do have a bit of good news 😄gatsby-plugin-sitemap actually does support internationalized sitemaps. It just takes a little bit of extra code.
I tried the suggested approach, but for me it is not working. The sitemap can no longer be pretty printed, but pages still don't have hreflang tags in them.
Usage in serialize function:
return {
url: site.siteMetadata.siteUrl + edge.node.path,
changefreq: `daily`,
priority: 0.7,
links: [
{ lang: 'en', url: `${site.siteMetadata.siteUrl}/en/${purePath}` },
{ lang: 'ar', url: `${site.siteMetadata.siteUrl}/ar/${purePath}` },
{ lang: 'x-default', url: `${site.siteMetadata.siteUrl}/${purePath}` }
]
}
@tinder-kyleboss not sure I understand your use case correctly yet as I see it it'll generate one sitemap with links to all pages in all languages right?
Does that make sense for Google?
And I don't understand where you get path from? Is it declared somewhere at the top?
I do it like this right now
const getSitemapForLanguage = lang => ({
output: `/${lang}/sitemap.xml`,
exclude: [`/${lang}/thanks`, `/${lang}/danke`, `/${lang}/404`],
createLinkInHead: false, // done manually in MainLayout
query: `
{
site {
siteMetadata {
siteUrl
}
}
allSitePage( filter: { path: { regex: "/^\/${lang}\//" } } ) {
edges {
node {
path
}
}
}
}`,
serialize: ({ site, allSitePage }) =>
allSitePage.edges.map(edge => ({
url: site.siteMetadata.siteUrl + edge.node.path,
changefreq: `daily`,
priority: 0.7,
})),
})
then in plugins array
[
{
resolve: `gatsby-plugin-sitemap`,
options: getSitemapForLanguage(`en`),
},
{
resolve: `gatsby-plugin-sitemap`,
options: getSitemapForLanguage(`de`),
},
]
could of course be looped sthg like
plugins.push([`en`, `de`].forEach(lang => {
resolve: `gatsby-plugin-sitemap`,
options: getSitemapForLanguage(lang),
}))
especially having more languages..
I define alternate languages in my layout file using (still) react-helmet
Or am I missing the point here?
@assainov Maybe it is of any help to you?
thanks @tinder-kyleboss it works for me, but is there any workaround to get it pretty-printed, or customize sitemap styling
@asainov maybe this could be of help, this is my working solution, tho its still not pretty printed
{
resolve: `gatsby-plugin-sitemap`,
options: {
query: `
{
site {
siteMetadata {
siteUrl
}
}
allSitePage {
edges {
node {
path
}
}
}
}`,
serialize: ({ site, allSitePage }) =>
allSitePage.edges.map((edge) => {
const { path } = edge.node
const pathArray = path.split('/')
const currentLang = pathArray[1]
const checkLang = currentLang.replace('-', '_')
let currentPage = path
const keyLanguages = ['en', 'id']
if (keyLanguages.includes(checkLang)) {
pathArray.splice(1, 1)
currentPage = pathArray.join('/')
}
const sitemapLangs = keyLanguages.concat(['x-default'])
const links = sitemapLangs.map((locale) => {
const replacedLocale = locale.replace('_', '-')
const isDefault = locale === 'en' || locale === 'x-default'
const hrefLocale = isDefault ? '' : `/${replacedLocale}`
const href = `${site.siteMetadata.siteUrl}${hrefLocale}${currentPage}`
return { lang: replacedLocale, url: href }
})
return {
url: site.siteMetadata.siteUrl + path, // https://sitemaps.com/page-path
changefreq: 'daily',
priority: 0.7,
links,
}
}),
},
},
Most helpful comment
Heya! 👋
For those stumbling across this issue looking to internationalize a sitemap of their own, I do have a bit of good news 😄gatsby-plugin-sitemap actually does support internationalized sitemaps. It just takes a little bit of extra code.
Let's say your website is https://sitemaps.com and your Spanish version is https://sitemaps.com/es, you will want to add the links property with an array of three alternative links: English, Spanish, and a default for a fall-back in case the page hasn't been translated to the user's preferred language just yet.
Here's how that works:
With this good news, I bring a slight round of bad news 🤷♂️ This will cause most web-viewers to not be able to pretty print the sitemap anymore. For an in-depth reason as to why, check out How to indicate alternate languages pages?. The sitemap is still a valid sitemap, however.
Could this be generalized and made a bit more dynamic? I'd say so. Just wanted to put it out there that it is possible with the current state-of-affairs 💙