Skip to content

Internationalization (i18n) following good practices - #1344

Merged
mlinksva merged 4 commits into
github:gh-pagesfrom
ContribuLibre:i18n-multilingual
Jul 12, 2026
Merged

Internationalization (i18n) following good practices#1344
mlinksva merged 4 commits into
github:gh-pagesfrom
ContribuLibre:i18n-multilingual

Conversation

@1000i100

Copy link
Copy Markdown
Contributor

This adds multilingual support. It leads with the live demo and the
practices you've asked for in the past (#68, #586), to show up front they're respected.

Good practices requested in #68 / #586 — and how this PR follows them

  • License legal text is never translated. Every _licenses/*.txt body is
    byte-for-byte unchanged; only the non-legal summaries and the interface are translated.
  • No license metadata is touched. Front matter (spdx-id, permissions, …) is
    unchanged, so licensee and the existing specs see exactly what they see today.
  • English is the single source of truth, never duplicated. Summaries stay in the
    .txt front matter, rule labels in _data/rules.yml; translations are overlays with
    automatic fallback to English. (Prose pages are one file per language — a translation,
    not a copy of the English page.)
  • English stays at the root. /licenses/mit/ is still English; only translations
    are prefixed (/fr/…). No /en-US/ redirects.
  • Existing tests still pass, and incomplete translations can't break the build
    (English fallback) — see Tests.
  • Works without JavaScript. The selector is plain links and every page has its
    own URL; JS only adds conveniences (remembering a choice, suggesting the browser
    language), never a forced redirect.
  • Minimal review/maintenance burden. Once crowd-sourced translation is wired up
    with Weblate (see WEBLATE.md), translations are maintained by the
    community with minimal effort from you — you mostly review and merge the pull requests
    Weblate opens, and an incomplete or outdated language always falls back to English, so
    nothing breaks.
  • Kept simple. Adding a language is a single line in _config.yml; from there
    every translation file — the YAML overlays and the per-page Markdown — is optional,
    with English filling in anything left untranslated.

What it adds

  • Per-language URLs via jekyll-polyglot, generated from the single English sources.

  • A deliberate split, so the right people work on the right parts and legal text is
    never touched:

    What Where Falls back to
    Interface — buttons, menus, headings, rule labels, home/appendix keyed YAML: _data/i18n/<lang>/ui.yml, rules.yml English
    Prose pages — About, Community, No License, Non-Software one Markdown file per language: about.<lang>.md, … the English page
    License summaries (no legal value) — description/how/note _data/i18n/<lang>/licenses.yml the .txt front matter
    License legal text — the body of _licenses/*.txt never translated
  • SEO: hreflang + x-default, localized <html lang>/dir (RTL), per-language
    <title>, meta description, Open Graph and og:locale, sitemap with the translated URLs.

  • Docs: TRANSLATING.md and WEBLATE.md.

Languages

The non-English translations are initial, AI-assisted drafts to be refined by native
speakers via Weblate.

Build & deploy

jekyll-polyglot isn't a GitHub Pages plugin, so the site must be built and deployed by a
GitHub Actions workflow (the opensource.guide approach), with the base path taken from
actions/configure-pages so the same workflow serves a domain root or a sub-path. This
exact pipeline runs the live demo above. The only manual, one-time step:

Settings → Pages → Build and deployment → Source → "GitHub Actions"

Tests

Existing specs and HTML-Proofer pass. spec_helper skips polyglot during the bare
site.read so collection counts stay exact. A small, non-blocking spec/i18n_spec.rb
guards the i18n layer — it flags a template referencing a missing key or a translation
using an unknown key/id, but never requires a translation to be complete. So community
translation PRs are validated automatically, at no cost to you.

How this PR is organized (4 commits)

  1. Internationalization infrastructure (English only) — all the plumbing; no
    visible change to the English site.
  2. French — the first real translation.
  3. Spanish, Portuguese, Chinese, Korean and Arabic — the remaining languages.
  4. Serve under a sub-path — makes the site work under a base path (no-op at a domain
    root). Independent of i18n; kept separate so you can review or drop it alone.

Each commit stands on its own, so you can review — or even merge — them incrementally.

@1000i100
1000i100 force-pushed the i18n-multilingual branch 3 times, most recently from 7ff8c25 to 6fc150f Compare June 19, 2026 06:27
@1000i100

Copy link
Copy Markdown
Contributor Author

@mlinksva could you review this PR ? I would like to know if merging it is an option (perhaps with some changes, tell-me), or if I should register another domain name to host an i18n fork ?

@mlinksva

Copy link
Copy Markdown
Contributor

Hi @1000i100 thanks for this! The live demo looks great and I appreciate all of the attention to feedback I've long forgotten. Current test failure is unrelated (fix in #1345). I need to figure out a CodeQL issue currently blocking merges but I see no obstacle to merging this once I do.

@1000i100
1000i100 force-pushed the i18n-multilingual branch from 6fc150f to da77afa Compare June 24, 2026 17:01
1000i100 and others added 4 commits July 10, 2026 15:26
Make the site translatable without changing the English site. jekyll-polyglot
serves the default language at the root and each other language under its own
prefix from the same sources, with automatic fallback to English. Adds the
translation lookups (t.html / tmd.html), the no-JS language selector plus a
progressive browser-language suggestion, localized hreflang/canonical/og:locale,
and a per-language Markdown page mechanism (i18n/<lang>/<page>.md overrides the
English page, which is the fallback).

Translations live in two mirrored trees, each with a README: _data/i18n/<lang>/
holds the keyed strings (YAML) and i18n/<lang>/ holds the prose pages (Markdown).
Because polyglot isn't a GitHub Pages plugin, the site is built and deployed via a
GitHub Actions workflow (the only one-time maintainer step: set Pages' source to
"GitHub Actions"). Includes a small non-blocking i18n spec, the English base
(_data/i18n/en/ui.yml), and docs (TRANSLATING.md, WEBLATE.md). No language other
than English is enabled yet, so there is no visible change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Enable French (fr): the interface, rule labels and license summaries
(_data/i18n/fr/*) plus the French prose pages (i18n/fr/*.md). It's an initial,
partially-reviewed translation meant to be refined by the community via Weblate;
anything missing falls back to English. French is included as the maintainer's
native language and the most-reviewed in the demo.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Enable es, pt, zh, ko and ar: their interface/summaries/rules data and prose pages
(i18n/<lang>/*.md), each falling back to English where incomplete. These are
initial, AI-assisted drafts to be refined via Weblate, seeded by earlier requests —
Spanish (github#1034), Portuguese (github#586), Chinese (github#67, github#72), Korean (github#62). Arabic is
included to exercise right-to-left support (text_direction drives <html dir> with a
[dir="rtl"] mirror; the legal <pre> stays ltr).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
So the site also works when served from a sub-path (e.g. a GitHub Pages project
site, or a staging deploy) — not only at a domain root. Root-relative links in
page bodies and license summaries are prefixed with site.baseurl at a single
injection point, the chrome uses relative_url, and the deploy builds with the
base path GitHub Pages reports (actions/configure-pages' base_path). When baseurl
is empty (a domain root, e.g. the upstream site) every change is a no-op.

This is independent of the i18n feature; it's kept as its own commit so it can be
reviewed — or dropped — on its own.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@1000i100
1000i100 force-pushed the i18n-multilingual branch from da77afa to 06151ec Compare July 10, 2026 13:27
@1000i100

1000i100 commented Jul 10, 2026

Copy link
Copy Markdown
Contributor Author

Rebase done ! @mlinksva could you re-allow the workflow to see if it work well this time ?

@1000i100

Copy link
Copy Markdown
Contributor Author

It fail for network check not changed in my PR. Do you prefer merge it anyway ? Or i add fix for this but it's out of the initial scope ? (and fix look like disable network check on ratio limited domains).
Or would you like an other pull request dedicated for this issue ? (perhapse with network cache mecanisme to fit in quota, or failsafe on archive.org version)... Tell me ;)

@mlinksva

Copy link
Copy Markdown
Contributor

@1000i100 don't worry about the flaky unrelated test. I think this is good to go.

I'll try to merge it this weekend. I need some time set aside because I believe a non-code configuration change is needed (switching from GitHub Pages default publication to Actions) and not having done that before I'm not 100% confident something unexpected won't need fixing.

@mlinksva
mlinksva merged commit 330adfd into github:gh-pages Jul 12, 2026
4 of 5 checks passed
@mlinksva

Copy link
Copy Markdown
Contributor

And it appears to have worked! (For the record, simply switching repo config from default/classic Pages to Actions-based workflow was all I needed to do.)

Many many thanks to @1000i100 for pulling this together very carefully and to @matbrgz and @benbalter others over the years for very patiently prototyping and suggesting solutions including some other single language forks such as from @tarciozemel and @damicofj and @weakish and @mickaelandrieu.

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.

2 participants