mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-10-05 19:28:25 +00:00
i18n: add cs/de/sv plurals for music track counts; teach skill to diff <plurals>
The find-missing-translations skill only diffed <string name=, so missing <plurals> resources slipped through. Updated Steps 2, 2.5, 3 to diff <plurals> independently and added 3 missing music playlist plurals across cs/de/sv with correct CLDR category coverage (Czech: one/few/many/other). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
a70e0e6cf9
commit
d27d215d97
@@ -51,17 +51,28 @@ Target: amethyst/src/main/res/values-<locale>/strings.xml
|
||||
|
||||
Always diff against `cs-rCZ` first — it is the most complete locale and serves as the reference. Any keys missing in `cs-rCZ` will also be missing in the other target locales.
|
||||
|
||||
You MUST diff **both** `<string name=` AND `<plurals name=` — these are independent resource types and a key that is a `<plurals>` in the source will never appear in a `<string>` diff. Forgetting `<plurals>` is the most common silent failure of this skill (it misses things like `music_playlist_track_count`, `notification_count_more`, etc.).
|
||||
|
||||
```bash
|
||||
# Extract translatable keys from default (exclude translatable="false")
|
||||
# Strings: extract translatable keys from default (exclude translatable="false")
|
||||
echo "=== missing <string> ==="
|
||||
comm -23 \
|
||||
<(grep '<string name=' amethyst/src/main/res/values/strings.xml \
|
||||
| grep -v 'translatable="false"' \
|
||||
| sed 's/.*name="\([^"]*\)".*/\1/' | sort) \
|
||||
<(grep '<string name=' amethyst/src/main/res/values-cs-rCZ/strings.xml \
|
||||
| sed 's/.*name="\([^"]*\)".*/\1/' | sort)
|
||||
|
||||
# Plurals: a separate resource type — MUST be diffed independently
|
||||
echo "=== missing <plurals> ==="
|
||||
comm -23 \
|
||||
<(grep '<plurals name=' amethyst/src/main/res/values/strings.xml \
|
||||
| sed 's/.*name="\([^"]*\)".*/\1/' | sort) \
|
||||
<(grep '<plurals name=' amethyst/src/main/res/values-cs-rCZ/strings.xml \
|
||||
| sed 's/.*name="\([^"]*\)".*/\1/' | sort)
|
||||
```
|
||||
|
||||
This gives the list of missing key names. Do NOT diff each locale separately — assume the same keys are missing in all target locales.
|
||||
This gives two lists of missing key names — keep them separate; `<plurals>` translations need the per-locale CLDR category set (see Step 5 → "Plurals: handle with care"). Do NOT diff each locale separately for strings — assume the same keys are missing in all target locales (but DO repeat the `<plurals>` diff per locale if you suspect Crowdin asymmetric stripping).
|
||||
|
||||
> **Caveat:** Crowdin can asymmetrically strip keys across locales (each translator independently chose source-identical for different keys). If the cs-rCZ list looks suspiciously short, run the same diff for each target locale individually and union the results before Step 2.5.
|
||||
|
||||
@@ -85,8 +96,9 @@ else
|
||||
fi
|
||||
|
||||
# For each locale, list only keys added after the Crowdin sync (truly new).
|
||||
# Run for BOTH <string> and <plurals>.
|
||||
for locale in cs-rCZ de-rDE sv-rSE; do
|
||||
echo "=== $locale: genuinely new (post-sync) keys ==="
|
||||
echo "=== $locale: genuinely new (post-sync) <string> keys ==="
|
||||
comm -23 \
|
||||
<(grep '<string name=' amethyst/src/main/res/values/strings.xml \
|
||||
| grep -v 'translatable="false"' \
|
||||
@@ -99,6 +111,19 @@ for locale in cs-rCZ de-rDE sv-rSE; do
|
||||
echo "$key"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "=== $locale: genuinely new (post-sync) <plurals> keys ==="
|
||||
comm -23 \
|
||||
<(grep '<plurals name=' amethyst/src/main/res/values/strings.xml \
|
||||
| sed 's/.*name="\([^"]*\)".*/\1/' | sort) \
|
||||
<(grep '<plurals name=' amethyst/src/main/res/values-$locale/strings.xml \
|
||||
| sed 's/.*name="\([^"]*\)".*/\1/' | sort) \
|
||||
| while IFS= read -r key; do
|
||||
added_ts=$(git log -1 --format=%ct -S "name=\"$key\"" -- amethyst/src/main/res/values/strings.xml)
|
||||
if [ -n "$added_ts" ] && [ "$added_ts" -gt "$sync_ts" ]; then
|
||||
echo "$key"
|
||||
fi
|
||||
done
|
||||
done
|
||||
```
|
||||
|
||||
@@ -118,10 +143,10 @@ If no Crowdin export commit can be found in history (`sync_ts=0` fallback), warn
|
||||
|
||||
### 3. Get English values for missing keys
|
||||
|
||||
For each missing key, extract its English value:
|
||||
For each missing key, extract its English value. `<string>` is a single line; `<plurals>` is a multi-line block — handle each appropriately.
|
||||
|
||||
```bash
|
||||
# For each missing key, extract the full line from default strings.xml
|
||||
# Missing <string>: full line from default strings.xml
|
||||
while IFS= read -r key; do
|
||||
grep "name=\"$key\"" amethyst/src/main/res/values/strings.xml
|
||||
done < <(comm -23 \
|
||||
@@ -130,6 +155,19 @@ done < <(comm -23 \
|
||||
| sed 's/.*name="\([^"]*\)".*/\1/' | sort) \
|
||||
<(grep '<string name=' amethyst/src/main/res/values-cs-rCZ/strings.xml \
|
||||
| sed 's/.*name="\([^"]*\)".*/\1/' | sort))
|
||||
|
||||
# Missing <plurals>: extract the multi-line block (opening tag through </plurals>)
|
||||
while IFS= read -r key; do
|
||||
awk -v key="$key" '
|
||||
$0 ~ "<plurals name=\"" key "\"" { in_p = 1 }
|
||||
in_p { print }
|
||||
in_p && /<\/plurals>/ { in_p = 0 }
|
||||
' amethyst/src/main/res/values/strings.xml
|
||||
done < <(comm -23 \
|
||||
<(grep '<plurals name=' amethyst/src/main/res/values/strings.xml \
|
||||
| sed 's/.*name="\([^"]*\)".*/\1/' | sort) \
|
||||
<(grep '<plurals name=' amethyst/src/main/res/values-cs-rCZ/strings.xml \
|
||||
| sed 's/.*name="\([^"]*\)".*/\1/' | sort))
|
||||
```
|
||||
|
||||
### 4. Audit missing strings for plural-shaped patterns
|
||||
@@ -262,7 +300,7 @@ When adding translated strings to locale files:
|
||||
## Common Mistakes
|
||||
|
||||
- **Forgetting `translatable="false"`** — these should never appear in locale files
|
||||
- **Not checking string-arrays/plurals** — only checking `<string>` misses other resource types
|
||||
- **Diffing only `<string name=`** — `<plurals>` is a separate resource type; a source `<plurals>` missing from a locale will never show up in a `<string>` diff. Always run the diff twice (once per resource type) as shown in Step 2. The same goes for `<string-array>` if the project uses it.
|
||||
- **Treating every missing key as actionable** — Crowdin strips on export any translation the translator marked as "use English", and we cannot distinguish that from "never seen" by looking at disk. Use the Step 2.5 sync-timestamp filter: only keys added to `values/strings.xml` after the last `l10n_crowdin_translations` sync are genuinely new.
|
||||
- **Trying to detect "stripped" from git history alone** — the on-disk locale file only sees keys the translator typed a non-identical value for. The "translator opened the key and picked English from the start" case never touches disk, so a history-only check misses it. Use the sync-timestamp cutoff instead.
|
||||
- **Adding source-identical fallbacks locally** — they get overwritten on the next Crowdin sync. Android falls back to `values/strings.xml` at runtime anyway, so there is no user-visible bug to fix.
|
||||
|
||||
@@ -2823,4 +2823,22 @@
|
||||
<string name="nowhere_link_card_drop">Nowhere Drop</string>
|
||||
<string name="nowhere_link_card_art">Nowhere Umění</string>
|
||||
<string name="nowhere_link_card_forum">Nowhere Fórum</string>
|
||||
<plurals name="music_playlist_track_count_short">
|
||||
<item quantity="one">%1$d stopa</item>
|
||||
<item quantity="few">%1$d stopy</item>
|
||||
<item quantity="many">%1$d stopy</item>
|
||||
<item quantity="other">%1$d stop</item>
|
||||
</plurals>
|
||||
<plurals name="music_playlist_track_count">
|
||||
<item quantity="one">%1$d stopa</item>
|
||||
<item quantity="few">%1$d stopy</item>
|
||||
<item quantity="many">%1$d stopy</item>
|
||||
<item quantity="other">%1$d stop</item>
|
||||
</plurals>
|
||||
<plurals name="music_playlist_more_tracks">
|
||||
<item quantity="one">+%1$d další stopa</item>
|
||||
<item quantity="few">+%1$d další stopy</item>
|
||||
<item quantity="many">+%1$d další stopy</item>
|
||||
<item quantity="other">+%1$d dalších stop</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
|
||||
@@ -2791,4 +2791,16 @@ anz der Bedingungen ist erforderlich</string>
|
||||
<string name="nowhere_link_card_drop">Nowhere Drop</string>
|
||||
<string name="nowhere_link_card_art">Nowhere Kunst</string>
|
||||
<string name="nowhere_link_card_forum">Nowhere Forum</string>
|
||||
<plurals name="music_playlist_track_count_short">
|
||||
<item quantity="one">%1$d Titel</item>
|
||||
<item quantity="other">%1$d Titel</item>
|
||||
</plurals>
|
||||
<plurals name="music_playlist_track_count">
|
||||
<item quantity="one">%1$d Titel</item>
|
||||
<item quantity="other">%1$d Titel</item>
|
||||
</plurals>
|
||||
<plurals name="music_playlist_more_tracks">
|
||||
<item quantity="one">+%1$d weiterer Titel</item>
|
||||
<item quantity="other">+%1$d weitere Titel</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
|
||||
@@ -2786,4 +2786,16 @@
|
||||
<string name="nowhere_link_card_drop">Nowhere Drop</string>
|
||||
<string name="nowhere_link_card_art">Nowhere Konst</string>
|
||||
<string name="nowhere_link_card_forum">Nowhere Forum</string>
|
||||
<plurals name="music_playlist_track_count_short">
|
||||
<item quantity="one">%1$d spår</item>
|
||||
<item quantity="other">%1$d spår</item>
|
||||
</plurals>
|
||||
<plurals name="music_playlist_track_count">
|
||||
<item quantity="one">%1$d spår</item>
|
||||
<item quantity="other">%1$d spår</item>
|
||||
</plurals>
|
||||
<plurals name="music_playlist_more_tracks">
|
||||
<item quantity="one">+%1$d spår till</item>
|
||||
<item quantity="other">+%1$d spår till</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user