Skip to content

Fixes #5039: Force LTR alignment for Terms of Service & Privacy Policy in RTL languages#6198

Open
nikhilkumarpanigrahi wants to merge 11 commits intooppia:developfrom
nikhilkumarpanigrahi:fix/5039-policies-rtl-final
Open

Fixes #5039: Force LTR alignment for Terms of Service & Privacy Policy in RTL languages#6198
nikhilkumarpanigrahi wants to merge 11 commits intooppia:developfrom
nikhilkumarpanigrahi:fix/5039-policies-rtl-final

Conversation

@nikhilkumarpanigrahi
Copy link
Copy Markdown
Contributor

Explanation

Fixes #5039

This PR fixes the issue where Terms of Service and Privacy Policy content was incorrectly right-aligned in RTL (Right-to-Left) languages like Arabic. Since these policies are canonical English content, they should always display in English with left-to-right alignment regardless of the user's selected app or system language.

Specifically, this PR:

  • Adds a ForcedActivityLanguageMode proto enum to languages.proto with values USE_APP_LANGUAGE, USE_SYSTEM_LANGUAGE, and USE_ENGLISH to represent the three possible activity language modes.
  • Creates InjectableEnglishOnlyAppCompatActivity.kt, a new base activity that forces the English locale via the USE_ENGLISH mode, intended for activities displaying canonical English content.
  • Refactors AppLanguageWatcherMixin.initialize() to accept ForcedActivityLanguageMode (proto enum) instead of the previous shouldOnlyUseSystemLanguage: Boolean parameter, enabling cleaner support for the new English-only mode.
  • Updates InjectableAutoLocalizedAppCompatActivity and InjectableSystemLocalizedAppCompatActivity to use the new proto enum.
  • Adds getEnglishLocale() to TranslationController to return a DataProvider<OppiaLocale.DisplayLocale> for the English language.
  • Updates PoliciesActivity to extend InjectableEnglishOnlyAppCompatActivity instead of InjectableAutoLocalizedAppCompatActivity.
  • Updates PoliciesFragmentPresenter to programmatically set LAYOUT_DIRECTION_LTR, TEXT_DIRECTION_LTR, and Gravity.START on the policy description text view to ensure proper left-alignment of list items (<li> tags) and bullet points.
  • Adds android:textDirection="ltr" and android:textAlignment="textStart" to policies_fragment.xml for the policy description text view.
  • Updates file_content_validation_checks.textproto to add exemptions for InjectableEnglishOnlyAppCompatActivity in the InjectableAppCompatActivity subclass check and the screen name check.
  • Adds test file exemption for InjectableEnglishOnlyAppCompatActivity in test_file_exemptions.textproto since it is a thin base class with no independent logic.
  • Updates AppLanguageWatcherMixinTest to use the new ForcedActivityLanguageMode proto enum instead of the old boolean parameter.
  • Adds languages_java_proto_lite dependency to the relevant BUILD targets (app_language_watcher_mixin, injectable_auto_localized_app_compat_activity, injectable_system_localized_app_compat_activity, injectable_english_only_app_compat_activity).

Essential Checklist

  • The PR title starts with "Fix #bugnum: " (If this PR fixes part of an issue, prefix the title with "Fix part of #bugnum: ...".)
  • The explanation section above starts with "Fixes #bugnum: " (If this PR fixes part of an issue, use instead: "Fixes part of #bugnum: ...".)
  • Any changes to scripts/assets files have their rationale included in the PR explanation.
  • The PR follows the style guide.
  • The PR does not contain any unnecessary code changes from Android Studio (reference).
  • The PR is made from a branch that's not called "develop" and is up-to-date with "develop".
  • The PR is assigned to the appropriate reviewers (reference).

For UI-specific PRs only

If your PR includes UI-related changes, then:

Testing performed:

  • Set app language to Arabic (RTL) → navigated to Help → Terms of Service → confirmed policy text is in English and left-aligned with bullet points on the left side.
  • Set app language to Arabic → navigated to Help → Privacy Policy → confirmed same left-aligned English behavior.
  • Set app language to English → confirmed policies display correctly (no regression).
  • Rotated device while viewing policies in Arabic mode → confirmed alignment is preserved after rotation.
  • Navigated back from policies page → confirmed the rest of the app remains in Arabic RTL layout.

Devices/Android versions tested on:

  • Android Emulator (API 35)

Screenshots/Videos:

ISSUE.5039.UI.TESTING.mov

…olicy in RTL languages

- Add ActivityLanguageMode enum (USE_APP_LANGUAGE, USE_SYSTEM_LANGUAGE, USE_ENGLISH)
  replacing the boolean shouldOnlyUseSystemLanguage parameter
- Create InjectableEnglishOnlyAppCompatActivity for English-only content
- Add getEnglishLocale() to TranslationController
- Update PoliciesActivity to extend InjectableEnglishOnlyAppCompatActivity
- Add textDirection=ltr and textAlignment=textStart to policy description XML
- Update all activity base classes and tests to use new enum API
- Add BUILD targets and validation exemptions for new activity class
- Add ForcedActivityLanguageMode proto enum to languages.proto (USE_APP_LANGUAGE,
  USE_SYSTEM_LANGUAGE, USE_ENGLISH) as specified in the contributing guidance
- Replace Kotlin ActivityLanguageMode enum with proto ForcedActivityLanguageMode
  throughout all activity base classes and AppLanguageWatcherMixin
- Update PoliciesFragmentPresenter to programmatically enforce LTR layout direction,
  text direction, and gravity on the policy description text view for proper
  list item (<li>) alignment in RTL locales
- Update all BUILD files with proto dependencies
- Update tests to use the new proto enum
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes RTL misalignment for canonical English policy pages (Terms of Service & Privacy Policy) by forcing English locale/LTR presentation regardless of the user’s selected app/system language.

Changes:

  • Introduces ForcedActivityLanguageMode proto enum and refactors AppLanguageWatcherMixin.initialize() to use it (including a new USE_ENGLISH mode).
  • Adds an English-only injectable base activity and migrates PoliciesActivity to it.
  • Forces LTR alignment for policies content via both XML attributes and runtime view configuration.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
scripts/assets/test_file_exemptions.textproto Exempts the new English-only activity from test requirements.
scripts/assets/file_content_validation_checks.textproto Updates validation rules to allow the new injectable activity subclass.
model/src/main/proto/languages.proto Adds ForcedActivityLanguageMode enum to represent activity locale resolution modes.
domain/src/main/java/org/oppia/android/domain/translation/TranslationController.kt Adds getEnglishLocale() to support USE_ENGLISH.
app/src/test/java/org/oppia/android/app/translation/AppLanguageWatcherMixinTest.kt Migrates tests to use the new enum-based API.
app/src/main/res/layout/policies_fragment.xml Adds LTR-related text attributes to the policy description TextView.
app/src/main/java/org/oppia/android/app/translation/BUILD.bazel Adds proto-lite dep for enum usage.
app/src/main/java/org/oppia/android/app/translation/AppLanguageWatcherMixin.kt Refactors initialization to use enum and adds English-locale branch.
app/src/main/java/org/oppia/android/app/policies/PoliciesFragmentPresenter.kt Forces LTR direction/gravity programmatically for policy content.
app/src/main/java/org/oppia/android/app/policies/PoliciesActivity.kt Switches base class to English-only injectable activity.
app/src/main/java/org/oppia/android/app/activity/InjectableSystemLocalizedAppCompatActivity.kt Updates mixin initialization to enum.
app/src/main/java/org/oppia/android/app/activity/InjectableEnglishOnlyAppCompatActivity.kt Adds new injectable base activity that forces English locale.
app/src/main/java/org/oppia/android/app/activity/InjectableAutoLocalizedAppCompatActivity.kt Updates mixin initialization to enum.
app/src/main/java/org/oppia/android/app/activity/BUILD.bazel Adds new build target + proto-lite deps for activities.
app/BUILD.bazel Wires new activity library into the app target.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +73 to 87
val activityLanguageLocaleDataProvider = when (forcedActivityLanguageMode) {
ForcedActivityLanguageMode.USE_SYSTEM_LANGUAGE ->
translationController.getSystemLanguageLocale()
ForcedActivityLanguageMode.USE_ENGLISH ->
translationController.getEnglishLocale()
ForcedActivityLanguageMode.USE_APP_LANGUAGE,
ForcedActivityLanguageMode.FORCED_ACTIVITY_LANGUAGE_MODE_UNSPECIFIED,
ForcedActivityLanguageMode.UNRECOGNIZED -> {
if (currentUserProfileId == null) {
translationController.getSystemLanguageLocale()
} else {
translationController.getAppLanguageLocale(currentUserProfileId)
}
}
}
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

The new USE_ENGLISH branch changes locale-resolution behavior, but the test suite updates only cover the enum migration. Please add a unit test that initializes the mixin with ForcedActivityLanguageMode.USE_ENGLISH and verifies the mixin selects the English locale (and does not switch when the app language changes).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Implemented. Added coverage that initializes AppLanguageWatcherMixin with ForcedActivityLanguageMode.USE_ENGLISH and verifies English remains selected even after app-language updates. This is now in the branch.

Comment on lines +78 to +86
ForcedActivityLanguageMode.USE_APP_LANGUAGE,
ForcedActivityLanguageMode.FORCED_ACTIVITY_LANGUAGE_MODE_UNSPECIFIED,
ForcedActivityLanguageMode.UNRECOGNIZED -> {
if (currentUserProfileId == null) {
translationController.getSystemLanguageLocale()
} else {
translationController.getAppLanguageLocale(currentUserProfileId)
}
}
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

Grouping FORCED_ACTIVITY_LANGUAGE_MODE_UNSPECIFIED and UNRECOGNIZED into the USE_APP_LANGUAGE behavior can hide misconfiguration/serialization issues and make failures harder to diagnose. Consider handling these cases explicitly by logging a warning (via OppiaLogger) and falling back deterministically (e.g., to system language), while keeping USE_APP_LANGUAGE as its own case.

Suggested change
ForcedActivityLanguageMode.USE_APP_LANGUAGE,
ForcedActivityLanguageMode.FORCED_ACTIVITY_LANGUAGE_MODE_UNSPECIFIED,
ForcedActivityLanguageMode.UNRECOGNIZED -> {
if (currentUserProfileId == null) {
translationController.getSystemLanguageLocale()
} else {
translationController.getAppLanguageLocale(currentUserProfileId)
}
}
ForcedActivityLanguageMode.USE_APP_LANGUAGE -> {
if (currentUserProfileId == null) {
translationController.getSystemLanguageLocale()
} else {
translationController.getAppLanguageLocale(currentUserProfileId)
}
}
ForcedActivityLanguageMode.FORCED_ACTIVITY_LANGUAGE_MODE_UNSPECIFIED,
ForcedActivityLanguageMode.UNRECOGNIZED -> {
oppiaLogger.w(
"AppLanguageWatcherMixin",
"Unexpected ForcedActivityLanguageMode: $forcedActivityLanguageMode. " +
"Falling back to system language."
)
translationController.getSystemLanguageLocale()
}

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Implemented. FORCED_ACTIVITY_LANGUAGE_MODE_UNSPECIFIED and UNRECOGNIZED are now handled explicitly with a warning log and deterministic fallback to system language, while USE_APP_LANGUAGE remains its own path.

Comment on lines +30 to +33
android:textAlignment="textStart"
android:textColor="@color/component_color_shared_primary_text_color"
android:textColorLink="@color/component_color_shared_link_text_color"
android:textDirection="ltr"
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

The alignment/direction is now enforced both in XML and in PoliciesFragmentPresenter, but the XML-only configuration here may not actually guarantee left alignment in RTL contexts since textStart depends on layout direction (not textDirection). To reduce drift and make the behavior self-contained, consider either (a) moving the full configuration to XML (e.g., include android:layoutDirection="ltr" and/or android:gravity="start") and removing the runtime overrides, or (b) removing these XML attributes and relying solely on the presenter.

Suggested change
android:textAlignment="textStart"
android:textColor="@color/component_color_shared_primary_text_color"
android:textColorLink="@color/component_color_shared_link_text_color"
android:textDirection="ltr"
android:textColor="@color/component_color_shared_primary_text_color"
android:textColorLink="@color/component_color_shared_link_text_color"

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed by choosing one source of truth. I removed the XML alignment and direction attrs and kept runtime enforcement in PoliciesFragmentPresenter to avoid drift between XML and code paths.

@nikhilkumarpanigrahi
Copy link
Copy Markdown
Contributor Author

Hi @BenHenning, all review feedback has been addressed and pushed, including the Copilot suggestions and the related failing regex test fix.
PTAL when you get a chance.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 5, 2026

Coverage Report

Results

Coverage Analysis: SKIP ⏭️

This PR did not introduce any changes to Kotlin source or test files.

To learn more, visit the Oppia Android Code Coverage wiki page

@adhiamboperes
Copy link
Copy Markdown
Contributor

@subhajitxyz, please take a first pass on this.

Copy link
Copy Markdown
Collaborator

@subhajitxyz subhajitxyz left a comment

Choose a reason for hiding this comment

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

@adhiamboperes , I have taken a first pass on it and leave some comment.

@subhajitxyz
Copy link
Copy Markdown
Collaborator

Thanks, @nikhilkumarpanigrahi , I have left some comment. PTAL.

@nikhilkumarpanigrahi
Copy link
Copy Markdown
Contributor Author

Hi @subhajitxyz,
Fixed all review comments and pushed the updates. PTAL when you get a chance.

@oppiabot
Copy link
Copy Markdown

oppiabot bot commented Apr 9, 2026

Unassigning @nikhilkumarpanigrahi since a re-review was requested. @nikhilkumarpanigrahi, please make sure you have addressed all review comments. Thanks!

@subhajitxyz
Copy link
Copy Markdown
Collaborator

subhajitxyz commented Apr 9, 2026

@nikhilkumarpanigrahi , Some checks has failed, please fix those.

@github-actions
Copy link
Copy Markdown

APK & AAB differences analysis

Note that this is a summarized snapshot. See the CI artifacts for detailed differences.

Dev

Expand to see flavor specifics

Universal APK

APK file size: 19 MiB (old), 19 MiB (new), 260 bytes (Added)

APK download size (estimated): 18 MiB (old), 18 MiB (new), 1191 bytes (Added)

Method count: 265367 (old), 265371 (new), 4 (Added)

Features: 1 (old), 1 (new), 0 (No change)

Permissions: 6 (old), 6 (new), 0 (No change)

Resources: 7118 (old), 7118 (new), 0 (No change)

  • Anim: 43 (old), 43 (new), 0 (No change)
  • Animator: 26 (old), 26 (new), 0 (No change)
  • Array: 15 (old), 15 (new), 0 (No change)
  • Attr: 922 (old), 922 (new), 0 (No change)
  • Bool: 9 (old), 9 (new), 0 (No change)
  • Color: 1005 (old), 1005 (new), 0 (No change)
  • Dimen: 1093 (old), 1093 (new), 0 (No change)
  • Drawable: 393 (old), 393 (new), 0 (No change)
  • Id: 1362 (old), 1362 (new), 0 (No change)
  • Integer: 37 (old), 37 (new), 0 (No change)
  • Interpolator: 11 (old), 11 (new), 0 (No change)
  • Layout: 401 (old), 401 (new), 0 (No change)
  • Menu: 3 (old), 3 (new), 0 (No change)
  • Mipmap: 1 (old), 1 (new), 0 (No change)
  • Plurals: 10 (old), 10 (new), 0 (No change)
  • Raw: 2 (old), 2 (new), 0 (No change)
  • String: 938 (old), 938 (new), 0 (No change)
  • Style: 840 (old), 840 (new), 0 (No change)
  • Xml: 7 (old), 7 (new), 0 (No change)

Lesson assets: 113 (old), 113 (new), 0 (No change)

AAB differences

Expand to see AAB specifics

Supported configurations:

  • hdpi (same)
  • ldpi (same)
  • mdpi (same)
  • tvdpi (same)
  • xhdpi (same)
  • xxhdpi (same)
  • xxxhdpi (same)

Base APK

APK file size: 19 MiB (old), 19 MiB (new), 264 bytes (Added)
APK download size (estimated): 18 MiB (old), 18 MiB (new), 1284 bytes (Added)
Method count: 265367 (old), 265371 (new), 4 (Added)

Configuration hdpi

APK file size: 50 KiB (old), 50 KiB (new), 0 bytes (No change)
APK download size (estimated): 18 KiB (old), 18 KiB (new), 0 bytes (No change)

Configuration ldpi

APK file size: 49 KiB (old), 49 KiB (new), 0 bytes (No change)
APK download size (estimated): 14 KiB (old), 14 KiB (new), 0 bytes (No change)

Configuration mdpi

APK file size: 46 KiB (old), 46 KiB (new), 0 bytes (No change)
APK download size (estimated): 14 KiB (old), 14 KiB (new), 0 bytes (No change)

Configuration tvdpi

APK file size: 86 KiB (old), 86 KiB (new), 0 bytes (No change)
APK download size (estimated): 29 KiB (old), 29 KiB (new), 0 bytes (No change)

Configuration xhdpi

APK file size: 57 KiB (old), 57 KiB (new), 0 bytes (No change)
APK download size (estimated): 21 KiB (old), 21 KiB (new), 0 bytes (No change)

Configuration xxhdpi

APK file size: 63 KiB (old), 63 KiB (new), 0 bytes (No change)
APK download size (estimated): 29 KiB (old), 29 KiB (new), 0 bytes (No change)

Configuration xxxhdpi

APK file size: 64 KiB (old), 64 KiB (new), 0 bytes (No change)
APK download size (estimated): 28 KiB (old), 28 KiB (new), 0 bytes (No change)

Alpha

Expand to see flavor specifics

Universal APK

APK file size: 11 MiB (old), 11 MiB (new), 56 bytes (Added)

APK download size (estimated): 10 MiB (old), 10 MiB (new), 4854 bytes (Added)

Method count: 118609 (old), 118586 (new), 23 (Removed)

Features: 1 (old), 1 (new), 0 (No change)

Permissions: 6 (old), 6 (new), 0 (No change)

Resources: 6052 (old), 6052 (new), 0 (No change)

  • Anim: 33 (old), 33 (new), 0 (No change)
  • Animator: 24 (old), 24 (new), 0 (No change)
  • Array: 14 (old), 14 (new), 0 (No change)
  • Attr: 888 (old), 888 (new), 0 (No change)
  • Bool: 8 (old), 8 (new), 0 (No change)
  • Color: 853 (old), 853 (new), 0 (No change)
  • Dimen: 815 (old), 815 (new), 0 (No change)
  • Drawable: 355 (old), 355 (new), 0 (No change)
  • Id: 1303 (old), 1303 (new), 0 (No change)
  • Integer: 32 (old), 32 (new), 0 (No change)
  • Interpolator: 11 (old), 11 (new), 0 (No change)
  • Layout: 359 (old), 359 (new), 0 (No change)
  • Menu: 1 (old), 1 (new), 0 (No change)
  • Mipmap: 1 (old), 1 (new), 0 (No change)
  • Plurals: 10 (old), 10 (new), 0 (No change)
  • String: 859 (old), 859 (new), 0 (No change)
  • Style: 485 (old), 485 (new), 0 (No change)
  • Xml: 1 (old), 1 (new), 0 (No change)

Lesson assets: 114 (old), 114 (new), 0 (No change)

AAB differences

Expand to see AAB specifics

Supported configurations:

  • hdpi (same)
  • ldpi (same)
  • mdpi (same)
  • tvdpi (same)
  • xhdpi (same)
  • xxhdpi (same)
  • xxxhdpi (same)

Base APK

APK file size: 11 MiB (old), 11 MiB (new), 60 bytes (Added)
APK download size (estimated): 10 MiB (old), 10 MiB (new), 1438 bytes (Added)
Method count: 118609 (old), 118586 (new), 23 (Removed)

Configuration hdpi

APK file size: 43 KiB (old), 43 KiB (new), 0 bytes (No change)
APK download size (estimated): 17 KiB (old), 17 KiB (new), 0 bytes (No change)

Configuration ldpi

APK file size: 45 KiB (old), 45 KiB (new), 0 bytes (No change)
APK download size (estimated): 13 KiB (old), 13 KiB (new), 0 bytes (No change)

Configuration mdpi

APK file size: 38 KiB (old), 38 KiB (new), 0 bytes (No change)
APK download size (estimated): 13 KiB (old), 13 KiB (new), 0 bytes (No change)

Configuration tvdpi

APK file size: 73 KiB (old), 73 KiB (new), 0 bytes (No change)
APK download size (estimated): 27 KiB (old), 27 KiB (new), 0 bytes (No change)

Configuration xhdpi

APK file size: 50 KiB (old), 50 KiB (new), 0 bytes (No change)
APK download size (estimated): 20 KiB (old), 20 KiB (new), 0 bytes (No change)

Configuration xxhdpi

APK file size: 55 KiB (old), 55 KiB (new), 0 bytes (No change)
APK download size (estimated): 28 KiB (old), 28 KiB (new), 0 bytes (No change)

Configuration xxxhdpi

APK file size: 55 KiB (old), 55 KiB (new), 0 bytes (No change)
APK download size (estimated): 27 KiB (old), 27 KiB (new), 0 bytes (No change)

Beta

Expand to see flavor specifics

Universal APK

APK file size: 11 MiB (old), 11 MiB (new), 220 bytes (Removed)

APK download size (estimated): 10 MiB (old), 10 MiB (new), 276 bytes (Added)

Method count: 118613 (old), 118590 (new), 23 (Removed)

Features: 1 (old), 1 (new), 0 (No change)

Permissions: 6 (old), 6 (new), 0 (No change)

Resources: 6052 (old), 6052 (new), 0 (No change)

  • Anim: 33 (old), 33 (new), 0 (No change)
  • Animator: 24 (old), 24 (new), 0 (No change)
  • Array: 14 (old), 14 (new), 0 (No change)
  • Attr: 888 (old), 888 (new), 0 (No change)
  • Bool: 8 (old), 8 (new), 0 (No change)
  • Color: 853 (old), 853 (new), 0 (No change)
  • Dimen: 815 (old), 815 (new), 0 (No change)
  • Drawable: 355 (old), 355 (new), 0 (No change)
  • Id: 1303 (old), 1303 (new), 0 (No change)
  • Integer: 32 (old), 32 (new), 0 (No change)
  • Interpolator: 11 (old), 11 (new), 0 (No change)
  • Layout: 359 (old), 359 (new), 0 (No change)
  • Menu: 1 (old), 1 (new), 0 (No change)
  • Mipmap: 1 (old), 1 (new), 0 (No change)
  • Plurals: 10 (old), 10 (new), 0 (No change)
  • String: 859 (old), 859 (new), 0 (No change)
  • Style: 485 (old), 485 (new), 0 (No change)
  • Xml: 1 (old), 1 (new), 0 (No change)

Lesson assets: 114 (old), 114 (new), 0 (No change)

AAB differences

Expand to see AAB specifics

Supported configurations:

  • hdpi (same)
  • ldpi (same)
  • mdpi (same)
  • tvdpi (same)
  • xhdpi (same)
  • xxhdpi (same)
  • xxxhdpi (same)

Base APK

APK file size: 11 MiB (old), 11 MiB (new), 224 bytes (Removed)
APK download size (estimated): 10 MiB (old), 10 MiB (new), 29 bytes (Added)
Method count: 118613 (old), 118590 (new), 23 (Removed)

Configuration hdpi

APK file size: 43 KiB (old), 43 KiB (new), 0 bytes (No change)
APK download size (estimated): 17 KiB (old), 17 KiB (new), 0 bytes (No change)

Configuration ldpi

APK file size: 45 KiB (old), 45 KiB (new), 0 bytes (No change)
APK download size (estimated): 13 KiB (old), 13 KiB (new), 0 bytes (No change)

Configuration mdpi

APK file size: 38 KiB (old), 38 KiB (new), 0 bytes (No change)
APK download size (estimated): 13 KiB (old), 13 KiB (new), 0 bytes (No change)

Configuration tvdpi

APK file size: 73 KiB (old), 73 KiB (new), 0 bytes (No change)
APK download size (estimated): 27 KiB (old), 27 KiB (new), 0 bytes (No change)

Configuration xhdpi

APK file size: 50 KiB (old), 50 KiB (new), 0 bytes (No change)
APK download size (estimated): 20 KiB (old), 20 KiB (new), 0 bytes (No change)

Configuration xxhdpi

APK file size: 55 KiB (old), 55 KiB (new), 0 bytes (No change)
APK download size (estimated): 28 KiB (old), 28 KiB (new), 0 bytes (No change)

Configuration xxxhdpi

APK file size: 55 KiB (old), 55 KiB (new), 0 bytes (No change)
APK download size (estimated): 27 KiB (old), 27 KiB (new), 0 bytes (No change)

Ga

Expand to see flavor specifics

Universal APK

APK file size: 11 MiB (old), 11 MiB (new), 340 bytes (Removed)

APK download size (estimated): 10 MiB (old), 10 MiB (new), 191 bytes (Removed)

Method count: 118613 (old), 118590 (new), 23 (Removed)

Features: 1 (old), 1 (new), 0 (No change)

Permissions: 6 (old), 6 (new), 0 (No change)

Resources: 6052 (old), 6052 (new), 0 (No change)

  • Anim: 33 (old), 33 (new), 0 (No change)
  • Animator: 24 (old), 24 (new), 0 (No change)
  • Array: 14 (old), 14 (new), 0 (No change)
  • Attr: 888 (old), 888 (new), 0 (No change)
  • Bool: 8 (old), 8 (new), 0 (No change)
  • Color: 853 (old), 853 (new), 0 (No change)
  • Dimen: 815 (old), 815 (new), 0 (No change)
  • Drawable: 355 (old), 355 (new), 0 (No change)
  • Id: 1303 (old), 1303 (new), 0 (No change)
  • Integer: 32 (old), 32 (new), 0 (No change)
  • Interpolator: 11 (old), 11 (new), 0 (No change)
  • Layout: 359 (old), 359 (new), 0 (No change)
  • Menu: 1 (old), 1 (new), 0 (No change)
  • Mipmap: 1 (old), 1 (new), 0 (No change)
  • Plurals: 10 (old), 10 (new), 0 (No change)
  • String: 859 (old), 859 (new), 0 (No change)
  • Style: 485 (old), 485 (new), 0 (No change)
  • Xml: 1 (old), 1 (new), 0 (No change)

Lesson assets: 114 (old), 114 (new), 0 (No change)

AAB differences

Expand to see AAB specifics

Supported configurations:

  • hdpi (same)
  • ldpi (same)
  • mdpi (same)
  • tvdpi (same)
  • xhdpi (same)
  • xxhdpi (same)
  • xxxhdpi (same)

Base APK

APK file size: 11 MiB (old), 11 MiB (new), 340 bytes (Removed)
APK download size (estimated): 10 MiB (old), 10 MiB (new), 1423 bytes (Removed)
Method count: 118613 (old), 118590 (new), 23 (Removed)

Configuration hdpi

APK file size: 43 KiB (old), 43 KiB (new), 0 bytes (No change)
APK download size (estimated): 17 KiB (old), 17 KiB (new), 0 bytes (No change)

Configuration ldpi

APK file size: 45 KiB (old), 45 KiB (new), 0 bytes (No change)
APK download size (estimated): 13 KiB (old), 13 KiB (new), 0 bytes (No change)

Configuration mdpi

APK file size: 38 KiB (old), 38 KiB (new), 0 bytes (No change)
APK download size (estimated): 13 KiB (old), 13 KiB (new), 0 bytes (No change)

Configuration tvdpi

APK file size: 73 KiB (old), 73 KiB (new), 0 bytes (No change)
APK download size (estimated): 27 KiB (old), 27 KiB (new), 0 bytes (No change)

Configuration xhdpi

APK file size: 50 KiB (old), 50 KiB (new), 0 bytes (No change)
APK download size (estimated): 20 KiB (old), 20 KiB (new), 0 bytes (No change)

Configuration xxhdpi

APK file size: 55 KiB (old), 55 KiB (new), 0 bytes (No change)
APK download size (estimated): 28 KiB (old), 28 KiB (new), 0 bytes (No change)

Configuration xxxhdpi

APK file size: 55 KiB (old), 55 KiB (new), 0 bytes (No change)
APK download size (estimated): 27 KiB (old), 27 KiB (new), 0 bytes (No change)

The test file ForcedActivityLanguageModeTest.kt was added but the
corresponding BUILD.bazel file in the test directory was missing,
causing Bazel to fail with 'no such package' error during test discovery.

This commit adds the BUILD.bazel file with the necessary kt_jvm_test
target to make the test discoverable and runnable by Bazel.
@github-actions
Copy link
Copy Markdown

Coverage Report

Results

Number of files assessed: 15
Overall Coverage: 92.59%
Coverage Analysis: PASS

Passing coverage

Files with passing code coverage
File Coverage Lines Hit Status Min Required
RegexPatternValidationCheck.ktscripts/src/java/org/oppia/android/scripts/regex/RegexPatternValidationCheck.kt
100.00% 104 / 104 70%
BinaryFileCheck.ktscripts/src/java/org/oppia/android/scripts/binary/BinaryFileCheck.kt
90.38% 94 / 104 70%
TranslationController.ktdomain/src/main/java/org/oppia/android/domain/translation/TranslationController.kt
93.57% 160 / 171 70%
CurrentUserProfileIdIntentDecorator.ktutility/src/main/java/org/oppia/android/util/profile/CurrentUserProfileIdIntentDecorator.kt
100.00% 12 / 12 70%
ForcedActivityLanguageMode.ktapp/src/main/java/org/oppia/android/app/model/ForcedActivityLanguageMode.kt
100.00% 3 / 3 70%
AppLanguageWatcherMixin.ktapp/src/main/java/org/oppia/android/app/translation/AppLanguageWatcherMixin.kt
71.05% 27 / 38 70%

Exempted coverage

Files exempted from coverage
File Exemption Reason
TopicController.ktdomain/src/main/java/org/oppia/android/domain/topic/TopicController.kt
This file is incompatible with code coverage tooling; skipping coverage check.
InjectableSystemLocalizedAppCompatActivity.ktapp/src/main/java/org/oppia/android/app/activity/InjectableSystemLocalizedAppCompatActivity.kt
This file is exempted from having a test file; skipping coverage check.
InjectableEnglishOnlyAppCompatActivity.ktapp/src/main/java/org/oppia/android/app/activity/InjectableEnglishOnlyAppCompatActivity.kt
This file is exempted from having a test file; skipping coverage check.
InjectableAutoLocalizedAppCompatActivity.ktapp/src/main/java/org/oppia/android/app/activity/InjectableAutoLocalizedAppCompatActivity.kt
This file is exempted from having a test file; skipping coverage check.
PoliciesFragmentPresenter.ktapp/src/main/java/org/oppia/android/app/policies/PoliciesFragmentPresenter.kt
This file is exempted from having a test file; skipping coverage check.
PoliciesActivity.ktapp/src/main/java/org/oppia/android/app/policies/PoliciesActivity.kt
This file is incompatible with code coverage tooling; skipping coverage check.
MarkChaptersCompletedFragmentPresenter.ktapp/src/main/java/org/oppia/android/app/devoptions/markchapterscompleted/MarkChaptersCompletedFragmentPresenter.kt
This file is exempted from having a test file; skipping coverage check.
AudioLanguageFragment.ktapp/src/main/java/org/oppia/android/app/options/AudioLanguageFragment.kt
This file is incompatible with code coverage tooling; skipping coverage check.
AsyncResultSubject.kttesting/src/main/java/org/oppia/android/testing/data/AsyncResultSubject.kt
This file is incompatible with code coverage tooling; skipping coverage check.

Refer test_file_exemptions.textproto for the comprehensive list of file exemptions and their required coverage percentages.

To learn more, visit the Oppia Android Code Coverage wiki page

@nikhilkumarpanigrahi
Copy link
Copy Markdown
Contributor Author

Hi @subhajitxyz, all checks have passed now PTAL.

@oppiabot
Copy link
Copy Markdown

oppiabot bot commented Apr 10, 2026

Unassigning @nikhilkumarpanigrahi since a re-review was requested. @nikhilkumarpanigrahi, please make sure you have addressed all review comments. Thanks!

Copy link
Copy Markdown
Collaborator

@subhajitxyz subhajitxyz left a comment

Choose a reason for hiding this comment

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

I’ve taken a pass on this and left a few comments. @adhiamboperes , there are a few decisions(mentioned) I’m unsure about, so passing it to you for further review.

@@ -0,0 +1,13 @@
package org.oppia.android.app.model
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.

I am not sure about creating a new package for these enum. Simply, we can keep it into app/src/main/java/org/oppia/android/app/translation or inside AppLanguageWatcherMixin.kt file.
@adhiamboperes what's your thought on this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Moved ForcedActivityLanguageMode into the translation package so it stays with the locale-handling code and avoids introducing a separate app.modelpackage for a single enum.

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.

Thanks @nikhilkumarpanigrahi . But still Keeping this conversation open for @adhiamboperes 's suggestion.

textDirection = View.TEXT_DIRECTION_LTR
gravity = Gravity.START
}

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.

Do we need to declare explicitly layout direction for all English only activities?
I am not sure about whether this function in InjectableAppCompatActivity handles layout direction for all activities or not.
@adhiamboperes What's you thought on this ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removed the explicit layoutDirection override since InjectableAppCompatActivity already handles layout direction; kept textDirection and gravity to preserve the English-only policy formatting

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.

Thanks. I am not sure whether we still need to add these two. Could you please check and test on device after removing these?

deps = [
":injectable_app_compat_activity",
"//app/src/main/java/org/oppia/android/app/model:forced_activity_language_mode",
"//model/src/main/proto:languages_java_proto_lite",
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.

Remove this line.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removed the forced_activity_language_mode dependency because the enum now lives in the translation package.

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.

Thanks, also remove the proto.

deps = [
":injectable_app_compat_activity",
"//app/src/main/java/org/oppia/android/app/model:forced_activity_language_mode",
"//model/src/main/proto:languages_java_proto_lite",
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.

Remove.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removed the extra forced_activity_language_mode dependency here as well after relocating the enum.

deps = [
":injectable_app_compat_activity",
"//app/src/main/java/org/oppia/android/app/model:forced_activity_language_mode",
"//model/src/main/proto:languages_java_proto_lite",
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.

Remove.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removed the remaining forced_activity_language_mode dependency for the same reason, since the enum is now part of translation

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.

Remove the proto also.

"//app/src/main/java/org/oppia/android/app/model:forced_activity_language_mode",
"//domain/src/main/java/org/oppia/android/domain/profile:profile_management_controller",
"//domain/src/main/java/org/oppia/android/domain/translation:translation_controller",
"//model/src/main/proto:languages_java_proto_lite",
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.

Remove this line.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removed the now-unneeded forced_activity_language_mode dependency after moving the enum into the translation package.

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.

Also remove proto.

@github-actions
Copy link
Copy Markdown

Coverage Report

Results

Number of files assessed: 14
Overall Coverage: 92.59%
Coverage Analysis: PASS

Passing coverage

Files with passing code coverage
File Coverage Lines Hit Status Min Required
RegexPatternValidationCheck.ktscripts/src/java/org/oppia/android/scripts/regex/RegexPatternValidationCheck.kt
100.00% 104 / 104 70%
BinaryFileCheck.ktscripts/src/java/org/oppia/android/scripts/binary/BinaryFileCheck.kt
90.38% 94 / 104 70%
TranslationController.ktdomain/src/main/java/org/oppia/android/domain/translation/TranslationController.kt
93.57% 160 / 171 70%
CurrentUserProfileIdIntentDecorator.ktutility/src/main/java/org/oppia/android/util/profile/CurrentUserProfileIdIntentDecorator.kt
100.00% 12 / 12 70%
AppLanguageWatcherMixin.ktapp/src/main/java/org/oppia/android/app/translation/AppLanguageWatcherMixin.kt
73.17% 30 / 41 70%

Exempted coverage

Files exempted from coverage
File Exemption Reason
TopicController.ktdomain/src/main/java/org/oppia/android/domain/topic/TopicController.kt
This file is incompatible with code coverage tooling; skipping coverage check.
InjectableSystemLocalizedAppCompatActivity.ktapp/src/main/java/org/oppia/android/app/activity/InjectableSystemLocalizedAppCompatActivity.kt
This file is exempted from having a test file; skipping coverage check.
InjectableEnglishOnlyAppCompatActivity.ktapp/src/main/java/org/oppia/android/app/activity/InjectableEnglishOnlyAppCompatActivity.kt
This file is exempted from having a test file; skipping coverage check.
InjectableAutoLocalizedAppCompatActivity.ktapp/src/main/java/org/oppia/android/app/activity/InjectableAutoLocalizedAppCompatActivity.kt
This file is exempted from having a test file; skipping coverage check.
PoliciesFragmentPresenter.ktapp/src/main/java/org/oppia/android/app/policies/PoliciesFragmentPresenter.kt
This file is exempted from having a test file; skipping coverage check.
PoliciesActivity.ktapp/src/main/java/org/oppia/android/app/policies/PoliciesActivity.kt
This file is incompatible with code coverage tooling; skipping coverage check.
MarkChaptersCompletedFragmentPresenter.ktapp/src/main/java/org/oppia/android/app/devoptions/markchapterscompleted/MarkChaptersCompletedFragmentPresenter.kt
This file is exempted from having a test file; skipping coverage check.
AudioLanguageFragment.ktapp/src/main/java/org/oppia/android/app/options/AudioLanguageFragment.kt
This file is incompatible with code coverage tooling; skipping coverage check.
AsyncResultSubject.kttesting/src/main/java/org/oppia/android/testing/data/AsyncResultSubject.kt
This file is incompatible with code coverage tooling; skipping coverage check.

Refer test_file_exemptions.textproto for the comprehensive list of file exemptions and their required coverage percentages.

To learn more, visit the Oppia Android Code Coverage wiki page

@nikhilkumarpanigrahi
Copy link
Copy Markdown
Contributor Author

Hi @subhajitxyz! addressed all the comments and made the changes PTAL when you get a chance.

@subhajitxyz
Copy link
Copy Markdown
Collaborator

subhajitxyz commented Apr 10, 2026

Thanks @nikhilkumarpanigrahi , left few feedbacks. Please update PR description based on current approach.

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.

[BUG]: Terms of Service and Privacy Policy content should still be left-aligned, even if the app is in an RTL language.

5 participants