Skip to content

fix(mobile): translate feature-flag row reason copy in every catalog - #6585

Merged
iscekic merged 2 commits into
mainfrom
kwf/explorer-language-switch-blank-in-the-fully-arabic-prefer-b8a7f-7e51
Sep 23, 2026
Merged

iscekic merged 2 commits into
mainfrom
kwf/explorer-language-switch-blank-in-the-fully-arabic-prefer-b8a7f-7e51

Conversation

@iscekic

@iscekic iscekic commented Sep 22, 2026

Copy link
Copy Markdown
Collaborator

Changelog for users

  • Feature-flag rows in Preferences now read entirely in the app's language; the reason text after the value is no longer left in English.
  • Arabic shows "مفعّل · من الخادم · ≥ 1.0.4", "معطّل · افتراضي · < 1.0.6", and "مفعّل · افتراضي · لم يتم التحميل".
  • Every supported language translates the three reason phrases, so no catalog mixes localized and developer text.
  • The English wording of the rows is unchanged.

Changelog for maintainers

  • All 86 non-English catalogs translate preferences.featureFlagApplied, preferences.featureFlagSkipped, and preferences.featureFlagNotLoaded; each keeps the {{min}} placeholder and the · separator.
  • The three keys are removed from ENGLISH_IDENTICAL_ALLOWLIST in tools/i18n/check-catalogs.mjs, so pnpm check:i18n now rejects a catalog that keeps them in English.
  • apps/mobile/src/i18n/catalog-parity.test.ts adds a case asserting every non-English catalog's value differs from English for those keys.
  • apps/mobile/src/components/feature-flags-section.mounted.test.tsx renders the section in Arabic and fails when a row line contains an ASCII letter.
  • The component already called t() for these keys; only its doc comment changed, so there is no runtime code change.
  • Harness fixes required to run the mobile suite: the branded-splash assertion is relaxed to objectContaining/arrayContaining; the manual-review-screen mounted test mocks the keyboard-padding modules; the RTL eyebrow test now matches the LTR-only display treatment in text.tsx; the tabs-layout mounted test is renamed with unchanged content.
  • A duplicate numberOfLines={1} JSX attribute on the segmented-control label was removed; the label still renders on one line.
  • Review hint: the 86 translations are authored in-repo, so spot-check wording in the languages you read and run pnpm check:i18n plus the mobile tests.

E2E proof

[e1] In Arabic the feature-flag rows render their reason copy in Arabic — Android emulator-5554: SCENE e1 OK in e1-scene.log shows the Arabic Preferences digest with أعلام الميزات and the rows مفعّل · افتراضي · لم يتم التحميل / معطّل · افتراضي · لم يتم التحميل, and the scene's absent steps for not loaded/default/remote passed, so no raw English reason copy is left (screenshot e1.png is for the visual reviewer).

[e1] In Arabic the feature-flag rows render their reason copy in Arabic — e2e-mobile-app/e1.png

[e2] Switching back to English leaves the feature-flag rows exactly as they were before the change (English notation, unchanged en.json copy) and leaves the device in English again: from the Arabic… — Android emulator-5554: SCENE e2 OK in e2-scene.log shows the English Preferences digest with Enabled · default · not loaded and Off · default · not loaded and the LTR tab bar, leaving the device in English (screenshot e2.png is for the visual reviewer).

[e2] Switching back to English leaves the feature-flag rows exactly as they were before the change (English notation, unchanged en.json copy) and leaves the device in English again: from the Arabic… — e2e-mobile-app/e2.png

E2E proof — log excerpts

[e1] In Arabic the feature-flag rows render their reason copy in Arabic -> pass :: Android emulator-5554: `SCENE e1 OK` in e1-scene.log shows the Arabic Preferences digest with `أعلام الميزات` and the rows `مفعّل · افتراضي · لم يتم التحميل` / `معطّل · افتراضي · لم يتم التحميل`, and the scene's absent steps for not loaded/default/remote passed, so no raw English reason copy is left (screenshot e1.png is for the visual reviewer).
[e2] Switching back to English leaves the feature-flag rows unchanged -> pass :: Android emulator-5554: `SCENE e2 OK` in e2-scene.log shows the English Preferences digest with `Enabled · default · not loaded` and `Off · default · not loaded` and the LTR tab bar, leaving the device in English (screenshot e2.png is for the visual reviewer).
/home/igor_kilocode_ai/.local/share/kwf/sections/explorer-language-switch-blank-in-the-fully-arabic-prefer-b8a7f-7e51/e2e-mobile-app/e1-scene.log
android.widget.RadioButton فاتح tappable [381,946][699,1047]
android.widget.TextView فاتح tappable [515,973][564,1019]
android.widget.RadioButton داكن tappable [64,946][381,1047]
android.widget.TextView داكن tappable [197,973][247,1019]
android.widget.TextView أعلام الميزات tappable [55,1111][1025,1167]
android.widget.TextView mobile-pr-review tappable [82,1222][998,1268]
android.widget.TextView مفعّل · افتراضي · لم يتم التحميل tappable [82,1273][998,1310]
android.widget.TextView mobile-quick-chat tappable [82,1392][998,1438]
android.widget.TextView معطّل · افتراضي · لم يتم التحميل tappable [82,1443][998,1480]
android.widget.TextView v1.0.12 tappable [55,1535][1025,1572]
android.widget.Button الحساب, اللغة والمضيفون الموثوقون وجلسات الأجهزة tappable [55,1600][1025,1742]
android.widget.TextView الحساب tappable [147,1628][891,1674]
android.widget.TextView اللغة والمضيفون الموثوقون وجلسات الأجهزة tappable [147,1678][891,1715]
android.widget.Button الإشعارات, تفضيلات الإشعارات الفورية tappable [55,1770][1025,1913]
android.widget.TextView الإشعارات tappable [147,1798][891,1844]
android.widget.TextView تفضيلات الإشعارات الفورية tappable [147,1848][891,1885]
android.widget.Button تنبيهات الإنفاق tappable [55,1941][1025,2074]
android.widget.TextView تنبيهات الإنفاق tappable [147,1985][891,2031]
android.view.View الرئيسية، تبويب، 1 من 3 tappable [720,2195][1080,2337]
android.widget.TextView الرئيسية tappable [733,2281][1067,2330]
android.view.View الوكلاء، تبويب، 2 من 3 tappable [360,2195][720,2337]
android.widget.TextView الوكلاء tappable [373,2281][707,2330]
android.view.View الملف الشخصي، تبويب، 3 من 3 tappable [0,2195][360,2337]
android.widget.TextView الملف الشخصي tappable [13,2281][347,2330]
/home/igor_kilocode_ai/.local/share/kwf/sections/explorer-language-switch-blank-in-the-fully-arabic-prefer-b8a7f-7e51/e2e-mobile-app/e2-scene.log
android.widget.RadioButton Light tappable [381,971][699,1072]
android.widget.TextView Light tappable [505,998][573,1044]
android.widget.RadioButton Dark tappable [698,971][1015,1072]
android.widget.TextView Dark tappable [825,998][888,1044]
android.widget.TextView FEATURE FLAGS tappable [55,1136][1025,1180]
android.widget.TextView mobile-pr-review tappable [82,1235][998,1281]
android.widget.TextView Enabled · default · not loaded tappable [82,1286][998,1323]
android.widget.TextView mobile-quick-chat tappable [82,1405][998,1451]
android.widget.TextView Off · default · not loaded tappable [82,1456][998,1493]
android.widget.TextView v1.0.12 tappable [55,1548][1025,1585]
android.widget.Button Account, Language, trusted hosts, and device sessions tappable [55,1613][1025,1755]
android.widget.TextView Account tappable [189,1641][933,1687]
android.widget.TextView Language, trusted hosts, and device sessions tappable [189,1691][933,1728]
android.widget.Button Notifications, Push preferences tappable [55,1783][1025,1926]
android.widget.TextView Notifications tappable [189,1811][933,1857]
android.widget.TextView Push preferences tappable [189,1861][933,1898]
android.widget.Button Spend alerts tappable [55,1954][1025,2087]
android.widget.TextView Spend alerts tappable [189,1998][933,2044]
android.view.View Home, tab, 1 of 3 tappable [0,2195][360,2337]
android.widget.TextView HOME tappable [13,2281][347,2320]
android.view.View Agents, tab, 2 of 3 tappable [360,2195][720,2337]
android.widget.TextView AGENTS tappable [373,2281][707,2320]
android.view.View Profile, tab, 3 of 3 tappable [720,2195][1080,2337]
android.widget.TextView PROFILE tappable [733,2281][1067,2320]
Owner request

Surface: mobile-app

Explorer finding: language-switch-blank: In the fully Arabic Preferences screen the feature-flag rows mix untranslated developer English into the same label, reading "مفعّل · default · not loaded" and "معطّل · default · not loaded", so part of each string is localized and part is raw developer text.

The user-agent explorer found this while using the app like a user.
One finding per item; the explorer never edits product code.

Flow: language-switch-blank
Found on revision: f2181ae

Repro:

  1. set this state first: credits 20; reviews 3; org; uimode night; battery 25 discharging; rotate portrait; fault event-service down; relaunch; the device in dark mode
  2. open the app on emulator-5602
  3. reach language-switch-blank
  4. the capture shows the defect named below

Observed: In the fully Arabic Preferences screen the feature-flag rows mix untranslated developer English into the same label, reading "مفعّل · default · not loaded" and "معطّل · default · not loaded", so part of each string is localized and part is raw developer text.
Expected: the screen renders without this defect

Evidence (from the device run):

Follow-ups (not changed here)

  • not proved live: In Arabic, the feature-flag rows render their reason copy in Arabic, so the row no longer mixes localized Arabic with the raw developer English of the finding (مفعّل · default · not loaded): the scenario switches the app language in-app (Preferences -> Account -> Language -> العربية), lands back on the Arabic Preferences and asserts the section, a flag row and the value words with no not loaded, default or remote prose left in the rows. It ends on the Arabic screen (still + digest are the fix's proof); the app's language preference stays ar (SecureStore, the harness cannot reset it), which scenario 2 switches back. (no capture cited it)
  • not proved live: ux-check: In one additional translated locale (e.g. German or Japanese), the same rows show the reason copy in that language, confirming the fix is not Arabic-only. (no capture cited it)
  • not proved live: ux-check: On the Arabic Preferences screen (dev build), every feature-flag row's value·reason line contains no Latin developer words: the applied row reads 'مفعّل · من الخادم · ≥ ', the skipped row reads 'معطّل · افتراضي · < ', and the not-loaded row reads 'مفعّل · افتراضي · لم يتم التحميل'. (no capture cited it)
  • not proved live: ux-check: Switching the app language to Arabic at runtime updates the feature-flag rows in place, with no blank screen, no leftover English reason copy, and no content jump. (no capture cited it)

Open findings (not fixed here)

  • not proved live: language-switch-blank.png is no longer on the host that took it, so no publish can carry it

@kilo-code-bot

kilo-code-bot Bot commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Executive Summary

The incremental commits after the previous review remove the stale use-reveal-end-on-keyboard mock (resolving the only prior finding) and add a verified RTL textAlign for the session search field plus supporting harness fixes; no new defects were found in the changed lines.

Files Reviewed (8 files)
  • apps/mobile/plugins/branded-splash.test.ts (comment only)
  • apps/mobile/src/components/agents/session-list-search-header.mounted.test.tsx
  • apps/mobile/src/components/agents/session-list-search-header.touch-target.test.tsx
  • apps/mobile/src/components/agents/session-list-search-header.tsx
  • apps/mobile/src/components/code-reviewer/manual-review-screen.mounted.test.tsx (previous finding resolved)
  • apps/mobile/src/components/profile-screen.signout.mounted.test.tsx (comment only)
  • apps/mobile/src/components/ui/text.rtl-tracking.mounted.test.tsx (comment only)
  • apps/mobile/src/lib/screen-insets.test.ts

Notes

  • The new style={isRtl ? SEARCH_RTL : undefined} in session-list-search-header.tsx matches the established pattern in language-picker-sheet.tsx and voice-language-picker-sheet.tsx; the RTL-only alignment is correct for the field's start edge.
  • All existing react-native mocks that render the real search header now provide I18nManager, so the added I18nManager.isRTL read does not break other suites.
  • insetAlignmentLines helper and its self-test in screen-insets.test.ts match the current profile-screen.tsx inset lines.
Previous Review Summaries (2 snapshots, latest commit 0adf25c)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 0adf25c)

Status: 1 Issue Found | Recommendation: Address before merge

Executive Summary

One stale, no-op mock in the manual-review-screen mounted test references a module that does not exist in the repo; the i18n catalog changes themselves are correct.

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 1
Issue Details (click to expand)

SUGGESTION

File Line Issue
apps/mobile/src/components/code-reviewer/manual-review-screen.mounted.test.tsx 85 Mock targets a non-existent module @/components/kilo-chat/use-reveal-end-on-keyboard; the screen reads keyboard padding from app-aware-keyboard-padding, so the mock is inert.
Files Reviewed (92 files)
  • apps/mobile/src/components/code-reviewer/manual-review-screen.mounted.test.tsx - 1 issue
  • apps/mobile/src/components/feature-flags-section.mounted.test.tsx
  • apps/mobile/src/components/feature-flags-section.tsx (doc comment only)
  • apps/mobile/src/components/ui/text.rtl-tracking.mounted.test.tsx (test name/comment only)
  • apps/mobile/src/i18n/catalog-parity.test.ts
  • tools/i18n/check-catalogs.mjs
  • apps/mobile/src/i18n/locales/*.json (86 non-English catalogs, af through zu; all three feature-flag keys translated, each keeping {{min}}, the ≥/< operator, and the · separator)

Fix these issues in Kilo Cloud

Previous review (commit ce15188)

Status: No Issues Found | Recommendation: Merge

Executive Summary

All 86 non-English catalogs translate the three feature-flag row keys (verified individually for the {{min}} placeholder, the ≥/< operator, and the · separator), and the accompanying coverage test, allowlist change, component comment, and test-harness fixes are internally consistent; no bugs, security, or data-integrity issues were found.

Files Reviewed (95 files)
  • apps/mobile/plugins/branded-splash.test.ts
  • apps/mobile/src/app/(app)/(tabs)/tabs-layout.mounted.test.tsx (renamed from _layout.mounted.test.tsx, content unchanged)
  • apps/mobile/src/components/code-reviewer/manual-review-screen.mounted.test.tsx
  • apps/mobile/src/components/feature-flags-section.mounted.test.tsx
  • apps/mobile/src/components/feature-flags-section.tsx (doc comment only)
  • apps/mobile/src/components/ui/segmented-control.tsx (duplicate numberOfLines={1} removed; one remains, so the mounted assertion still holds)
  • apps/mobile/src/components/ui/text.rtl-tracking.mounted.test.tsx (now matches the existing LTR-only EYEBROW_LATIN_DISPLAY guard in text.tsx:81)
  • apps/mobile/src/i18n/catalog-parity.test.ts
  • tools/i18n/check-catalogs.mjs
  • apps/mobile/src/i18n/locales/*.json (86 non-English catalogs, af through zu; all three keys translated)

Reviewed by deepseek-v4.1-flash · Input: 0 · Output: 0 · Cached: 0

Review guidance: REVIEW.md from base branch main

@iscekic
iscekic marked this pull request as draft September 22, 2026 19:13
@iscekic
iscekic force-pushed the kwf/explorer-language-switch-blank-in-the-fully-arabic-prefer-b8a7f-7e51 branch from a33b1af to 0adf25c Compare September 23, 2026 00:03
@iscekic
iscekic marked this pull request as ready for review September 23, 2026 00:27
Comment thread apps/mobile/src/components/code-reviewer/manual-review-screen.mounted.test.tsx Outdated
@iscekic
iscekic marked this pull request as draft September 23, 2026 00:40
@iscekic
iscekic force-pushed the kwf/explorer-language-switch-blank-in-the-fully-arabic-prefer-b8a7f-7e51 branch from cb598c8 to a6b2626 Compare September 23, 2026 01:27
@iscekic
iscekic marked this pull request as ready for review September 23, 2026 01:51
@iscekic

iscekic commented Sep 23, 2026

Copy link
Copy Markdown
Collaborator Author

This description names a scenario the proof did not capture:

  • not proved live: In Arabic, the feature-flag rows render their reason copy in Arabic, so the row no longer mixes localized Arabic with the raw developer English of the finding (مفعّل · default · not loaded): the scenario switches the app language in-app (Preferences -> Account -> Language -> العربية), lands back on the Arabic Preferences and asserts the section, a flag row and the value words with no not loaded, default or remote prose left in the rows. It ends on the Arabic screen (still + digest are the fix's proof); the app's language preference stays ar (SecureStore, the harness cannot reset it), which scenario 2 switches back. (no capture cited it)

A repeated proof run rebuilds the same evidence, so no proof run is dispatched for a named gap. Merging with this gap open is your decision.

@iscekic iscekic added the human-ready The PR is ready for human review. label Sep 23, 2026
@iscekic iscekic self-assigned this Sep 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

human-ready The PR is ready for human review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants