#i18n + SEO vs. file based routing

5 messages · Page 1 of 1 (latest)

proper plinth
#

Hi folks,

I'm relatively new to Astro but already like for its easy approaches to solve most things.

I am building a multi-language page with Astro (v5.13.5). there are "hard coded" pages (e.g. imprint.astro) and also /subpage/[...slug].astro --> everything works fine, pages are generated and have their needed content (md-files).

However, SEO entered the room. SEO wants the slugs to be translated in every language. SEO also wants the hreflang alternate links (e.g. <link rel="alternate" hreflang="de" href="https://docs.astro.build/de/guides/routing/">) for each page and of course in the sitemap, in every language. This is where things get complicated for me.

example structure:

Layout:

  • ./layouts/layout.astro

Pages/Routes:

  • ./pages/en/imprint.astro
    • ./pages/de/impressum.astro
  • ./pages/en/news/[...slug].astro
    • ./pages/de/news/[...slug].astro

(two pages with translated slugs)

Content

  • ./content/en/imprint.md
  • ./content/de/impressum.md
  • ./content/de/news/weltherrschaft-fuer-dummies.md
  • ./content/en/news/world-domination-for-dummies.md

My approach so far: I added the alternate links in the content md files, in the "frontmatter" part

// impressum.md/imprint.md

alternates:
  de: impressum
  en: imprint

Now, the pages know its siblings in other languages. I can generate the alternate links for the head. But I don't know how to configure the sitemap plugin (<@&1055234544183287879>/sitemap v3.5.1) to also add the links. The sitemap config looks like that:

see next comment because its to long

#

continued from opening post

sitemap({
      i18n: {
        defaultLocale: "en",
        locales: {
          en: "en",
          de: "de",
        },
      },
      serialize(item) {
        console.log(item);
/* 
log output: {
  url: 'https://example.com/en/imprint/',
  links: undefined,
  lastmod: undefined,
  priority: undefined,
  changefreq: undefined
} 
*/
        if(!item.links) {
      console.log('NO LINKS AND I DONT KNOW HOW TO ADD THEM, MUH')
/*
I would like to have item.links to have following value:
links: [
    {
      url: 'https://example.com/de/impressum/',
      lang: 'de'
    },
    {
      url: 'https://example.com/en/imprint/',
      lang: 'en'
    }
  ],

*/
    }
        return item;
      },
})

See the comments in the js snippet above: I don't know how to go further.

Am I missing something? Is there another way of solving it?

little nexus
#

I think this is an expected limitation of the sitemap integration, because integrations currently do not have access to content collections. Unless you have a manual map of matching routes, I don't see a way to do that currently.
I can see Matt has opened a proposal in roadmap that could unlock such a use case: https://github.com/withastro/roadmap/discussions/1200

A workaround to handle this could be to create your own sitemap, without the integration, using a static file endpoint by getting inspiration in the RSS recipe.

proper plinth
#

Hi Armand,

thx for the reply. I figured the sitemap integration is not able to do that yet. I also tried third party plugins like @inox-tools/sitemap-ext without a solution. After some fiddling I now have implemented it in a bit dirty fashion with a custom sitemap integration and a tmp file, (via fs.writeFileSync() call in Layout.astro). This will do for now.

little nexus
#

Thanks for the feedback! I didn't think of Fryuni's integration! I wonder if it would be possible to pass additional data the same way he uses sitemap() per route to opt-in or not. 🤔

But any cases, yeah, I think at the moment this would require a manual approach to be able to do that unfortunately!