Skip to content

feat(i18n): add fr_CA translation and apply string context rule #minor - #58

Open
Revenantal wants to merge 12 commits into
mainfrom
feature/translations
Open

Revenantal wants to merge 12 commits into
mainfrom
feature/translations

Conversation

@Revenantal

@Revenantal Revenantal commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Context

Wicket: none
Related PRs: industrialdev/wicket-wp-base-plugin#63, industrialdev/wicket-wp-theme#19, industrialdev/wicket-wp-financial-fields#10

What

  • Adds a Canadian French (fr_CA) translation (.po, .mo, .l10n.php) for all 1,040 strings in wicket-acc.pot, including plurals.
  • Applies the short-string context rule across the plugin and its ACF field strings.
  • Scopes ACF translation to the Account Centre's own fields and makes ACF strings extractable.
  • Fixes the Account Center label for sites set to account-center.

Why

Many Account Centre strings were missing context, were split into fragments, or were translated through a site-wide ACF filter that affected other plugins. Wicket now ships fr_CA, following the Atlas translations convention (conv.stack.translations).

How

Contexts and strings

  • Every 1 to 3 word string gets a gettext context that names its kind (label, button label, status, message, and so on). Full sentences drop their contexts. Specific contexts stay only where the same text has a different meaning (role name, relationship type).
  • Ambiguous strings and abbreviations get translator comments. Inline translator comments move onto their own lines so make-pot attaches them to the right string.
  • "the contact" / "the member" fragments become full sentences. The cascade seat-limit error is now wrapped in __().

ACF

  • An acf/prepare_field filter replaces the site-wide acf/settings/l10n_textdomain filter. It translates only fields from includes/acf-json.
  • composer i18n:acf (.ci/acf-i18n-strings.php) generates languages/acf-strings.php, so make-pot extracts ACF strings with a context.

Fixes

  • getAccName() now returns "Account Center" when the site uses the center setting.
  • The VitalSource action label now reads "eBook Fulfilment". The stored value is unchanged, so MDP matching still works.
  • The .pot hook runs faster and supports package excludes.

Impact on existing translations

Re-contexted strings no longer match existing site translations. We accepted this because client translation coverage is under 1% and fr_CA now ships with the plugin. Site-level translations (Loco, wp-content/languages) still take precedence.

alex91ckua and others added 12 commits September 28, 2026 11:56
- Packaging & Labeling -> Packaging & Labelling (Business Services label)
- gray out -> grey out (org selector ACF instructions)
- Account Center -> Account Centre (getAccName center branch)
- Add a pre-commit hook that regenerates languages/<text-domain>.pot
  from the staged files. It uses `wp` on PATH, or downloads a pinned,
  checksum-verified WP-CLI into the user cache. It never blocks a commit.
- Make `composer setup-hooks` install the pre-commit hook.
- Add a PR check that fails when the committed .pot is out of date.
- Read extra comma-separated exclude paths from .ci/pot-exclude.
- Leave excluded paths out of the staged snapshot, so large folders
  are not copied.
getAccName() returned "Account Centre" for sites set to account-center,
so the Centre/Center localization option had no effect.
… the pot

- Replace the site-wide acf/settings/l10n_textdomain filter with an
  acf/prepare_field filter that translates only fields from includes/acf-json,
  so other plugins' and the theme's ACF groups keep their own domains.
- Add .ci/acf-i18n-strings.php (composer i18n:acf) to generate
  languages/acf-strings.php, which lets make-pot extract ACF field strings
  with a context and a field-group comment.
- Use the Canadian spelling "eBook Fulfilment" for the VitalSource action
  label; the stored value stays unchanged for MDP matching.
- Add translators comments to ambiguous strings and abbreviations
  (Left/Right, Clear, Download, Member, Other, N/A, FY, Soc., PAC, CEO...).
  Existing msgids are unchanged so current site translations keep working.
- Move inline translators comments onto their own lines so make-pot stops
  attaching them to the next string (Remove, Edit Permissions, File must be
  a valid image).
- Replace "the contact"/"the member"/"this member" fragments with full
  sentences for the no-name success messages, using _x() contexts.
- Keep spaces out of the "(Start %s)" strings and give them a context.
- Wrap the cascade seat-limit error in __().
- Add both account-centre and account-center block search keywords.
- Add wicket-acc-fr_CA.po covering all 1,040 strings in wicket-acc.pot,
  including plurals, with Canadian French terminology and typography.
- Add the compiled .mo and WordPress 6.5+ .l10n.php files.

Site-level translations (Loco, wp-content/languages) still take precedence.
- Give every string of 1 to 3 words a gettext context and drop contexts from
  full sentences, following the Atlas translations convention.
- Contexts name the kind of string (label, button label, status, message,
  accessibility label, ...), not where it shows, so identical strings with the
  same meaning share one translation entry. Specific contexts are kept only
  where the same text has a different meaning (role name, relationship type).
- ACF field strings follow the same rule in the runtime translator and the
  languages/acf-strings.php generator.

Changes msgids' contexts, so existing site translations of these keys stop
matching; accepted because client coverage is under 1% and Wicket ships fr_CA.

@EstebanForge EstebanForge left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. Same shape as the base plugin PR and it holds up. What I verified:

  • msgfmt --check passes on the fr_CA catalog (1041 messages), the shipped .mo matches, and the .l10n.php is valid with matching plural rules. CI pot check is green, so the pot is in sync with source.
  • The domain-load fix is real: the old dirname(plugin_basename(__FILE__)) . '/languages/' pointed at src/languages/, which never existed, so bundled translations never loaded. The new root-relative load on init priority 1, admin included, fixes it.
  • The ACF pipeline is guarded: translate_acf_field() only touches field keys collected from includes/acf-json, and .ci/acf-i18n-strings.php mirrors the runtime context map and the 1-to-3-word rule exactly.
  • WP_Error codes are unchanged across services, the touchpoint display_type branches only exist in blocks whose signature has the parameter, and the added escaping (wp_die, email bodies, template-not-found) is a real hardening. Good riddance to the hardcoded njbia.org in the welcome email, now the site's own host.

Two nits, fine to fix later:

  1. Same slug, two source strings: getAccPageTitles() uses "Bulk Upload Members" while RequiredPagesNotice::pageTitles() uses "Organization Members Bulk Upload". Different admin screens can show different titles for the same page. Please pick one.
  2. The 1-to-3-word rule and the setting-to-context map now live in two places (Blocks.php runtime, .ci/acf-i18n-strings.php generator). A future drift makes ACF strings silently untranslatable. Please consider generating the map from one source, or a test that diffs the two.

Two behavior notes so nobody is surprised: handleWooCommerceMyAccountPage() now uses the translated title, so on a French site the safeguard pass renames the actual WooCommerce My Account page to French (slug stays my-account, URLs are safe). And the ui:i1e8n to ui:i18n fix in Schema means enumNames localization now actually applies where it silently never did.

Thanks Adrian, solid work across 171 files.

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.

3 participants