Skip to content

Re-extract POT to include recycle-bin and posts-window strings#107

Open
epeicher wants to merge 2 commits intotrunkfrom
fix/104-pot-reextraction
Open

Re-extract POT to include recycle-bin and posts-window strings#107
epeicher wants to merge 2 commits intotrunkfrom
fix/104-pot-reextraction

Conversation

@epeicher
Copy link
Copy Markdown
Collaborator

@epeicher epeicher commented May 6, 2026

Summary

  • Re-extract POT so the ~136 __() / _x() calls inside src/recycle-bin/ and src/posts-window/ become translatable.
  • msgmerge languages/desktop-mode-es_ES.po against the new POT, refresh the .mo, and regenerate per-handle JSON via npm run build:i18n (added in PR Fix JS translations filename for the desktop-mode handle #100).
  • New strings ship untranslated; English fallback continues to work until translators get to them.

Changes

  • languages/desktop-mode.pot: 140 → 396 msgids (256 new), including 120 references under src/recycle-bin/ and src/posts-window/.
  • languages/desktop-mode-es_ES.po: msgmerged. 96 translated, 27 fuzzy, 272 untranslated, 2 obsolete entries flagged (Open new %s, Detach to new tab).
  • languages/desktop-mode-es_ES.mo: regenerated.
  • languages/desktop-mode-es_ES-desktop-mode.json: 79 → 156 strings.
  • languages/desktop-mode-es_ES-desktop-mode-recycle-bin.json: new, 11 strings.
  • languages/desktop-mode-es_ES-desktop-mode-posts-window.json: new, 85 strings.

Extraction pipeline (and why)

The "obvious" wp i18n make-pot . languages/desktop-mode.pot --include='src/*.ts,src/**/*.ts' --skip-js produces zero JS-side strings. Two reasons:

  1. --skip-js disables the JS extractor entirely.
  2. Without --skip-js, wp-cli's JsCodeExtractor is hardcoded to [js, jsx] extensions only, and its Peast parser chokes on TypeScript syntax (interface, generics, type, as Foo). Renaming .ts.js fails for the same Peast reason.

What worked (a two-pass extraction merged with msgcat):

  1. PHP-only POT: wp i18n make-pot . languages/desktop-mode.pot --skip-js --slug=alcazaba-plugin --package-name="Desktop Mode" --headers='{"Report-Msgid-Bugs-To":"https://wordpress.org/support/plugin/alcazaba-plugin"}' (slug preserved to keep this diff focused).
  2. TS POT: xgettext --language=TypeScript --keyword=__:1 --keyword=_x:1,2c --keyword=_n:1,2 --keyword=_nx:1,2,4c --add-comments=translators --no-wrap over every non-test src/**/*.ts into a temp POT (GNU gettext-tools handles TS natively).
  3. Merge: msgcat --no-wrap --use-first languages/desktop-mode.pot /tmp/ts.pot -o languages/desktop-mode.pot.
  4. PO update: msgmerge --no-wrap --update --backup=off languages/desktop-mode-es_ES.po languages/desktop-mode.pot.
  5. MO compile: msgfmt languages/desktop-mode-es_ES.po -o languages/desktop-mode-es_ES.mo.
  6. JSON: npm run build:i18n (from PR Fix JS translations filename for the desktop-mode handle #100).

Worth landing this as a documented bin/build-pot.sh in a follow-up so the next contributor doesn't rediscover the wp-cli/Peast TS gap.

Verified

  • npm run build clean (six bundles built including pwa-sw).
  • npm run lint clean.
  • tsc --noEmit clean.
  • npm run test:js: 803 / 87 files all green.
  • msgfmt --check --statistics passes.
  • Sanity: grep -c "src/recycle-bin\|src/posts-window" languages/desktop-mode.pot returns 120 (vs 0 on trunk).

Notes

  • Stacked on PR Fix JS translations filename for the desktop-mode handle #100 (fix/96-js-translations-filename) because npm run build:i18n was added there. When Fix JS translations filename for the desktop-mode handle #100 lands, this PR's diff collapses to a single commit.
  • New strings are untranslated; translators will pick them up.
  • Two strings became obsolete (Open new %s, Detach to new tab) and msgmerge flagged them with #~.
  • xgettext warned: src/window/tabs.ts:324: warning: invalid escape sequence in string. Pre-existing source code; not investigated here.
  • The Report-Msgid-Bugs-To URL still says alcazaba-plugin (the project's old slug). Preserved to keep this PR focused; should be fixed to desktop-mode in a separate change.

Closes #104

Open WordPress Playground Preview

epeicher added 2 commits May 6, 2026 19:48
The shipped JSON bundle was named
`desktop-mode-es_ES-wp-desktop.json`, a leftover from the plugin's
old `wp-desktop` slug. WordPress derives JS translation filenames
as `{textdomain}-{locale}-{handle}.json` and we now register three
handles (desktop-mode, desktop-mode-recycle-bin,
desktop-mode-posts-window), none of which is `wp-desktop`, so the
file was orphaned and JS strings rendered untranslated for es_ES.

Rename the bundle to the handle WordPress actually looks for
(`desktop-mode-es_ES-desktop-mode.json`). The recycle-bin and
posts-window bundles have no PO entries yet (those source files
postdate the last POT extraction), so no JSON ships for them.

Add bin/build-i18n.sh (and its bin/build-i18n-merge.php helper)
so future locales regenerate the right filenames automatically.
The script invokes `wp i18n make-json --extensions=ts` and merges
the per-source JSONs into one per-handle JSON using a prefix map
that points each script handle at its source tree. Wire it up as
`npm run build:i18n` and document the flow in docs/DEVELOPMENT.md.

Fixes #96
The POT was last extracted before src/recycle-bin/ and src/posts-window/
landed, so the 136 __()/_x() calls in those bundles were never
translatable. Re-extracted to bring them in.

Extraction pipeline:

1. wp i18n make-pot . languages/desktop-mode.pot --skip-js \
     --slug=alcazaba-plugin --package-name="Desktop Mode" \
     --headers='{"Report-Msgid-Bugs-To":"https://wordpress.org/support/plugin/alcazaba-plugin"}'
   (PHP-only pass; wp-cli's JS extractor is .js/.jsx-only and chokes on
   TypeScript syntax.)

2. xgettext --language=TypeScript --keyword=__:1 --keyword=_x:1,2c \
     --keyword=_n:1,2 --keyword=_nx:1,2,4c --add-comments=translators \
     --no-wrap (run over every src/**/*.ts excluding tests) into a
   temporary POT.

3. msgcat --no-wrap --use-first to merge the TS strings into the wp-cli
   POT, keeping the wp-cli header.

4. msgmerge --no-wrap --update languages/desktop-mode-es_ES.po against
   the new POT. msgfmt to refresh the .mo.

5. npm run build:i18n to regenerate per-handle JSON files. New files
   shipped: desktop-mode-es_ES-desktop-mode-recycle-bin.json (11 strings)
   and desktop-mode-es_ES-desktop-mode-posts-window.json (85 strings).
   The desktop-mode handle JSON now has 156 strings (up from 79).

POT msgid count: 140 -> 396. New strings are untranslated for now,
English fallback continues to work for them.

Closes #104
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 6, 2026

✅ WordPress Plugin Check Report

✅ Status: Passed

📊 Report

All checks passed! No errors or warnings found.


🤖 Generated by WordPress Plugin Check Action • Learn more about Plugin Check

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Re-extract POT so recycle-bin and posts-window JS strings can be translated

1 participant