Skip to content

Commit dfbea5d

Browse files
committed
Polish translation agent skill
1 parent 8fa98d2 commit dfbea5d

5 files changed

Lines changed: 91 additions & 36 deletions

File tree

.github/skills/translate-po/SKILL.md

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
name: translate-po
3-
description: Use this when asked to update a PO translation catalog with GitHub Copilot. It refreshes the POT file, syncs the target PO file, fills safe untranslated entries, validates the result, and prepares a pull request.
3+
description: Use this when asked to update a PO translation catalog with GitHub Copilot. It uses the POT file already prepared on the branch, syncs the target PO file, fills safe untranslated entries, validates the result, and prepares a pull request.
44
---
55

66
# Translate PO catalogs
@@ -15,40 +15,66 @@ Use this skill when asked to update translations in `superdesk-client-core`.
1515
- Optional glossary file, for example `docs/i18n/es-glossary.md`
1616
- Translation rules: `docs/i18n/translation-rules.md`
1717

18-
## Required workflow
18+
## Environment requirements
19+
20+
Before doing any translation work, ensure the environment is ready:
1921

20-
1. Refresh the source template:
22+
1. Use Node.js 22.
23+
2. Install project dependencies:
2124

2225
```bash
23-
npm run gettext-extract
26+
npm ci
2427
```
2528

26-
2. Sync the PO file structurally from the template:
29+
3. Ensure GNU gettext tools are installed and available on PATH:
30+
- `msgmerge`
31+
32+
## POT preconditions
33+
34+
Assume `po/superdesk.pot` was prepared by a human developer in a complete local environment.
35+
36+
- Do not run `npm run gettext-extract` as part of the agent workflow.
37+
- Use the existing `po/superdesk.pot` already present on the branch as the source of truth.
38+
- If the POT on the branch looks incomplete or inconsistent, stop and explain the problem instead of regenerating it.
39+
40+
## Required workflow
41+
42+
1. Sync the PO file structurally from the template already present on the branch:
2743

2844
```bash
2945
npm run gettext-update-po -- <lang>
3046
```
3147

32-
3. Fill only empty `msgstr` and `msgstr[n]` entries in `po/<lang>.po`.
48+
2. Fill only empty `msgstr` and `msgstr[n]` entries in `po/<lang>.po`.
3349

34-
4. Validate the result:
50+
3. Validate the result:
3551

3652
```bash
3753
grunt nggettext_compile
3854
```
3955

40-
5. Prepare a pull request against `develop`.
56+
4. Prepare a pull request against `develop`.
57+
58+
## Sync safety checks
59+
60+
After syncing `po/<lang>.po` from the POT:
61+
62+
- check that existing translations were not removed unexpectedly
63+
- if a large number of entries suddenly become obsolete, stop and investigate before translating
64+
- treat mass obsolescence of planning or analytics entries as a failure signal, not as a valid update
4165

4266
## Hard rules
4367

4468
- Never modify runtime JSON files directly.
4569
- Never edit `msgid`.
4670
- Never rewrite unrelated entries.
4771
- Never overwrite existing non-empty translations.
72+
- Do not prune obsolete entries during agent-driven PO sync.
4873
- Preserve all `{{...}}` placeholders exactly, including spacing and nested expressions.
4974
- Preserve plural structures exactly.
5075
- Keep diffs minimal and reviewable.
5176
- Follow the target-language glossary when one exists.
77+
- Clean up unnecessary whitespace in translated strings before saving.
5278

5379
## Skip rules
5480

@@ -59,6 +85,15 @@ Skip the entry and leave it unchanged if it is:
5985
- unsafe because of unusual placeholders or formatting
6086
- likely to require broader terminology review
6187

88+
## Whitespace and punctuation rules
89+
90+
- Do not introduce leading or trailing spaces in translated text.
91+
- Do not introduce double spaces unless they are already required by the source.
92+
- Do not add spaces before punctuation marks in Spanish.
93+
- Do not add unnecessary spaces inside parentheses, quotes, or around slashes.
94+
- Preserve placeholder text exactly, but make the surrounding Spanish punctuation and spacing natural.
95+
- Before saving, re-read each changed entry once focusing only on whitespace and punctuation.
96+
6297
## Current Spanish configuration
6398

6499
For the current Spanish workflow:

docs/i18n/ai-agent-instructions.md

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,32 @@ Follow these rules when updating translations in `superdesk-client-core`.
1010
- Optional excluded PO files: any locale-specific files that the workflow marks as out of scope
1111
- Optional glossary: a language-specific glossary file if one exists
1212

13+
## Environment Requirements
14+
15+
- Use Node.js 22.
16+
- Install project dependencies with `npm ci`.
17+
- Ensure GNU gettext tools are installed and available:
18+
- `msgmerge`
19+
20+
## POT Preconditions
21+
22+
Assume `po/superdesk.pot` was prepared outside the agent flow.
23+
24+
- Do not run `npm run gettext-extract` as part of the agent flow.
25+
- Use the existing `po/superdesk.pot` already present on the branch as the source of truth.
26+
- If the POT on the branch looks incomplete or inconsistent, stop and explain the problem instead of regenerating it.
27+
1328
## Required Workflow
1429

15-
1. Assume `npm run gettext-extract` has refreshed `po/superdesk.pot`.
30+
1. Use the existing `po/superdesk.pot` on the branch as the source of truth.
1631
2. Assume `npm run gettext-update-po -- <lang>` has structurally synced `po/<lang>.po`.
1732
3. Only then fill missing translations in `po/<lang>.po`.
1833

34+
## Sync Safety Checks
35+
36+
- After PO sync, verify that existing translations were not removed unexpectedly.
37+
- If many entries suddenly become obsolete, especially in planning or analytics areas, treat it as an extraction-environment problem and stop.
38+
1939
## Hard Rules
2040

2141
- Never modify runtime JSON files directly.
@@ -24,10 +44,12 @@ Follow these rules when updating translations in `superdesk-client-core`.
2444
- Never touch excluded locale files.
2545
- Never overwrite existing non-empty translations.
2646
- Only fill empty `msgstr` or empty plural `msgstr[n]` values when safe.
47+
- Do not prune obsolete entries during agent-driven PO sync.
2748
- Preserve all `{{...}}` placeholders exactly, including spacing and nested expressions.
2849
- Preserve plural structures exactly.
2950
- Keep diffs minimal and reviewable.
3051
- Follow the glossary for the target language if one is provided.
52+
- Remove unnecessary whitespace before saving translated strings.
3153

3254
## Skip Rules
3355

@@ -38,6 +60,15 @@ Skip the entry and leave it unchanged if it is:
3860
- unsafe because of unusual placeholders or formatting
3961
- likely to require broader terminology review
4062

63+
## Whitespace Rules
64+
65+
- Do not add leading or trailing spaces.
66+
- Do not add double spaces unless the source requires them.
67+
- Do not add spaces before punctuation marks.
68+
- Do not add unnecessary spaces inside parentheses, quotes, or around slashes.
69+
- Preserve placeholders exactly, but keep surrounding Spanish spacing natural.
70+
- Re-read changed translations once with a whitespace-only review before finishing.
71+
4172
## Validation Mindset
4273

4374
- Existing compile and validation tooling is the final safety net.

docs/i18n/translation-rules.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ This document defines the current rules for AI-assisted Spanish localization in
66

77
- Source of truth for new and changed strings is `po/superdesk.pot`.
88
- Initial write target is `po/es.po` only.
9+
- `po/superdesk.pot` should be refreshed by a human developer before the agent translation step.
910
- Do not modify runtime JSON files directly.
1011
- Run `npm run gettext-update-po -- es` before asking AI to translate.
1112
- Do not change extraction, compile, or validation tooling.
@@ -15,7 +16,8 @@ This document defines the current rules for AI-assisted Spanish localization in
1516

1617
- Translate only entries that exist in `po/superdesk.pot`.
1718
- Update only matching entries in `po/es.po`.
18-
- Let the sync step add or remove catalog entries structurally.
19+
- Let the sync step add matching catalog entries structurally.
20+
- Do not prune obsolete entries as part of the agent-driven update flow.
1921
- Never modify `msgid`.
2022
- Never rewrite unrelated entries.
2123
- Do not overwrite existing non-empty Spanish translations.
@@ -49,15 +51,14 @@ When skipping, leave the entry unchanged.
4951

5052
After preparing changes:
5153

52-
1. Refresh the template with `npm run gettext-extract`.
54+
1. Ensure `po/superdesk.pot` was refreshed by a human developer in a known complete environment.
5355
2. Sync the Spanish catalog with `npm run gettext-update-po -- es`.
5456
3. Ensure AI changes are limited to translation content in `po/es.po`.
5557
4. Ensure `msgid` values are untouched.
5658
5. Ensure placeholders and plural structures still match the source exactly.
5759
6. Run the existing compile/validation flow so current tooling can reject invalid placeholder changes:
5860

5961
```bash
60-
npm run gettext-extract
6162
npm run gettext-update-po -- es
6263
grunt nggettext_compile
6364
```

docs/i18n/translation-workflow.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,37 +4,36 @@ This is the manual GitHub Copilot agent workflow for AI-assisted translations in
44

55
## Flow
66

7-
1. Ask the GitHub Copilot agent to update Spanish translations using the repository skill in `.github/skills/translate-po/`.
7+
1. A human developer refreshes `po/superdesk.pot` in a known complete local environment before invoking the agent.
88

9-
2. The agent refreshes the source template:
9+
2. Ask the GitHub Copilot agent to update translations for the target language using the repository skill in `.github/skills/translate-po/`.
1010

11-
```bash
12-
npm run gettext-extract
13-
```
11+
3. The agent uses the existing `po/superdesk.pot` on the branch as the source of truth.
1412

15-
3. The agent syncs the target PO file from the template:
13+
4. The agent syncs the target PO file from the template:
1614

1715
```bash
1816
npm run gettext-update-po -- es
1917
```
2018

21-
4. The agent fills empty `msgstr` and `msgstr[n]` entries in `po/es.po`, using `po/superdesk.pot` as the source of truth.
19+
5. The agent fills empty `msgstr` and `msgstr[n]` entries in `po/es.po`, using `po/superdesk.pot` as the source of truth.
2220

23-
5. The agent validates with existing tooling:
21+
6. The agent validates with existing tooling:
2422

2523
```bash
2624
grunt nggettext_compile
2725
```
2826

29-
6. The agent prepares a PR against `develop`.
27+
7. The agent prepares a PR against `develop`.
3028

31-
7. Review the diff and the PR.
29+
8. Review the diff and the PR.
3230

3331
## AI Step Boundaries
3432

3533
- Read `po/superdesk.pot` as the source of truth.
3634
- Update only `po/es.po`.
3735
- Translate only empty entries in `po/es.po`.
36+
- Do not prune obsolete entries during the agent-driven sync step.
3837
- Never modify runtime JSON files directly.
3938
- Never edit `msgid`.
4039
- Never overwrite non-empty Spanish translations.
@@ -44,7 +43,8 @@ grunt nggettext_compile
4443
## Notes
4544

4645
- `npm run gettext-update-po -- <lang>` is generic and can be reused for other existing top-level PO files later.
47-
- The current workflow remains Spanish-only for AI translation.
46+
- The current examples use Spanish (`es`), but the agent workflow and skill are designed to work for other supported languages too.
4847
- The primary trigger is manual: ask the GitHub Copilot agent to perform the translation update.
48+
- `npm run gettext-extract` is intentionally outside the agent flow and should be run by a human developer when the POT needs to be refreshed.
4949
- The repository skill for this lives in `.github/skills/translate-po/SKILL.md`.
5050
- `docs/i18n/ai-agent-instructions.md` contains the generic agent rules; this document defines the current Spanish run configuration.

tasks/gettext-update-po.js

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,21 +42,9 @@ try {
4242
],
4343
{stdio: 'inherit'}
4444
);
45-
46-
execFileSync(
47-
'msgattrib',
48-
[
49-
'--no-obsolete',
50-
'--no-wrap',
51-
'-o',
52-
poFile,
53-
poFile,
54-
],
55-
{stdio: 'inherit'}
56-
);
5745
} catch (error) {
5846
if (error.code === 'ENOENT') {
59-
console.error('GNU gettext tools are required. Ensure "msgmerge" and "msgattrib" are installed.');
47+
console.error('GNU gettext tools are required. Ensure "msgmerge" is installed.');
6048
}
6149

6250
process.exit(error.status ?? 1);

0 commit comments

Comments
 (0)