Skip to content

feat(i18n): add 67 missing dashboard keys and guard placeholder integrity - #64

Merged
haim-barad merged 3 commits into
mainfrom
feat/i18n-dashboard-missing-keys
Aug 5, 2026
Merged

feat(i18n): add 67 missing dashboard keys and guard placeholder integrity#64
haim-barad merged 3 commits into
mainfrom
feat/i18n-dashboard-missing-keys

Conversation

@loc-kodeplus

@loc-kodeplus loc-kodeplus commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

User description

Summary

Audited every i18n key the core_api dashboard references against this repo's en-US source of truth. 67 keys existed only in the frontend's bundled English fallback, so they were never offered to Crowdin and non-English users saw English. Also fixes one key whose placeholder never interpolated, and adds tests so both classes of defect cannot recur silently.

Missing keys added (locales/en-US/common.json)

Area Keys
integrations.lightspeed.* 45 — Lightspeed X-Series connect / outlets / sync UI
programs.edit.dataTools.* 11 — whole-program points reset control
broadcast.form.sent* 5 — post-send delivery summary
app.auth.register.* 3 — ToS / DPA / privacy links
customers.*.pointsClamped 2 — overspend-prevented event label
nav.lightspeed 1

English copied verbatim from the frontend fallback so the two agree. Verified 0 original keys lost or modified (2783 -> 2850).

Deliberately NOT added: a stray _comment key carrying a Portuguese editorial note that leaked into the English bundle. It is not a translatable string; removed on the core_api side instead.

Placeholder fix

loyalty.forms.scanForm.showCustomer stored a single-brace {id}. Both consumers interpolate {{variable}} — i18next in the dashboard, translation_loader.py on the backend — so the dashboard, which calls it as t(..., { id: field.value }), rendered the literal text #{id} in every locale. es-ES had lost the placeholder entirely and showed no number at all. Fixed across all 8 locales.

Guardrail (src/__tests__/all-languages.test.js)

Two rules, 15 tests:

  1. no single-brace {var}
  2. every target locale carries the same variables as en-US

Rule 2 is the important one: key parity cannot see a translator deleting a variable — the key is present, its variable is not — which is exactly how es-ES lost the customer number.

Verified non-vacuous: injecting #{id} and dropping {{name}} from French makes both rules fail with pinpointed messages.

Known issues are listed explicitly in the test with the reason each is unresolved, rather than silently allowlisted:

  • LITERAL_TOKEN_KEYS — permanent. The WordPress plugin substitutes {name}/{value}/{currency} itself and instructs merchants to type them; tab.placeholderInfo documents the ${Name} pass syntax. Doubling these would break the plugin.
  • PENDING_SINGLE_BRACE — 10 errors/notifications keys with no caller in core_api, likely consumed by the Square/Shopify/Clover/WordPress repos. Needs the consumer confirmed before changing.
  • PENDING_PARITY — 6 Italian strings that dropped a variable, and a pt-BR subject that invented {{merchantName}} that nothing supplies. Left for a Crowdin pass rather than machine-written prose.

Expected CI state

validate-locales / key-coverage tests now report */common alongside the pre-existing */giftCards, until the new strings round-trip through Crowdin (crowdin:upload -> translate -> crowdin:download). Measured: baseline on main had 7 key-coverage mismatches, this branch has 14 — same class, same cause. The suite was already red before this change.


CodeAnt-AI Description

Add missing dashboard translations and keep localized placeholders working

What Changed

  • Adds English dashboard text for Lightspeed integration, point resets, broadcast delivery results, signup policy links, and overspending events across supported locales
  • Fixes customer scan messages so the customer number appears instead of raw or missing placeholder text
  • Corrects translated certificate error messages so the actual error detail is displayed
  • Adds checks that detect missing translations and mismatched or improperly formatted placeholders before release

Impact

✅ Lightspeed and dashboard features show translated labels
✅ Customer numbers appear correctly after scans
✅ Clearer certificate error details
✅ Fewer untranslated or broken localized messages

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

Audited every key the core_api dashboard references against this repo's
source of truth. 67 were only ever present in the frontend's bundled English
fallback (i18n-utils.ts), so non-English users saw English for them and the
strings were never offered to Crowdin for translation.

  integrations.lightspeed.*   45   Lightspeed X-Series connect/outlets/sync UI
  programs.edit.dataTools.*   11   whole-program points reset control
  broadcast.form.sent*         5   post-send delivery summary
  app.auth.register.*          3   ToS / DPA / privacy links
  customers.*.pointsClamped    2   overspend-prevented event label
  nav.lightspeed               1

English text is copied verbatim from the frontend fallback so the two agree.

Deliberately NOT added: a stray '_comment' key carrying a Portuguese editorial
note ('Traducoes portuguesas (Portugal) - a completar via Lokalise AI
Translation') that leaked into the English bundle. It is not a translatable
string and should be removed from the frontend fallback instead.

en-US only, per the flow the giftCards keys already follow: validate-locales
now reports */common alongside the pre-existing */giftCards until the strings
round-trip through Crowdin (crowdin:upload -> translate -> crowdin:download).
…ders

Both consumers substitute {{variable}} — i18next in the dashboard and
translation_loader.py on the backend — so the single-brace {id} this key carried
was never replaced. The dashboard calls it as
t('loyalty.forms.scanForm.showCustomer', { id: field.value }), so every locale
rendered the literal text '#{id}' instead of the customer number. es-ES had lost
the placeholder altogether and showed no number at all.

Adds two checks to the language suite:

  - no single-brace {var}, with an allowlist for strings whose braces are not
    interpolation: the WordPress plugin substitutes {name}/{value}/{currency}
    itself and its 'adjust the message' string instructs merchants to type them,
    and tab.placeholderInfo documents the ${Name} pass syntax.

  - every target locale carries the same variables as en-US. Key parity cannot
    see this class of defect — the key is present, its variable is not — which is
    how es-ES dropped the customer number unnoticed.

Ten errors/notifications keys and seven translations that dropped or invented a
variable are listed in the test as pending rather than fixed here: the former
need their consumer confirmed, the latter are translation content that belongs
in a Crowdin pass. The checks stop new regressions meanwhile.
@codeant-ai

codeant-ai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

🤖 CodeAnt AI — Review Status

Status Commit Started (UTC) Finished (UTC)
✅ Reviewed your PR e03f750 Aug 05, 2026 · 13:54 13:57

@codeant-ai

codeant-ai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@codeant-ai codeant-ai Bot added the size:L This PR changes 100-499 lines, ignoring generated files label Aug 5, 2026
@greptile-apps

greptile-apps Bot commented Aug 5, 2026

Copy link
Copy Markdown

Greptile Summary

The PR expands the en-US source catalog with dashboard translation keys and corrects customer-ID interpolation across supported locales.

  • Adds 67 source strings for Lightspeed, program reset controls, broadcast results, registration links, and customer events.
  • Replaces the malformed {id} customer placeholder with {{id}} in all eight supported locales.
  • Adds tests for single-brace placeholders and cross-locale interpolation-variable parity, with documented exceptions for known existing cases.

Confidence Score: 5/5

The PR appears safe to merge, with no actionable changed-code defect identified.

The locale edits consistently use the configured double-brace interpolation syntax, and the new validation operates over fixed supported locales while preserving explicitly documented existing exceptions.

Important Files Changed

Filename Overview
packages/i18n/locales/en-US/common.json Adds the missing dashboard source strings and corrects the customer-ID interpolation syntax; no actionable defect identified.
packages/i18n/src/tests/all-languages.test.js Adds placeholder syntax and parity guardrails using trusted locale constants and explicit known-defect exceptions; no actionable defect identified.
packages/i18n/locales/es-ES/common.json Restores the previously omitted customer ID with the correct interpolation variable.
packages/i18n/locales/en-GB/common.json Corrects the customer-ID placeholder to the supported double-brace syntax.
packages/i18n/locales/es-MX/common.json Corrects the customer-ID placeholder to the supported double-brace syntax.
packages/i18n/locales/fr/common.json Corrects the customer-ID placeholder to the supported double-brace syntax.
packages/i18n/locales/it/common.json Corrects the customer-ID placeholder to the supported double-brace syntax.
packages/i18n/locales/pt-BR/common.json Corrects the customer-ID placeholder to the supported double-brace syntax.
packages/i18n/locales/pt-PT/common.json Corrects the customer-ID placeholder to the supported double-brace syntax.

Reviews (1): Last reviewed commit: "fix(i18n): make scanForm.showCustomer in..." | Re-trigger Greptile

greptile-apps[bot]
greptile-apps Bot previously approved these changes Aug 5, 2026
Comment thread packages/i18n/src/__tests__/all-languages.test.js Outdated
Comment thread packages/i18n/src/__tests__/all-languages.test.js Outdated
Comment thread packages/i18n/src/__tests__/all-languages.test.js Outdated
…y locale

Review feedback:

- The variable extractor captured only the identifier before a dot, so
  {{shop.name}} and {{shop.domain}} both read as 'shop' and a translation could
  substitute one for the other undetected. Dots are now part of the name.

- Single-brace exemptions applied to a whole key, permanently blinding every
  locale for it. They now name the specific variable, so any other single-brace
  variable in those strings still fails, and a locale corrected to {{var}} simply
  stops matching.

- The parity check skipped keys absent from the target on the grounds that key
  coverage was asserted elsewhere; that assertion only covers 'common', so a
  missing key in errors/emails/notifications escaped both checks. Absent keys are
  now reported, with the pre-existing giftCards backlog exempted by namespace.

Widening the extractor immediately exposed two defects it had been blind to:

- common.templates.detail.deleteButton read 'Delete {template.name}' in en-US —
  a JS template literal captured as text by an extractor. The key exists, so
  i18next returned it verbatim and the button rendered the literal placeholder.
  Set to 'Delete', matching all seven other locales.

- errors.operations.failed_to_renew_certificate had its PLACEHOLDER NAME
  translated: {mensaje} in es-ES/es-MX, {mensagem} in pt-BR/pt-PT. Those would
  never interpolate even once the braces are doubled, because the caller passes
  'message'. Identifier restored, translated prose kept.

Also seeds the 67 new keys into the seven target locales with the English source
text, which is what CI's key-coverage tests require. This changes nothing for
users — the dashboard already served English for these via its bundled fallback —
and it puts the strings in front of Crowdin for a real translation pass.

Full suite green: 243 passed.
@greptile-apps
greptile-apps Bot dismissed their stale review August 5, 2026 14:25

Dismissed because a newer commit was pushed; Greptile will re-review the current head.

@loc-kodeplus

Copy link
Copy Markdown
Contributor Author

@CodeAnt-AI: review

@codeant-ai

codeant-ai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

CodeAnt AI is running the review.

@codeant-ai

codeant-ai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@codeant-ai

codeant-ai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Sequence Diagram

This PR adds missing dashboard translations across supported locale resources and ensures dynamic placeholders remain consistent. The flow shows localized lookup, placeholder interpolation, and automated integrity checks.

sequenceDiagram
    participant Dashboard
    participant I18n
    participant LocaleFiles
    participant User
    participant TestSuite

    Dashboard->>I18n: Request dashboard text with values
    I18n->>LocaleFiles: Load selected locale keys
    LocaleFiles-->>I18n: Return localized text and placeholders
    I18n-->>Dashboard: Interpolate placeholder values
    Dashboard-->>User: Render localized dashboard text

    TestSuite->>LocaleFiles: Scan all locale strings
    TestSuite->>TestSuite: Verify placeholder syntax and parity
    TestSuite-->>TestSuite: Report integrity result
Loading

Generated by CodeAnt AI

@codeant-ai codeant-ai Bot added size:XL This PR changes 500-999 lines, ignoring generated files and removed size:L This PR changes 100-499 lines, ignoring generated files labels Aug 5, 2026
@codeant-ai

codeant-ai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

CodeAnt AI finished running the review.

@loc-kodeplus loc-kodeplus self-assigned this Aug 5, 2026
@loc-kodeplus
loc-kodeplus requested a review from haim-barad August 5, 2026 14:51

@haim-barad haim-barad left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Approved

@loc-kodeplus

Copy link
Copy Markdown
Contributor Author

@haim-barad Please help me to merge this. Thanks!

@haim-barad
haim-barad merged commit b1245e3 into main Aug 5, 2026
7 checks passed
@haim-barad
haim-barad deleted the feat/i18n-dashboard-missing-keys branch August 5, 2026 15:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL This PR changes 500-999 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants