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

feat(android): add support for Android's API 33 Per-app languages #14120

Closed
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
import java.text.DateFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Locale;

import org.appcelerator.kroll.KrollDict;
import org.appcelerator.kroll.KrollModule;
import org.appcelerator.kroll.annotations.Kroll;
import org.appcelerator.kroll.common.Log;
Expand All @@ -21,8 +23,12 @@
import org.appcelerator.titanium.util.TiPlatformHelper;
import org.appcelerator.titanium.util.TiRHelper;

import android.os.Build;
import android.telephony.PhoneNumberUtils;

import androidx.appcompat.app.AppCompatDelegate;
import androidx.core.os.LocaleListCompat;

@Kroll.module
public class LocaleModule extends KrollModule
{
Expand All @@ -33,6 +39,62 @@ public LocaleModule()
super("Locale");
}

@Kroll.setProperty
public void setApplicationLocales(String locales)
{
if (Build.VERSION.SDK_INT < 33) {
Log.w(TAG, "This property is only supported on android API 33 and above.");
AbdullahFaqeir marked this conversation as resolved.
Show resolved Hide resolved
return;
}
LocaleListCompat appLocale = LocaleListCompat.forLanguageTags(locales);
AppCompatDelegate.setApplicationLocales(appLocale);
}

@Kroll.getProperty
public KrollDict[] getApplicationLocales()
Copy link
Collaborator

Choose a reason for hiding this comment

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

It is very uncommon to have different types for the getter and setter. And there is Ti.Locale.setLanguage already. So I would propose:

  • Use the new Android 33+ API in Ti.Locale.setLanguage(language)
  • Expose the getter as a new Titanium API (if there isn't one already to get language details - if so, update that one)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Seems like this PR is with no use so I'll close it

{
if (Build.VERSION.SDK_INT < 33) {
Log.w(TAG, "This property is only supported on android API 33 and above.");
AbdullahFaqeir marked this conversation as resolved.
Show resolved Hide resolved
return new KrollDict[0];
}
LocaleListCompat localeListCompat = AppCompatDelegate.getApplicationLocales();
int size = localeListCompat.size();
KrollDict[] locales = new KrollDict[size];
for (int i = 0; i < size; i++) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

The loop looks a bit "oldskool". Things to change:

  • Use a more modern loop technique, e.g. this one and append it a to an array instead of maintaining an index
  • Do not add all the logic in the null check. Instead, check for locale == null and continue early

Locale locale = localeListCompat.get(i);
if (locale != null) {
KrollDict localeObj = new KrollDict();
localeObj.put("country", locale.getCountry());
localeObj.put("iso3_country", locale.getISO3Country());
AbdullahFaqeir marked this conversation as resolved.
Show resolved Hide resolved
localeObj.put("display_country", locale.getDisplayCountry());
localeObj.put("language", locale.getLanguage());
localeObj.put("iso3_language", locale.getISO3Language());
localeObj.put("display_language", locale.getDisplayLanguage());
localeObj.put("variant", locale.getVariant());
localeObj.put("display_variant", locale.getDisplayVariant());
localeObj.put("script", locale.getScript());
localeObj.put("display_script", locale.getDisplayScript());
localeObj.put("display_name", locale.getDisplayName());
localeObj.put("language_tag", locale.toLanguageTag());
Character[] extensionKeys = new Character[locale.getExtensionKeys().size()];
String[] extensions = new String[locale.getExtensionKeys().size()];
Iterator<Character> extensionKeysSize = locale.getExtensionKeys().iterator();
int l = 0;
while (extensionKeysSize.hasNext()) {
extensionKeys[l] = extensionKeysSize.next();
extensions[l] = locale.getExtension(extensionKeys[l]);
l++;
}
localeObj.put("extension_keys", extensionKeys);
localeObj.put("extensions", extensions);
locales[i] = localeObj;
} else {
locales[i] = null;
}
}
return locales;
}

@Kroll.getProperty
public String getCurrentLanguage()
{
Expand Down
2 changes: 1 addition & 1 deletion android/templates/build/ti.constants.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

project.ext {
tiNdkVersion = '26.2.11394342'
tiAndroidXAppCompatLibVersion = '1.4.1'
tiAndroidXAppCompatLibVersion = '1.6.1'
AbdullahFaqeir marked this conversation as resolved.
Show resolved Hide resolved
tiAndroidXCoreLibVersion = '1.9.0'
tiAndroidXFragmentLibVersion = '1.5.7'
tiMaterialLibVersion = '1.6.1'
Expand Down
11 changes: 11 additions & 0 deletions apidoc/Titanium/Locale/Locale.yml
Original file line number Diff line number Diff line change
Expand Up @@ -235,3 +235,14 @@ properties:
sections of wikipedia for reference.
type: String
permission: read-only

- name: applicationLocales
summary: Update or retrieve Android's Per-app languages.
platforms: [android]
description: |
This property holds the values of Android's Per-app languages which is an array of defined Per-app languages,
if no languages defined, an empty array will be returned. You can set the value of it like this `en-US,en-GB,ar-SA`.
This property requires android API 33 and above.
AbdullahFaqeir marked this conversation as resolved.
Show resolved Hide resolved
See the [Android's Per-app languages](https://developer.android.com/guide/topics/resources/app-languages).
type: Array
Copy link
Collaborator

Choose a reason for hiding this comment

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

Add the array typings

Copy link
Contributor Author

Choose a reason for hiding this comment

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

can you please explain

Copy link
Collaborator

Choose a reason for hiding this comment

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

See the newer comments to split the API. But in general, you just have an array as the return value, but really it's Array<LocaleDetails> to document all properties. This should not just refer to the Android docs, as there may be newer properties in the future that are not exposed in Titanium, yet.

since: "12.6.0"
Loading