Agent skill

Sync Translations

by symfony in symfony/symfony

Synchronize translation catalogs across maintained Symfony branches: find messages that newer branches added to the English catalogs but that are still missing from the oldest maintained branch…

MITAuto-check passedWriting & Content

Install Sync Translations

skills CLI
$ npx skills add symfony/symfony --skill sync-translations -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install symfony/symfony sync-translations --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/symfony/symfony.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/sync-translations .claude/skills/sync-translations && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
sync-translations
GitHub stars
31k
Token cost
~1.9k tokens
SKILL.md length
751 words
Files
2 (incl. scripts)
Skills in repo
9
Repo updated
First seen
Licence
MIT

At a glance

Synchronize translation catalogs across maintained Symfony branches: find messages that newer branches added to the English catalogs but that are still missing from the oldest maintained branch…

  • Works in 6 steps: Get maintained branches and fetch them → Create the branch off the oldest… → Discover the missing messages per catalog → …
  • The user says synchronize translations
  • SKILL.md covers Core convention, Progress checklist, Step 1 — Get maintained… and Step 2 — Create the branch off…, plus 5 more sections
  • Runs PHP scripts from its folder; calls git, php and curl; reaches symfony.com

What it does

Sync Translations is an agent skill from symfony/symfony. Synchronize translation catalogs across maintained Symfony branches: find messages that newer branches added to the English catalogs but that are still missing from the oldest maintained branch, then add them (with a translation per locale) on that oldest branch so they cascade up via merges. Use when the user says "synchronize translations", "sync new translations", "sync the translation catalogs", "add the missing translation messages", or "propagate new xlf messages".

Its SKILL.md is about 1.9k tokens, which your agent loads only when the skill is triggered. The skill folder holds 2 other files, including scripts.

It sits in Writing & Content, covering Translation. It works with Symfony and PHP. The repository describes itself as: The Symfony PHP framework. The licence is MIT.

When your agent uses it

  • The user says synchronize translations
  • Sync new translations
  • Sync the translation catalogs
  • Add the missing translation messages

Example prompts

  • “synchronize translations”
  • “sync new translations”
  • “sync the translation catalogs”
  • “/sync-translations”

Workflow steps

6 steps, taken from the step headings in SKILL.md.

  1. Get maintained branches and fetch them
  2. Create the branch off the oldest maintained branch
  3. Discover the missing messages per catalog
  4. Add each missing message to every locale
  5. Verify
  6. Commit per component (do not push)

What it can do on your machine

Read from SKILL.md and the folder at commit d977c80. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Ships 1 file in scripts/ (PHP), which the agent can run.

    Shell commands in SKILL.md call:

    • git
    • php
    • curl

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Hosts in commands or code, which the agent is likely to contact:

    • symfony.com

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Sync Translations loads about 1.9k tokens when it runs. Until then it costs about 123 tokens; SKILL.md has 751 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~123
When it runs · the whole SKILL.md, loaded when a task matches
~1.9k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); the scripts in this folder are not scanned.

SKILL.md

The full file from symfony/symfony at commit d977c80, republished under its MIT licence (© symfony). 751 words, ~1,906 tokens.

Download SKILL.mdSave it as .claude/skills/sync-translations/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.
name
sync-translations
description
Synchronize translation catalogs across maintained Symfony branches: find messages that newer branches added to the English catalogs but that are still missing from the oldest maintained branch, then add them (with a translation per locale) on that oldest branch so they cascade up via merges. Use when the user says "synchronize translations", "sync new translations", "sync the translation catalogs", "add the missing translation messages", or "propagate new xlf messages".

Symfony Translation Catalog Synchronization

New messages get added to the English catalog only (e.g. validators.en.xlf), usually on the newest branch where a feature lands. This skill discovers every such message missing from the oldest maintained branch and adds it there, in all locales, so it cascades up through the regular merge-up.

Core convention

Translation messages always land on the oldest maintained branch, even when the feature that introduced them only exists on a newer branch. Catalogs are append-only with sequential ids, so the newer branch is a superset of the oldest: the missing messages are exactly the trailing entries whose id is greater than the oldest branch's current maximum. Adding them on the oldest branch with the same ids keeps the eventual merge-up conflict-free.

Progress checklist

  • Step 1: Get maintained branches and fetch them
  • Step 2: Create the branch off the oldest maintained branch
  • Step 3: Discover the missing messages per catalog
  • Step 4: Add each missing message to every locale
  • Step 5: Verify
  • Step 6: Commit per component (do not push)

Step 1 — Get maintained branches and fetch them

Use the same endpoint as the merge-up skill:

bash
curl -s https://symfony.com/releases.json

Read maintained_versions, already sorted oldest → newest (e.g. ["6.4", "7.4", "8.0", "8.1"]). The first is the TARGET (oldest); the rest are the NEWER branches. Fetch all of them from upstream:

bash
for b in <all maintained versions>; do git fetch upstream "$b"; done

Step 2 — Create the branch off the oldest maintained branch

Branch off the upstream ref, never a local branch. Suffix the branch name with the current date (date +%Y-%m-%d) so it stays unique across runs:

bash
git checkout -b "sync-translations-$(date +%Y-%m-%d)" upstream/<TARGET>

Step 3 — Discover the missing messages per catalog

The English catalogs to compare (one per component that ships translations):

bash
git ls-tree -r --name-only upstream/<TARGET> | grep -E 'Resources/translations/.*\.en\.xlf$'

(Today: Validator/.../validators.en.xlf, Form/.../validators.en.xlf, Security/Core/.../security.en.xlf. A NEWER branch may also introduce a brand-new catalog file absent from the TARGET; pick those up by listing catalogs on the newest branch too.)

Helper to extract id<TAB>source pairs from a catalog at any ref:

bash
extract() { # $1 = git ref, $2 = path
  git show "$1:$2" 2>/dev/null | php -r '
$c = stream_get_contents(STDIN);
preg_match_all("#<trans-unit id=\"(\d+)\">\s*<source>(.*?)</source>#s", $c, $m, PREG_SET_ORDER);
foreach ($m as $x) { echo $x[1]."\t".$x[2]."\n"; }'
}

For each catalog file, go over every NEWER branch (oldest → newest) and collect trans-units whose id is greater than the TARGET's current maximum id for that file:

bash
TARGET_MAX=$(extract upstream/<TARGET> "$f" | cut -f1 | sort -n | tail -1)
extract upstream/<NEWER> "$f" | awk -F'\t' -v max="$TARGET_MAX" '$1 > max'

Union the results across NEWER branches and dedup by id (newer branches are cumulative, so the newest usually already contains the full set). Cross-check: every collected source must be absent from the TARGET catalog. If a source already exists in the TARGET under a different id, the catalogs have diverged or been renumbered: stop and ask the user.

Report the discovered messages (component, id, English source) before editing.


Show full SKILL.md (345 more words)Show less

Step 4 — Add each missing message to every locale

For each missing message, write a JSON file mapping every non-en locale of the catalog to its translated target, then run the bundled script. Translate the source yourself (a real translation per locale, never the English fallback); the script adds the state="needs-review-translation" flag that marks them for native-speaker review.

bash
# translations.json: {"af": "...", "ar": "...", ..., "zh_TW": "..."}
php scripts/add_message.php \
  --dir src/Symfony/Component/Validator/Resources/translations \
  --id 146 \
  --source "This value is not a valid cron expression." \
  --translations translations.json

The script inserts the <trans-unit> before </body> in every *.xlf of the directory: the English catalog gets the source as its target, every other locale gets its translation. It is idempotent (a locale already holding the id is skipped) and exits non-zero if the JSON doesn't cover exactly the catalog's non-en locales. Pass --source already XML-ready (escape &, <, > if present) so it is reused byte-for-byte. Run it once per catalog and per missing id.

Resulting entries look like:

xml
            <trans-unit id="146">
                <source>This value is not a valid cron expression.</source>
                <target>This value is not a valid cron expression.</target>
            </trans-unit>
xml
            <trans-unit id="146">
                <source>This value is not a valid cron expression.</source>
                <target state="needs-review-translation">Cette valeur n'est pas une expression cron valide.</target>
            </trans-unit>

Step 5 — Verify

Well-formedness of every catalog touched:

bash
for f in <catalog dir>/*.xlf; do xmllint --noout "$f" || echo "BAD: $f"; done

Catalog consistency (same ids/sources across all locales). Run only the TranslationFilesTest of the components you actually touched, e.g. for Validator:

bash
./phpunit src/Symfony/Component/Validator/Tests/Resources/TranslationFilesTest.php

Each touched component has its own test under src/Symfony/Component/<Name>/Tests/Resources/TranslationFilesTest.php (Validator, Form, Security/Core). All must be clean. An unrelated PHPUnit-config schema warning is fine; a test failure is not.


Step 6 — Commit per component (do not push)

One atomic commit per affected component, staging only that component's translation directory:

bash
git add src/Symfony/Component/Validator/Resources/translations/
git commit -m "[Validator] Add translated messages for the <Feature> constraint"

Name the commit after the feature when the new messages map to one (e.g. the Cron constraint); otherwise describe the synchronization. Then stop: never push or open the PR, hand control back to the user.


Gotchas

  • The feature (constraint, attribute) introducing a message may not exist on the oldest branch at all. That is expected: only the catalog message goes there, never the feature code.
  • Every locale gets the entry, not just *.en.xlf, otherwise TranslationFilesTest fails on a missing id.
  • Reuse the id and byte-for-byte English <source> from the NEWER branch, including placeholders like {{ size }}; a different id or altered source breaks the conflict-free merge-up and the consistency test.
  • A catalog may legitimately have no missing messages; skip it silently.
  • Handle each catalog (Validator, Form, Security/Core) independently, with its own commit and [Component] prefix.

© symfony, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 1 other file (scripts) in .agents/skills/sync-translations of symfony/symfony.

  • SKILL.md
  • scripts/add_message.php

Open the folder on GitHubat commit d977c80

Compare with similar skills

Sync Translations next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Sync Translations compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Sync Translations this skillsymfony/symfony31k—~1.9kAutomated safety check: PassMIT
Staticphp Documentation Synccrazywhalecc/static-php-cli1.9k—~2.2kAutomated safety check: PassMIT
I18n Lang FilesMes-Open/OpenMes158—~1.1kAutomated safety check: PassAGPL-3.0
Translation Diff ExportDevolutions/UniGetUI26k—~1.1kAutomated safety check: PassMIT
Translation Diff ImportDevolutions/UniGetUI26k—~750Automated safety check: PassMIT
Translation Diff TranslateDevolutions/UniGetUI26k—~934Automated safety check: PassMIT

Similar skills

  • Staticphp Documentation Sync

    crazywhalecc/static-php-cli

    Synchronize bilingual documentation when StaticPHP v3 user-facing or developer-facing documentation must change.

    1.9k GitHub stars~2.2k tokensUpdated today
    DevelopmentAuto-check passed
  • I18n Lang Files

    Mes-Open/OpenMes

    Editing or merging backend/lang/en.json and pl.json. An agent skill from Mes-Open/OpenMes.

    158 GitHub stars~1.1k tokensUpdated today
    Frontend & DesignAuto-check passed
  • Translation Diff Export

    Devolutions/UniGetUI

    Compares UniGetUI JSON locale files against English, identifies untranslated or source-changed keys, and generates patch, reference, and handoff files for a target language.

    26k GitHub stars~1.1k tokensUpdated today
    Writing & ContentAuto-check passed
  • Translation Diff Import

    Devolutions/UniGetUI

    Merges translated key-value pairs from a UniGetUI JSON localization patch back into the full language file and validates the merged result.

    26k GitHub stars~750 tokensUpdated today
    Writing & ContentAuto-check passed
  • Translation Diff Translate

    Devolutions/UniGetUI

    Translates a sparse UniGetUI JSON language patch, writes completed entries into the working copy, preserves placeholders and terminology, and prepares the patch for merge-back.

    26k GitHub stars~934 tokensUpdated today
    Writing & ContentAuto-check passed
  • Generate Translations

    payloadcms/payload

    A skill your agent uses when new translation keys are added to packages to generate new translations strings

    45k GitHub stars~1.1k tokensUpdated today
    Writing & ContentAuto-check passed

More from symfony/symfony

All 9 skills in this repo
  • Bug Triage

    symfony/symfony

    Decide whether open Bug PRs target the correct branch. An agent skill from symfony/symfony.

    31k GitHub stars~1.9k tokensUpdated today
    Auto-check passed
  • Merge Up

    symfony/symfony

    Cascade-merge maintained Symfony branches from oldest to newest (e.g.

    31k GitHub stars~4k tokensUpdated today
    Auto-check passed
  • PR Merge

    symfony/symfony

    Merge a reviewed pull request the way the Symfony core team does: one --no-ff merge commit per PR, whose message archives the whole discussion, with the review gates checked first.

    31k GitHub stars~3.1k tokensUpdated today
    Auto-check passed
  • Security Triage

    symfony/symfony

    Triage a reported security finding into a disposition: a private CVE (coordinated disclosure + advisory), a public hardening PR (fix in the open, no CVE), or not-a-security-issue (reply to reporter).

    31k GitHub stars~2.6k tokensUpdated today
    Auto-check passed
  • Review a change (a PR, the current branch diff, or a set of files) or audit a component or the whole tree for missing or incorrect security hardening.

    31k GitHub stars~2.9k tokensUpdated today
    Auto-check passed
  • Hardening Rule

    symfony/symfony

    Decide whether a recurring hardening invariant is worth a CI gate, and add it without hitting the traps.

    31k GitHub stars~1.2k tokensUpdated today
    Auto-check passed

Works with

Questions about Sync Translations

What does Sync Translations do?

Synchronize translation catalogs across maintained Symfony branches: find messages that newer branches added to the English catalogs but that are still missing from the oldest maintained branch…. Sync Translations is an agent skill from symfony/symfony. Synchronize translation catalogs across maintained Symfony branches: find messages that newer branches added to the English catalogs but that are still missing from the oldest maintained branch, then add them (with a translation per locale) on that oldest branch so they cascade up via merges.

When should I use Sync Translations?

Sync Translations fits situations like: the user says synchronize translations; sync new translations; sync the translation catalogs; add the missing translation messages.

How do I install Sync Translations in Claude Code?

Run `npx skills add symfony/symfony --skill sync-translations -a claude-code`. Or copy the skill folder (.agents/skills/sync-translations in symfony/symfony) into .claude/skills/sync-translations in your project. Claude Code loads it when a task matches its description.

How do I install Sync Translations in Codex?

Run `npx skills add symfony/symfony --skill sync-translations -a codex`. Or copy the skill folder (.agents/skills/sync-translations in symfony/symfony) into .agents/skills/sync-translations in your project. Codex loads it when a task matches its description.

Can I use Sync Translations in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add symfony/symfony --skill sync-translations -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/sync-translations, .gemini/skills/sync-translations, .github/skills/sync-translations and .opencode/skills/sync-translations in your project.

What does Sync Translations need to run?

Going by SKILL.md and its folder, Sync Translations needs PHP for the scripts in its folder and the command-line tools its instructions call (git, php and curl).

Does Sync Translations access the network?

SKILL.md names 1 domain. In commands or code: symfony.com; the agent is likely to contact it when it follows the instructions. This is read from the text; nothing was executed.

Is Sync Translations safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. The check reads SKILL.md only: the scripts in the folder are not scanned, so read them before running anything.

What licence does Sync Translations use?

Sync Translations is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Sync Translations use?

About 1.9k tokens (SKILL.md is roughly 7.6k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Sync Translations?

Skills that share tags, products or a category with Sync Translations: Staticphp Documentation Sync (crazywhalecc/static-php-cli, 1.9k stars), I18n Lang Files (Mes-Open/OpenMes, 158 stars), Translation Diff Export (Devolutions/UniGetUI, 26k stars) and Translation Diff Import (Devolutions/UniGetUI, 26k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Sync Translations?

symfony (a GitHub organization) maintains it in symfony/symfony, which has 31,184 GitHub stars. The repository holds 9 skills in this directory. The repository was last updated on October 9, 2026.

Source: symfony/symfony on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.