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-actions[bot]@users.noreply.github.com>
This commit is contained in:
Gadfly 2025-04-14 22:07:24 +08:00 committed by GitHub
parent 3b1018e0e2
commit 1e0fd63543
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 35 additions and 4 deletions

View file

@ -4,7 +4,6 @@ on:
branches: [ develop ] branches: [ develop ]
paths: paths:
- 'src/Resources/Locales/**' - 'src/Resources/Locales/**'
- 'README.md'
workflow_dispatch: workflow_dispatch:
workflow_call: workflow_call:
@ -32,8 +31,8 @@ jobs:
git config --global user.name 'github-actions[bot]' git config --global user.name 'github-actions[bot]'
git config --global user.email 'github-actions[bot]@users.noreply.github.com' git config --global user.email 'github-actions[bot]@users.noreply.github.com'
if [ -n "$(git status --porcelain)" ]; then if [ -n "$(git status --porcelain)" ]; then
git add README.md TRANSLATION.md git add TRANSLATION.md src/Resources/Locales/*.axaml
git commit -m 'doc: Update translation status and missing keys' git commit -m 'doc: Update translation status and sort locale files'
git push git push
else else
echo "No changes to commit" echo "No changes to commit"

View file

@ -14,6 +14,22 @@ async function parseXml(filePath) {
return parser.parseStringPromise(data); 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() { async function calculateTranslationRate() {
const enUSData = await parseXml(enUSFile); const enUSData = await parseXml(enUSFile);
const enUSKeys = new Set(enUSData.ResourceDictionary['x:String'].map(item => item.$['x:Key'])); 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 localeKeys = new Set(localeData.ResourceDictionary['x:String'].map(item => item.$['x:Key']));
const missingKeys = [...enUSKeys].filter(key => !localeKeys.has(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(' <x:String', '\n <x:String');
await fs.writeFile(filePath, xmlStr, 'utf8');
if (missingKeys.length > 0) { if (missingKeys.length > 0) {
const progress = ((enUSKeys.size - missingKeys.length) / enUSKeys.size) * 100; const progress = ((enUSKeys.size - missingKeys.length) / enUSKeys.size) * 100;
const badgeColor = progress >= 75 ? 'yellow' : 'red'; const badgeColor = progress >= 75 ? 'yellow' : 'red';
@ -41,7 +73,7 @@ async function calculateTranslationRate() {
lines.push(`<details>\n<summary>Missing keys in ${file}</summary>\n\n${missingKeys.map(key => `- ${key}`).join('\n')}\n\n</details>`) lines.push(`<details>\n<summary>Missing keys in ${file}</summary>\n\n${missingKeys.map(key => `- ${key}`).join('\n')}\n\n</details>`)
} else { } else {
lines.push(`### ![${locale}](https://img.shields.io/badge/${locale}-%E2%88%9A-brightgreen)`); lines.push(`### ![${locale}](https://img.shields.io/badge/${locale}-%E2%88%9A-brightgreen)`);
} }
} }
const content = lines.join('\n\n'); const content = lines.join('\n\n');