diff --git a/.claude/skills/transifex/SKILL.md b/.claude/skills/transifex/SKILL.md
index afec997..55e71b2 100644
--- a/.claude/skills/transifex/SKILL.md
+++ b/.claude/skills/transifex/SKILL.md
@@ -9,8 +9,8 @@ Translations for this app live in the shared Nextcloud Transifex project
(`o:nextcloud:p:nextcloud`, resource `r:attendance` — see `.tx/config`).
Translators raise questions and issues on individual source strings there.
This skill covers the loop: fetch what's open, triage, fix source strings
-where the translators have a point, get the user's approval, then post
-replies.
+where the translators have a point, persist answers as `TRANSLATORS`
+context hints in the code, get the user's approval, then post replies.
## Prerequisites
@@ -24,14 +24,22 @@ replies.
## Step 1 — Fetch and reconstruct threads
```bash
-python3 .claude/skills/transifex/scripts/tx_feedback.py list --open
+python3 .claude/skills/transifex/scripts/tx_feedback.py list --open --new
```
This prints every thread that needs attention as JSON: the source string
(text, key, context), whether it has an open issue, and the full comment
transcript. `--me` defaults to `magdeflow` (the maintainer account); a
thread "needs attention" if it has an open issue or the last word wasn't
-ours. Drop `--open` to see everything including settled threads.
+ours.
+
+`--new` additionally drops threads without activity since the
+`answered_up_to` watermark in `state.json` (next to this SKILL.md) —
+that is what keeps already-handled threads from being answered twice,
+especially open issues we cannot resolve ourselves (they stay "open"
+forever, see Step 5). Drop `--new` only when the user explicitly wants
+to revisit older threads; drop `--open` to see everything including
+settled threads.
Reading the output, keep in mind:
@@ -50,7 +58,10 @@ that context. Then sort:
1. **Just answer** — context questions ("noun or verb?", "what does {x}
mean?"). Draft a reply that explains where the string appears and how
- it behaves; that is what the translator actually needs.
+ it behaves; that is what the translator actually needs. **Every
+ answered context question must also become a `TRANSLATORS` context
+ hint in the code** (see "Context hints" below) — the reply helps one
+ translator once, the hint helps every language forever.
2. **Fix the source string** — the translator is right (wrong spacing,
sentence fragments, split plurals, capitalization, concatenation).
Fix per the translation guidelines in `CLAUDE.md` (only first word
@@ -58,6 +69,46 @@ that context. Then sort:
3. **Needs the user's call** — product wording decisions, renames,
anything ambiguous. Ask instead of guessing.
+## Context hints for translators (always, when answering)
+
+Whenever a thread gets answered, persist the answer as a context hint
+next to the string in the code, per
+https://docs.nextcloud.com/server/latest/developer_manual/basics/translations.html#provide-context-hints-for-translators
+— the extractor copies these comments into the .pot, so future
+translators of every language see the hint directly in Transifex.
+
+Syntax by location:
+
+```php
+// TRANSLATORS Shown as button label in the check-in popup
+$l->t('Add new file');
+```
+
+```javascript
+// TRANSLATORS Name that is appended to copied files
+const label = t('attendance', 'copy')
+```
+
+```html
+
+{{ t('attendance', 'Required') }}
+```
+
+Rules:
+
+- The comment binds only to the **first** translation call on the
+ following line — one call per line, each with its own comment.
+- In Vue `` blocks use the HTML comment form, in `