Translation template: joolweb-sessions-pro.pot (text domain joolweb-sessions-pro).

Bundled locale (French):
- joolweb-sessions-pro-fr_FR.po / .mo — full plugin UI + emails (~780 strings)
- fr-translations-map.php — English → French map (core)
- fr-translations-missing-batch.php — batch synced from POT 1.1.0 (merged at build)
- fr-translations-extra.php — overrides / strings not yet in the last POT export

WordPress loads the .mo when the site or user locale is fr_FR (emails also use run_in_user_locale per recipient).

Runtime overlay (required when a WordPress.org language pack exists: the bundled .mo is then skipped):
- `includes/helpers/class-joolwebsp-fr-translations.php` — gettext filters, French locales only
- Completes strings still equal to English from map + missing-batch + extra.php
- Premium domain uses `joolweb-sessions-pro-premium/languages/fr-translations.php`

`fr-translations-extra.php` is shipped in the distribution zip so Hostinger / zip installs pick up new FR strings without waiting for a language pack.

Regenerate the POT (WP-CLI, from plugin root):

  wp i18n make-pot . languages/joolweb-sessions-pro.pot --domain=joolweb-sessions-pro --exclude=docs,node_modules,vendor

Merge into the French PO (keeps existing translations):

  wp i18n update-po languages/joolweb-sessions-pro.pot languages/joolweb-sessions-pro-fr_FR.po

Sync new PO strings into the extra map, then rebuild PO/MO (from site root):

  php wp-content/plugins/wp-sport/languages/sync-po-to-map.php
  php wp-content/plugins/wp-sport/languages/build-full-fr_FR.php

Optional: refresh msgids list after code changes:

  php wp-content/plugins/wp-sport/languages/extract-msgids.php

Then add missing strings to fr-translations-map.php or fr-translations-extra.php and rebuild.

Check gaps (English fallback): languages/fr-missing.txt after build-full-fr_FR.php

On WordPress.org, community translations are managed at translate.wordpress.org after approval.
