International SEO: hreflang and canonicalId in Astro
How to organize trilingual Astro pages with hreflang, canonical URLs, and canonicalId without creating route chaos.
Publishing in three languages looks simple until the first detail breaks: one version points to the wrong slug, another forgets the canonical URL, and the third does not appear in the language switcher. International SEO does not start with translation. It starts with organization.
In Astro, that organization can stay simple if each post has a shared editorial identity across languages.
The problem with loose translations
When each language is born as an independent file, the site gains freedom, but also risk. The Portuguese post can have one slug, the English version another, and the Spanish version another. That is normal. The problem is losing the relationship between them.
Without that relationship, it becomes harder to generate alternate links, build the language switcher, and signal to search engines that those pages are equivalent versions of the same content.
CanonicalId as editorial glue
The canonicalId solves this as an editorial key. It does not need to be the URL. It needs to be the stable identifier of the subject.
Example:
- PT:
seo-internacional-hreflang-canonicalid-astro - EN:
international-seo-hreflang-canonicalid-astro - ES:
seo-internacional-hreflang-canonicalid-astro
The slugs can change by language, but the canonicalId remains the same. With that, the code can find related translations and build alternates.
Hreflang in the layout layer
hreflang should not be written manually in each post. That creates repetition and silent errors.
The best place for this logic is the layout. The page calculates the alternates, passes them to the layout, and the layout renders:
pt-BRenesx-default
That keeps content focused on the article, while the infrastructure handles technical signals.
The routine that prevents errors
Every new trilingual publication should pass through a short list:
- Does the same
canonicalIdexist in all three versions? - Does each
canonicalpoint to the correct final URL? - Does the
languagefield match the folder? - Does the language switcher point to the equivalent version?
- Did the static build generate all three routes?
This checklist looks small, but it prevents most problems. Good technical SEO is much less about tricks and much more about consistency.