mirror of
https://github.com/langgenius/dify.git
synced 2026-05-06 10:28:10 +08:00
Revert "test(i18n): add pull_request trigger for CI testing" This reverts commits7130bbebfeand7051d96841. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
347 lines
17 KiB
YAML
347 lines
17 KiB
YAML
name: Translate i18n Files with Claude Code
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
paths:
|
|
- 'web/i18n/en-US/*.json'
|
|
workflow_dispatch:
|
|
inputs:
|
|
files:
|
|
description: 'Specific files to translate (space-separated, e.g., "app common"). Leave empty for all files.'
|
|
required: false
|
|
type: string
|
|
languages:
|
|
description: 'Specific languages to translate (space-separated, e.g., "zh-Hans ja-JP"). Leave empty for all supported languages.'
|
|
required: false
|
|
type: string
|
|
mode:
|
|
description: 'Sync mode: incremental (only changes) or full (re-check all keys)'
|
|
required: false
|
|
default: 'incremental'
|
|
type: choice
|
|
options:
|
|
- incremental
|
|
- full
|
|
|
|
permissions:
|
|
contents: write
|
|
pull-requests: write
|
|
|
|
jobs:
|
|
translate:
|
|
if: github.repository == 'langgenius/dify'
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 60
|
|
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Configure Git
|
|
run: |
|
|
git config --global user.name "github-actions[bot]"
|
|
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
|
|
|
- name: Install pnpm
|
|
uses: pnpm/action-setup@v4
|
|
with:
|
|
package_json_file: web/package.json
|
|
run_install: false
|
|
|
|
- name: Set up Node.js
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: 'lts/*'
|
|
cache: pnpm
|
|
cache-dependency-path: ./web/pnpm-lock.yaml
|
|
|
|
- name: Detect changed files and generate diff
|
|
id: detect_changes
|
|
run: |
|
|
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
|
|
# Manual trigger
|
|
if [ -n "${{ github.event.inputs.files }}" ]; then
|
|
echo "CHANGED_FILES=${{ github.event.inputs.files }}" >> $GITHUB_OUTPUT
|
|
else
|
|
# Get all JSON files in en-US directory
|
|
files=$(ls web/i18n/en-US/*.json 2>/dev/null | xargs -n1 basename | sed 's/.json$//' | tr '\n' ' ')
|
|
echo "CHANGED_FILES=$files" >> $GITHUB_OUTPUT
|
|
fi
|
|
echo "TARGET_LANGS=${{ github.event.inputs.languages }}" >> $GITHUB_OUTPUT
|
|
echo "SYNC_MODE=${{ github.event.inputs.mode || 'incremental' }}" >> $GITHUB_OUTPUT
|
|
|
|
# For manual trigger with incremental mode, get diff from last commit
|
|
# For full mode, we'll do a complete check anyway
|
|
if [ "${{ github.event.inputs.mode }}" == "full" ]; then
|
|
echo "Full mode: will check all keys" > /tmp/i18n-diff.txt
|
|
echo "DIFF_AVAILABLE=false" >> $GITHUB_OUTPUT
|
|
else
|
|
git diff HEAD~1..HEAD -- 'web/i18n/en-US/*.json' > /tmp/i18n-diff.txt 2>/dev/null || echo "" > /tmp/i18n-diff.txt
|
|
if [ -s /tmp/i18n-diff.txt ]; then
|
|
echo "DIFF_AVAILABLE=true" >> $GITHUB_OUTPUT
|
|
else
|
|
echo "DIFF_AVAILABLE=false" >> $GITHUB_OUTPUT
|
|
fi
|
|
fi
|
|
else
|
|
# Push trigger - detect changed files from the push
|
|
changed=$(git diff --name-only ${{ github.event.before }} ${{ github.sha }} -- 'web/i18n/en-US/*.json' 2>/dev/null | xargs -n1 basename 2>/dev/null | sed 's/.json$//' | tr '\n' ' ' || echo "")
|
|
echo "CHANGED_FILES=$changed" >> $GITHUB_OUTPUT
|
|
echo "TARGET_LANGS=" >> $GITHUB_OUTPUT
|
|
echo "SYNC_MODE=incremental" >> $GITHUB_OUTPUT
|
|
|
|
# Generate detailed diff for the push
|
|
git diff ${{ github.event.before }}..${{ github.sha }} -- 'web/i18n/en-US/*.json' > /tmp/i18n-diff.txt 2>/dev/null || echo "" > /tmp/i18n-diff.txt
|
|
if [ -s /tmp/i18n-diff.txt ]; then
|
|
echo "DIFF_AVAILABLE=true" >> $GITHUB_OUTPUT
|
|
else
|
|
echo "DIFF_AVAILABLE=false" >> $GITHUB_OUTPUT
|
|
fi
|
|
fi
|
|
|
|
# Truncate diff if too large (keep first 50KB)
|
|
if [ -f /tmp/i18n-diff.txt ]; then
|
|
head -c 50000 /tmp/i18n-diff.txt > /tmp/i18n-diff-truncated.txt
|
|
mv /tmp/i18n-diff-truncated.txt /tmp/i18n-diff.txt
|
|
fi
|
|
|
|
echo "Detected files: $(cat $GITHUB_OUTPUT | grep CHANGED_FILES || echo 'none')"
|
|
|
|
- name: Run Claude Code for Translation Sync
|
|
if: steps.detect_changes.outputs.CHANGED_FILES != ''
|
|
uses: anthropics/claude-code-action@v1
|
|
with:
|
|
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
timeout_minutes: 55
|
|
prompt: |
|
|
You are a professional i18n synchronization engineer for the Dify project.
|
|
Your task is to keep all language translations in sync with the English source (en-US).
|
|
|
|
## Context
|
|
- Changed/target files: ${{ steps.detect_changes.outputs.CHANGED_FILES }}
|
|
- Target languages (empty means all supported): ${{ steps.detect_changes.outputs.TARGET_LANGS }}
|
|
- Sync mode: ${{ steps.detect_changes.outputs.SYNC_MODE }}
|
|
- Translation files are located in: web/i18n/{locale}/{filename}.json
|
|
- Language configuration is in: web/i18n-config/languages.ts
|
|
- Git diff is available: ${{ steps.detect_changes.outputs.DIFF_AVAILABLE }}
|
|
|
|
## CRITICAL DESIGN: Verify First, Then Sync
|
|
|
|
You MUST follow this three-phase approach:
|
|
|
|
═══════════════════════════════════════════════════════════════
|
|
║ PHASE 1: VERIFY - Analyze and Generate Change Report ║
|
|
═══════════════════════════════════════════════════════════════
|
|
|
|
### Step 1.1: Analyze Git Diff (for incremental mode)
|
|
```bash
|
|
cat /tmp/i18n-diff.txt 2>/dev/null || echo "No diff available"
|
|
```
|
|
|
|
Parse the diff to categorize changes:
|
|
- Lines with `+` (not `+++`): Added or modified values
|
|
- Lines with `-` (not `---`): Removed or old values
|
|
- Identify specific keys for each category:
|
|
* ADD: Keys that appear only in `+` lines (new keys)
|
|
* UPDATE: Keys that appear in both `-` and `+` lines (value changed)
|
|
* DELETE: Keys that appear only in `-` lines (removed keys)
|
|
|
|
### Step 1.2: Read Language Configuration
|
|
```bash
|
|
cat web/i18n-config/languages.ts
|
|
```
|
|
Extract all languages with `supported: true`.
|
|
|
|
### Step 1.3: Run i18n:check for Each Language
|
|
```bash
|
|
cd web && pnpm install --frozen-lockfile
|
|
pnpm run i18n:check
|
|
```
|
|
|
|
This will report:
|
|
- Missing keys (need to ADD)
|
|
- Extra keys (need to DELETE)
|
|
|
|
### Step 1.4: Generate Change Report
|
|
|
|
Create a structured report identifying:
|
|
```
|
|
╔══════════════════════════════════════════════════════════════╗
|
|
║ I18N SYNC CHANGE REPORT ║
|
|
╠══════════════════════════════════════════════════════════════╣
|
|
║ Files to process: [list] ║
|
|
║ Languages to sync: [list] ║
|
|
╠══════════════════════════════════════════════════════════════╣
|
|
║ ADD (New Keys): ║
|
|
║ - [filename].[key]: "English value" ║
|
|
║ ... ║
|
|
╠══════════════════════════════════════════════════════════════╣
|
|
║ UPDATE (Modified Keys - MUST re-translate): ║
|
|
║ - [filename].[key]: "Old value" → "New value" ║
|
|
║ ... ║
|
|
╠══════════════════════════════════════════════════════════════╣
|
|
║ DELETE (Extra Keys): ║
|
|
║ - [language]/[filename].[key] ║
|
|
║ ... ║
|
|
╚══════════════════════════════════════════════════════════════╝
|
|
```
|
|
|
|
**IMPORTANT**: For UPDATE detection, compare git diff to find keys where
|
|
the English value changed. These MUST be re-translated even if target
|
|
language already has a translation (it's now stale!).
|
|
|
|
═══════════════════════════════════════════════════════════════
|
|
║ PHASE 2: SYNC - Execute Changes Based on Report ║
|
|
═══════════════════════════════════════════════════════════════
|
|
|
|
### Step 2.1: Process ADD Operations
|
|
For each key in the ADD list:
|
|
1. Get the English value from en-US file
|
|
2. Translate to target language
|
|
3. Add to target language JSON file (maintain alphabetical order if file uses it)
|
|
|
|
### Step 2.2: Process UPDATE Operations (CRITICAL!)
|
|
For each key in the UPDATE list:
|
|
1. Get the NEW English value
|
|
2. Translate to target language
|
|
3. **OVERWRITE** the existing translation (old one is stale!)
|
|
|
|
### Step 2.3: Process DELETE Operations
|
|
For extra keys reported by i18n:check:
|
|
- Run: `cd web && pnpm run i18n:check --auto-remove`
|
|
- Or manually remove from target language JSON files
|
|
|
|
## Translation Guidelines
|
|
|
|
- PRESERVE all placeholders exactly as-is:
|
|
- `{{variable}}` - Mustache interpolation
|
|
- `${variable}` - Template literal
|
|
- `<tag>content</tag>` - HTML tags
|
|
- `_one`, `_other` - Pluralization suffixes (these are KEY suffixes, not values)
|
|
- Use appropriate language register (formal/informal) based on existing translations
|
|
- Match existing translation style in each language
|
|
- Technical terms: check existing conventions per language
|
|
- For CJK languages: no spaces between characters unless necessary
|
|
- For RTL languages (ar-TN, fa-IR): ensure proper text handling
|
|
|
|
## Output Format Requirements
|
|
- Alphabetical key ordering (if original file uses it)
|
|
- 2-space indentation
|
|
- Trailing newline at end of file
|
|
- Valid JSON (use proper escaping for special characters)
|
|
|
|
═══════════════════════════════════════════════════════════════
|
|
║ PHASE 3: RE-VERIFY - Confirm All Issues Resolved ║
|
|
═══════════════════════════════════════════════════════════════
|
|
|
|
### Step 3.1: Run Lint Fix (IMPORTANT!)
|
|
```bash
|
|
cd web && pnpm lint:fix --quiet -- 'i18n/**/*.json'
|
|
```
|
|
This ensures:
|
|
- JSON keys are sorted alphabetically (jsonc/sort-keys rule)
|
|
- Valid i18n keys (dify-i18n/valid-i18n-keys rule)
|
|
- No extra keys (dify-i18n/no-extra-keys rule)
|
|
|
|
### Step 3.2: Run Final i18n Check
|
|
```bash
|
|
cd web && pnpm run i18n:check
|
|
```
|
|
|
|
### Step 3.3: Fix Any Remaining Issues
|
|
If check reports issues:
|
|
- Go back to PHASE 2 for unresolved items
|
|
- Repeat until check passes
|
|
|
|
### Step 3.4: Generate Final Summary
|
|
```
|
|
╔══════════════════════════════════════════════════════════════╗
|
|
║ SYNC COMPLETED SUMMARY ║
|
|
╠══════════════════════════════════════════════════════════════╣
|
|
║ Language │ Added │ Updated │ Deleted │ Status ║
|
|
╠══════════════════════════════════════════════════════════════╣
|
|
║ zh-Hans │ 5 │ 2 │ 1 │ ✓ Complete ║
|
|
║ ja-JP │ 5 │ 2 │ 1 │ ✓ Complete ║
|
|
║ ... │ ... │ ... │ ... │ ... ║
|
|
╠══════════════════════════════════════════════════════════════╣
|
|
║ i18n:check │ PASSED - All keys in sync ║
|
|
╚══════════════════════════════════════════════════════════════╝
|
|
```
|
|
|
|
## Mode-Specific Behavior
|
|
|
|
**SYNC_MODE = "incremental"** (default):
|
|
- Focus on keys identified from git diff
|
|
- Also check i18n:check output for any missing/extra keys
|
|
- Efficient for small changes
|
|
|
|
**SYNC_MODE = "full"**:
|
|
- Compare ALL keys between en-US and each language
|
|
- Run i18n:check to identify all discrepancies
|
|
- Use for first-time sync or fixing historical issues
|
|
|
|
## Important Notes
|
|
|
|
1. Always run i18n:check BEFORE and AFTER making changes
|
|
2. The check script is the source of truth for missing/extra keys
|
|
3. For UPDATE scenario: git diff is the source of truth for changed values
|
|
4. Create a single commit with all translation changes
|
|
5. If any translation fails, continue with others and report failures
|
|
|
|
═══════════════════════════════════════════════════════════════
|
|
║ PHASE 4: COMMIT AND CREATE PR ║
|
|
═══════════════════════════════════════════════════════════════
|
|
|
|
After all translations are complete and verified:
|
|
|
|
### Step 4.1: Check for changes
|
|
```bash
|
|
git status --porcelain
|
|
```
|
|
|
|
If there are changes:
|
|
|
|
### Step 4.2: Create a new branch and commit
|
|
```bash
|
|
BRANCH_NAME="chore/i18n-sync-$(date +%Y%m%d-%H%M%S)"
|
|
git checkout -b "$BRANCH_NAME"
|
|
git add web/i18n/
|
|
git commit -m "chore(i18n): sync translations with en-US
|
|
|
|
- Synced translation files based on en-US changes
|
|
- Mode: ${{ steps.detect_changes.outputs.SYNC_MODE }}
|
|
- Files: ${{ steps.detect_changes.outputs.CHANGED_FILES }}
|
|
|
|
🤖 Generated with Claude Code GitHub Action"
|
|
git push origin "$BRANCH_NAME"
|
|
```
|
|
|
|
### Step 4.3: Create Pull Request
|
|
```bash
|
|
gh pr create \
|
|
--title "chore(i18n): sync translations with en-US" \
|
|
--body "## Summary
|
|
|
|
This PR was automatically generated to sync i18n translation files.
|
|
|
|
### Changes
|
|
- Mode: ${{ steps.detect_changes.outputs.SYNC_MODE }}
|
|
- Files processed: ${{ steps.detect_changes.outputs.CHANGED_FILES }}
|
|
|
|
### Verification
|
|
- [x] \`i18n:check\` passed
|
|
- [x] \`lint:fix\` applied
|
|
|
|
🤖 Generated with Claude Code GitHub Action" \
|
|
--base main
|
|
```
|
|
|
|
claude_args: |
|
|
--max-turns 100
|
|
--allowedTools "Read,Write,Edit,Bash(git:*),Bash(gh:*),Bash(cd:*),Bash(pnpm:*),Bash(cat:*),Bash(ls:*),Glob,Grep"
|