Skip to content

feat(SEO/i18n): add alternate links for multilingual pages - #3524

Merged
SoonIter merged 8 commits into
mainfrom
fix/i18n-alternate-links
Jul 16, 2026
Merged

SoonIter merged 8 commits into
mainfrom
fix/i18n-alternate-links

Conversation

@SoonIter

@SoonIter SoonIter commented Jul 15, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Add reciprocal rel="alternate" and hreflang links to the document head for multilingual routes that actually exist.
  • Keep generated URLs consistent with base, siteOrigin, and route.cleanUrls across SSG, CSR fallbacks, and the experimental SSG worker.
  • Cover the behavior with unit and production E2E tests, and document it in the English and Chinese guides.

Example

Given the following configuration:

import { defineConfig } from '@rspress/core';

export default defineConfig({
  base: '/docs/',
  siteOrigin: 'https://example.com',
  locales: [
    { lang: 'en', label: 'English' },
    { lang: 'zh', label: '简体中文' },
  ],
});

When both /guide and /zh/guide exist, Rspress adds the reciprocal links to both documents:

<link rel="alternate" hreflang="en" href="https://example.com/docs/guide.html">
<link rel="alternate" hreflang="zh" href="https://example.com/docs/zh/guide.html">

Only translations that actually exist are included. Locale IDs containing underscores keep their route path while the generated hreflang value uses hyphens:

<link rel="alternate" hreflang="en-US" href="https://example.com/docs/en_US/guide.html">

Related Issue

Related to #3512.

Checklist

  • Tests updated (or not required).
  • Documentation updated (or not required).

Copilot AI review requested due to automatic review settings July 15, 2026 09:26

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds automatic rel="alternate"/hreflang link generation for multilingual routes during production rendering, ensuring URLs respect base, siteOrigin, and route.cleanUrls, and documents/tests the behavior across unit + e2e fixtures.

Changes:

  • Generate per-route alternate-language link sets from the route list and inject them into the rendered HTML <head>.
  • Thread alternate-link data through SSG (including CSR fallbacks) and the experimental SSG worker.
  • Add unit + production e2e coverage, and document multilingual SEO behavior in EN/ZH guides.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
website/docs/zh/guide/basic/i18n.mdx Documents multilingual SEO alternate link generation (ZH).
website/docs/zh/guide/advanced/custom-head.mdx Adds alternate-link tag to the auto-injected head tag list (ZH).
website/docs/en/guide/basic/i18n.mdx Documents multilingual SEO alternate link generation (EN).
website/docs/en/guide/advanced/custom-head.mdx Adds alternate-link tag to the auto-injected head tag list (EN).
packages/core/src/node/ssg/renderPageWorker.ts Passes per-route alternate links into worker rendering.
packages/core/src/node/ssg/renderPages.ts Computes alternate links once and wires them through SSG/CSR/worker paths.
packages/core/src/node/ssg/renderPage.ts Extends renderPage to accept alternate links and forwards them to template rendering.
packages/core/src/node/ssg/renderHtmlTemplate.ts Injects alternate link tags at HEAD_MARKER and standardizes attribute spacing.
packages/core/src/node/ssg/alternateLinks.ts Implements alternate link computation (grouping by route + version + language).
packages/core/src/node/ssg/alternateLinks.test.ts Unit tests for alternate link generation + head injection.
e2e/fixtures/i18n/rspress.config.ts Sets siteOrigin for deterministic absolute alternate-link URLs in build output.
e2e/fixtures/i18n/index.test.ts Adds production-build assertions for reciprocal alternate links in generated HTML.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/core/src/node/ssg/alternateLinks.ts Outdated
Comment thread packages/core/src/node/ssg/renderPages.ts Outdated
Comment thread packages/core/src/node/ssg/renderPages.ts Outdated
Comment thread packages/core/src/node/ssg/renderPageWorker.ts Outdated
Comment thread packages/core/src/node/ssg/renderPageWorker.ts Outdated
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 15, 2026 •

Copy link
Copy Markdown

Deploying rspress-v2 with  Cloudflare Pages  Cloudflare Pages

Latest commit: bad42d6
Status: ✅  Deploy successful!
Preview URL: https://8797863c.rspress-v2.pages.dev
Branch Preview URL: https://fix-i18n-alternate-links.rspress-v2.pages.dev

View logs

@SoonIter SoonIter changed the title feat(core): add alternate links for multilingual pages feat(SEO/i18n): add alternate links for multilingual pages Jul 16, 2026
@SoonIter
SoonIter force-pushed the fix/i18n-alternate-links branch from 0fcd680 to 351183d Compare July 16, 2026 07:47

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 351183dbf1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/core/src/node/ssg/alternateLinks.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8bb6fab75b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/core/src/node/ssg/alternateLinks.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ef638a695a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/core/src/node/ssg/alternateLinks.ts Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated no new comments.

@SoonIter
SoonIter requested a review from Timeless0911 July 16, 2026 09:57
@SoonIter
SoonIter enabled auto-merge (squash) July 16, 2026 09:58
@SoonIter
SoonIter merged commit 92f9166 into main Jul 16, 2026
7 checks passed
@SoonIter
SoonIter deleted the fix/i18n-alternate-links branch July 16, 2026 10:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants