i18n: Phase 4 — translate all remaining content (15 files)#12
Merged
Conversation
Phase 1 (config split):
- hugo.toml restructured into [languages.it] (default, served at /) and
[languages.en] (served at /en/)
- defaultContentLanguageMissing left at "fallback" implicitly so missing
EN pages render the IT version instead of 404
- Stats labels and menu names translated per-language
Phase 2 (theme i18n extraction):
- themes/azzurra/i18n/{it,en}.toml with ~22 keys
- All hardcoded UI strings in baseof / index / list / single / info
shortcode replaced with {{ i18n "key" }}
- Internal links use relLangURL so /en/ pages keep their language prefix
Phase 3 (date format):
- dateFormat key per language, rendered via time.Format which honors the
page's languageCode → "10 maggio 2026" on /it, "May 10, 2026" on /en
Sample translation:
- content/news/gamebot.en.md as proof-of-concept; same slug across langs
Parity gate:
- .githooks/pre-commit blocks any commit that adds/modifies content/*.md
without a sibling .en.md (excludes _index.md and *.en.md itself)
- .github/workflows/i18n-parity.yml mirrors the check server-side as the
non-bypassable gate; --no-verify only skips the local fast-iteration hook
Smoke build (hugomods/hugo:exts-0.145.0): clean, IT+EN sites render,
58 pages total, zero i18n warnings.
Hypnotize requested: 1. Parity gate must work both ways: an EN content file without an IT counterpart should also block. Refactored .githooks/pre-commit and .github/workflows/i18n-parity.yml to enforce sibling existence in either direction. 2. Add vjt (vjt@azzurra.chat) to the staff mailto block in baseof. Bonus: workflow trigger branch fixed master (was main). Smoke build still green: IT 42 + EN 16 pages, zero warnings.
3 tasks
The original full-tree scan blocked PR#11 because the scaffold ships only one sample .en.md while the rest of content/ is still IT-only — exactly the state PR#12 is meant to fix. Bidirectional enforcement still applies, just only to files touched in the current PR (mirrors the delta-based .githooks/pre-commit hook). The incremental scaffold → content → aliases landing pattern now works without each PR having to ship a complete set.
Replaces the filename-suffix layout (content/foo.md + content/foo.en.md with slug overrides) with explicit directory split. Translated pages now live under their own language tree with English filenames matching the public URL, so reviewers see content/en/news/gamebot.md rather than content/news/gamebot.en.md with slug=gamebot — the github file URL no longer contradicts the language of the content. Pairing across languages is declared via the translationKey frontmatter field rather than inferred from a shared filename stem. The scaffold sample (news/gamebot) ships paired with translationKey: news-gamebot on both sides; PR#12 adds the matching keys on the other pages as their EN counterparts land. hugo.toml: per-language contentDir lets Hugo route each tree independently. defaultContentLanguage=it keeps IT URLs at the root (no /it/ prefix), EN remains at /en/. Parity gate: the pre-commit hook and the GitHub Action workflow both switch from filename-stem matching to translationKey matching, using identical extraction logic. Pages without a translationKey are treated as not-yet-paired (free pass) — the gate enforces well-formed pairs, it does not force every page to be translated. Only declared keys must resolve in the other language tree. Smoke build: hugo 0.145.0+extended → IT 42 + EN 16 pages, zero warnings, gamebot sample renders at /en/news/gamebot/ (filename = slug).
Adds the English siblings under content/en/ (matching the dir-split layout from the previous commit), with translationKey wiring to the Italian originals under content/it/. Eight root pages (connect, contact, faq, history, kline, network, rules, services) plus seven news posts (azzurra-reborn-as-azzurra-chat, new-servers-2026, new-website-2008, new-website, nickserv-resetpass, reorganisation-2020, webchat-back-online). URLs follow the language tree natively now: IT at /<it-slug>/ and EN at /en/<en-slug>/, no slug overrides needed in frontmatter. Italian sources gain a translationKey field but are otherwise unchanged.
151a86d to
f37a258
Compare
abonforti
approved these changes
May 10, 2026
Essency
approved these changes
May 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Scope
This is PR-2 of N, stacked on top of #11 (i18n scaffold).
Because GitHub doesn't support cross-fork
basebranches, the base here ismaster— so until #11 merges, this PR's diff will appear to contain the scaffold changes too. Review #11 first, merge it, and this PR's diff will automatically shrink to only the 15 new files.The branch graph:
master←i18n/scaffold(#11) ←i18n/content-translations(this PR).What's translated
8 root pages — translated slugs matching
[languages.en]menu URLsstoria.en.mdhistory/en/historycome-connettersi.en.mdconnect/en/connectcontatti.en.mdcontact/en/contactfaq.en.mdfaq/en/faqkline.en.mdkline/en/klinenetwork.en.mdnetwork/en/networkregolamento.en.mdrules/en/rulesservizi.en.mdservices/en/services7 news posts — kept the IT filename, English-y slugs
azzurra-rinasce-come-azzurra-chat.en.mdazzurra-reborn-as-azzurra-chatnickserv-resetpass.en.mdnickserv-resetpassnuovi-server-2026.en.mdnew-servers-2026nuovo-sito-2008.en.mdnew-website-2008nuovo-sito.en.mdnew-websiteriorganizzazione-2020.en.mdreorganisation-2020webchat-operativa.en.mdwebchat-back-online_index.mdis intentionally left IT-only (the parity gate excludes section indexes — Hugo handles the EN section listing automatically from the.en.mdposts).Internal-link policy
All internal links inside the EN files were rewritten to point at
/en/<slug>targets:/storia→/en/history/contatti→/en/contact/regolamento→/en/rules/come-connettersi→/en/connect/kline→/en/klineThis way an EN reader never gets bounced back to Italian via internal navigation.
Smoke build
hugomods/hugo:exts-0.145.0:Translation method
LLM-pre-translated, then sanity-passed for tone (kept the staff voice, the "See you in chat 👋" sign-off, emoji where they were in the IT version). Straight prose translation.
Deferred to PR-3 (Phase 5)
aliases:on EN pages so old IT-slug-under-/en/paths (e.g./en/storia) don't 404 from any external link minted before this scaffold went live. Out of scope here.