Commit eeddc5af authored by Trevor Perrier's avatar Trevor Perrier Committed by Commit Bot

[Android] Add language decouple UI

This is the last of four CLs for the Clank language decouple.

It adds UI to the Language settings that allows users to set an
application specific language.

The UI is behind the flag DETAILED_LANGUAGE_SETTINGS.

Screenshot: https://bugs.chromium.org/p/chromium/issues/detail?id=1068667#c6
Bug: 1068667
Change-Id: Ie32a7efe66091a5072499bd886e1f9c8728e75e2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2355494
Commit-Queue: Trevor  Perrier <perrier@chromium.org>
Reviewed-by: default avatarMegan Jablonski <megjablon@chromium.org>
Reviewed-by: default avatarTheresa  <twellington@chromium.org>
Reviewed-by: default avatarLijin Shen <lazzzis@google.com>
Reviewed-by: default avatarAndrew Grieve <agrieve@chromium.org>
Reviewed-by: default avatarNatalie Chouinard <chouinard@chromium.org>
Cr-Commit-Position: refs/heads/master@{#805907}
parent b3f7ca84
......@@ -884,6 +884,7 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/language/GlobalAppLocaleController.java",
"java/src/org/chromium/chrome/browser/language/LanguageAskPrompt.java",
"java/src/org/chromium/chrome/browser/language/settings/AddLanguageFragment.java",
"java/src/org/chromium/chrome/browser/language/settings/AvailableUiLanguages.java",
"java/src/org/chromium/chrome/browser/language/settings/LanguageItem.java",
"java/src/org/chromium/chrome/browser/language/settings/LanguageListBaseAdapter.java",
"java/src/org/chromium/chrome/browser/language/settings/LanguageListPreference.java",
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.language.settings;
import org.chromium.base.BundleUtils;
import org.chromium.base.LocaleUtils;
import org.chromium.chrome.browser.ProductConfig;
import java.util.Arrays;
import java.util.Comparator;
/**
* Utility to determine if a language code is available as the UI language.
* Uses the lists from ProductConfig to stay in sync with compiled resources.
*/
public class AvailableUiLanguages {
private AvailableUiLanguages() {}
/**
* Get available language set from {@link ProductConfig}, which is a sorted
* array of language tags included in this build.
*/
private static String[] getLanguageList() {
if (BundleUtils.isBundle()) {
return ProductConfig.UNCOMPRESSED_LOCALES;
}
return ProductConfig.COMPRESSED_LOCALES;
}
/**
* Return true if the language is available as the UI language. This is used to disable
* the overflow option when selecting a UI language.
* @param language BCP-47 language tag representing a locale (e.g. "en-US")
*/
public static boolean isAvailable(String language) {
return Arrays.binarySearch(getLanguageList(), language, LANGUAGE_COMPARATOR) >= 0;
}
/**
* Comparator that removes any country or script information from either language tag
* since they are not needed for locale availability checks.
* Example: "es-MX" and "es-ES" will evaluate as equal.
*/
private static final Comparator<String> LANGUAGE_COMPARATOR = new Comparator<String>() {
@Override
public int compare(String a, String b) {
String langA = LocaleUtils.toLanguage(a);
String langB = LocaleUtils.toLanguage(b);
return langA.compareTo(langB);
}
};
}
......@@ -16,9 +16,11 @@ public class LanguageItem {
private final boolean mSupportTranslate;
private boolean mSupportAppUI;
/**
* Creates a new {@link LanguageItem}.
* @param code The string resource id for the text to show for this item.
* @param code The BCP-47 language tag for this language item.
* @param displayName The display name of the language in the current app locale.
* @param nativeDisplayName The display name of the language in the language's locale.
* @param supportTranslate Whether Chrome supports translate for this language.
......@@ -29,10 +31,11 @@ public class LanguageItem {
mDisplayName = displayName;
mNativeDisplayName = nativeDisplayName;
mSupportTranslate = supportTranslate;
mSupportAppUI = AvailableUiLanguages.isAvailable(mCode);
}
/**
* @return The ISO code of the language item.
* @return The BCP-47 language tag of the language item.
*/
public String getCode() {
return mCode;
......@@ -58,4 +61,11 @@ public class LanguageItem {
public boolean isSupported() {
return mSupportTranslate;
}
/**
* @return Whether this language supports the Chrome UI.
*/
public boolean isUISupported() {
return mSupportAppUI;
}
}
......@@ -18,7 +18,11 @@ import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
import org.chromium.base.BuildInfo;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.language.AppLocaleUtils;
import org.chromium.chrome.browser.language.GlobalAppLocaleController;
import org.chromium.chrome.browser.preferences.Pref;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.translate.TranslateBridge;
......@@ -29,6 +33,7 @@ import org.chromium.components.browser_ui.widget.listmenu.ListMenuItemProperties
import org.chromium.components.user_prefs.UserPrefs;
import org.chromium.ui.modelutil.MVCListAdapter.ListItem;
import org.chromium.ui.modelutil.MVCListAdapter.ModelList;
import org.chromium.ui.widget.Toast;
/**
* A preference that displays the current accept language list.
......@@ -69,6 +74,21 @@ public class LanguageListPreference extends Preference {
menuItems.add(item);
}
// Show "Use as language" option if "Change Application Language" is enabled.
if (ChromeFeatureList.isEnabled(ChromeFeatureList.DETAILED_LANGUAGE_SETTINGS)) {
// Mark as checked if current item is set as language pref.
int endIconResId = AppLocaleUtils.isAppLanguagePref(info.getCode())
? R.drawable.ic_check_googblue_24dp
: 0;
ListItem item = buildMenuListItemWithEndIcon(
R.string.languages_set_application_language_prompt, 0, endIconResId,
info.isUISupported());
item.model.set(
ListMenuItemProperties.TINT_COLOR_ID, R.color.default_icon_color_blue);
menuItems.add(item);
}
int languageCount = getItemCount();
// Enable "Remove" option if there are multiple accept languages.
menuItems.add(buildMenuListItem(R.string.remove, 0, 0, languageCount > 1));
......@@ -98,7 +118,13 @@ public class LanguageListPreference extends Preference {
.ENABLE_TRANSLATE_FOR_SINGLE_LANGUAGE
: LanguagesManager.LanguageSettingsActionType
.DISABLE_TRANSLATE_FOR_SINGLE_LANGUAGE);
} else if (textId == R.string.languages_set_application_language_prompt) {
updateOverrideLanguage(info);
} else if (textId == R.string.remove) {
// If the removed language is the override language reset UI to system language.
if (AppLocaleUtils.isAppLanguagePref(info.getCode())) {
resetOverrideLanguage();
}
LanguagesManager.getInstance().removeFromAcceptLanguages(info.getCode());
LanguagesManager.recordAction(
LanguagesManager.LanguageSettingsActionType.LANGUAGE_REMOVED);
......@@ -119,6 +145,37 @@ public class LanguageListPreference extends Preference {
.setMenuButtonDelegate(() -> new BasicListMenu(mContext, menuItems, delegate));
}
/**
* Updates the app language preference and shows Toast notifing user language
* will change after restart. If attempting to set the current app language pref
* instead reset override language to use system language.
* @param info LanguageItem to update application language to.
*/
private void updateOverrideLanguage(LanguageItem info) {
String newLanguageCode = info.getCode();
if (AppLocaleUtils.isAppLanguagePref(newLanguageCode)) {
resetOverrideLanguage();
return;
}
// Set the language preference value. The UI will not change until a full restart.
AppLocaleUtils.setAppLanguagePref(newLanguageCode);
showAppLanguageToast(info.getDisplayName());
}
private void resetOverrideLanguage() {
AppLocaleUtils.setAppLanguagePref(null);
showAppLanguageToast(GlobalAppLocaleController.getInstance()
.getOriginalSystemLocale()
.getDisplayName());
}
private void showAppLanguageToast(String languageName) {
String appName = BuildInfo.getInstance().hostPackageLabel;
String text = mContext.getString(
R.string.languages_set_as_application_language, appName, languageName);
Toast.makeText(mContext, text, Toast.LENGTH_LONG).show();
}
@Override
public void onDataUpdated() {
if (mDragStateDelegate.getDragActive()) {
......
......@@ -93,6 +93,7 @@ public class SettingsActivity extends ChromeBaseAppCompatActivity
@SuppressLint("InlinedApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
setTitle(R.string.settings);
ensureActivityNotExported();
// The browser process must be started here because this Activity may be started explicitly
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment