Skip to content

fix(i18n): four locale gaps — spinner words, savings message, Crisp locale, date casing - #2618

Merged
jjramirezn merged 5 commits into
devfrom
fix/i18n-locale-gaps
Aug 5, 2026
Merged

fix(i18n): four locale gaps — spinner words, savings message, Crisp locale, date casing#2618
jjramirezn merged 5 commits into
devfrom
fix/i18n-locale-gaps

Conversation

@jjramirezn

@jjramirezn jjramirezn commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Four user-reported locale gaps, one commit each:

  1. Payment spinner cycled hardcoded English words (Cracking, Outsmarting SWIFT, …) in every locale. The 34 words move into the message catalogs under paymentLoading (en / es-419 / pt-BR; es-AR inherits es-419 — the words carry no second-person conjugation). words.ts keeps only the typed key list; CyclingLoading translates at render. The /dev/loading-words preview reads the English catalog directly.
  2. "saved ~$X compared to card!" was built in English by getSavingsMessage(). The cents/dollars split now lives in ICU messages (qrPay.success.savedVsCardCents|Dollars) resolved with useTranslations; the util is removed and its mock dropped from the qr-pay test, which now asserts the real catalog string.
  3. Crisp chatbox always booted in English. The support proxy URL now carries the app locale and the proxy page sets CRISP_RUNTIME_CONFIG.locale (es-419/es-AR → es, pt-BR → pt-br). Capacitor's native Crisp messenger follows the device language and is untouched.
  4. "24 De Julio De 2026" in history/notifications. The date group headers carried Tailwind capitalize, title-casing every word of the localized date. The catalogs already ship "Today"/"Hoy" capitalized, so the class is simply removed.

Risks / breaking changes

QA

  • tsc --noEmit clean; full jest: only the pre-existing env-dependent add-money-states local failure (green in CI, red on clean origin/dev locally).
  • qr-pay savings test now exercises the real ICU message.

Screenshots: N/A for 1–3 (text swaps in place, same layout); 4 is a text-transform removal — before/after is 'De Julio' → 'de julio' in the header line.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added localized, varied payment-loading messages in English, Spanish, and Portuguese.
    • QR payment confirmations now show localized savings compared with card payments, with cent- and dollar-specific formatting.
    • Crisp support pages now respect the selected application locale.
  • Style

    • Date-group headings in history and notifications no longer force capitalization.
  • Bug Fixes

    • Improved loading-message localization and QR payment savings display consistency.

The payment spinner cycled through 34 hardcoded English gerunds for every
locale. The copy moves into the catalogs under paymentLoading; words.ts
keeps only the key list, and CyclingLoading translates at render.
getSavingsMessage built the string in English for every locale. The
cents/dollars split moves into ICU messages (qrPay.success.savedVsCard*)
resolved at render; the now-unused util is removed.
The proxy never told Crisp which language the app runs in, so the chatbox
always booted in English. The app locale now rides the proxy URL and lands
in CRISP_RUNTIME_CONFIG.locale (es-419/es-AR map to es, pt-BR to pt-br).
The history and notifications group headers carried Tailwind 'capitalize',
which uppercases every word of the Spanish date ('24 De Julio De 2026').
The catalogs already ship 'Today'/'Hoy' capitalized, so the class only
ever did damage.
@vercel

vercel Bot commented Aug 5, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
peanut-wallet Ready Ready Preview Aug 5, 2026 6:44pm

Request Review

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: bfbd3f7d-1f5f-4c57-9950-3b6e9350c185

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The change localizes payment loading and QR savings messages, propagates application locale values to Crisp, and removes forced capitalization from history and notification date headers.

Changes

Payment localization

Layer / File(s) Summary
Localized payment loading messages
src/components/Global/PeanutLoading/*, src/app/dev/loading-words/page.tsx, src/i18n/app/messages/*.json
Payment loading now selects typed message keys and renders translated text in the loading component and preview.
Localized QR savings messages
src/app/(mobile-ui)/qr-pay/page.tsx, src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx, src/utils/qr-payment.utils.ts, src/i18n/app/messages/*.json
QR success screens and tests use localized cent or dollar savings messages. The obsolete getSavingsMessage helper and mock were removed.

Crisp locale propagation

Layer / File(s) Summary
Crisp proxy locale handling
src/hooks/useCrispProxyUrl.ts, src/app/crisp-proxy/page.tsx
The proxy URL includes a mapped application locale. The Crisp script applies the optional locale to runtime configuration.

Date header styling

Layer / File(s) Summary
Date-group header rendering
src/app/(mobile-ui)/history/page.tsx, src/app/(mobile-ui)/notifications/page.tsx
Date-group headers no longer use the capitalize class.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested labels: enhancement

Suggested reviewers: innolope-dev, hugo0, kushagrasarathe

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the four localization fixes implemented in the pull request.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/i18n-locale-gaps

Comment @coderabbitai help to get the list of available commands.

@jjramirezn

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Code-analysis diff

Painscore total: 7061.25 → 7055.03 (-6.22)
Findings: 0 net (+18 new, -18 resolved)

🆕 New findings (18)

  • critical complexity — src/app/(mobile-ui)/qr-pay/page.tsx — CC 306, MI 52.56, SLOC 1078
  • critical method-complexity — src/app/(mobile-ui)/qr-pay/page.tsx:89 — QRPayPage CC 76 SLOC 403
  • high hotspot — src/app/(mobile-ui)/qr-pay/page.tsx — 98 commits, +1175/-1118 lines since 6 months ago
  • medium react-long-component — src/app/(mobile-ui)/qr-pay/page.tsx:89 — QRPayPage is 1558 lines — split it
  • medium high-mdd — src/app/(mobile-ui)/qr-pay/page.tsx:89 — QRPayPage: MDD 463.0 (uses across many lines from declarations)
  • medium high-dlt — src/app/(mobile-ui)/qr-pay/page.tsx:89 — QRPayPage: DLT 123 (calls 123 distinct functions — high context load)
  • medium high-mdd — src/app/(mobile-ui)/notifications/page.tsx:19 — NotificationsPage: MDD 66.9 (uses across many lines from declarations)
  • medium high-mdd — src/hooks/useCrispProxyUrl.ts:27 — useCrispProxyUrl: MDD 29.8 (uses across many lines from declarations)
  • medium complexity — src/hooks/useCrispProxyUrl.ts — CC 26, MI 55.96, SLOC 37
  • medium method-complexity — src/hooks/useCrispProxyUrl.ts:29 — CC 24 SLOC 26
  • medium complexity — src/app/dev/loading-words/page.tsx — CC 18, MI 72.44, SLOC 53
  • medium react-effect-derives-state — src/components/Global/PeanutLoading/CyclingLoading.tsx:15 — useEffect with empty deps + setState — derived state anti-pattern
  • low high-mdd — src/app/(mobile-ui)/qr-pay/page.tsx:1455 — : MDD 18.5 (uses across many lines from declarations)
  • low high-mdd — src/app/(mobile-ui)/notifications/page.tsx:167 — : MDD 16.7 (uses across many lines from declarations)
  • low high-mdd — src/hooks/useCrispProxyUrl.ts:29 — : MDD 16.0 (uses across many lines from declarations)
  • low missing-return-type — src/app/crisp-proxy/page.tsx:214 — CrispProxyPage: exported fn missing return type annotation
  • low missing-return-type — src/app/dev/loading-words/page.tsx:13 — LoadingWordsPreview: exported fn missing return type annotation
  • low missing-return-type — src/components/Global/PeanutLoading/CyclingLoading.tsx:11 — CyclingLoading: exported fn missing return type annotation

✅ Resolved (18)

  • src/app/(mobile-ui)/qr-pay/page.tsx — CC 305, MI 52.63, SLOC 1072
  • src/app/(mobile-ui)/qr-pay/page.tsx:89 — QRPayPage CC 75 SLOC 397
  • src/app/(mobile-ui)/qr-pay/page.tsx — 97 commits, +1166/-1116 lines since 6 months ago
  • src/app/(mobile-ui)/qr-pay/page.tsx:89 — QRPayPage is 1551 lines — split it
  • src/app/(mobile-ui)/qr-pay/page.tsx:89 — QRPayPage: MDD 460.6 (uses across many lines from declarations)
  • src/app/(mobile-ui)/qr-pay/page.tsx:89 — QRPayPage: DLT 124 (calls 124 distinct functions — high context load)
  • src/app/(mobile-ui)/notifications/page.tsx:19 — NotificationsPage: MDD 67.5 (uses across many lines from declarations)
  • src/hooks/useCrispProxyUrl.ts:16 — useCrispProxyUrl: MDD 27.6 (uses across many lines from declarations)
  • src/hooks/useCrispProxyUrl.ts — CC 26, MI 58.52, SLOC 29
  • src/hooks/useCrispProxyUrl.ts:17 — CC 24 SLOC 25
  • src/app/dev/loading-words/page.tsx — CC 17, MI 72.28, SLOC 50
  • src/components/Global/PeanutLoading/CyclingLoading.tsx:13 — useEffect with empty deps + setState — derived state anti-pattern
  • src/app/(mobile-ui)/qr-pay/page.tsx:1448 — : MDD 18.5 (uses across many lines from declarations)
  • src/app/(mobile-ui)/notifications/page.tsx:169 — : MDD 16.7 (uses across many lines from declarations)
  • src/hooks/useCrispProxyUrl.ts:17 — : MDD 16.0 (uses across many lines from declarations)
  • src/app/crisp-proxy/page.tsx:211 — CrispProxyPage: exported fn missing return type annotation
  • src/app/dev/loading-words/page.tsx:12 — LoadingWordsPreview: exported fn missing return type annotation
  • src/components/Global/PeanutLoading/CyclingLoading.tsx:10 — CyclingLoading: exported fn missing return type annotation

📈 Painscore deltas (top movers)

File Before After Δ
src/hooks/useCrispProxyUrl.ts 9.9 10.6 +0.7
src/utils/qr-payment.utils.ts 4.8 4.1 -0.7

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

🧪 UI test report — ✅ all green

Suites

  • unit: 2633 ran, 0 failed, 0 skipped, 44.3s

📊 Coverage (unit)

metric %
statements 64.0%
branches 47.6%
functions 53.6%
lines 64.6%
⏱ 10 slowest test cases
time test
3.4s src/components/Card/share-asset/__tests__/shareAssetLayout.test.ts › never places two stickers in heavy overlap (broad seed sweep)
1.1s src/utils/__tests__/demo-api.test.ts › isDemoMode() is false when not running under Capacitor
0.6s src/components/Card/share-asset/__tests__/shareAssetLayout.test.ts › every sticker stays within canvas at any count
0.4s src/utils/__tests__/sentry.utils.test.ts › defaults to the client budget under a browser global
0.3s src/app/(mobile-ui)/withdraw/__tests__/withdraw-states.test.tsx › Bank withdrawal keeps the $1 minimum for sub-$1 amounts
0.3s src/utils/__tests__/auth-token.test.ts › returns null when the Preferences plugin is unavailable (older binary)
0.3s src/utils/__tests__/sentry.utils.test.ts › still lets a per-call timeoutMs win over the default
0.3s src/app/actions/__tests__/api-headers-extended.test.ts › should not include apiKey in validateInviteCode body
0.3s src/utils/__tests__/auth-token.test.ts › ignores the guarded marker and falls back to the plain token
0.3s src/utils/__tests__/auth-token.test.ts › is none — never guarded — when only the guarded marker is present
📍 Inline annotations are in the **Unit test report** check above. Coverage artifact: `coverage-unit`. Generated by `.github/workflows/tests.yml`.

@coderabbitai coderabbitai Bot 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.

🧹 Nitpick comments (1)
src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx (1)

1246-1258: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add coverage for the cents message path.

This test only exercises savedVsCardDollars with 150 cents. Add cases below 100 cents, including 1 and a plural value. This verifies the threshold and both plural branches.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/`(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx around lines
1246 - 1258, Add test cases near the existing savings assertion in
completeMantecaPayment coverage for calculateSavingsInCents values below 100,
including 1 cent and a plural cent amount. Assert the localized savings message
uses the cents format and both singular and plural wording, while preserving the
existing 150-cent dollar-path case.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/app/`(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx:
- Around line 1246-1258: Add test cases near the existing savings assertion in
completeMantecaPayment coverage for calculateSavingsInCents values below 100,
including 1 cent and a plural cent amount. Assert the localized savings message
uses the cents format and both singular and plural wording, while preserving the
existing 150-cent dollar-path case.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 40dd1e21-9829-4599-b026-9c3dfb3f2e74

📥 Commits

Reviewing files that changed from the base of the PR and between a075240 and 2fbc6d9.

📒 Files selected for processing (13)
  • src/app/(mobile-ui)/history/page.tsx
  • src/app/(mobile-ui)/notifications/page.tsx
  • src/app/(mobile-ui)/qr-pay/__tests__/qr-pay-states.test.tsx
  • src/app/(mobile-ui)/qr-pay/page.tsx
  • src/app/crisp-proxy/page.tsx
  • src/app/dev/loading-words/page.tsx
  • src/components/Global/PeanutLoading/CyclingLoading.tsx
  • src/components/Global/PeanutLoading/words.ts
  • src/hooks/useCrispProxyUrl.ts
  • src/i18n/app/messages/en.json
  • src/i18n/app/messages/es-419.json
  • src/i18n/app/messages/pt-BR.json
  • src/utils/qr-payment.utils.ts
💤 Files with no reviewable changes (1)
  • src/utils/qr-payment.utils.ts

@jjramirezn

Copy link
Copy Markdown
Contributor Author

CodeRabbit nitpick addressed: added test.each cases for the cents path (1 cent singular, 42 cents plural) alongside the existing 150-cent dollar case.

@jjramirezn
jjramirezn marked this pull request as ready for review August 5, 2026 18:41
@jjramirezn
jjramirezn merged commit 74c5985 into dev Aug 5, 2026
16 of 19 checks passed
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.

1 participant