resx-translation
GitHub自动化处理.NET应用.resx本地化文件,支持翻译、补全缺失内容及新增语言。通过专用脚本高效审计与更新资源,避免全量读取大文件,确保XML结构与格式规范。
Trigger Scenarios
Install
npx skills add itsfatduck/optimizerDuck --skill resx-translation -g -y
SKILL.md
Frontmatter
{
"name": "resx-translation",
"description": "Translate, extend, and create `.resx` localization files for .NET apps with project-aware wording and minimal file churn. Use this skill whenever the user wants to localize or update `Translations.resx`, `*.resx`, WPF\/WinForms\/.NET resource files, add a new language like `vi`, `ja`, or `fr-FR`, fill missing translations, or improve an existing locale while preserving XML structure, placeholders, naming conventions, and current formatting. Trigger even when the user does not mention `.resx` explicitly but is clearly asking to localize app text, UI labels, menus, dialogs, settings, validation messages, or existing app translations. Also trigger for requests like \"translate this resx\", \"add a new language\", \"fill missing strings\", \"localize my app\", \"translate resource files\", or \"complete the existing locale\"."
}
Resx Translation Skill
Golden Rule: Use helpers, NEVER read the full file
Do NOT use read/glob/grep to discover files, check encoding, or audit translations.
Use the helper scripts — they return structured data in <10 lines, saving hundreds of tokens.
Never read an entire .resx file. Files can exceed 100k tokens.
Use (filename:line) annotations from helpers to read only the relevant lines:
# resx_audit shows: [-] AppTitle (default:L42 #3) = 'OptimizerDuck'
read Translations.vi-VN.resx offset=42 limit=5
Only read 1-5 lines around each flagged key — never the whole file.
Helper Scripts Reference
All scripts are in <skill>\helpers\. Replace <skill> with the skill base path.
resx_core.py — Core library (do not run directly)
Shared data structures and operations used by all other scripts:
ResxEntry/ResxFile— parsed .resx with index, line numbers, encodingparse_resx(path)— parse a .resx fileauto_detect(directory)— detect base file and locale patterndiff_files(default, locale)— compare two files, returnsKeyDifflistwrite_translations(path, dict, mode)— batch add/update keysadd_keys(path, dict)— add new keys before</root>update_values(path, dict)— update existing key valuesparse_batch_input(raw)— parse KEY=VALUE pairs from textformat_entries_table(entries)— compact aligned table outputformat_diffs_compact(diffs)— compact diff output with status markers
resx_audit.py — Audit translations (missing, empty, untranslated, warnings)
What it does: Compares all locale files against the default. Reports issues with line numbers, indices, and warnings (mixed encodings, key count mismatch, duplicate keys, Designer.cs sync).
Usage:
python <skill>\helpers\resx_audit.py Resources\Languages
python <skill>\helpers\resx_audit.py Resources\Languages --lang vi-VN
python <skill>\helpers\resx_audit.py Resources\Languages --json
Flags:
| Flag | Description |
|---|---|
--lang CODE |
Filter by locale (e.g. vi, ja-JP) |
--no-missing |
Hide missing keys |
--no-empty |
Hide empty values |
--no-untranslated |
Hide untranslated |
--no-warnings |
Hide warnings |
--check-designer |
Audit .Designer.cs sync |
--by-key |
Group by key name |
--json |
JSON output (full metadata per issue) |
--fail-on-any |
Exit code 1 if any issues (CI gate) |
Output:
============================================================
resx manager — audit
============================================================
default : Translations.resx (45 keys)
locales : 13
[vi-VN] — Translations.vi-VN.resx
missing=15 | untranslated=5
missing (15):
[-] AppTitle (default:L42 #3) = 'OptimizerDuck'
[-] ButtonCancel (default:L55 #12) = 'Cancel'
untranslated (5):
[U] LabelStatus (Translations.vi-VN.resx:L120 #45)
warnings (1):
! mixed encodings: UTF-8 with BOM, UTF-8 (no BOM)
============================================================
summary
============================================================
keys : 45
locales : 13
missing : 15
untranslated: 5
warnings : 1
resx_list.py — List all translations with index and line numbers
What it does: Lists every translation entry with index, key, line number, and value. Supports locale filtering and key search.
Usage:
# List all files and entries
python <skill>\helpers\resx_list.py Resources\Languages
# Filter by locale
python <skill>\helpers\resx_list.py Resources\Languages --lang vi-VN
# Search keys
python <skill>\helpers\resx_list.py Resources\Languages --key Dashboard
# Keys only (no values)
python <skill>\helpers\resx_list.py Resources\Languages --keys-only
# JSON output
python <skill>\helpers\resx_list.py Resources\Languages --json
Flags:
| Flag | Description |
|---|---|
--lang CODE |
Filter by locale |
--key TEXT |
Filter keys by substring |
--keys-only |
Show only keys, no values |
--no-values |
Hide values entirely |
--json |
JSON output |
Output:
============================================================
resx manager — file listing
============================================================
directory : Resources\Languages
default : Translations.resx (45 keys, UTF-8 with BOM)
locales : 13
--- Translations.resx (default) ---
[#0 ] Sidebar.Dashboard = 'Dashboard' (Translations.resx:L125)
[#1 ] Sidebar.Settings = 'Settings' (Translations.resx:L127)
[#2 ] Button.Close = 'Close' (Translations.resx:L133)
[#3 ] Dashboard.SystemInfo.Cpu.Cores = '{0} Cores' (Translations.resx:L136)
resx_create.py — Create a new locale file
What it does: Copies the source .resx to create a new locale file. Preserves encoding, BOM, XML structure.
Usage:
python <skill>\helpers\resx_create.py Resources\Languages --locale vi-VN
python <skill>\helpers\resx_create.py Resources\Languages --locale ja-JP --dry-run
Flags:
| Flag | Description |
|---|---|
--locale |
(Required) Language code |
--source |
Source filename (default: auto-detected) |
--dry-run |
Preview without creating |
--json |
JSON output |
resx_sync.py — Sync missing keys from source to locales
What it does: Copies keys that exist in source but are missing from locale files.
Usage:
# Sync with English fallback values
python <skill>\helpers\resx_sync.py Resources\Languages --fill-source
# Sync with TODO markers
python <skill>\helpers\resx_sync.py Resources\Languages --fill-marker "TODO"
# Sync specific locale only
python <skill>\helpers\resx_sync.py Resources\Languages --locale vi-VN --fill-source
Flags:
| Flag | Description |
|---|---|
--fill-source |
Copy source value as-is |
--fill-marker "TEXT" |
Fill with marker string |
--locale CODE |
Target specific locale |
--dry-run |
Preview without writing |
--json |
JSON output |
resx_write.py — Batch write translations to multiple locales
What it does: Write/update translation keys across multiple locale files. Supports --key/--value, --file, or --stdin input. Modes: auto (add+update), update (existing only), add (new only).
Usage:
# Single key to all locales
python <skill>\helpers\resx_write.py Resources\Languages --key AppTitle --value "OptimizerDuck" --locale all
# Single key to specific locale
python <skill>\helpers\resx_write.py Resources\Languages --key Button.Close --value "Đóng" --locale vi-VN
# Write from file (KEY=VALUE or JSON)
python <skill>\helpers\resx_write.py Resources\Languages --file translations.txt --locale vi-VN
# Write from stdin
echo "Button.Close=Đóng" | python <skill>\helpers\resx_write.py Resources\Languages --stdin --locale vi-VN
# Dry run
python <skill>\helpers\resx_write.py Resources\Languages --key Button.Close --value "Đóng" --locale vi-VN --dry-run
KEY=VALUE file format:
# Comments and blank lines are ignored
Button.Close=Đóng
Button.Save=Lưu
Sidebar.Dashboard=Bảng điều khiển
Flags:
| Flag | Description |
|---|---|
--key TEXT |
Single key to write |
--value TEXT |
Value for --key |
--file PATH |
File with KEY=VALUE or JSON |
--stdin |
Read from stdin |
--locale CODE |
Target locale (vi, ja, all) |
--mode |
auto / update / add / upsert |
--dry-run |
Preview without writing |
--json |
JSON output |
--source |
Source .resx to create locale from if missing |
Task Dispatch
| User says | Action |
|---|---|
| "dịch các translation còn thiếu" | resx_audit → ask → resx_write for flagged keys |
| "dịch ngôn ngữ mới" | resx_create → resx_sync --fill-source → resx_write |
| "dịch các translation" | resx_audit --no-missing → resx_write for untranslated |
| "cập nhật translations" | resx_sync --fill-source → resx_audit → resx_write |
| "liệt kê translations" | resx_list |
| "tìm key X" | resx_list --key X |
| "kiểm tra Designer.cs" | resx_audit --check-designer |
Workflow
0. Always ask before translating
Before any translation work, use the question tool to:
- If multiple locales have issues: Ask which locale(s) to work on
- Confirm the approach: Describe what
resx_auditfound and what you plan to do - Domain context: If the app has specialized terminology, ask about preferred translations
A. Fill Missing Translations
- Run
resx_audit.pyto find issues - Ask user: which locale, confirm scope
- Use
resx_write.pyto write translations:
Or batch from file:python <skill>\helpers\resx_write.py Resources\Languages --key Button.Close --value "Đóng" --locale vi-VNpython <skill>\helpers\resx_write.py Resources\Languages --file translations.txt --locale vi-VN - Verify: run
resx_audit.pyagain
B. Add New Language
- Run
resx_list.pyto see existing files - Ask user: confirm language code
- Run
resx_create.py --locale <code> - Run
resx_sync.py --fill-sourceto fill with English fallback - Run
resx_audit.py --lang <code>to find untranslated - Use
resx_write.pyto translate all untranslated keys
C. Batch Translate from File
- Create a KEY=VALUE file:
Button.Close=Đóng Button.Save=Lưu Sidebar.Dashboard=Bảng điều khiển - Run
resx_write.py --file translations.txt --locale vi-VN - Verify:
resx_audit.py --lang vi-VN
Translation Rules
- Translate only user-facing text. Never change keys, node names, attributes, or XML structure.
- Preserve exactly:
{0},{1},%splaceholders; HTML/XAML fragments; product names; error codes. - Short strings (
Open,Save,Apply,Reset) depend on context — inspect nearby code if unsure. - Keep English terms that function as product language (
Playlist,Profile,Driver,Theme,Preset). - Preserve original encoding (UTF-8 with/without BOM).
Editing Behavior
- Use
resx_write.pyfor all writes — never manually edit.resxfiles. - The script preserves XML structure, encoding, and indentation.
- Report back briefly: which file was updated, language, key count.
Quick Reference
| Need | Command |
|---|---|
| Audit all locales | resx_audit.py <dir> |
| Audit specific locale | resx_audit.py <dir> --lang vi-VN |
| List all translations | resx_list.py <dir> |
| Search keys | resx_list.py <dir> --key Dashboard |
| Create new locale | resx_create.py <dir> --locale vi-VN |
| Sync missing keys | resx_sync.py <dir> --fill-source |
| Write single key | resx_write.py <dir> --key K --value V --locale vi-VN |
| Write from file | resx_write.py <dir> --file tr.txt --locale vi-VN |
| Write to all locales | resx_write.py <dir> --key K --value V --locale all |
| CI check | resx_audit.py <dir> --fail-on-any |
| Designer.cs check | resx_audit.py <dir> --check-designer |
Version History
-
f68192e
Current 2026-07-23 11:36
重构了辅助脚本体系:移除find_resx.py和audit_translations.py,新增resx_core.py核心库与resx_audit.py审计工具;优化了行号定位语法以支持更精确的文件片段读取。
- b472afe 2026-07-06 00:03


