Translating NiroHelp

Home » Developers » Translating NiroHelp

Every user-facing string passes through __() / _e() / esc_html_e() in PHP
and __() from @wordpress/i18n in the React admin, all under the text domain
nirohelp.

Plugin header values #

Text Domain: nirohelp
Domain Path: /languages

The .pot file #

languages/nirohelp.pot. Hand it to a translator or open it in Poedit or Loco
Translate; both produce the matching .po and .mo.

languages/easyhelp.pot is a pre-rename leftover and is not used by anything.
Ignore it.

File naming #

WordPress loads .mo files named with the locale:

languages/nirohelp-fr_FR.po      # human-editable source
languages/nirohelp-fr_FR.mo      # compiled, this is what WordPress loads
languages/nirohelp-de_DE.mo
languages/nirohelp-bn_BD.mo

The admin SPA needs a third form. See The SPA’s strings below.

Regenerating the template #

Build first. The SPA’s strings are extracted from the compiled bundle, not
from spa/:

yarn build
composer run makepot
composer run make-json

makepot runs:

wp i18n make-pot . languages/nirohelp.pot \
  --exclude=node_modules,vendor,docs,release,tests,website,spa

Note spa in the exclude list — that is deliberate, and it is the part most
worth understanding.

Why extraction runs over the bundle #

WP-CLI’s string scanner reads .js and .jsx. It cannot parse .tsx at all,
so pointing it at spa/ yields zero strings, silently, while
Controllers\Admin\App goes on calling wp_set_script_translations() for
translations that could never exist. Extraction therefore runs over
build/admin-app.js, where webpack has rewritten the calls into
(0,i.__)("…","nirohelp") — a form the scanner does understand.

Two consequences:

  • makepot must run after yarn build. Without it, hundreds of strings
    vanish from the POT without a word. The script now refuses to run when
    build/admin-app.js is missing, and composer run release builds first.
  • Do not rename or move the bundle. make-json keys each JSON file by
    md5() of the script’s path, so the PO references have to say
    build/admin-app.js — exactly what wp_enqueue_script() registers. Rename
    it and every SPA translation silently stops loading. If you move it,
    regenerate both files.

The SPA’s strings #

composer run make-json converts each .po in languages/ into the JSON
files wp_set_script_translations() loads at runtime, one per script handle,
named nirohelp-{locale}-{md5-of-path}.json and registered against the nirohelp-admin-app script handle. PHP strings come from the .mo;
React strings come from these. A locale needs both, so run make-json
after every .po update, not only after makepot.

Loading translations #

Translations load automatically when a matching locale is active in Settings
-> General -> Site Language
, provided the .mo (and, for the admin screens,
the .json) exists.

Per-user language #

Individual users can pick a language under Users -> Profile -> Language.
NiroHelp respects it: an admin reading WordPress in French sees the plugin in
French even when the site default is English.

What is not translatable #

  • cdn/chat.min.js, the chatbot widget. It is a vendor bundle served from
    the CDN to sites that are not necessarily WordPress, and its own defaults
    (Support, Type a message..., the offline greeting) are English. Override
    them per site with the data-agent-name, data-input-placeholder,
    data-welcome-message and data-offline-message attributes.
  • assets/tickets/js/embed.js, the embeddable ticket form. Its labels are
    hard-coded English. Copy the file and edit it if you need another language.
  • A handful of button states in assets/common/js/init.js.

None of these load through wp_set_script_translations(), so a .json file
does not reach them.

Never run yarn lint:js --fix #

Unrelated to translation but relevant to touching these files: the lint script’s
own glob covers cdn/chat.min.js, and --fix reformats that vendor bundle into
a 500-line diff. It ignores a path argument, so narrowing the command does not
help.

Was this doc helpful?

Scroll to Top