ci(workflow): validate i18n locale files are synchronized (#2347)
This commit is contained in:
63
.github/workflows/ci.yml
vendored
63
.github/workflows/ci.yml
vendored
@@ -22,6 +22,69 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
i18n:
|
||||
name: i18n Check
|
||||
if: github.event_name == 'pull_request'
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
NUMBER: ${{ github.event.pull_request.number }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Pnpm Setup
|
||||
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
|
||||
with:
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Get pnpm store directory
|
||||
shell: bash
|
||||
run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
|
||||
|
||||
- name: Setup pnpm cache
|
||||
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||
with:
|
||||
path: ${{ env.STORE_PATH }}
|
||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pnpm-store-
|
||||
|
||||
- name: Install dependencies
|
||||
env:
|
||||
CI: true
|
||||
run: pnpm install
|
||||
|
||||
- name: i18n Check
|
||||
shell: bash
|
||||
env:
|
||||
BODY: |
|
||||
The i18n check failed because translation messages are out of sync.
|
||||
|
||||
This usually happens when you've added or modified translation strings in your code but haven't updated the translation file.
|
||||
|
||||
Please run `pnpm i18n:extract` and commit the changes.
|
||||
run: |
|
||||
retry() { n=0; until "$@"; do n=$((n+1)); [ $n -ge 3 ] && break; echo "retry $n: $*" >&2; sleep 2; done; }
|
||||
node bin/check-i18n.js
|
||||
check_failed=$?
|
||||
if [ $check_failed -eq 1 ]; then
|
||||
retry gh pr edit "$NUMBER" -R "$GH_REPO" --add-label "i18n-out-of-sync" || true
|
||||
retry gh pr comment "$NUMBER" -R "$GH_REPO" -b "$BODY" || true
|
||||
else
|
||||
retry gh pr edit "$NUMBER" -R "$GH_REPO" --remove-label "i18n-out-of-sync" || true
|
||||
fi
|
||||
exit $check_failed
|
||||
|
||||
test:
|
||||
name: Lint & Test Build
|
||||
if: github.event_name == 'pull_request'
|
||||
|
||||
39
bin/check-i18n.js
Normal file
39
bin/check-i18n.js
Normal file
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Check that i18n locale files are in sync with extracted messages.
|
||||
* Runs `pnpm i18n:extract` and compares en.json; exits 1 if they differ.
|
||||
*/
|
||||
const { execSync } = require('child_process');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const localePath = path.join(
|
||||
__dirname,
|
||||
'..',
|
||||
'src',
|
||||
'i18n',
|
||||
'locale',
|
||||
'en.json'
|
||||
);
|
||||
const backupPath = `${localePath}.bak`;
|
||||
|
||||
try {
|
||||
fs.copyFileSync(localePath, backupPath);
|
||||
execSync('pnpm i18n:extract', { stdio: 'inherit' });
|
||||
const original = fs.readFileSync(backupPath, 'utf8');
|
||||
const extracted = fs.readFileSync(localePath, 'utf8');
|
||||
fs.unlinkSync(backupPath);
|
||||
|
||||
if (original !== extracted) {
|
||||
console.error(
|
||||
"i18n messages are out of sync. Please run 'pnpm i18n:extract' and commit the changes."
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
} catch (err) {
|
||||
if (fs.existsSync(backupPath)) {
|
||||
fs.unlinkSync(backupPath);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
Reference in New Issue
Block a user