Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android 13 per app language preferences #18363

Closed
wants to merge 7 commits into from

Conversation

ravishanker
Copy link
Contributor

@ravishanker ravishanker commented May 4, 2023

This PR adds Per-app language preferences introduced in Android 13 (API 33) level. Some of this work was done as part of HACK week, and was put on hold pending Android 13 upgrade. Since Android 13 upgrade is now complete, it is time to roll this out.

  • Let AndroidX handle the locale storage so that the user's preference persists
  • Provides migration for handing over storage to system

TODO:

Note
Potential improvements to handle separately

  • Auto generate locales_config.xml using release-toolkit when we download the list of locales from GlotPress. This can also be auto generated apparently with upcoming Android Studio Giraffe
  • Remove in-app language picker altogether, since this is backward compatible, and fixes all locale related issues
  • Probably need to upgrade Android Gradle Plugin from 7.2.1 to 7.3.1 or later in settings.gradle
  • Auto generate translations using ChatGPT. This could even be done in the AS itself with Studio Bot perhaps! That also means many more languages can be added on both WP / JP, potentially saving time, resources and money!!
System Settings App Settings
device-2022-09-16-114901.mp4
device-2022-09-16-114935.mp4

To test:

Test 1:

  • Build and run
  • Launch WordPress or Jetpack app on a device running Android 13
  • Now go to device Settings > System > Languages & Input > App Languages > Select (WP or JP)
  • Ensure WordPress or Jetpack app shows in *App Languages
  • Tap on the app. It should navigate to App Language selection screen

Test 2:

  • Build and run
  • Launch WordPress or Jetpack app on a device running Android 13
  • Settings > Apps > Select (WP or JP) > Language (scroll if required)
  • Tap on the Language option. It should navigate to App Language selection screen

Test 3:

  • Launch WordPress or Jetpack app on a device running Android 13
  • WordPress app / Jetpack app already have in app Language picker ( Me > App Settings > Interface Language)
  • Select another language
  • Ensure, the language change takes effect
  • Navigate to Settings > Apps > Select (WP or JP) > Language (scroll if required)
  • Tap on the Language option. It should navigate to App Language selection screen
  • Ensure, the language selected in in-app language picker also takes effect in System settings

Test 4:

  • Build and run
  • Launch WordPress or Jetpack app on a device/emulator running Android 12
  • Navigate to in app Language picker ( Me > App Settings > Interface Language)
  • Select another language
  • Ensure, the language change takes effect

Test 5:

  • Build and run
  • Launch WordPress or Jetpack app on a device/emulator running Android 12
  • Upgrade to Android 13
  • Navigate to in app Language picker ( Me > App Settings > Interface Language), Note language
  • Navigate to Settings > Apps > Select (WordPress app or Jetpack app) > Language (scroll if required)
  • Tap on the Language option. It should navigate to App Language selection screen, Note language
  • Ensure, the language selected in in-app language picker, and in Systems settings are same

To test:

Regression Notes

  1. Potential unintended areas of impact
    Language and Locale in some places

  2. What I did to test those areas of impact (or what existing automated tests I relied on)
    Tested various features and in both ways from in-app picker to system settings and vice versa

  3. What automated tests I added (or what prevented me from doing so)
    Existing unit tests

PR submission checklist:

  • I have completed the Regression Notes.
  • I have considered adding accessibility improvements for my changes.
  • I have considered if this change warrants user-facing release notes and have added them to RELEASE-NOTES.txt if necessary.

with localeConfig tag
the build system only includes language resource in the APK for these specified languages, preventing translated strings from being included from other libraries that might support languages that our app does not support
Update in app picker related when Language changed in System settings
Updates app locale from in app picker to System Settings
Let AndroidX handle the locale storage so that the user's preference persists.
@ravishanker ravishanker modified the milestones: 22.5, 22.6 May 24, 2023
@wpmobilebot
Copy link
Contributor

WordPress📲 You can test the changes from this Pull Request in WordPress by scanning the QR code below to install the corresponding build.
App NameWordPress WordPress
FlavorJalapeno
Build TypeDebug
Versionpr18363-4e144ce
Commit4e144ce
Direct Downloadwordpress-prototype-build-pr18363-4e144ce.apk
Note: Google Login is not supported on these builds.

@wpmobilebot
Copy link
Contributor

Jetpack📲 You can test the changes from this Pull Request in Jetpack by scanning the QR code below to install the corresponding build.
App NameJetpack Jetpack
FlavorJalapeno
Build TypeDebug
Versionpr18363-4e144ce
Commit4e144ce
Direct Downloadjetpack-prototype-build-pr18363-4e144ce.apk
Note: Google Login is not supported on these builds.

Copy link
Contributor

@AliSoftware AliSoftware left a comment

Choose a reason for hiding this comment

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

I don't feel knowledgeable enough in Android internals to review that part of the PR, so I'll let that to @ParaskP7 and other Android devs.

As for the tooling aspect:

1️⃣ Locale codes format discrepency

Running the bundle exec fastlane download_translations lane after this change will result in an error, because our check_declared_locales_consistency method will find discrepencies between the locales declared in resourceConfigurations and the ones declared in the fastlane/lanes/translations.rb's JP_APP_LOCALES constant used to tell what locales to download from GlotPress.

  • One of the reason for this discrepancy is that in the resourceConfigurations you added, you use the pt_BR syntax for locale codes, while in the Fastfile constant we use the pt-rBR syntax (because that value is used to know in which res/values-{code}/strings.xml file to write the downloaded translations into)
    • To be honest I'm not sure if your syntax (pt_BR) is valid in the context of resourceConfigurations, or if you should have used pt-rBR syntax for it to work as expected, or if both are supported and it doesn't matter to gradle.
    • If the right syntax is pt_BR (the one you used) and values like pt-rBR would not work in the context of resourceConfigurations field, then that means we've been doing it wrong for the jetpack flavor all that time (see line 213) 😱 and we'll need to fix jetpack's resourceConfigurations (and adjust the logic of the check_declared_locales_consistency code)
    • But if pt-rBR syntax works in the resourceConfigurations context, then I'd suggest to use that syntax instead so that we're consistent with the values-* folder names and so that check_declared_locales_consistency would not need fixing
  • Another reason for why check_declared_locales_consistency reports an issue is that there are indeed some locales in one place and not the other
    • In your resourceConfigurations, you included en_US, while in the Fastfile that's not a locale we download from GlotPress (in fact, that locale is not configured in GlotPress' WordPress project, because US English is considered to be the originals for the strings, not needing translations). Also, we don't have a values-en-rUS folder in src/main/res anyway — instead, US English is considered our base language living in values. Given all that, I think it's not necessary to include en-rUS (or en_US, whatever the syntax) locale in your resourceConfigurations for wordpress
    • There are inconsistencies around he/id used in the Fastfile vs iw/in used in resourceConfigurations. Those are legacy vs more modern locale codes for Hebrew and Indonesian, and this issue has already been discussed and addressed [in a recent separate PR]. To match how we dealt with this for Jetpack, we need to use he/id in resourceConfigurations (as those are the modern ones), and add in/iw separately (to highlight that they are legacy ones), like how it's done on lines 214-216 for jetpack
    • There's also an inconsistency between kmr used in Fastfile's constant (since the folder is values-kmr) vs km used in resourceConfigurations
    • Finally, the Fastfile also downloads the lv and uz locales from GlotPress (and we have the corresponding values-lv and values-uz folders in src/main/res) but those were not added to your resourceConfigurations list

⚠️ By the way, same question about the syntax in locales_config.xml, are we sure Android expects us to use the pt-BR syntax in that context vs pt-rBR or pt_BR? (open question; haven't checked the docs). Maybe it's ok, because it seems to be what's used in the available_languages.xml file too… but available_languages.xml is not an official file expected by Android (but instead just a regular string-array resource read/used by the java code of our custom language picker), so worth double-checking the case for locales_config.xml (boy those different formats for Android locales codes depending on contexts is so annoying!)

💡 Tip: How I figured out the differences To help me figure out the differences in the two lists, I made the following changes in the `check_declared_locales_consistency` method… which could actually be a good idea to commit while we're at it, to help for future debugging too:
        UI.user_error! <<~ERROR
          The list of `resourceConfigurations` declared in your `build.gradle` for the `#{app_flavor}` flavor
          does not match the list of locales we hardcoded in the `fastlane/lanes/localization.rb` for this app.

+          - In `build.gradle`'s `resourceConfigurations`:
+            #{resource_configs.inspect}`
+          - In `Fastfile`:
+            #{expected_locales.inspect}

          If you recently updated the hardcoded list of locales to include for this app, be sure to apply those
          changes in both places, to keep the Fastlane scripts consistent with the gradle configuration of your app.
        ERROR

Then, for testing purposes, I commented out the android_download_translations calls in the download_translations lane (so that this lane would only do the calls to check_declared_locales_consistency) and ran that download_translations lane to check if the consistency checks were happy.

2️⃣ Generate the locales_config.xml by code in Fastfile

This is to make sure it's always kept consistent with the list of locales we download from GlotPress and we include as resourceConfigurations, to avoid future discrepancies. I know that you mentioned in your PR description:

Potential improvements to handle separately

  • Auto generate locales_config.xml using release-toolkit when we download the list of locales from GlotPress. This can also be auto generated apparently with upcoming Android Studio Giraffe

And I agree that implementing it in release-toolkit can be kept for later. But I'd still advocate to quickly jot some simple code in the Fastfile to generate that XML (see 3️⃣ below for my take at such an implementation).
We can then keep for later the idea of migrating that code into a proper fastlane action in release-toolkit when we have the time, but in the meantime, but in the meantime having that simple code directly in the Fastfile is simple enough and will ensure we don't break the app for some locales later… without realizing it until after a long time.

3️⃣ Issue with the locales_config being common with WP and JP flavors

Finally, shouldn't we also add a locales_config.xml file for Jetpack in src/jetpack/res/xml, that would restrict the list to the smaller subset of locales supported by Jetpack?

⚠️ We'd also have to make sure that this src/jetpack/res/xml/locales_config.xml file would be used as an override of the src/main/res/xml/locales_config.xml for Jetpack, instead of having it merged with the locales declared in src/main/res/xml when compiling the jetpack flavor (which would result in Jetpack exposing more locales in the language switch that it actually supports).

So maybe that means also moving src/main/res/xml/locales_config.xml to src/wordpress/res/xml/locales_config.xml instead?

I've taken a stab at generating those with some ruby code from the Fastfile, and this could look like this:

def generate_locales_config_file(app_flavor:, locales_list: )
  locale_codes = locales_list.map { |l| l[:android].gsub('-r', '_') }
  # Support for legacy locale codes
  expected_locales << 'in' if expected_locales.include?('id')
  expected_locales << 'iw' if expected_locales.include?('he')

  doc = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
    xml.comment('Warning: Auto-generated file, do not edit.')
    xml.send(:'locale-config', 'xmlns:tools': 'http://schemas.android.com/tools') do
      locale_codes.each { |code| xml.locale('android:name': code.gsub('-r', '-')) }
    end
  end
  File.write(File.join(PROJECT_ROOT_FOLDER, 'WordPress', 'src', app_flavor.to_s, 'res', 'xml', 'locales_config.xml'), doc.to_xml)
end

Then we can call this generate_locales_config_file(app_flavor: …, locales_list: …) inside the download_translations lane each for WP and JP case, just after and with the same parameters as when we call check_declared_locales_consistency(…) there.

@irfano irfano modified the milestones: 22.6, 22.7 Jun 12, 2023
@ravishanker ravishanker removed this from the 22.7 milestone Jun 19, 2023
@ravishanker ravishanker added this to the 22.8 milestone Jun 19, 2023
@ravishanker ravishanker modified the milestones: 22.8, Future Jul 5, 2023
@ParaskP7
Copy link
Contributor

ParaskP7 commented Aug 2, 2023

👋 @ravishanker !

I am not sure what's the latest status on this, but I just wanted to let you know now that we've merged AGP 8.1.0 into trunk, you can configure the app to support per-app language preferences automatically.

For more info see: Automatic per-app language support

@ParaskP7
Copy link
Contributor

👋 @ravishanker !

FYI: I'll unassign myself from this PR, just so that it gets removed from my Review requests list. Feel free to assign me again on it when you progress it a bit further.

@ParaskP7 ParaskP7 removed their request for review August 17, 2023 07:18
@ravishanker
Copy link
Contributor Author

Thank you all for your input. I'll attempt to do this afresh later given some more developments in this space like Android Studio Giraffe

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants