Skip to content

fix: localize shop category titles - #1301

Open
jvsena42 wants to merge 8 commits into
masterfrom
fix/715-localize-shop-categories
Open

jvsena42 wants to merge 8 commits into
masterfrom
fix/715-localize-shop-categories

Conversation

@jvsena42

@jvsena42 jvsena42 commented Sep 17, 2026

Copy link
Copy Markdown
Member

Fixes #715
Related to #1275

This PR moves the Shop gift card category titles into string resources so they can be translated.

Description

  • Replaces the hardcoded English category titles with string resources so Transifex can translate all 22 Shop Discover categories.
  • Passes the localized category title to the gift card web view so its top bar matches the tapped row.
  • Keeps "VoIP" non-translatable, following the rule that acronyms are not localized.

Out of Scope

  • values-*/strings.xml: translations for the new keys arrive with the next Transifex pull; until then every locale shows the English titles.
  • other__shop__categories__travel: kept as its own key next to other__shop__discover__travel__title so every category follows one naming scheme, even though both read "Travel".
  • Shop Discover: the v62 "Shop Gift Card Categories" redesign (Overview / Gift Cards / Map tabs, Subscriptions tile, categories button) is a follow-up.
  • journeys/shop/gift-card-category-titles.xml: the journey written during device verification is committed with this PR and its row added to journeys/README.md; the diff is inlined below too.
  • iOS and RN: both still hardcode the category names; an iOS parity change (and the journey port) is a follow-up.

Design

Preview

Figma English, top English, bottom
Figma Shop Discover Shop Discover English top Shop Discover English bottom
Web view title App locale de (no translations yet)
Food Delivery web view Shop Discover de fallback

Test-only build with a temporary, uncommitted values-de override for three keys, showing the resources are wired end to end:

Discover top Discover bottom Web view
de override top de override bottom de override web view

QA Notes

Manual Tests

  • 1. Drawer → Shop → Shop Discover: all 22 gift card categories show the same English titles as before, from Apparel to VoIP, with "Health & Beauty" rendered unescaped.
  • 2. Shop Discover → tap Food Delivery: Shop Web View top bar reads "Shop Food Delivery" and the Bitrefill page loads.
  • 3. regression: App locale set to a non-English language → Shop Discover: no crash; chrome is translated and category rows fall back to English until Transifex sync.
  • 4. regression: Shop Discover → Travel card and Travel category row: both open the Bitrefill travel page.

The journey covers tests 1 to 3. It was run against this branch and every step passed, and it is committed at journeys/shop/gift-card-category-titles.xml; the same diff is inlined below.

gift-card-category-titles.xml
diff --git a/journeys/shop/gift-card-category-titles.xml b/journeys/shop/gift-card-category-titles.xml
new file mode 100644
index 000000000..f94b01fd5
--- /dev/null
+++ b/journeys/shop/gift-card-category-titles.xml
@@ -0,0 +1,36 @@
+<journey name="gift card category titles">
+  <description>
+    Proves the Shop Discover gift card category rows render all 22 titles in order, survive an app
+    locale change, and pass the title shown on the row to the gift card web view. Precondition:
+    onboarded debug build, dev mode on (the screen deeplink is debug-only and gated on it), device
+    and app locale English, network access to Bitrefill.
+
+    This journey does not yet distinguish resource-backed titles from the hardcoded enum they
+    replace, and a pass is not proof of localization. The English values added in
+    `values/strings.xml:572-593` are the same text the enum carried, and no `values-*` file carries
+    an `other__shop__categories__*` key yet, so every row reads English in every shipped locale
+    either way. A pseudolocale cannot close the gap: `androidResources.localeFilters`
+    (`app/build.gradle.kts:276`) keeps only the 16 shipped locales, so `en-XA` resources are
+    stripped. Once the Transifex pull lands the German strings, replace the German step below with
+    assertions on concrete translated titles ("Food Delivery" and "Health &amp; Beauty" rows plus
+    the web view top bar) and drop the English fallback allowance; that is what makes this journey
+    discriminate. "VoIP" is not translatable and stays "VoIP" in every locale.
+
+    The screen deeplink skips the Shop intro without marking it seen; iOS has no screen router, so a
+    port reaches Shop Discover through the drawer's Shop entry instead.
+  </description>
+  <actions>
+    <action>Run `adb shell am start -W -a android.intent.action.VIEW -d "bitkit://screen/shop-discover" to.bitkit.dev`</action>
+    <action>Verify that the Shop Discover screen is visible with the "Tab-shop" and "Tab-map" tabs and a "GIFT CARD CATEGORIES" header</action>
+    <action>Scroll the category list to the end and verify these 22 rows appear in order: "Apparel", "Automobiles", "Cruises", "Ecommerce", "Electronics", "Entertainment", "Experiences", "Flights", "Food", "Food Delivery", "Games", "Gifts", "Groceries", "Health &amp; Beauty", "Home", "Multi-Brand", "Pets", "Restaurants", "Retail", "Streaming", "Travel", "VoIP"</action>
+    <action>Tap "Food Delivery"</action>
+    <action>Verify that the top bar title reads "Shop Food Delivery"</action>
+    <action>Wait for the web view to load, then take a screenshot and verify the Bitrefill Food Delivery listing is visible</action>
+    <action>Press the device back button</action>
+    <action>Run `adb shell cmd locale set-app-locales to.bitkit.dev --locales de`, then `adb shell am force-stop to.bitkit.dev` and relaunch the app</action>
+    <action>Run `adb shell am start -W -a android.intent.action.VIEW -d "bitkit://screen/shop-discover" to.bitkit.dev`</action>
+    <action>Verify that the app did not crash, the Map tab reads "Karte", and all 22 category rows are still listed in the same order; until the German strings land they all read their English titles, which is the expected state and not a failure</action>
+    <action>Run `adb shell cmd locale set-app-locales to.bitkit.dev --locales ''`, then `adb shell am force-stop to.bitkit.dev` and relaunch the app</action>
+    <action>Verify that the wallet overview is visible in English</action>
+  </actions>
+</journey>

Automated Checks

  • BitrefillCategoryTest.kt: Robolectric test pinned to en-rUS that asserts each of the 22 BitrefillCategory entries points at the string resource named after it, that the resolved labels are distinct and non-blank, and that the routes are distinct buy/ paths. Negative control: swapping the APPAREL and AUTOMOBILES ids fails the resource-name check and passes the other two.
  • Not covered: wrong text inside a correctly named key, wrong icon, a route slug aimed at the wrong Bitrefill page, and values-* translations.
  • Local runs: just compile, just test and just lint pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jvsena42 jvsena42 self-assigned this Sep 17, 2026
@greptile-apps

greptile-apps Bot commented Sep 17, 2026

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

The PR appears safe to merge; the localized resource mapping and navigation flow are complete and internally consistent.

Summary

This PR moves all 22 Bitrefill gift-card category titles from hardcoded enum strings into Android string resources and passes the resolved localized title through to the shop web view.

  • Replaces BitrefillCategory.title with an annotated string-resource identifier.
  • Resolves each category title in Compose for both row rendering and web-view navigation.
  • Keeps VoIP non-translatable and documents the localization improvement in the changelog.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
    A[BitrefillCategory titleRes] --> B[stringResource]
    B --> C[Shop Discover category row]
    B --> D[Shop web-view navigation]
    D --> E[Localized top-bar title]
    A --> F[Unchanged Bitrefill route]
    F --> G[Bitrefill page URL]
Loading

Reviews (1) · Last reviewed commit: "fix: localize shop category titles"

@github-actions

github-actions Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Regtest APK

Built from 8cded33 (run).

Download bitkit-dev-debug universal APK (expires in 30 days).

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Approved — no HIGH/MEDIUM findings at head c9be3ec33. (Posted as a comment because GitHub does not allow approving your own PR.)

Checked: Every one of the 22 BitrefillCategory entries keeps its route string byte-for-byte (buy/apparel through buy/voip, including buy/health-beauty and buy/food-delivery), so the Bitrefill pages loaded by the web view are unchanged. A git grep at head shows the enum's only consumer is ShopTabContent in ShopDiscoverScreen.kt; no other main, test or androidTest code read the removed title field. The resolved string feeds both the row label and Routes.ShopWebView.title, which ShopWebViewScreen.kt only uses as display text in the top bar (line 57), never in a URL. VoIP is translatable="false", &amp; is escaped correctly, and the 22 new keys sit in alphabetical order before other__shop__discover__*.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jvsena42
jvsena42 requested a review from ovitrif September 18, 2026 13:26

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Approved — no blocking HIGH/MEDIUM findings at head fe1f4fd1f. (Posted as a comment because GitHub does not allow approving your own PR.)

Inline: LOW — Journey passes unchanged on master, so it cannot detect a revert to hardcoded titles

Checked: Round 4 (f2663e4, new journey): Reviewed the journey commit f2663e4. The route in works on the dev build: bitkit://screen/shop-discover resolves through ScreenDeepLinks (enabled only in the debug ScreenDeepLinkRuntime, queued behind dev mode), Routes.ShopDiscover is deepLinkableComposable, and nothing geoblocks or flag-gates the Shop routes. Tab-shop and Tab-map come from CustomTabRowWithSpacing ("Tab-${tab.name.lowercase()}"), the header is Text13Up upper-casing "Gift card categories", the 22 rows match the enum order and the default strings, the web view top bar is "${nav_title} $title" = "Shop Food Delivery", and values-de has other__shop__discover__tabs__map = "Karte", so the locale switch is confirmed on screen. The README suite row and the cross-platform "not ported" row are both present. The one gap: no step fails if the enum goes back to hardcoded English.

Comment thread journeys/shop/gift-card-category-titles.xml Outdated
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Approved — no blocking HIGH/MEDIUM findings at head 6646dde27. (Posted as a comment because GitHub does not allow approving your own PR.)

Checked: Follow-up: Reviewed 6646dde only. The description no longer claims the journey proves resource-backed titles and states that a pass is not proof of localization. Its cited facts hold at head: the 22 other__shop__categories__* values sit at values/strings.xml:572-593 with the same English text the enum carried, only values/strings.xml defines those keys, and localeFilters.addAll(androidLocales) is at app/build.gradle.kts:276. The German step now expects all 22 rows in order with English text and "Karte" for the Map tab (values-de other__shop__discover__tabs__map), which is what the app renders, so a runner gets neither a false fail nor a claimed localization pass.

ovi-reviewer[bot]

This comment was marked as resolved.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Approved — no blocking HIGH/MEDIUM findings at head 124c2959e. (Posted as a comment because GitHub does not allow approving your own PR.)

Checked: Follow-up on 124c295: test-only. BitrefillCategoryTest pins each enum entry to the string resource named after it, requires distinct non-blank labels, and requires every route to be a distinct buy/<slug> path, which is the regression guard the journey cannot provide until translations land.

ovitrif

This comment was marked as resolved.

@ovitrif

ovitrif commented Sep 18, 2026

Copy link
Copy Markdown
Collaborator

@jvsena42 conflicts

@ovitrif
ovitrif enabled auto-merge September 18, 2026 16:15
ovi-reviewer[bot]

This comment was marked as resolved.

ovi-reviewer[bot]

This comment was marked as resolved.

@ovitrif ovitrif left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

utAck

@ovi-reviewer ovi-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Verdict: ✅ Approve


Reaudit: diff 1 file.
Counterpart synonymdev/bitkit-ios#722: not compared.

Findings:
N/A

Audit:
Already done in comment.

QA: emu-1 Pixel 10 Pro emulator on Android 16/API 36, dev debug build app-dev-arm64-v8a-debug.apk

  1. passed: All 22 category titles remained ordered in English, and Health & Beauty rendered unescaped.

    Test 1:
    Drawer → Shop → Shop Discover: all 22 gift card categories show the same English titles as before, from…
    1.mp4
  2. passed: Food Delivery opened with the Shop Food Delivery title and loaded Bitrefill listings.

    Test 2:
    Shop Discover → tap Food Delivery: Shop Web View top bar reads "Shop Food Delivery" and the Bitrefill page…
    2.mp4
  3. passed: German locale kept the app running, translated the chrome, and fell back to English category titles.

    Test 3:
    `regression:` App locale set to a non-English language → Shop Discover: no crash; chrome is translated and…
    3.mp4
  4. passed: Both the Travel card and Travel category row opened the loaded Bitrefill Travel page.

    Test 4:
    `regression:` Shop Discover → Travel card and Travel category row: both open the Bitrefill travel page.
    4.mp4

Ticked Manual Tests 1-4 in the PR body.

Tip

Test 1 worth a journey:

  • Open the drawer and tap Shop
  • Continue past the Shop intro
  • Verify the Shop and Map tabs and the gift card categories header
  • Scroll from Apparel to VoIP and verify all 22 titles stay in order
  • Verify Health & Beauty shows an ampersand

Test 2 worth a journey:

  • Open Shop Discover
  • Scroll to Food Delivery
  • Tap Food Delivery
  • Verify the top bar reads Shop Food Delivery
  • Wait for Bitrefill and verify the Food Delivery listings load

Test 3 worth a journey:

  • Leave the Food Delivery page with the device back button
  • Set the Bitkit app locale to German
  • Force-stop and relaunch Bitkit
  • Open Shop Discover with the screen deeplink
  • Verify translated chrome includes Karte
  • Scroll through all 22 category rows and verify they stay in English and in order
  • Clear the app locale and relaunch
  • Verify the English wallet overview returns

Test 4 worth a journey:

  • Open Shop Discover
  • Tap the large Travel card
  • Verify the Shop Travel header and loaded Bitrefill Travel listings
  • Return to Shop Discover
  • Scroll to the Travel category row
  • Tap the Travel category row
  • Verify the Shop Travel header and loaded Bitrefill Travel listings again

Coverage:
QA: 4 of 4 manual tests passed


Reviewed by gpt-5.6-sol-high via gh-pr-review-loop skill
Commands: @ovi-reviewer review · test · retest · audit (author or owner)

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.

Missing some Bitrefill translations

2 participants