---
title: "Localized URLs Break hreflang: Keep One English Slug"
canonical: https://wavect.io/blog/english-slugs-vs-localized-urls-hreflang/
language: en
description: "Translated URL slugs add a per-document mapping table and a class of silent hreflang failures. The case for one language-independent slug, and the honest trade-off."
image: "https://wavect.io/img/blog/headers/header_english-slugs-vs-localized-urls-hreflang.png"
---

[**Back**](/blog/overview/)

[![Kevin Riedl](/img/team/kevin.webp)](/team/kevin-riedl/)

[Kevin Riedl](/team/kevin-riedl/) https://linkedin.com/in/wsdt

7 min read · 18 Aug 2026 Last reviewed August 18, 2026

[**Next**](/blog/can-an-ai-agent-use-your-product/)

# Localized URLs Break hreflang. We Keep One English Slug Instead.

TL;DR

Most hreflang defects on multilingual sites come from translating the URL, not from the annotations themselves. hreflang requires every page in a language set to point at every version including itself, and for each pointer to be returned by its target. With translated slugs that reciprocity depends on a correct, current mapping table between several strings per document, which produces four recurring failures: broken reciprocity after a rename, annotations pointing at redirects, dangling pointers where a translation does not exist yet, and path collisions when two documents translate to the same slug. All four appear per document rather than site-wide, so spot checks look clean. Keeping one language-independent slug makes the language graph a function of the path prefix, so hreflang can be generated from the locale list with no table to maintain, and translation parity becomes a set comparison that a build gate can enforce. The cost is real: you lose the URL keyword in every language except English. That is a weak signal next to fully translated titles, headings and body, and worth trading at four languages and several hundred routes. For a small site in one market, translate the slugs.

**Most hreflang bugs on multilingual sites are not hreflang bugs. They are slug bugs.** Translate the URL as well as the page and every rename, redirect and missing translation becomes a way for the language graph to fall apart, silently, on a subset of pages nobody is looking at.

We run this site in four languages and we deliberately do not translate slugs. The German page for AI visibility lives at `/de/services/ai-visibility/`, not at a German path. This is a real trade-off with a real cost, and we think it is the right one for most teams. Here is the reasoning, and the cost.

## What hreflang actually demands

The contract is simpler than the tooling suggests. Every page in a language set must point at every other version, including itself, and every one of those pointers must be returned by the page it points at. A self-referencing hreflang is correct and required, not a redundancy to optimise away.

That reciprocity requirement is where localized slugs get expensive. With one slug you need to know the language prefixes. With translated slugs you need a correct, current mapping table between four different strings per document, and you need it to survive every edit anyone makes.

## The four failures localized slugs create

| Failure | What causes it | Symptom |
| --- | --- | --- |
| Broken reciprocity | One locale's slug was renamed, the others still point at the old string | The language cluster splits into two clusters that each look authoritative |
| hreflang to a redirect | Annotations point at the pre-rename URL, which now 301s | The annotation is discounted, so the pages compete instead of grouping |
| Partial translation | A locale has no version of this document yet | Either a dangling pointer or a silent gap, depending on how the loop was written |
| Path collisions | Two English documents translate to the same target-language slug | One page overwrites the other, usually noticed by a customer |

None of these is unfixable. All of them are per-document, which is the problem: they appear on a handful of pages rather than site-wide, so a spot check looks clean.

## What one slug buys you

If the slug is language-independent, the language graph becomes a function of the path prefix. The template can generate every hreflang pointer from the locale list and the page's own file name, with no mapping table to maintain and nothing to drift out of sync. Reciprocity is structural rather than something you verify.

It also makes the neighbouring checks cheap. Once every locale's version of a document shares a slug, "is this document translated everywhere?" is a set comparison over file names. We gate that in the build: one script asserts that the four locales contain the same entry sets for every data file, and another compares per-locale content for drift. Both are only possible because the identifier is shared.

The same property helps machines that are not search engines. An agent that has your English URL can construct the German one by rule. Combined with a [Markdown mirror per route](/blog/agent-readable-website-llms-txt-markdown-mirrors/), that means one predictable address per document per language, with no lookup step.

## The honest cost

You lose the keyword in the URL for every language except English. For a German buyer searching a German phrase, a German slug is a small, real relevance and click-through signal, and we are choosing not to have it.

We accept that for three reasons. The URL keyword is a weak signal compared with the title, headings and body, which are all fully translated. The failure mode it prevents is silent and compounding, while the benefit it costs is small and measurable. And on a site where answer engines matter as much as search engines, a predictable address is worth more than a keyword in a path.

If your business is primarily local-language search in one market and you have two dozen pages, translate the slugs. The mapping stays small enough to keep correct by hand. The argument here is about what happens at four languages and several hundred routes, where nobody keeps a mapping table correct by hand.

## Migrating without losing the pages you have

If you already have localized slugs, this is not urgent and it is not free. When you do it:

1. Pick the English slug as the canonical one and keep it stable from then on. The rename you do now should be the last one.
2. 301 every localized slug to it, permanently. Leave those redirects in place; there is no good reason to ever remove them.
3. Regenerate hreflang from the locale list rather than from a table, and confirm every page returns a self-reference.
4. Resubmit the sitemap and ping the index-now endpoints so the change is picked up in days rather than months.
5. Check that internal links point at the new slug directly rather than through the redirect, because a site full of internal 301s is its own slow problem.

Step five is the one people skip. A redirect that is only reachable from your own navigation is a redirect you will never notice is wrong.

## Frequently Asked Questions

### Should URL slugs be translated for each language?

For a small site in one or two languages, yes, the keyword is worth having and the mapping stays manageable. Past a few hundred routes and three or more languages, one language-independent slug per document is more robust, because hreflang reciprocity then follows from the path prefix instead of a mapping table nobody keeps current.

### Is a self-referencing hreflang tag required?

Yes. Every page in a language set must list every version including itself. It is not redundant and removing it is a common cause of a language cluster being ignored.

### Does an English slug hurt local rankings?

Slightly, and honestly. You lose a weak relevance and click-through signal in the target language. Title, headings and body carry far more weight and stay fully translated, which is why we consider the trade worthwhile at scale.

### What if a page is not translated into every language yet?

Emit hreflang only for the versions that exist, and never point at a URL that is missing or redirects. A dangling annotation is worse than an absent one.

### How do we keep translations from drifting apart?

Make the shared slug the join key and check it in the build. We assert that all four locales contain the same entry sets for every data file, and compare per-locale content for drift. Both checks depend on the identifier being shared across languages.

### Do we need to keep the old localized URLs working?

Yes, permanently. 301 them to the canonical slug and leave the redirects in place. External links and citations do not get updated, and a broken old URL is a lost reference.

## Final thoughts

Translating the URL adds a per-document mapping table to a system that otherwise needs none, and every entry in that table is a chance for the language graph to break quietly.

Keep one language-independent slug, put the language in the path prefix, generate hreflang from the locale list, and gate translation parity in the build. You give up a weak keyword signal and you remove an entire class of silent failures.

## You may also like..

[**Agent-Readable Websites: llms.txt and Markdown Mirrors** The four surfaces that decide whether an answer engine can read you, and the conversion failures worth gating.](/blog/agent-readable-website-llms-txt-markdown-mirrors/) [**Wavect vs a generalist dev agency** Where the work overlaps, and where pricing and scope ownership do not.](/compare/wavect-vs-dev-agencies/)

Agent engineering

## Continue through this cluster

Coding agents, MCP, context systems, evaluation and the controls required for dependable automation.

[Start with the cornerstone**Graph Engineering for AI Agents: When Does a Knowledge Graph Pay Off?**](/blog/graph-engineering-ai-agents/)

- [Agent-Readable Websites: llms.txt, Markdown Mirrors and What Breaks](/blog/agent-readable-website-llms-txt-markdown-mirrors/)
- [Can an AI Agent Use Your Product, or Only Read About It?](/blog/can-an-ai-agent-use-your-product/)
- [Graft Review 2026: Do Agent Repo Maps Belong in Git?](/blog/graft-review-agent-repo-map/)
- [How Coding Agents Keep Token Bills in Check with Output Compression](/blog/codag-cost-control/)
- [Smarter Token Usage with Your AI Coding Agent](/blog/smarter-token-usage-with-your-ai-coding-agent/)

Inbox, without the noise

## Follow the work that matters to you

Get a short email when we publish something new. Follow the whole blog or only the problems you care about.

[**Back**](/blog/overview/)

[![Kevin Riedl](/img/team/kevin.webp)](/team/kevin-riedl/)

[Kevin Riedl](/team/kevin-riedl/) https://linkedin.com/in/wsdt

7 min read · 18 Aug 2026 Last reviewed August 18, 2026

[**Next**](/blog/can-an-ai-agent-use-your-product/)

New posts by email ×

×

Get new posts by email

A short email when we publish. Free, no tracking.

## Structured Data

```json
{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@id": "https://wavect.io/#organization",
      "@type": [
        "Organization",
        "ProfessionalService",
        "LocalBusiness"
      ],
      "employee": [
        {
          "@id": "https://wavect.io/team/kevin-riedl/#person",
          "@type": "Person",
          "jobTitle": "Managing Director",
          "name": "Kevin Riedl",
          "url": "https://wavect.io/team/kevin-riedl/",
          "worksFor": {
            "@id": "https://wavect.io/#organization",
            "@type": [
              "Organization",
              "ProfessionalService",
              "LocalBusiness"
            ]
          }
        },
        {
          "@id": "https://wavect.io/team/christof-jori/#person",
          "@type": "Person",
          "jobTitle": "Managing Director",
          "name": "Christof Jori",
          "url": "https://wavect.io/team/christof-jori/",
          "worksFor": {
            "@id": "https://wavect.io/#organization",
            "@type": [
              "Organization",
              "ProfessionalService",
              "LocalBusiness"
            ]
          }
        }
      ],
      "founder": [
        {
          "@id": "https://wavect.io/team/kevin-riedl/#person",
          "@type": "Person",
          "jobTitle": "Managing Director",
          "name": "Kevin Riedl",
          "url": "https://wavect.io/team/kevin-riedl/",
          "worksFor": {
            "@id": "https://wavect.io/#organization",
            "@type": [
              "Organization",
              "ProfessionalService",
              "LocalBusiness"
            ]
          }
        },
        {
          "@id": "https://wavect.io/team/christof-jori/#person",
          "@type": "Person",
          "jobTitle": "Managing Director",
          "name": "Christof Jori",
          "url": "https://wavect.io/team/christof-jori/",
          "worksFor": {
            "@id": "https://wavect.io/#organization",
            "@type": [
              "Organization",
              "ProfessionalService",
              "LocalBusiness"
            ]
          }
        }
      ],
      "legalRepresentative": [
        {
          "@id": "https://wavect.io/team/kevin-riedl/#person",
          "@type": "Person",
          "jobTitle": "Managing Director",
          "name": "Kevin Riedl",
          "url": "https://wavect.io/team/kevin-riedl/",
          "worksFor": {
            "@id": "https://wavect.io/#organization",
            "@type": [
              "Organization",
              "ProfessionalService",
              "LocalBusiness"
            ]
          }
        },
        {
          "@id": "https://wavect.io/team/christof-jori/#person",
          "@type": "Person",
          "jobTitle": "Managing Director",
          "name": "Christof Jori",
          "url": "https://wavect.io/team/christof-jori/",
          "worksFor": {
            "@id": "https://wavect.io/#organization",
            "@type": [
              "Organization",
              "ProfessionalService",
              "LocalBusiness"
            ]
          }
        }
      ],
      "name": "Wavect GmbH",
      "subjectOf": {
        "@id": "https://wavect.io/verified-claims.json#dataset",
        "@type": "Dataset",
        "creator": {
          "@id": "https://wavect.io/#organization",
          "@type": [
            "Organization",
            "ProfessionalService",
            "LocalBusiness"
          ]
        },
        "description": "A machine-readable registry of quantitative and qualitative claims published by Wavect, with review dates, localized page appearances and public third-party citations where available.",
        "inLanguage": "en",
        "isAccessibleForFree": true,
        "license": "https://creativecommons.org/licenses/by/4.0/",
        "name": "Wavect verified publication claims",
        "url": "https://wavect.io/verified-claims.json"
      },
      "url": "https://wavect.io/"
    },
    {
      "@id": "https://wavect.io/team/kevin-riedl/#person",
      "@type": "Person",
      "jobTitle": "Managing Director",
      "name": "Kevin Riedl",
      "sameAs": [
        "https://www.wikidata.org/wiki/Q139796365",
        "https://www.linkedin.com/in/wsdt",
        "https://github.com/wsdt"
      ],
      "url": "https://wavect.io/team/kevin-riedl/",
      "worksFor": {
        "@id": "https://wavect.io/#organization",
        "@type": [
          "Organization",
          "ProfessionalService",
          "LocalBusiness"
        ]
      }
    },
    {
      "@id": "https://wavect.io/team/christof-jori/#person",
      "@type": "Person",
      "jobTitle": "Managing Director",
      "name": "Christof Jori",
      "sameAs": [
        "https://www.wikidata.org/wiki/Q139796367",
        "https://www.linkedin.com/in/jocr77/",
        "https://github.com/jo-chris"
      ],
      "url": "https://wavect.io/team/christof-jori/",
      "worksFor": {
        "@id": "https://wavect.io/#organization",
        "@type": [
          "Organization",
          "ProfessionalService",
          "LocalBusiness"
        ]
      }
    },
    {
      "@id": "https://wavect.io/#website",
      "@type": "WebSite",
      "inLanguage": [
        "en",
        "de",
        "es",
        "zh"
      ],
      "name": "Wavect",
      "potentialAction": {
        "@type": "SearchAction",
        "query-input": "required name=search_term_string",
        "target": {
          "@type": "EntryPoint",
          "urlTemplate": "https://wavect.io/search/?q={search_term_string}"
        }
      },
      "publisher": {
        "@id": "https://wavect.io/#organization",
        "@type": [
          "Organization",
          "ProfessionalService",
          "LocalBusiness"
        ]
      },
      "url": "https://wavect.io/"
    },
    {
      "@id": "https://wavect.io/blog/english-slugs-vs-localized-urls-hreflang/#webpage",
      "@type": "WebPage",
      "dateModified": "2026-08-18",
      "inLanguage": "en",
      "isPartOf": {
        "@id": "https://wavect.io/#website",
        "@type": "WebSite"
      },
      "lastReviewed": "2026-08-18",
      "url": "https://wavect.io/blog/english-slugs-vs-localized-urls-hreflang/"
    }
  ]
}
```

```json
{
  "@context": "https://schema.org",
  "@type": "BlogPosting",
  "abstract": "Most hreflang defects on multilingual sites come from translating the URL, not from the annotations themselves. hreflang requires every page in a language set to point at every version including itself, and for each pointer to be returned by its target. With translated slugs that reciprocity depends on a correct, current mapping table between several strings per document, which produces four recurring failures: broken reciprocity after a rename, annotations pointing at redirects, dangling pointers where a translation does not exist yet, and path collisions when two documents translate to the same slug. All four appear per document rather than site-wide, so spot checks look clean. Keeping one language-independent slug makes the language graph a function of the path prefix, so hreflang can be generated from the locale list with no table to maintain, and translation parity becomes a set comparison that a build gate can enforce. The cost is real: you lose the URL keyword in every language except English. That is a weak signal next to fully translated titles, headings and body, and worth trading at four languages and several hundred routes. For a small site in one market, translate the slugs.",
  "articleBody": " Blog overview/AI and agents/Agent engineering Localized URLs Break hreflang. We Keep One English Slug Instead. TL;DR Most hreflang defects on multilingual sites come from translating the URL, not from the annotations themselves. hreflang requires every page in a language set to point at every version including itself, and for each pointer to be returned by its target. With translated slugs that reciprocity depends on a correct, current mapping table between several strings per document, which produces four recurring failures: broken reciprocity after a rename, annotations pointing at redirects, dangling pointers where a translation does not exist yet, and path collisions when two documents translate to the same slug. All four appear per document rather than site-wide, so spot checks look clean. Keeping one language-independent slug makes the language graph a function of the path prefix, so hreflang can be generated from the locale list with no table to maintain, and translation parity becomes a set comparison that a build gate can enforce. The cost is real: you lose the URL keyword in every language except English. That is a weak signal next to fully translated titles, headings and body, and worth trading at four languages and several hundred routes. For a small site in one market, translate the slugs. Most hreflang bugs on multilingual sites are not hreflang bugs. They are slug bugs. Translate the URL as well as the page and every rename, redirect and missing translation becomes a way for the language graph to fall apart, silently, on a subset of pages nobody is looking at. We run this site in four languages and we deliberately do not translate slugs. The German page for AI visibility lives at /de/services/ai-visibility/, not at a German path. This is a real trade-off with a real cost, and we think it is the right one for most teams. Here is the reasoning, and the cost. What hreflang actually demands The contract is simpler than the tooling suggests. Every page in a language set must point at every other version, including itself, and every one of those pointers must be returned by the page it points at. A self-referencing hreflang is correct and required, not a redundancy to optimise away. That reciprocity requirement is where localized slugs get expensive. With one slug you need to know the language prefixes. With translated slugs you need a correct, current mapping table between four different strings per document, and you need it to survive every edit anyone makes. The four failures localized slugs create FailureWhat causes itSymptom Broken reciprocityOne locale's slug was renamed, the others still point at the old stringThe language cluster splits into two clusters that each look authoritative hreflang to a redirectAnnotations point at the pre-rename URL, which now 301sThe annotation is discounted, so the pages compete instead of grouping Partial translationA locale has no version of this document yetEither a dangling pointer or a silent gap, depending on how the loop was written Path collisionsTwo English documents translate to the same target-language slugOne page overwrites the other, usually noticed by a customer None of these is unfixable. All of them are per-document, which is the problem: they appear on a handful of pages rather than site-wide, so a spot check looks clean. What one slug buys you If the slug is language-independent, the language graph becomes a function of the path prefix. The template can generate every hreflang pointer from the locale list and the page's own file name, with no mapping table to maintain and nothing to drift out of sync. Reciprocity is structural rather than something you verify. It also makes the neighbouring checks cheap. Once every locale's version of a document shares a slug, \"is this document translated everywhere?\" is a set comparison over file names. We gate that in the build: one script asserts that the four locales contain the same entry sets for every data file, and another compares per-locale content for drift. Both are only possible because the identifier is shared. The same property helps machines that are not search engines. An agent that has your English URL can construct the German one by rule. Combined with a Markdown mirror per route, that means one predictable address per document per language, with no lookup step. The honest cost You lose the keyword in the URL for every language except English. For a German buyer searching a German phrase, a German slug is a small, real relevance and click-through signal, and we are choosing not to have it. We accept that for three reasons. The URL keyword is a weak signal compared with the title, headings and body, which are all fully translated. The failure mode it prevents is silent and compounding, while the benefit it costs is small and measurable. And on a site where answer engines matter as much as search engines, a predictable address is worth more than a keyword in a path. If your business is",
  "articleSection": "Engineering",
  "author": {
    "@id": "https://wavect.io/team/kevin-riedl/#person",
    "@type": "Person",
    "name": "Kevin Riedl",
    "sameAs": [
      "https://www.wikidata.org/wiki/Q139796365",
      "https://www.linkedin.com/in/wsdt",
      "https://github.com/wsdt"
    ],
    "url": "https://wavect.io/team/kevin-riedl/"
  },
  "dateModified": "2026-08-18",
  "datePublished": "2026-08-18",
  "description": "Most hreflang defects on multilingual sites come from translating the URL, not from the annotations themselves. hreflang requires every page in a language set to point at every version including itself, and for each pointer to be returned by its target. With translated slugs that reciprocity depends on a correct, current mapping table between several strings per document, which produces four recurring failures: broken reciprocity after a rename, annotations pointing at redirects, dangling pointers where a translation does not exist yet, and path collisions when two documents translate to the same slug. All four appear per document rather than site-wide, so spot checks look clean. Keeping one language-independent slug makes the language graph a function of the path prefix, so hreflang can be generated from the locale list with no table to maintain, and translation parity becomes a set comparison that a build gate can enforce. The cost is real: you lose the URL keyword in every language except English. That is a weak signal next to fully translated titles, headings and body, and worth trading at four languages and several hundred routes. For a small site in one market, translate the slugs.",
  "headline": "Localized URLs Break hreflang: Keep One English Slug",
  "image": "https://wavect.io/img/blog/headers/header_english-slugs-vs-localized-urls-hreflang.svg",
  "inLanguage": "en",
  "keywords": "AI Visibility, Multilingual",
  "mainEntityOfPage": {
    "@id": "https://wavect.io/blog/english-slugs-vs-localized-urls-hreflang/",
    "@type": "WebPage"
  },
  "publisher": {
    "@id": "https://wavect.io/#organization",
    "@type": [
      "Organization",
      "ProfessionalService",
      "LocalBusiness"
    ]
  },
  "url": "https://wavect.io/blog/english-slugs-vs-localized-urls-hreflang/",
  "wordCount": 1668
}
```

```json
{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    {
      "@type": "ListItem",
      "item": "https://wavect.io/",
      "name": "Home",
      "position": 1
    },
    {
      "@type": "ListItem",
      "item": "https://wavect.io/blog/overview/",
      "name": "Blog overview",
      "position": 2
    },
    {
      "@type": "ListItem",
      "item": "https://wavect.io/blog/topics/ai-agents/",
      "name": "AI and agents",
      "position": 3
    },
    {
      "@type": "ListItem",
      "item": "https://wavect.io/blog/clusters/agent-engineering/",
      "name": "Agent engineering",
      "position": 4
    },
    {
      "@type": "ListItem",
      "item": "https://wavect.io/blog/english-slugs-vs-localized-urls-hreflang/",
      "name": "Localized URLs Break hreflang: Keep One English Slug | ",
      "position": 5
    }
  ]
}
```

```json
{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "For a small site in one or two languages, yes, the keyword is worth having and the mapping stays manageable. Past a few hundred routes and three or more languages, one language-independent slug per document is more robust, because hreflang reciprocity then follows from the path prefix instead of a mapping table nobody keeps current."
      },
      "name": "Should URL slugs be translated for each language?"
    },
    {
      "@type": "Question",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Yes. Every page in a language set must list every version including itself. It is not redundant and removing it is a common cause of a language cluster being ignored."
      },
      "name": "Is a self-referencing hreflang tag required?"
    },
    {
      "@type": "Question",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Slightly, and honestly. You lose a weak relevance and click-through signal in the target language. Title, headings and body carry far more weight and stay fully translated, which is why we consider the trade worthwhile at scale."
      },
      "name": "Does an English slug hurt local rankings?"
    },
    {
      "@type": "Question",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Emit hreflang only for the versions that exist, and never point at a URL that is missing or redirects. A dangling annotation is worse than an absent one."
      },
      "name": "What if a page is not translated into every language yet?"
    },
    {
      "@type": "Question",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Make the shared slug the join key and check it in the build. We assert that all four locales contain the same entry sets for every data file, and compare per-locale content for drift. Both checks depend on the identifier being shared across languages."
      },
      "name": "How do we keep translations from drifting apart?"
    },
    {
      "@type": "Question",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Yes, permanently. 301 them to the canonical slug and leave the redirects in place. External links and citations do not get updated, and a broken old URL is a lost reference."
      },
      "name": "Do we need to keep the old localized URLs working?"
    }
  ]
}
```
