**TL;DR.** Multi-language SEO in 2026 has three rules. (1) Pick one URL structure and use it everywhere. (2) Emit reciprocal hreflang clusters that include only actually-translated locales per entity. (3) Translate the entire user journey, not just product titles. Get these right and you'll outrank single-locale competitors in each translated market.

## Why this matters in 2026

Cross-border ecommerce continues to grow. According to industry estimates, roughly 28% of global ecommerce orders crossed borders in 2025. Merchants who serve multiple regions natively rank better in those regions and convert better because the experience is localized.

AI search engines (Perplexity, ChatGPT, Claude, Google AI Overviews) handle multilingual content less elegantly than Google's classic SERP. Pages with strong locale signals — clean URLs, accurate hreflang, in-language metadata, locale-specific JSON-LD — are cited more reliably than ambiguous bilingual pages.

## Step 1: Pick a URL structure

| Structure       | Example                | Pros                                              | Cons                                          |
| --------------- | ---------------------- | ------------------------------------------------- | --------------------------------------------- |
| ccTLD           | `example.de`           | Strongest geo-signal; clear to users              | Splits domain authority; multiple SSL certs   |
| Subdomain       | `de.example.com`       | Easy to set per-region hosting                     | Treated as separate site by some signals      |
| Path prefix     | `example.com/de/`      | Consolidates authority; cheap to set up           | Slightly weaker geo-signal than ccTLD         |
| Query parameter | `example.com/?lang=de` | Easiest to add                                    | **Don't use.** Google treats as duplicate.    |

The 2026 default is **path prefix**. It's what Ordiko uses by default (`example.com/de/`, `example.com/fr/`, etc.).

## Step 2: Emit a complete hreflang cluster

For every translated URL, output:

```html
<link rel="alternate" hreflang="en" href="https://example.com/en/products/leather-bag" />
<link rel="alternate" hreflang="de" href="https://example.com/de/products/leather-bag" />
<link rel="alternate" hreflang="fr" href="https://example.com/fr/products/leather-bag" />
<link rel="alternate" hreflang="x-default" href="https://example.com/en/products/leather-bag" />
```

Rules:

1. Each URL must self-reference (the `en` URL emits `hreflang="en"` for itself).
2. Each URL must list every other variant.
3. `x-default` points at the locale you serve when no language matches (typically English or your default).
4. Use ISO 639-1 language codes (`en`, `de`, `fr`), optionally combined with ISO 3166-1 region (`en-GB`, `en-US`).
5. Don't include a variant that returns a non-200 HTTP status.

## Step 3: Filter to actually-translated entities

A common mistake: emitting the full locale set for every URL even when many entities are only translated to a subset.

**Wrong**:

```html
<!-- product only has en + de translations -->
<link rel="alternate" hreflang="en" href=".../en/products/x" />
<link rel="alternate" hreflang="de" href=".../de/products/x" />
<link rel="alternate" hreflang="fr" href=".../fr/products/x" />  <!-- returns 404 -->
```

**Right**:

```html
<link rel="alternate" hreflang="en" href=".../en/products/x" />
<link rel="alternate" hreflang="de" href=".../de/products/x" />
<link rel="alternate" hreflang="x-default" href=".../en/products/x" />
```

Ordiko implements this via `EntityForSeo.availableLocales` — every product, category, brand, and page can specify which locales it's translated into, and `alternates.languages` is the intersection of `store.supportedLocales` and `availableLocales`.

## Step 4: Translate the entire customer journey

Common gaps that hurt rankings and conversion:

| Surface                  | Translated?                                |
| ------------------------ | ------------------------------------------ |
| Meta title               | Yes (per locale)                            |
| Meta description         | Yes                                         |
| H1                       | Yes                                         |
| Breadcrumb labels        | Yes                                         |
| Category names           | Yes                                         |
| Product schema fields    | Yes (`name`, `description`, `category`)     |
| Image alt text           | Yes                                         |
| Error messages (404/410) | Yes                                         |
| Checkout copy            | Yes                                         |
| Email templates          | Yes                                         |

A page that's 80% German with English error messages and English alt text is a flag for both users and Google.

## Step 5: Configure currency and shipping per locale

Currency and locale are not the same (Switzerland uses CHF and serves German/French/Italian) but they are usually correlated. In 2026 Product schema:

```json
{
  "@type": "Offer",
  "priceCurrency": "EUR",
  "price": "49.00",
  "availability": "https://schema.org/InStock",
  "shippingDetails": [{
    "@type": "OfferShippingDetails",
    "shippingDestination": { "@type": "DefinedRegion", "addressCountry": "DE" },
    "shippingRate": { "@type": "MonetaryAmount", "value": "4.99", "currency": "EUR" },
    "deliveryTime": {
      "@type": "ShippingDeliveryTime",
      "handlingTime": { "@type": "QuantitativeValue", "minValue": 0, "maxValue": 1, "unitCode": "DAY" },
      "transitTime": { "@type": "QuantitativeValue", "minValue": 2, "maxValue": 5, "unitCode": "DAY" }
    }
  }]
}
```

Per-region pricing and shipping should match what the user sees on the page. Mismatches between schema and visible price cause Google to suppress the rich result.

## Step 6: Submit sitemaps

Two viable patterns:

**Pattern A — one sitemap per locale:**

```
/sitemap.xml (index)
/sitemap-en.xml
/sitemap-de.xml
/sitemap-fr.xml
```

**Pattern B — single sitemap with hreflang annotations:**

```xml
<url>
  <loc>https://example.com/en/products/x</loc>
  <xhtml:link rel="alternate" hreflang="de" href="https://example.com/de/products/x" />
  <xhtml:link rel="alternate" hreflang="fr" href="https://example.com/fr/products/x" />
</url>
```

Pattern A is easier to debug. Pattern B is more compact. Ordiko uses Pattern A by default.

## Step 7: Verify

In Google Search Console:

1. **Settings → International Targeting → Language tab** — shows hreflang errors.
2. **Coverage → Pages** — confirms each locale variant is indexed.
3. **Performance → Filters → Country** — confirms each locale ranks in its target region.

For AI search:

```bash
curl -A "PerplexityBot" https://example.com/de/products/x
# should return 200 with German content and German hreflang cluster
```

## Common pitfalls

- Non-reciprocal hreflang. Always emit a complete cluster.
- Wrong language codes. Use ISO 639-1 (`zh-Hans` not `zh-CN` for simplified Chinese).
- Including unreachable URLs. Filter out 404/410 targets.
- Mixing structures. Don't put German content on `/products/x?lang=de` *and* `/de/products/x`.
- Ignoring AI engines. Add Markdown twins and explicit `inLanguage` in JSON-LD.

## FAQ

**Should I use ccTLDs, subdomains, or path prefixes?**
Path prefixes (example.com/de/) are the modern default — they consolidate domain authority, are easy to configure, and Google handles them well. ccTLDs (example.de) give the strongest geo-signal but split authority. Subdomains (de.example.com) sit between. Pick path prefixes unless you have a specific reason not to.

**Does hreflang affect ranking directly?**
Not directly. Hreflang controls which locale variant Google serves to a given user — it does not boost rankings. Done correctly it prevents the wrong-language variant from outranking the right one in a given region, which translates to measurable conversion lift.

**How do AI engines handle multilingual content?**
Perplexity, ChatGPT Search, and Claude index pages independently per locale, with weaker hreflang awareness than Google. Best practice in 2026: emit a Markdown twin per locale (e.g. /de/blog/slug.md), explicitly mark inLanguage in JSON-LD, and consider llms.txt entries per locale.

**What's the most common hreflang mistake?**
Non-reciprocal links. If page A links to page B but B doesn't link back to A, Google ignores the entire cluster. Always emit a complete cluster including the self-reference.
