From 1e0fd63543607b07664eb5083f6368ab804479e8 Mon Sep 17 00:00:00 2001 From: Gadfly Date: Mon, 14 Apr 2025 22:07:24 +0800 Subject: [PATCH] localization: add translation sorting and formatting (#1186) * doc: Update translation status and missing keys * localization: add translation sorting and formatting --------- Co-authored-by: github-actions[bot] --- .github/workflows/localization-check.yml | 5 ++-- build/scripts/localization-check.js | 34 +++++++++++++++++++++++- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/.github/workflows/localization-check.yml b/.github/workflows/localization-check.yml index cc5201ab..8dcd61c8 100644 --- a/.github/workflows/localization-check.yml +++ b/.github/workflows/localization-check.yml @@ -4,7 +4,6 @@ on: branches: [ develop ] paths: - 'src/Resources/Locales/**' - - 'README.md' workflow_dispatch: workflow_call: @@ -32,8 +31,8 @@ jobs: git config --global user.name 'github-actions[bot]' git config --global user.email 'github-actions[bot]@users.noreply.github.com' if [ -n "$(git status --porcelain)" ]; then - git add README.md TRANSLATION.md - git commit -m 'doc: Update translation status and missing keys' + git add TRANSLATION.md src/Resources/Locales/*.axaml + git commit -m 'doc: Update translation status and sort locale files' git push else echo "No changes to commit" diff --git a/build/scripts/localization-check.js b/build/scripts/localization-check.js index 1e8f1f0d..fc27fd1b 100644 --- a/build/scripts/localization-check.js +++ b/build/scripts/localization-check.js @@ -14,6 +14,22 @@ async function parseXml(filePath) { return parser.parseStringPromise(data); } +async function filterAndSortTranslations(localeData, enUSKeys, enUSData) { + const strings = localeData.ResourceDictionary['x:String']; + // Remove keys that don't exist in English file + const filtered = strings.filter(item => enUSKeys.has(item.$['x:Key'])); + + // Sort based on the key order in English file + const enUSKeysArray = enUSData.ResourceDictionary['x:String'].map(item => item.$['x:Key']); + filtered.sort((a, b) => { + const aIndex = enUSKeysArray.indexOf(a.$['x:Key']); + const bIndex = enUSKeysArray.indexOf(b.$['x:Key']); + return aIndex - bIndex; + }); + + return filtered; +} + async function calculateTranslationRate() { const enUSData = await parseXml(enUSFile); const enUSKeys = new Set(enUSData.ResourceDictionary['x:String'].map(item => item.$['x:Key'])); @@ -33,6 +49,22 @@ async function calculateTranslationRate() { const localeKeys = new Set(localeData.ResourceDictionary['x:String'].map(item => item.$['x:Key'])); const missingKeys = [...enUSKeys].filter(key => !localeKeys.has(key)); + // Sort and clean up extra translations + const sortedAndCleaned = await filterAndSortTranslations(localeData, enUSKeys, enUSData); + localeData.ResourceDictionary['x:String'] = sortedAndCleaned; + + // Save the updated file + const builder = new xml2js.Builder({ + headless: true, + renderOpts: { pretty: true, indent: ' ' } + }); + let xmlStr = builder.buildObject(localeData); + + // Add an empty line before the first x:String + xmlStr = xmlStr.replace(' 0) { const progress = ((enUSKeys.size - missingKeys.length) / enUSKeys.size) * 100; const badgeColor = progress >= 75 ? 'yellow' : 'red'; @@ -41,7 +73,7 @@ async function calculateTranslationRate() { lines.push(`
\nMissing keys in ${file}\n\n${missingKeys.map(key => `- ${key}`).join('\n')}\n\n
`) } else { lines.push(`### ![${locale}](https://img.shields.io/badge/${locale}-%E2%88%9A-brightgreen)`); - } + } } const content = lines.join('\n\n');