Skip to content

Send the docs to Crowdin with the app's strings - #159

Merged
feruzm merged 2 commits into
developmentfrom
chore/docs-to-crowdin
Sep 21, 2026
Merged

feruzm merged 2 commits into
developmentfrom
chore/docs-to-crowdin

Conversation

@feruzm

@feruzm feruzm commented Sep 21, 2026

Copy link
Copy Markdown
Member

Part of #152, the pipeline half.

The docs pages and pages.json (the titles and descriptions) become Crowdin sources, so an edit to an English page reaches translators the same way a new app string does. Translations land in the folder the app already reads, src/docs/<code>/, using the app's own short code rather than a locale, because the URL carries it (/docs/de/oauth2). Chinese is the only pair whose two letters would collide, so zh-CN and zh-TW are named explicitly.

The upload workflow watched only src/i18n/locales/en-US.json; it now watches src/docs/en/** and this config too.

What this does not do

The 16 English pages are 18,908 words. Translating them into the other 24 languages is about 454,000 words, which is a Crowdin job with a proofreading pass per language, not a repo edit. Nothing can flow until the repository variable CROWDIN_PROJECT_ID and the secret CROWDIN_PERSONAL_TOKEN are set, which is still open from #144.

Already in place from #151, so #152 needs nothing more here:

  • a page a language has not translated yet shows the English page with a note, never a blank or broken page
  • docs.test.ts compares each translation with its English source and fails on a changed heading id, a lost or altered code block, or a changed link
  • DOC_LANGUAGES in src/docs/content.ts is checked against the folders that exist, so a language appears in the app only once its folder is there

Verification

crowdin.yml and the workflow both parse. Docs tests 8/8, typecheck clean.

The docs pages and their titles become Crowdin sources, so an edit to an
English page reaches translators the way a new string does, and every
language lands in the folder the app reads: src/docs/<code>/, by the app's
own short code, because the URL carries it. Chinese is the only pair whose
two letters would collide, so both forms are named.

The upload workflow now watches the docs and this file too, not only the
dictionary.
@qodo-code-review

Copy link
Copy Markdown

ⓘ Qodo reviews are paused because your trial has ended. Ask your workspace admin to add credits to resume reviews. Manage billing

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Upload documentation sources to Crowdin

✨ Enhancement ⚙️ Configuration changes 🕐 10-20 Minutes

Grey Divider

AI Description

• Upload English documentation pages and metadata to Crowdin alongside application strings.
• Write translations into app-compatible folders, preserving distinct Chinese language codes.
• Trigger uploads when English documentation or Crowdin mappings change.
Diagram

graph TD
  SOURCES["English sources"] --> FILTER["Path filters"] --> UPLOAD["Upload workflow"] --> CROWDIN[("Crowdin project")] --> DOWNLOAD["Download workflow"] --> OUTPUT["Localized docs"]
  CONFIG["Source mappings"] --> UPLOAD
Loading
High-Level Assessment

The current approach appropriately extends the existing Crowdin pipeline rather than introducing a separate documentation translation process. Using app language codes for destination folders matches runtime routing, while explicit zh-CN and zh-TW mappings prevent the only two-letter-code collision; locale-based destinations were considered but would not match the app's documentation paths.

Files changed (2) +30 / -3

Enhancement (1) +24 / -0
crowdin.ymlMap documentation sources and translations +24/-0

Map documentation sources and translations

• Adds Crowdin source entries for English Markdown pages and pages.json metadata, targeting src/docs/<code>/. Explicit mappings preserve distinct zh-CN and zh-TW destinations while other languages use their two-letter app codes.

crowdin.yml

Other (1) +6 / -3
crowdin-upload.ymlTrigger Crowdin uploads for documentation changes +6/-3

Trigger Crowdin uploads for documentation changes

• Expands the development-branch path filters to include English documentation and crowdin.yml. The workflow comments now describe both application-string and documentation uploads.

.github/workflows/crowdin-upload.yml

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Translated docs never reach the app ✓ Resolved 📎 Requirement gap ☼ Reliability
Description
crowdin-download.yml checks and stages only src/i18n/locales, even though crowdin.yml writes
translated Markdown and pages.json under src/docs//. On docs-only exports the workflow reports
“No translation changes,” while mixed exports commit only dictionaries, leaving documentation
outside the generated pull request and discarded with the runner.
Code

crowdin.yml[R26-27]

+  - source: /src/docs/en/*.md
+    translation: /src/docs/%two_letters_code%/%original_file_name%
Evidence
The Crowdin configuration places both translated documentation file types beneath src/docs, while
the workflow’s quiet change check and git add commands are restricted to src/i18n/locales. This
proves that generated documentation is never committed for the runtime to load and that later
documentation edits cannot flow through the established translation pipeline required by compliance
rule 13.

Integrate documentation sources with Crowdin
crowdin.yml[26-27]
.github/workflows/crowdin-download.yml[61-68]
crowdin.yml[26-40]
.github/workflows/crowdin-download.yml[65-80]
src/docs/content.ts[21-35]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Crowdin now exports translated Markdown and `pages.json` under `src/docs`, but the download workflow only detects, stages, and commits application locale files under `src/i18n/locales`. As a result, docs-only exports exit early and mixed exports omit documentation from the translation pull request.
## Fix Focus Areas
- .github/workflows/crowdin-download.yml[61-80]
- crowdin.yml[26-40]
- src/docs/content.ts[13-19]
## Recommended Fix
Update the download workflow’s change detection, staging, commit, and pull-request messaging to include both `src/i18n/locales` and `src/docs`, ensuring that a docs-only export creates or updates the translation pull request rather than exiting early. Keep `DOC_LANGUAGES` synchronized with accepted documentation folders before running the documentation tests, and include those changes in the translation pull request.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Untranslated pages look translated ✓ Resolved 📎 Requirement gap ≡ Correctness
Description
The new localized pages.json export retains every source entry when the approved-only download
substitutes English for untranslated strings, and hasPage interprets each retained entry as an
available translation. Once a downloaded language folder is enabled, an unapproved page loads its
English export as localized content without the unavailable-translation note.
Code

crowdin.yml[R35-36]

+  - source: /src/docs/en/pages.json
+    translation: /src/docs/%two_letters_code%/%original_file_name%
Evidence
Compliance rule 14 requires untranslated localized routes to show English with a clear notice. The
added localized pages.json output is downloaded through a workflow that documents English-source
substitution for unapproved strings, while the application decides translation availability solely
from the presence of an index entry.

Fall back safely to English for missing translations
crowdin.yml[32-40]
.github/workflows/crowdin-download.yml[38-44]
src/docs/content.ts[32-34]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Localized page indexes can retain English source entries for unapproved translations, causing the application to classify untranslated pages as translated and suppress its English-fallback notice.
## Fix Focus Areas
- crowdin.yml[35-40]
- .github/workflows/crowdin-download.yml[38-44]
- src/docs/content.ts[32-34]
## Recommended Fix
Post-process each downloaded documentation index so it lists only pages whose complete translation is approved, or configure an equivalent export mechanism that omits untranslated page entries. Add coverage showing that an unapproved page is absent from the localized index and therefore uses the labeled English fallback.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. The first docs translation fails sync ✓ Resolved 🐞 Bug ☼ Reliability
Description
DOC_LANGUAGES remains ['en'], while docs.test.ts requires it to equal all directories that the
new Crowdin entries create under src/docs. As soon as any approved language is exported, the
download job's mandatory test run sees the new directory and fails before it can open a translation
pull request.
Code

crowdin.yml[R26-27]

+  - source: /src/docs/en/*.md
+    translation: /src/docs/%two_letters_code%/%original_file_name%
Evidence
Crowdin's new destination creates language directories, while the registry contains only English and
the test compares it exactly with every docs directory. That test runs after every Crowdin download
and before the workflow's commit step.

crowdin.yml[26-40]
src/docs/content.ts[13-19]
src/docs/docs.test.ts[40-47]
.github/workflows/crowdin-download.yml[52-63]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Crowdin now creates translated language directories automatically, but the static docs language registry remains English-only and the download workflow runs a test requiring exact agreement between that registry and the directories.
## Fix Focus Areas
- src/docs/content.ts[13-19]
- src/docs/docs.test.ts[40-47]
- .github/workflows/crowdin-download.yml[52-63]
## Recommended Fix
Make the docs language registry derive from the available translated docs modules or add a deterministic workflow generation step that updates the registry from valid downloaded language directories before build and test. Preserve validation that every derived directory is one of the app's supported language codes.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can add REVIEW.md to your repo root and Qodo follows it on every PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread crowdin.yml
Comment thread crowdin.yml
Comment thread crowdin.yml
@greptile-apps

greptile-apps Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

The PR appears safe to merge; the previously identified documentation staging and language-registration failures are fully addressed.

Fix All in Claude CodeFindings

  1. P1 Docs Never Reach PR ▶
  2. P1 Translated Folders Fail Tests ▶

Summary

This PR extends the existing Crowdin pipeline to synchronize documentation alongside application strings.

  • Adds Markdown and pages.json sources to the Crowdin configuration, including distinct Simplified and Traditional Chinese paths.
  • Watches English documentation changes in the upload workflow.
  • Prunes untranslated or invalid downloaded pages and updates DOC_LANGUAGES.
  • Stages documentation changes in generated translation pull requests.
  • Adds focused tests for pruning and language-registry synchronization.
  • The changes since the previous review fully address both earlier findings: documentation is now staged, and retained language folders are registered before tests run.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[English strings or docs change] --> B[Crowdin upload workflow]
  B --> C[Crowdin sources]
  C --> D[Approved translations downloaded]
  D --> E[docs-translations.mjs]
  E --> F[Remove untranslated or invalid pages]
  F --> G[Rewrite DOC_LANGUAGES]
  G --> H[Build and tests]
  H --> I[Stage app strings and docs]
  I --> J[Translation pull request]
Loading

Reviews (2) · Last reviewed commit: "Bring the downloaded docs home: prune wh..."

Comment thread crowdin.yml
# link. The build refuses a page without them and `docs.test.ts` compares
# each translation with its English source.
- source: /src/docs/en/*.md
translation: /src/docs/%two_letters_code%/%original_file_name%

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Docs Never Reach PR

The new configuration downloads documentation translations into src/docs/<code>/, but the download workflow checks and stages only src/i18n/locales. A docs-only download is therefore reported as having no changes, while a mixed download commits only the dictionaries. In both cases, the approved documentation translations never reach the generated pull request. Update the download workflow's diff and staging paths to include src/docs.

Fix in Claude Code

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fixed in eed096a: the workflow checks and stages src/docs alongside src/i18n/locales, so an export with only docs in it still opens the pull request.

Comment thread crowdin.yml
# metadata read. A language shows the pages listed here and falls back to
# English for the rest.
- source: /src/docs/en/pages.json
translation: /src/docs/%two_letters_code%/%original_file_name%

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Translated Folders Fail Tests

Downloading the first translated documentation folder makes the download job fail before it can open a pull request. DOC_LANGUAGES remains ['en'], but the docs test requires it to match every folder under src/docs. Register generated language folders during synchronization, or change the registry and test mechanism to support them.

Fix in Claude Code

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fixed in eed096a: a sync step between the download and the build writes DOC_LANGUAGES from the folders that kept a translated page, so the first exported language no longer fails the test that compares the two.

@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: df57b0567f

ℹ️ 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 crowdin.yml
# link. The build refuses a page without them and `docs.test.ts` compares
# each translation with its English source.
- source: /src/docs/en/*.md
translation: /src/docs/%two_letters_code%/%original_file_name%

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Include downloaded docs in the sync commit

When Crowdin downloads an approved translation to this new path, .github/workflows/crowdin-download.yml still checks for changes only under src/i18n/locales and stages only that directory. A docs-only export therefore exits as “No translation changes,” while even an export accompanied by dictionary changes leaves src/docs unstaged, so no documentation translation can reach the generated pull request.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fixed in eed096a. Change detection and git add both cover src/docs now, and the pull request body names the docs pages as well as the app strings.

Comment thread crowdin.yml
# metadata read. A language shows the pages listed here and falls back to
# English for the rest.
- source: /src/docs/en/pages.json
translation: /src/docs/%two_letters_code%/%original_file_name%

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Register documentation languages produced by the export

As soon as this mapping creates any non-English docs folder, the download workflow's pnpm test fails because DOC_LANGUAGES remains ['en'] while src/docs/docs.test.ts requires it to equal the folders on disk. The same registry also makes hasDocs ignore downloaded translations at runtime, so the sync needs to update or otherwise coordinate DOC_LANGUAGES for every exported language.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fixed in eed096a. The sync step rewrites DOC_LANGUAGES from the pruned folders (and formats the file, since lint:ci runs before a deploy), so both the test and hasDocs see the exported languages.

…r the rest

Review round on #159.

The download workflow looked at src/i18n/locales alone, so a docs-only export
reported no changes and a mixed one left the pages unstaged: no translated
page could reach the pull request. It now checks, stages and describes
src/docs too.

An approved-only export fills the rest with the English source, so a language
arrives listing pages nobody translated, sometimes as English Markdown under a
translated name and sometimes with no file at all. Shown as they are, those
pages look translated and the reader never sees the note; a listed page with
no file throws on import. scripts/docs-translations.mjs keeps only the pages
that differ from English, drops the files no index lists, removes a language
that translated nothing, and writes DOC_LANGUAGES from the folders that
remain, which is what made the first export fail the docs test that compares
that list with the folders on disk.
@feruzm
feruzm merged commit 7ea7c4f into development Sep 21, 2026
4 checks passed
@feruzm
feruzm deleted the chore/docs-to-crowdin branch September 21, 2026 21:17
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.

1 participant