Add scripts to allow addons from personal repos to be synchronized with Crowdin#1
Add scripts to allow addons from personal repos to be synchronized with Crowdin#1nvdaes wants to merge 131 commits intonvaccess:masterfrom
Conversation
… addedwith dev role to Crowdin if they use a project not owned by them to upload source files)
…flow to upload/update files in Crowdin
…k pass creating a PR at nvdaes/translateNvdaaddonsWithCrowdin repo
PurposeAdd-on authors may wish to help translators use Crowdin, the same framework where they translate NVDA. to translate messages and documentation for maintained add-ons: Other details
Development approachA workflow (GitHub Actions), and several scripts (Python and Powershell), as well as a json file with language mappings have been added. |
|
I've tested that all check pass using this pyproject.toml file on this PR: nvdaes/translateNvdaAddonsWithCrowdin#11 I use precommit, CodeQL and a workflow to check that all translatable messages have comments for translators. I'll try to use the cache action to cache some add-on metadata like its id, and also hashfiles from l10nSources (taking the value of buildVars.py), and the hasf¡hfile of the readme.md, to determine if pot and xliff files should be updated. |
|
Export translations to Crowdin running the workflow with update=False works properly: https://github.com/nvdaes/translateNvdaAddonsWithCrowdin/actions/runs/19802210157 |
|
This time, updatexLiff is failing. Seems that adding blank lines to readme may cause problems: https://github.com/nvdaes/translateNvdaAddonsWithCrowdin/actions/runs/19802391926/job/56731562709 |
|
If someone can help with this issue when update xliff, I'll be grateful. |
|
It might be easier to avoid xliff and just translate the markdown files directly. This won't support diffs very well but worth experimenting with |
|
@seanbudd wrote:
OK. |
|
@CyrilleB79, you were interested in this framework. If you want, feel free to see how the translateNvdaAddonsWithCrowdin.md can be translated in the project. Using xliff files is causing problems, as mentioned, and we are experimenting uploading md files instead. |
|
Hi @nvdaes, Thanks for the updates! I noticed a small bug in the last commit that triggers an API ERROR: 'language_id'. It seems that when converting variables to camelCase, the dictionary key for the Crowdin API response was changed to language_id (line 98). However, the Crowdin API returns this specific key as languageId. I've tested it by changing it back to langApi = item["data"]["languageId"] and it works perfectly again. Do you want me to push the fix or will you handle it? Thanks! ☺ |
The recent refactoring to camelCase accidentally changed the dictionary key 'languageId' to 'language_id' when accessing the API response data. Since the Crowdin API strictly returns 'languageId', this caused a KeyError. - Restored 'languageId' in getScoreFromApi function to ensure proper score retrieval[cite: 2]. - Verified that other internal camelCase variables remain unchanged to satisfy NVDA coding standards[cite: 2].
|
@abdel792 wrote:
Please fix it yourself. Do you want to test it in one of your add-ons, or should I perform the final test? |
|
Hi @nvdaes, I've just pushed a fix for the During the camelCase refactoring, the dictionary key for the Crowdin API response was changed to I have:
The script is now working perfectly again for all file types (.po, .md, and .xliff). Sorry for missing that during the initial review! ☺ |
|
Thanks so much. I'l perform the final test. |
|
Hi @nvdaes, I've just pushed the fix for I am currently testing the script directly on my PC using PowerShell, as I mentioned before. I'm iterating through my local add-on directories and querying the Crowdin API for each one to verify the scores. Everything is working as expected now! You can perform a final test on your side if you wish, but from my end, the script is fully functional and ready for the final review. ☺ |
|
I'll perform a final test to show publicly that it works. Thanks for your work! |
|
@abdel792 , I've run pre-commit to fix chekcs. https://github.com/nvdaes/readFeeds/actions/runs/25120306831/job/73618870755 |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 12 changed files in this pull request and generated 8 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Remove temp file as a general good practice, though this is not needed since this is intended just to be used with GitHub Actions. Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…as a way to request an invitation
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
… to prevent failures
|
@seanbudd and @abdel792 I've updated the readme and addressed Copilot suggestions.
See the last test at https://github.com/nvdaes/readFeeds/actions/runs/25177842831/job/73814743331 |
|
Hi @nvdaes, |
seanbudd
left a comment
There was a problem hiding this comment.
Note: I haven't thoroughly reviewed .github/scripts. I need a clearer PR description to understand the purpose and design of these
| # When excluding concrete paths relative to a directory, | ||
| # not matching multiple folders by name e.g. `__pycache__`, | ||
| # paths are relative to the configuration file. | ||
| ".github/scripts/markdownTranslate.py", |
There was a problem hiding this comment.
can we block this whole folder? .github/scripts
| Ensure that your repository includes the following files (provided in this template): | ||
| * **Workflows:** `.github/workflows/crowdinL10n.yml` | ||
| * **Scripts:** The `.github/scripts/` folder containing `checkTranslation.py`, `markdownTranslate.py`, `languageMappings.json`, `setOutputs.py`, and `crowdinSync.ps1`. |
There was a problem hiding this comment.
shouldn't this be included automatically via the template?
|
|
||
| The translation workflow will be run weekly. Also, you can run the workflow manually from GitHub or using GitHub CLI. | ||
|
|
||
| If you have various add-ons, please edit the cron line of workflows in each repo, so that your API token is not used at the same time. |
There was a problem hiding this comment.
Maybe we could add a random 0-5 min sleep at the start of the job to offset them?
| @@ -0,0 +1,148 @@ | |||
| # checkTranslation.py | |||
There was a problem hiding this comment.
It's still not clear to me what the purpose of this file is. Can you please update the PR description to describe the changes in this PR and why?
I've set it to copilot's output for now.
TODO: review this file later
| # --- 3.2 DOCUMENTATION PROCESSING (MD & XLIFF) --- | ||
| $scoreMd = 0.0 | ||
| $scoreXliff = 0.0 | ||
|
|
||
| if (Test-Path $remoteMd) { | ||
| Write-Host "DEBUG: Evaluating Remote Markdown score..." | ||
| $res = uv run python .github/scripts/checkTranslation.py "$addonId.md" $crowdinLang | ||
| $scoreMd = [double]($res | Select-String "mdScore=").ToString().Split("=")[1] | ||
| } else { | ||
| Write-Host "DEBUG: No remote Markdown file found for this language." | ||
| } | ||
|
|
||
| if (Test-Path $remoteXliff) { | ||
| Write-Host "DEBUG: Evaluating Remote XLIFF score..." | ||
| $res = uv run python .github/scripts/checkTranslation.py "$addonId.xliff" $crowdinLang | ||
| $scoreXliff = [double]($res | Select-String "xliffScore=").ToString().Split("=")[1] | ||
| } else { | ||
| Write-Host "DEBUG: No remote XLIFF file found for this language." | ||
| } |
Co-authored-by: Sean Budd <seanbudd123@gmail.com>
Co-authored-by: Sean Budd <seanbudd123@gmail.com>
Co-authored-by: Sean Budd <seanbudd123@gmail.com>
Co-authored-by: Sean Budd <seanbudd123@gmail.com>
Co-authored-by: Sean Budd <seanbudd123@gmail.com>
This pull request introduces a complete, automated workflow for synchronizing translations with Crowdin, including new scripts, a scheduled GitHub Actions workflow, and supporting documentation. The main changes add Python and PowerShell scripts for translation status checking and synchronization, a workflow for scheduled and manual Crowdin sync, language mapping configuration, and documentation updates. These improvements enable seamless translation management for add-on projects.
Crowdin Synchronization Workflow and Automation:
.github/workflows/crowdinL10n.ymlto automate translation synchronization with Crowdin, running weekly and on demand. It sets up the environment, downloads required tools, and triggers the sync process..github/scripts/crowdinSync.ps1, a comprehensive PowerShell script that updates source files, uploads them to Crowdin, exports translations, evaluates translation quality, and commits updates back to the repository.Translation Quality and Language Mapping Utilities:
.github/scripts/checkTranslation.py, a Python script that checks translation progress for a given file and language using the Crowdin API, supporting quality thresholds for importing translations..github/scripts/languageMappings.jsonto map local language codes to Crowdin-compatible codes, ensuring correct language matching during synchronization..github/scripts/setOutputs.py, a Python script to extract and expose the add-on ID for use in workflows.Configuration and Documentation:
pyproject.tomlto include new scripts in the exclude list for packaging and removed the unusedrequestsdependency. [1] [2]readme.mdwith detailed instructions on setting up and using the Crowdin translation workflow, including project setup and required secrets..python-versionspecifying Python 3.13 for consistent workflow environments.These changes collectively provide a robust, maintainable infrastructure for managing translations in add-on projects with Crowdin.