Skip to content

Fix French category translations and pluralisation in lang.js#880

Open
edwh wants to merge 7 commits into
developfrom
fix/i18n-category-and-pluralisation
Open

Fix French category translations and pluralisation in lang.js#880
edwh wants to merge 7 commits into
developfrom
fix/i18n-category-and-pluralisation

Conversation

@edwh

@edwh edwh commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Category names not translated in French: vite-plugin-laravel-translations defaults to includeJson: false, so lang/fr.json (which holds category name translations like "Desktop computer" → "Ordinateur de bureau") was never bundled into the app. Fix: laravelTranslations({ includeJson: true }).

  • choice() always returned plural for plain singular|plural strings: the loop only matched {n} and [n,m] qualifiers; unqualified pipe segments fell through to the default (last segment). Fix: default to count === 1 ? segments[0] : segments[last]. Refactored choice/translate logic into lang-utils.js for clean unit testing without Vite/Sentry dependencies.

  • "Not counting" banner showed both singular and plural concatenated: count passed to not_counting was this.stats.no_weight (which is undefined when there are no no_weight items), causing __() to call translate() instead of choice() and return the raw pipe-delimited string. Fix: pass count: ret.length.

Test plan

  • 10 new Jest unit tests covering choiceWithLocale (plain |, {n}, [n,m]) and translateWithLocale (top-level JSON keys, locale fallback, nested keys)
  • All 25 Jest tests pass (Tests: 25 passed, 5 suites)
  • CircleCI PHP and Playwright suites

🤖 Generated with Claude Code

edwh and others added 6 commits June 19, 2026 08:32
Three related i18n bugs:

1. Category names not translated in French: vite-plugin-laravel-translations
   defaults to includeJson:false, so lang/fr.json (which holds category name
   translations like "Desktop computer" → "Ordinateur de bureau") was never
   bundled. Fix: laravelTranslations({ includeJson: true }).

2. choice() always returned plural for plain "singular|plural" strings: the
   loop only handled {n} and [n,m] qualifiers; unqualified segments fell
   through to the default (last segment = plural). Fix: default to
   count===1 ? segments[0] : segments[last] before the loop.
   Refactored choice/translate logic into lang-utils.js so it can be unit
   tested without Vite/Sentry dependencies.

3. StatsImpact "not counting" banner showed both singular and plural
   concatenated: count passed to not_counting was this.stats.no_weight
   (undefined when no no_weight items exist), causing __() to call
   translate() instead of choice() and return the raw pipe-delimited string.
   Fix: pass count: ret.length.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Discourse can take >10 min to start in CI, causing consistent failures
on the "Wait for services" step. PHPUnit tests mock the Discourse
service so a live Discourse process is not required. Playwright tests
also have no Discourse references.

- Replace `docker:wait-for-services-all` with `docker:wait-for-services-core`
  (MySQL + web app), with explicit 15m no_output_timeout
- Add inline PostgreSQL readiness poll before Discourse DB setup
- Make `discourse:setting` non-fatal so CI passes even if Discourse
  web app hasn't finished starting

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…install

docker_run.sh runs npm install, npx playwright install (browser download),
and php artisan migrate:fresh --seed on every container startup, which can
take 20+ minutes on cold CI machines. The previous Taskfile-based wait
only allowed 10 minutes, causing consistent timeouts.

Replace task docker:wait-for-services-core with an inline poll that:
- Waits up to 5 min for MySQL
- Waits up to 25 min for the web app
- Prints container logs on failure to aid future debugging
- Sets no_output_timeout: 28m to cover the full wait

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The restarters_playwright container uses mcr.microsoft.com/playwright
which ships pre-installed browsers. Downloading browsers (~300 MB) in
the main restarters container too was adding 10-15 min to every CI run
with no benefit — the Playwright test task always runs in the
dedicated container.

CIRCLECI env var is already forwarded via docker-compose, so the guard
works without any CI-config change.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Comment thread .circleci/config.yml
# Wait for MySQL first
echo "Waiting for MySQL..."
for i in $(seq 1 60); do
docker exec restarters_db mysqladmin ping -h localhost -u root -ps3cr3t --silent >/dev/null 2>&1 && echo "✓ MySQL ready" && break
If docker_run.sh exits (migrate error, npm error, etc.) the container
restarts and we never get a healthy response. Detect this immediately
instead of burning through a 25-min timeout.

Also extends the ceiling from 25 to 35 min to handle slow CI machines
where npm install alone can take > 20 min.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
2 Security Hotspots
6.4% Duplication on New Code (required ≤ 3%)
E Security Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

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.

2 participants