Skip to content

🌐 server: add spanish translations push notifications#878

Open
aguxez wants to merge 5 commits intomainfrom
translations
Open

🌐 server: add spanish translations push notifications#878
aguxez wants to merge 5 commits intomainfrom
translations

Conversation

@aguxez
Copy link
Copy Markdown
Contributor

@aguxez aguxez commented Mar 12, 2026

closes #855


Open with Devin

Summary by CodeRabbit

  • New Features

    • Push notifications for various transaction and account activities—card purchases, withdrawals, deposits, refunds, fiat onramp account activation, and credit mode changes—are now fully available in both English and Spanish languages.
  • Chores

    • Integrated i18next library as a new runtime dependency.
    • Updated TypeScript compiler and spell-check configurations to support new localization resources.

@aguxez aguxez requested a review from nfmelendez as a code owner March 12, 2026 08:48
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 12, 2026

🦋 Changeset detected

Latest commit: 2a4b978

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@exactly/server Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the server's push notification system by integrating Spanish translations for a wide array of user-facing messages. The update ensures that Spanish-speaking users receive localized and culturally relevant notifications for key events, improving accessibility and overall user experience without altering the core functionality of the notifications.

Highlights

  • Internationalization: Added Spanish translations for various push notification headings and contents across multiple server-side files.
  • Notification Coverage: Implemented Spanish translations for notifications related to card mode changes, funds received, withdrawal completions, fiat onramp activation, deposited funds, refund processing, and card purchases.
  • Testing: Updated an existing test case to reflect the new Spanish translations for withdraw completed notifications, ensuring correctness.
Changelog
  • server/api/card.ts
    • Added Spanish translations for 'Card mode' and 'Credit mode is active' in push notification headings and contents.
  • server/hooks/activity.ts
    • Added Spanish translations for 'Funds received' heading and the corresponding content for asset reception and yield earning.
    • Added Spanish translations for 'Card mode changed' heading and 'Credit mode activated' content.
  • server/hooks/block.ts
    • Added Spanish translations for 'Withdraw completed' heading and the content describing the amount sent to a receiver.
    • Added Spanish translations for 'Withdraw completed' heading and the content describing the amount sent to a receiver in another withdrawal function.
  • server/hooks/manteca.ts
    • Added Spanish translations for 'Fiat onramp activated' heading and content.
    • Added Spanish translations for 'Deposited funds' heading and content.
  • server/hooks/panda.ts
    • Added Spanish translations for 'Refund processed' heading and content.
    • Added Spanish translations for 'Card purchase' heading and content, including currency formatting and payment method details.
  • server/test/hooks/block.test.ts
    • Updated the expected push notification content in a test to include Spanish translations for 'Withdraw completed'.
Activity
  • No specific activity has been recorded for this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

gemini-code-assist[bot]

This comment was marked as resolved.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 12, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • ✅ Review completed - (🔄 Check again to review again)

Walkthrough

This PR introduces i18n support for push notifications across multiple server-side hooks by replacing hardcoded English strings with i18n translations. Changes include adding the i18next dependency, creating a new server-side i18n module with English and Spanish translation files, updating six hook files to use localized notifications, and updating corresponding tests to expect translated payloads.

Changes

Cohort / File(s) Summary
Server Hooks - I18n Integration
server/api/card.ts, server/hooks/activity.ts, server/hooks/block.ts, server/hooks/manteca.ts, server/hooks/panda.ts, server/hooks/bridge.ts
Replaced hardcoded English push notification strings with i18n t() calls across card mode, credit activation, withdraw completion, fiat onramp, deposits, refunds, and card purchase notifications. Control flow and error handling unchanged.
I18n Infrastructure
server/i18n/index.ts, server/i18n/en.json, server/i18n/es.json
Added new i18n module that initializes i18next with English and Spanish translations, exposing a t() function that returns localized strings for both languages. English and Spanish translation files contain notification keys with placeholders for dynamic values.
Dependencies & Configuration
server/package.json, server/tsconfig.json, cspell.json
Added i18next runtime dependency, included i18n directory in TypeScript compilation, and added cspell override for server-side Spanish translations.
Test Updates
server/test/hooks/block.test.ts, server/test/hooks/bridge.test.ts
Updated push notification payload assertions to expect both English (en) and Spanish (es) translations in headings and contents fields.
Release Notes
.changeset/tough-houses-wave.md
Added changeset documenting patch version bump for @exactly/server with i18next push notification i18n introduction.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • cruzdanilo
  • nfmelendez
🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title directly describes the main change: adding Spanish translations for push notifications in the server component.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch translations

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

devin-ai-integration[bot]

This comment was marked as resolved.

@sentry
Copy link
Copy Markdown

sentry bot commented Mar 12, 2026

✅ All tests passed.

coderabbitai[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (3)
server/hooks/panda.ts (1)

757-766: ⚠️ Potential issue | 🟡 Minor

Use explicit locales for the translated purchase amounts.

These branches still call toLocaleString(undefined, ...), so the amount format comes from the server/runtime locale instead of the notification language. That can render the new Spanish copy with non-Spanish currency formatting. Pass "en" and "es" explicitly here.

♻️ Proposed fix
                 contents: {
-                  en: `${(payload.body.spend.localAmount / 100).toLocaleString(undefined, {
+                  en: `${(payload.body.spend.localAmount / 100).toLocaleString("en", {
                     style: "currency",
                     currency: payload.body.spend.localCurrency,
                   })} at ${payload.body.spend.merchantName.trim()}. Paid ${{ 0: "with USDC", 1: "with credit" }[card.mode] ?? `in ${card.mode} installments`}`,
-                  es: `${(payload.body.spend.localAmount / 100).toLocaleString(undefined, {
+                  es: `${(payload.body.spend.localAmount / 100).toLocaleString("es", {
                     style: "currency",
                     currency: payload.body.spend.localCurrency,
                   })} en ${payload.body.spend.merchantName.trim()}. Pagado ${{ 0: "con USDC", 1: "con crédito" }[card.mode] ?? `en ${card.mode} cuotas`}`,
                 },
server/api/card.ts (1)

385-386: ⚠️ Potential issue | 🟡 Minor

Add inline cspell:ignore for the new Spanish literals.

These strings are already tripping spell-check. Keep the file green by suppressing the one-off Spanish words on the same lines instead of expanding the shared dictionary.

📝 Proposed fix
-                headings: { en: "Card mode", es: "Modo de tarjeta" },
-                contents: { en: "Credit mode is active", es: "El modo crédito está activo" },
+                headings: { en: "Card mode", es: "Modo de tarjeta" }, // cspell:ignore tarjeta
+                contents: { en: "Credit mode is active", es: "El modo crédito está activo" }, // cspell:ignore crédito está activo

As per coding guidelines Place cspell:ignore annotations on the same line as the unknown word; only add words to cspell.json when the term is broadly used project-wide; keep one-off occurrences (variable names, company names, URLs, hashes) as inline cspell:ignore.

server/hooks/activity.ts (1)

129-132: ⚠️ Potential issue | 🟡 Minor

Suppress the new spell-check hits inline.

These Spanish literals are already producing spell-check warnings. Add same-line cspell:ignore annotations here instead of broadening the shared dictionary.

📝 Proposed fix
-        headings: { en: "Funds received", es: "Fondos recibidos" },
+        headings: { en: "Funds received", es: "Fondos recibidos" }, // cspell:ignore fondos recibidos
         contents: {
           en: `${value ? `${value} ` : ""}${assetSymbol} received${marketsByAsset.has(underlying) ? " and instantly started earning yield" : ""}`,
-          es: `${value ? `${value} ` : ""}${assetSymbol} recibidos${marketsByAsset.has(underlying) ? " y empezaron a generar rendimiento" : ""}`,
+          es: `${value ? `${value} ` : ""}${assetSymbol} recibidos${marketsByAsset.has(underlying) ? " y empezaron a generar rendimiento" : ""}`, // cspell:ignore recibidos empezaron generar rendimiento
         },

As per coding guidelines Place cspell:ignore annotations on the same line as the unknown word; only add words to cspell.json when the term is broadly used project-wide; keep one-off occurrences (variable names, company names, URLs, hashes) as inline cspell:ignore.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 965fa720-71b2-4403-8a6f-015286bc896c

📥 Commits

Reviewing files that changed from the base of the PR and between c9ced4c and 564d5ff.

📒 Files selected for processing (7)
  • .changeset/tame-candles-itch.md
  • server/api/card.ts
  • server/hooks/activity.ts
  • server/hooks/block.ts
  • server/hooks/manteca.ts
  • server/hooks/panda.ts
  • server/test/hooks/block.test.ts

devin-ai-integration[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
cspell.json (1)

215-244: 🧹 Nitpick | 🔵 Trivial

Narrow this cspell override to the files that actually contain Spanish copy.

Allowlisting these terms for all server/**/*.ts weakens spellcheck across the whole backend for strings that, per this PR, appear to live in a small set of notification/test files. Prefer inline cspell:ignore on the affected lines or a file-scoped override for those specific files unless these words are already reused broadly across server/**. Based on learnings, Place cspell:ignore annotations on the same line as the unknown word; only add words to cspell.json when the term is broadly used project-wide; keep one-off occurrences (variable names, company names, URLs, hashes) as inline cspell:ignore.

#!/bin/bash
set -euo pipefail

terms='activada|activado|activo|cambiado|completado|compra|crédito|cuenta|cuotas|depositados|empezaron|enviados|está|fondos|fueron|generar|pagado|procesado|rampa|recibidos|reembolsados|reembolso|rendimiento|retiro|sido|tarjeta'

# Verify how broadly these terms are used inside server TypeScript files.
# If matches are limited to a few translation-bearing files, prefer inline ignores
# or a narrower override instead of a blanket `server/**/*.ts` override.
rg -n --type ts -g 'server/**/*.ts' "\\b(${terms})\\b" -C1

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 12eae0a0-cddd-45b1-a893-ebf0a365688a

📥 Commits

Reviewing files that changed from the base of the PR and between cdcacae and a9e2880.

📒 Files selected for processing (1)
  • cspell.json

@aguxez aguxez marked this pull request as draft March 12, 2026 12:16
@aguxez aguxez force-pushed the translations branch 3 times, most recently from 9270b44 to 9056fc2 Compare March 12, 2026 16:02
coderabbitai[bot]

This comment was marked as resolved.

@aguxez aguxez force-pushed the translations branch 3 times, most recently from 6beaa6e to 89ea61f Compare March 13, 2026 14:26
@aguxez aguxez marked this pull request as ready for review March 13, 2026 14:40
devin-ai-integration[bot]

This comment was marked as resolved.

sentry[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

@aguxez aguxez force-pushed the translations branch 3 times, most recently from a2f1cca to c46af07 Compare March 18, 2026 10:58
chatgpt-codex-connector[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

chatgpt-codex-connector[bot]

This comment was marked as resolved.

chatgpt-codex-connector[bot]

This comment was marked as resolved.

chatgpt-codex-connector[bot]

This comment was marked as resolved.

sentry[bot]

This comment was marked as resolved.

chatgpt-codex-connector[bot]

This comment was marked as resolved.

chatgpt-codex-connector[bot]

This comment was marked as resolved.

chatgpt-codex-connector[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

@aguxez aguxez force-pushed the translations branch 3 times, most recently from e9312ef to 1a7f1b4 Compare March 21, 2026 10:16
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1a7f1b49e5

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

typeof value === "string"
? { minimumFractionDigits: 0, maximumFractionDigits: value.split(".")[1]?.length ?? 0 }
: { maximumSignificantDigits: 6 };
return { en: n.toLocaleString("en-US", options), es: n.toLocaleString("es-AR", options) };
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid region-specific formats for generic en/es pushes

The mobile app collapses locales to bare language codes (src/app/_layout.tsx uses only languageCode), but this helper now hardcodes en-US and es-AR for every translated amount; server/hooks/panda.ts repeats the same choice for card purchases. That means es-419/es-ES recipients will now get Argentina-specific separators/symbol placement (for example, 1234.56 becomes 1.234,56), and non-US English users get US conventions, in every translated deposit/withdraw/refund push. Because OneSignal only receives generic en/es variants, this change is region-wrong for all users outside those two locales.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2a4b978ccc

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

});

export function formatAmount(value: number | string) {
const n = typeof value === "string" ? Number(value) : value;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep numeric precision when formatting string amounts

formatAmount() coerces every string input through Number(value) before localization, which silently changes exact decimal strings used by webhook and onchain payloads. For example, long decimal strings (like values from formatUnits(...)) can lose precision during coercion, so translated push notifications may show a different amount than the source event. This is a regression from the previous behavior that interpolated the original string directly.

Useful? React with 👍 / 👎.

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.

server: localize notifications

2 participants