feat(i18n): multi-language proof-of-concept (ru, de, zh-cn, hi)#593
feat(i18n): multi-language proof-of-concept (ru, de, zh-cn, hi)#593Timur Tukaev (tym83) wants to merge 10 commits into
Conversation
Add Hugo languages config and per-language content mounts (base + production override) for German, Russian, Simplified Chinese, Hindi. English stays at root (defaultContentLanguageInSubdir: false). Includes translated getting-started/_index.md for all four as the first PoC page. Verified: Hugo registers all languages and resolves all content mounts; the four language getting-started pages appear in the site model with correct URLs. Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Timur Tukaev <timur.tukaev@aenix.io>
…de/zh-cn/hi Cross-vendor validation pass: accepted Codex's accuracy/structure/fluency fixes (DE missing 'on your machine'; ZH/HI merged-line split; HI deployment-term consistency; several fluency edits). Rejected Codex's removal of source_digest/ translation_status/l10n — those are intentional pipeline metadata. Terminology decisions recorded in the glossaries. Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Timur Tukaev <timur.tukaev@aenix.io>
…d SEO blocks Transcreated _index.html (hero, taglines, benefits, features, community) for all four languages. Shortcodes, icons, URLs, code, and brand names (AWS, VMware, Kubernetes, FluxCD) preserved. Each carries an Ahrefs-derived seo: block (keyword-localized title/description/keywords — English terms kept where the data favors them) plus pipeline metadata. Terminology follows the seeded glossaries. Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Timur Tukaev <timur.tukaev@aenix.io>
…n/hi Completes the PoC-1 page set (landing + getting-started + support + blog) across four writing systems. Code blocks, slugs, taxonomy terms, commands, and URLs preserved; image bundles copied per language. Pipeline metadata + glossary terms applied. Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Timur Tukaev <timur.tukaev@aenix.io>
✅ Deploy Preview for cozystack ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
Warning Review limit reached
Next review available in: 52 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. 📝 WalkthroughWalkthroughAdds German, Hindi, Russian, and Chinese website content, configures Hugo multilingual mounts and translations, localizes homepage labels, and introduces automated i18n key and translation freshness checks in CI. ChangesMultilingual website localization
Estimated code review effort: 3 (Moderate) | ~30 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request introduces localization support for German, Russian, Simplified Chinese, and Hindi by adding translated homepages, blog posts, getting started guides, and support pages, alongside configuring Hugo mounts and language settings in hugo.yaml and config/production/hugo.yaml. The review feedback correctly identifies that the "Get Started" buttons on the localized homepages still point to the hardcoded English documentation path (/docs/get-started/) instead of their respective localized paths, which should be updated to ensure a consistent user experience.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
|
|
||
| <div class="hero-gitops"> | ||
| {{% blocks/hero title="Cozystack: Kostenlose Cloud-Plattform auf Basis von Kubernetes" color="primary" | ||
| height="auto" link_title="Erste Schritte" link_url="/docs/get-started/" %}} |
There was a problem hiding this comment.
The link_url for the "Erste Schritte" (Get Started) button is hardcoded to the root English path /docs/get-started/. Since this is the German localized homepage, it should point to the German version of the documentation to ensure a consistent localized user experience.
height="auto" link_title="Erste Schritte" link_url="/de/docs/get-started/" %}}
|
|
||
| <div class="hero-gitops"> | ||
| {{% blocks/hero title="Cozystack: Kubernetes पर आधारित मुफ़्त क्लाउड प्लेटफ़ॉर्म" color="primary" | ||
| height="auto" link_title="शुरुआत करें" link_url="/docs/get-started/" %}} |
There was a problem hiding this comment.
The link_url for the "शुरुआत करें" (Get Started) button is hardcoded to the root English path /docs/get-started/. Since this is the Hindi localized homepage, it should point to the Hindi version of the documentation to ensure a consistent localized user experience.
height="auto" link_title="शुरुआत करें" link_url="/hi/docs/get-started/" %}}
|
|
||
| <div class="hero-gitops"> | ||
| {{% blocks/hero title="Cozystack: бесплатная облачная платформа на базе Kubernetes" color="primary" | ||
| height="auto" link_title="Начать" link_url="/docs/get-started/" %}} |
There was a problem hiding this comment.
The link_url for the "Начать" (Get Started) button is hardcoded to the root English path /docs/get-started/. Since this is the Russian localized homepage, it should point to the Russian version of the documentation to ensure a consistent localized user experience.
height="auto" link_title="Начать" link_url="/ru/docs/get-started/" %}}
|
|
||
| <div class="hero-gitops"> | ||
| {{% blocks/hero title="Cozystack:基于 Kubernetes 的免费云平台" color="primary" | ||
| height="auto" link_title="开始使用" link_url="/docs/get-started/" %}} |
There was a problem hiding this comment.
The link_url for the "开始使用" (Get Started) button is hardcoded to the root English path /docs/get-started/. Since this is the Simplified Chinese localized homepage, it should point to the Simplified Chinese version of the documentation to ensure a consistent localized user experience.
height="auto" link_title="开始使用" link_url="/zh-cn/docs/get-started/" %}}
…l translation)
The translated getting-started/_index.md linked to sibling pages via
{{% ref %}}, but those siblings exist only in English (only _index is
translated in the PoC). Hugo resolves ref within the current language, so the
build failed with REF_NOT_FOUND. Point the links at the canonical English
pages instead — correct behavior for a partially-translated section and the
build passes. Verified with pinned Hugo 0.160.1 (HUGO_ENV=preview): all four
languages and all PoC pages render, navbar language switcher lists all five.
Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Timur Tukaev <timur.tukaev@aenix.io>
The landing section headings (Benefits, Features, Screenshots) and the CNCF sandbox line were hardcoded English in the home shortcodes, so they stayed English on translated pages even though the cards (from front matter) were translated. Externalize them to i18n strings (T "home_*") with en/de/ru/zh-cn/hi values. This is the correct Hugo-native way to localize layout strings, and it demonstrates UI-string localization alongside content translation. English output is unchanged; verified on pinned Hugo 0.160.1. Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Timur Tukaev <timur.tukaev@aenix.io>
The de/ru/zh-cn/hi translation files defined only the four new home_* keys, while i18n/en.toml also defines the repo-local theme keys used by layouts/ (note, warning, caution, join_community, outdated_blog__message, docs_*, ui_*). Because hugo.yaml sets enableMissingTranslationPlaceholders: true, a key missing from a language file renders a visible '[i18n] <key>' placeholder on the translated page instead of falling back to English. Add every en.toml key, translated, to all four language files so translated pages render clean. Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
The four language trees are machine-translated and awaiting native-speaker ratification. Extend the existing noindex head-end hook (already used for legacy doc versions) to emit '<meta name="robots" content="noindex, follow">' for de/ru/zh-cn/hi pages, keeping them live for review and link-following users but out of search indexes until ratified. Remove a language from the list once a native owner ratifies it. Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
Add hack/check-i18n.sh plus an i18n-lint workflow that runs on PRs touching i18n/ or content/. Two guards, no Hugo/Node needed: 1. key parity: every i18n/<lang>.toml must define exactly the same keys as i18n/en.toml, catching the missing-key -> placeholder class before it ships. 2. translation freshness: every translated page's source_digest front matter must equal the current sha256 of its English source, flagging translations that went stale after the English page changed. Populate the previously-placeholder source_digest field in all 16 translated pages with the real English-source hash (computed by the same script via 'update-digests'), so the freshness guard has a baseline. Signed-off-by: IvanHunters <xorokhotnikov@gmail.com>
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (1)
.github/workflows/i18n-lint.yml (1)
31-32: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low valueDisable credential persistence in checkout.
To improve security hygiene and prevent accidental token leakage (e.g., if artifact uploads or untrusted scripts are added later), consider explicitly disabling credential persistence for the checkout action, as this workflow does not push changes back to the repository.
♻️ Proposed fix
- name: Checkout uses: actions/checkout@v4 + with: + persist-credentials: false🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/i18n-lint.yml around lines 31 - 32, Update the Checkout step using actions/checkout@v4 to explicitly disable credential persistence by setting persist-credentials to false, while leaving the rest of the workflow unchanged.Source: Linters/SAST tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@content/de/_index.html`:
- Around line 69-70: The hero CTA uses a root-relative URL that bypasses Hugo
language routing. Update the link_url in the blocks/hero invocation for
content/de/_index.html lines 69-70, content/hi/_index.html lines 69-70,
content/ru/_index.html lines 69-70, and content/zh-cn/_index.html lines 69-70 to
target each locale’s Getting Started overview, preserving the existing hero
configuration.
In `@content/de/support.md`:
- Around line 13-14: Align the support table separator rows with their
three-column headers by removing the extra delimiter cell in
content/de/support.md lines 13-14 and content/hi/support.md lines 13-14. Do not
change the table headers or data rows.
- Line 15: Replace the invalid image alt text with a concise meaningful
description such as “Aenix logo” in the image markup at content/de/support.md
lines 15-15 and content/hi/support.md lines 15-15.
In `@content/ru/support.md`:
- Line 14: Remove the extra delimiter cell from the support-table separator in
content/ru/support.md at line 14 and content/zh-cn/support.md at line 14, so
each separator contains three cells matching the tables’ three-column headers
and rows.
- Line 15: Replace the literal Markdown expression in the logo image alt text
with meaningful provider-name text, or use an empty alt value if the logo is
decorative. Apply the same correction in content/ru/support.md at lines 15-15
and content/zh-cn/support.md at lines 15-15; no other table content needs
changing.
---
Nitpick comments:
In @.github/workflows/i18n-lint.yml:
- Around line 31-32: Update the Checkout step using actions/checkout@v4 to
explicitly disable credential persistence by setting persist-credentials to
false, while leaving the rest of the workflow unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 877b3b6f-62dd-452b-b29a-88ab4f9ae413
⛔ Files ignored due to path filters (4)
content/de/blog/2026-05-19-introducing-cozystack-wizard/cozystack-wizard.pngis excluded by!**/*.pngcontent/hi/blog/2026-05-19-introducing-cozystack-wizard/cozystack-wizard.pngis excluded by!**/*.pngcontent/ru/blog/2026-05-19-introducing-cozystack-wizard/cozystack-wizard.pngis excluded by!**/*.pngcontent/zh-cn/blog/2026-05-19-introducing-cozystack-wizard/cozystack-wizard.pngis excluded by!**/*.png
📒 Files selected for processing (30)
.github/workflows/i18n-lint.ymlconfig/production/hugo.yamlcontent/de/_index.htmlcontent/de/blog/2026-05-19-introducing-cozystack-wizard/index.mdcontent/de/docs/v1.4/getting-started/_index.mdcontent/de/support.mdcontent/hi/_index.htmlcontent/hi/blog/2026-05-19-introducing-cozystack-wizard/index.mdcontent/hi/docs/v1.4/getting-started/_index.mdcontent/hi/support.mdcontent/ru/_index.htmlcontent/ru/blog/2026-05-19-introducing-cozystack-wizard/index.mdcontent/ru/docs/v1.4/getting-started/_index.mdcontent/ru/support.mdcontent/zh-cn/_index.htmlcontent/zh-cn/blog/2026-05-19-introducing-cozystack-wizard/index.mdcontent/zh-cn/docs/v1.4/getting-started/_index.mdcontent/zh-cn/support.mdhack/check-i18n.shhugo.yamli18n/de.tomli18n/en.tomli18n/hi.tomli18n/ru.tomli18n/zh-cn.tomllayouts/partials/hooks/head-end.htmllayouts/shortcodes/home/benefits.htmllayouts/shortcodes/home/cncf.htmllayouts/shortcodes/home/features.htmllayouts/shortcodes/home/screenshot-gallery.html
| {{% blocks/hero title="Cozystack: Kostenlose Cloud-Plattform auf Basis von Kubernetes" color="primary" | ||
| height="auto" link_title="Erste Schritte" link_url="/docs/get-started/" %}} |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
The CTA button links back to the English site.
Since English is configured at the site root, the absolute path /docs/get-started/ bypasses Hugo's language routing and will immediately navigate users away from the translated site back to the English site.
To ensure users reach the translated Getting Started overview, please update this path to use a localized path or a relative path, or update the upstream blocks/hero shortcode to process link_url with relLangURL.
content/de/_index.html#L69-L70: Updatelink_urlto remain within the German locale (e.g.,/de/docs/get-started/).content/hi/_index.html#L69-L70: Updatelink_urlto remain within the Hindi locale.content/ru/_index.html#L69-L70: Updatelink_urlto remain within the Russian locale.content/zh-cn/_index.html#L69-L70: Updatelink_urlto remain within the Chinese locale.
📍 Affects 4 files
content/de/_index.html#L69-L70(this comment)content/hi/_index.html#L69-L70content/ru/_index.html#L69-L70content/zh-cn/_index.html#L69-L70
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@content/de/_index.html` around lines 69 - 70, The hero CTA uses a
root-relative URL that bypasses Hugo language routing. Update the link_url in
the blocks/hero invocation for content/de/_index.html lines 69-70,
content/hi/_index.html lines 69-70, content/ru/_index.html lines 69-70, and
content/zh-cn/_index.html lines 69-70 to target each locale’s Getting Started
overview, preserving the existing hero configuration.
| | Organisation | Kontakt | Leistungsbeschreibung | | ||
| | ------------ | ------- | ---- | ------------------ | |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Align the support table delimiter with the three-column header.
content/de/support.md#L13-L14: remove the extra delimiter cell from the separator row.content/hi/support.md#L13-L14: remove the extra delimiter cell from the separator row.
📍 Affects 2 files
content/de/support.md#L13-L14(this comment)content/hi/support.md#L13-L14
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@content/de/support.md` around lines 13 - 14, Align the support table
separator rows with their three-column headers by removing the extra delimiter
cell in content/de/support.md lines 13-14 and content/hi/support.md lines 13-14.
Do not change the table headers or data rows.
|
|
||
| | Organisation | Kontakt | Leistungsbeschreibung | | ||
| | ------------ | ------- | ---- | ------------------ | | ||
| | <img src="/img/logo.png" alt="[drawing](https://aenix.io/contact/)" width="200"/> | [Website](https://aenix.io/contact/) [LinkedIn](https://www.linkedin.com/company/aenix-io)| Wir bieten jede Art von Unterstützung: Beratung, Entwicklung fehlender Funktionen, Design sowie Hilfe bei Installation und Integration. | |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Replace the invalid Aenix alt text with a meaningful description.
content/de/support.md#L15: change the alt text to a concise description such asAenix logo.content/hi/support.md#L15: change the alt text to a concise description such asAenix logo.
📍 Affects 2 files
content/de/support.md#L15-L15(this comment)content/hi/support.md#L15-L15
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@content/de/support.md` at line 15, Replace the invalid image alt text with a
concise meaningful description such as “Aenix logo” in the image markup at
content/de/support.md lines 15-15 and content/hi/support.md lines 15-15.
| ## Эти компании предоставляют корпоративную поддержку Cozystack. | ||
|
|
||
| | Организация | Контакт | Описание услуг | | ||
| | ------------ | ------- | ---- | ------------------ | |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Align the support-table delimiter with the three-column table.
Both translations declare four delimiter cells for a table whose header and rows contain three columns.
content/ru/support.md#L14: remove the extra delimiter cell.content/zh-cn/support.md#L14: remove the extra delimiter cell.
📍 Affects 2 files
content/ru/support.md#L14-L14(this comment)content/zh-cn/support.md#L14-L14
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@content/ru/support.md` at line 14, Remove the extra delimiter cell from the
support-table separator in content/ru/support.md at line 14 and
content/zh-cn/support.md at line 14, so each separator contains three cells
matching the tables’ three-column headers and rows.
|
|
||
| | Организация | Контакт | Описание услуг | | ||
| | ------------ | ------- | ---- | ------------------ | | ||
| | <img src="/img/logo.png" alt="[drawing](https://aenix.io/contact/)" width="200"/> | [Сайт](https://aenix.io/contact/) [LinkedIn](https://www.linkedin.com/company/aenix-io)| Мы оказываем все виды помощи: консультации, разработку недостающих функций, проектирование, помощь с установкой и интеграцией. | |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Replace the literal Markdown syntax in the logo alt text.
The first logo uses alt="[drawing](...)", which is not meaningful accessible text.
content/ru/support.md#L15: use a meaningful provider name oralt=""if decorative.content/zh-cn/support.md#L15: use a meaningful provider name oralt=""if decorative.
📍 Affects 2 files
content/ru/support.md#L15-L15(this comment)content/zh-cn/support.md#L15-L15
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@content/ru/support.md` at line 15, Replace the literal Markdown expression in
the logo image alt text with meaningful provider-name text, or use an empty alt
value if the logo is decorative. Apply the same correction in
content/ru/support.md at lines 15-15 and content/zh-cn/support.md at lines
15-15; no other table content needs changing.
Summary
Proof-of-concept for website localization. Adds Russian, German, Simplified Chinese, and Hindi versions of a representative set of pages so reviewers can see all four writing systems on the real layout (typography, CJK/Devanagari rendering, the navbar language switcher) and evaluate quality.
Machine-translated and cross-checked with a second model; pending native-speaker review. This is a PoC to validate the approach end-to-end before committing to the full pipeline — a design proposal/discussion accompanies it.
Live preview
https://deploy-preview-593--cozystack.netlify.app — use the navbar language dropdown, or jump straight in:
Each language has: landing, Getting Started, Support, and the "Introducing Cozystack Wizard" blog post.
What
languages:config forru/de/zh-cn(zh-Hans) /hi, plus per-language content mounts (base + production override). English stays at the root (defaultContentLanguageInSubdir: false) — no existing URLs change; other languages live under/de/,/ru/,/zh-cn/,/hi/.content/<lang>/:_index.html) — transcreated, with keyword-localized SEO front matterdocs/v1.4/getting-started/_index.md)support.md)Why
Validate localization on the live layout before building the full automated pipeline: confirm the structure (
content/<lang>/siblings, mirroring kubernetes/website), the Docsy language dropdown, and translation/terminology quality across very different writing systems.Notes & open items
v1.4) is in scope for translation; older versions stay English._indexis translated in this PoC) — honest behavior for a partially-translated section.<html lang>/ self-canonical wiring and the automated translation pipeline come as follow-ups (covered in the design proposal).Summary by CodeRabbit