Commit c1f0e65c authored by Trevor Perrier's avatar Trevor Perrier Committed by Chromium LUCI CQ

[Android] Add app and target language to detailed language settings.

This CL enables selecting the app and translate target languages in
the new detailed language settings on Android.  This feature is all
behind a release flag.

Both settings preferences use the added LanguageItemPreference which
launches the existing AddLanguageFragment on tap to select a language.
Languages options in the AddLanguageFragment are filtered based on what
the language will be used for.

setTargetLanguage is added to the TranslateBridge.

The Advanced Settings section is implemented as an Expandable
Preference Group.  Currently the only preference that works in the
advanced section is the Target Language.

Screenshots can be found here: https://crbug.com/1127531#c5

Bug: 1127531
Change-Id: I18707df2e3736920d1e7a4102b55863b99eb21e3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2593923
Commit-Queue: Trevor  Perrier <perrier@chromium.org>
Reviewed-by: default avatarTheresa  <twellington@chromium.org>
Reviewed-by: default avatarNatalie Chouinard <chouinard@chromium.org>
Reviewed-by: default avatarMegan Jablonski <megjablon@chromium.org>
Cr-Commit-Position: refs/heads/master@{#842665}
parent f9b806e5
......@@ -752,8 +752,8 @@ chrome_java_sources = [
"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/DetailedLanguageListPreference.java",
"java/src/org/chromium/chrome/browser/language/settings/LanguageItem.java",
"java/src/org/chromium/chrome/browser/language/settings/LanguageItemPickerPreference.java",
"java/src/org/chromium/chrome/browser/language/settings/LanguageListBaseAdapter.java",
"java/src/org/chromium/chrome/browser/language/settings/LanguageListPreference.java",
"java/src/org/chromium/chrome/browser/language/settings/LanguageSettings.java",
......
......@@ -4,16 +4,47 @@
found in the LICENSE file. -->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<org.chromium.chrome.browser.language.settings.DetailedLanguageListPreference
android:key="preferred_languages"
android:layout="@layout/languages_preference"
android:widgetLayout="@layout/accept_languages_list" />
<PreferenceCategory
android:key="app_language_section"
android:order="1">
<org.chromium.components.browser_ui.settings.ChromeSwitchPreference
android:key="translate_switch"
android:summaryOn="@string/languages_offer_translate_switch"
android:summaryOff="@string/languages_offer_translate_switch" />
<org.chromium.chrome.browser.language.settings.LanguageItemPickerPreference
android:key="app_language_preference" />
</PreferenceCategory>
<PreferenceCategory
android:key="content_langauges_section"
android:title="@string/languages_content_title"
android:order="2"
app:allowDividerAbove="true">
<org.chromium.chrome.browser.language.settings.LanguageListPreference
android:key="content_languages_preference"
android:layout="@layout/languages_preference"
android:widgetLayout="@layout/accept_languages_list" />
</PreferenceCategory>
<PreferenceCategory
android:key="translation_settings_section"
android:order="3"
android:title="@string/languages_settings_title"
app:initialExpandedChildrenCount="1">
<org.chromium.components.browser_ui.settings.ChromeSwitchPreference
android:key="translate_switch"
android:summaryOn="@string/languages_send_translate_switch"
android:summaryOff="@string/languages_send_translate_switch" />
<org.chromium.chrome.browser.language.settings.LanguageItemPickerPreference
android:key="translate_settings_target_language"
android:title="@string/languages_settings_target"
app:allowDividerBelow="false" />
</PreferenceCategory>
</PreferenceScreen>
......@@ -30,6 +30,9 @@ public class AppLocaleUtils {
private static final String TAG = "AppLocale";
// Value of AppLocale preference when the system language is used.
public static final String SYSTEM_LANGUAGE_VALUE = null;
/**
* Return true if languageName is the same as the current application override
* language stored preference.
......@@ -45,7 +48,7 @@ public class AppLocaleUtils {
*/
public static String getAppLanguagePref() {
return SharedPreferencesManager.getInstance().readString(
ChromePreferenceKeys.APPLICATION_OVERRIDE_LANGUAGE, null);
ChromePreferenceKeys.APPLICATION_OVERRIDE_LANGUAGE, SYSTEM_LANGUAGE_VALUE);
}
/**
......@@ -58,7 +61,7 @@ public class AppLocaleUtils {
@SuppressWarnings("DefaultSharedPreferencesCheck")
protected static String getAppLanguagePrefStartUp(Context base) {
return PreferenceManager.getDefaultSharedPreferences(base).getString(
ChromePreferenceKeys.APPLICATION_OVERRIDE_LANGUAGE, null);
ChromePreferenceKeys.APPLICATION_OVERRIDE_LANGUAGE, SYSTEM_LANGUAGE_VALUE);
}
/**
......@@ -69,7 +72,7 @@ public class AppLocaleUtils {
SharedPreferencesManager.getInstance().writeString(
ChromePreferenceKeys.APPLICATION_OVERRIDE_LANGUAGE, languageName);
if (BundleUtils.isBundle()) {
ensureLaguageSplitInstalled(languageName);
ensureLanguageSplitInstalled(languageName);
}
}
......@@ -89,14 +92,14 @@ public class AppLocaleUtils {
}
/**
* For bundle builds ensure that the language split for languageName is download.
* For bundle builds ensure that the language split for languageName is downloaded.
*/
private static void ensureLaguageSplitInstalled(String languageName) {
private static void ensureLanguageSplitInstalled(String languageName) {
SplitInstallManager splitInstallManager =
SplitInstallManagerFactory.create(ContextUtils.getApplicationContext());
// TODO(perrier): check if languageName is already installed. https://crbug.com/1103806
if (languageName != null) {
if (!TextUtils.equals(languageName, SYSTEM_LANGUAGE_VALUE)) {
SplitInstallRequest installRequest =
SplitInstallRequest.newBuilder()
.addLanguage(Locale.forLanguageTag(languageName))
......
......@@ -24,6 +24,7 @@ import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.components.browser_ui.settings.SettingsUtils;
import java.util.ArrayList;
......@@ -35,7 +36,14 @@ import java.util.Locale;
* accept languages. There is a {@link SearchView} on its Actionbar to make a quick lookup.
*/
public class AddLanguageFragment extends Fragment {
static final String INTENT_NEW_ACCEPT_LANGUAGE = "AddLanguageFragment.NewLanguage";
// Intent key to pass selected language code from AddLanguageFragment.
static final String INTENT_SELECTED_LANGUAGE = "AddLanguageFragment.SelectedLanguages";
// Intent key to receive type of languages to populate fragment with.
static final String INTENT_LANGUAGE_OPTIONS = "AddLanguageFragment.LanguageOptions";
// Intent keys to select language options to use.
static final int LANGUAGE_OPTIONS_ACCEPT_LANGUAGES = 0; // Default
static final int LANGUAGE_OPTIONS_UI_LANGUAGES = 1;
static final int LANGUAGE_OPTIONS_TRANSLATE_LANGUAGES = 2;
/**
* A host to launch AddLanguageFragment and receive the result.
......@@ -97,7 +105,11 @@ public class AddLanguageFragment extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActivity().setTitle(R.string.add_language);
if (ChromeFeatureList.isEnabled(ChromeFeatureList.DETAILED_LANGUAGE_SETTINGS)) {
getActivity().setTitle(R.string.languages_select);
} else {
getActivity().setTitle(R.string.add_language);
}
setHasOptionsMenu(true);
LanguagesManager.recordImpression(
LanguagesManager.LanguageSettingsPageType.PAGE_ADD_LANGUAGE);
......@@ -117,10 +129,20 @@ public class AddLanguageFragment extends Fragment {
mRecyclerView.addItemDecoration(
new DividerItemDecoration(activity, layoutManager.getOrientation()));
mFullLanguageList = LanguagesManager.getInstance().getLanguageItemsExcludingUserAccept();
int languageOption = getActivity().getIntent().getIntExtra(
INTENT_LANGUAGE_OPTIONS, LANGUAGE_OPTIONS_ACCEPT_LANGUAGES);
if (languageOption == LANGUAGE_OPTIONS_UI_LANGUAGES) {
mFullLanguageList = LanguagesManager.getInstance().getAvailableUiLanguageItems();
mFullLanguageList.add(0, LanguageItem.makeSystemDefaultLanguageItem());
} else if (languageOption == LANGUAGE_OPTIONS_TRANSLATE_LANGUAGES) {
mFullLanguageList = LanguagesManager.getInstance().getTranslateLanguageItems();
} else {
mFullLanguageList =
LanguagesManager.getInstance().getLanguageItemsExcludingUserAccept();
}
mItemClickListener = item -> {
Intent intent = new Intent();
intent.putExtra(INTENT_NEW_ACCEPT_LANGUAGE, item.getCode());
intent.putExtra(INTENT_SELECTED_LANGUAGE, item.getCode());
activity.setResult(Activity.RESULT_OK, intent);
activity.finish();
};
......
// 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 static org.chromium.components.browser_ui.widget.listmenu.BasicListMenu.buildMenuListItem;
import static org.chromium.components.browser_ui.widget.listmenu.BasicListMenu.buildMenuListItemWithEndIcon;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.TextView;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
import androidx.recyclerview.widget.DividerItemDecoration;
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.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;
import org.chromium.components.browser_ui.widget.TintedDrawable;
import org.chromium.components.browser_ui.widget.listmenu.BasicListMenu;
import org.chromium.components.browser_ui.widget.listmenu.ListMenu;
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.
*/
public class DetailedLanguageListPreference extends Preference {
private static class LanguageListAdapter
extends LanguageListBaseAdapter implements LanguagesManager.AcceptLanguageObserver {
private final Context mContext;
LanguageListAdapter(Context context) {
super(context);
mContext = context;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
super.onBindViewHolder(holder, position);
final LanguageItem info = getItemByPosition(position);
showDragIndicatorInRow((LanguageRowViewHolder) holder);
ModelList menuItems = new ModelList();
// Show "Offer to translate" option if "Chrome Translate" is enabled.
if (UserPrefs.get(Profile.getLastUsedRegularProfile())
.getBoolean(Pref.OFFER_TRANSLATE_ENABLED)) {
// Set this row checked if the language is unblocked.
int endIconResId = TranslateBridge.isBlockedLanguage(info.getCode())
? 0
: R.drawable.ic_check_googblue_24dp;
ListItem item = buildMenuListItemWithEndIcon(
R.string.languages_item_option_offer_to_translate, 0, endIconResId,
info.isSupported());
item.model.set(
ListMenuItemProperties.TINT_COLOR_ID, R.color.default_icon_color_blue);
// Add checked icon at the end.
menuItems.add(item);
}
// Show "Use as language" and 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));
// Add some appropriate options for moving the language when the list is not
// draggable. E.g. in the accessibility mode.
if (!mDragStateDelegate.getDragEnabled()) {
// Add "Move to top" and "Move up" menu when it's not the first one.
if (position > 0) {
menuItems.add(buildMenuListItem(R.string.menu_item_move_to_top, 0, 0));
menuItems.add(buildMenuListItem(R.string.menu_item_move_up, 0, 0));
}
// Add "Move down" menu when it's not the last one.
if (position < (languageCount - 1)) {
menuItems.add(buildMenuListItem(R.string.menu_item_move_down, 0, 0));
}
}
ListMenu.Delegate delegate = (model) -> {
int textId = model.get(ListMenuItemProperties.TITLE_ID);
if (textId == R.string.languages_item_option_offer_to_translate) {
// Toggle current blocked state of this language.
boolean state = model.get(ListMenuItemProperties.END_ICON_ID) == 0;
TranslateBridge.setLanguageBlockedState(info.getCode(), !state);
LanguagesManager.recordAction(state
? LanguagesManager.LanguageSettingsActionType
.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);
} else if (textId == R.string.menu_item_move_up) {
LanguagesManager.getInstance().moveLanguagePosition(info.getCode(), -1, true);
} else if (textId == R.string.menu_item_move_down) {
LanguagesManager.getInstance().moveLanguagePosition(info.getCode(), 1, true);
} else if (textId == R.string.menu_item_move_to_top) {
LanguagesManager.getInstance().moveLanguagePosition(
info.getCode(), -position, true);
}
// Re-generate list items.
if (textId != R.string.remove) {
notifyDataSetChanged();
}
};
((LanguageRowViewHolder) holder)
.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()) {
enableDrag();
} else {
disableDrag();
}
setDisplayedLanguages(LanguagesManager.getInstance().getUserAcceptLanguageItems());
}
}
private TextView mAddLanguageButton;
private RecyclerView mRecyclerView;
private LanguageListAdapter mAdapter;
private AddLanguageFragment.Launcher mLauncher;
public DetailedLanguageListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
mAdapter = new LanguageListAdapter(context);
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
assert mLauncher != null;
mAddLanguageButton = (TextView) holder.findViewById(R.id.add_language);
mAddLanguageButton.setCompoundDrawablesRelativeWithIntrinsicBounds(
TintedDrawable.constructTintedDrawable(
getContext(), R.drawable.plus, R.color.default_control_color_active),
null, null, null);
mAddLanguageButton.setOnClickListener(view -> {
mLauncher.launchAddLanguage();
LanguagesManager.recordAction(
LanguagesManager.LanguageSettingsActionType.CLICK_ON_ADD_LANGUAGE);
});
mRecyclerView = (RecyclerView) holder.findViewById(R.id.language_list);
LinearLayoutManager layoutMangager = new LinearLayoutManager(getContext());
mRecyclerView.setLayoutManager(layoutMangager);
mRecyclerView.addItemDecoration(
new DividerItemDecoration(getContext(), layoutMangager.getOrientation()));
// We do not want the RecyclerView to be announced by screen readers every time
// the view is bound.
if (mRecyclerView.getAdapter() != mAdapter) {
mRecyclerView.setAdapter(mAdapter);
LanguagesManager.getInstance().setAcceptLanguageObserver(mAdapter);
// Initialize accept language list.
mAdapter.onDataUpdated();
}
}
/**
* Register a launcher for AddLanguageFragment. Preference's host fragment should call
* this in its onCreate().
*/
void registerActivityLauncher(AddLanguageFragment.Launcher launcher) {
mLauncher = launcher;
}
/**
* Notify LanguageListAdapter of pref changes to update list items.
*/
void notifyPrefChanged() {
mAdapter.onDataUpdated();
}
}
......@@ -4,6 +4,15 @@
package org.chromium.chrome.browser.language.settings;
import android.text.TextUtils;
import org.chromium.base.ContextUtils;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.language.AppLocaleUtils;
import org.chromium.chrome.browser.language.GlobalAppLocaleController;
import java.util.Locale;
/**
* Simple object representing the language item.
*/
......@@ -31,7 +40,11 @@ public class LanguageItem {
mDisplayName = displayName;
mNativeDisplayName = nativeDisplayName;
mSupportTranslate = supportTranslate;
mSupportAppUI = AvailableUiLanguages.isAvailable(mCode);
if (TextUtils.equals(code, AppLocaleUtils.SYSTEM_LANGUAGE_VALUE)) {
mSupportAppUI = true; // system language is a supported UI language
} else {
mSupportAppUI = AvailableUiLanguages.isAvailable(mCode);
}
}
/**
......@@ -68,4 +81,18 @@ public class LanguageItem {
public boolean isUISupported() {
return mSupportAppUI;
}
/**
* Create a LanguageItem representing the system default language.
* @return LanguageItem
*/
public static LanguageItem makeSystemDefaultLanguageItem() {
String displayName = ContextUtils.getApplicationContext().getResources().getString(
R.string.default_lang_subtitle);
String nativeName =
GlobalAppLocaleController.getInstance().getOriginalSystemLocale().getDisplayName(
Locale.getDefault());
return new LanguageItem(
AppLocaleUtils.SYSTEM_LANGUAGE_VALUE, displayName, nativeName, true);
}
}
// 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 android.content.Context;
import android.text.TextUtils;
import android.util.AttributeSet;
import org.chromium.chrome.browser.language.AppLocaleUtils;
import org.chromium.components.browser_ui.settings.ChromeBasePreference;
/**
* Chrome Preference that enables selecting a single LanguageItem.
*/
public class LanguageItemPickerPreference extends ChromeBasePreference {
private LanguageItem mLanguageItem;
private boolean mUseLanguageItemForTitle;
public LanguageItemPickerPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* Set the LanguageItem value.
* @param LanguageItem The LanguageItem to use for this preference
*/
public void setLanguageItem(LanguageItem languageItem) {
assert languageItem != null;
mLanguageItem = languageItem;
updateDisplay();
}
/**
* Set the LanguageItem value based on the string locale code. If null is used the system
* default language is set as the preference's LanguageItem
* @param String languageCode The iso639 languageCode for LanguageItem
*/
public void setLanguageItem(String languageCode) {
LanguageItem languageItem;
if (TextUtils.equals(languageCode, AppLocaleUtils.SYSTEM_LANGUAGE_VALUE)) {
languageItem = LanguageItem.makeSystemDefaultLanguageItem();
} else {
languageItem = LanguagesManager.getInstance().getLanguageItem(languageCode);
}
setLanguageItem(languageItem);
}
/**
* By default only the summary text is synced to the LanguageItem. Enabling this will make the
* preference title the display name and summary the native display name.
* @param boolean use
*/
public void useLanguageItemForTitle(boolean useForTitle) {
mUseLanguageItemForTitle = useForTitle;
updateDisplay();
}
/**
* Update the title and summary to display
*/
private void updateDisplay() {
if (mLanguageItem == null) {
return;
} else if (mUseLanguageItemForTitle) {
setTitle(mLanguageItem.getDisplayName());
setSummary(mLanguageItem.getNativeDisplayName());
} else {
setSummary(mLanguageItem.getDisplayName());
}
}
}
......@@ -10,15 +10,19 @@ import android.os.Bundle;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceFragmentCompat;
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.preferences.Pref;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate;
import org.chromium.chrome.browser.settings.SettingsLauncher;
import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
import org.chromium.chrome.browser.translate.TranslateBridge;
import org.chromium.components.browser_ui.settings.ChromeSwitchPreference;
import org.chromium.components.browser_ui.settings.SettingsUtils;
import org.chromium.components.prefs.PrefService;
......@@ -30,12 +34,22 @@ import org.chromium.components.user_prefs.UserPrefs;
*/
public class LanguageSettings
extends PreferenceFragmentCompat implements AddLanguageFragment.Launcher {
private static final int REQUEST_CODE_ADD_LANGUAGES = 1;
private static final int REQUEST_CODE_ADD_ACCEPT_LANGUAGE = 1;
private static final int REQUEST_CODE_CHANGE_APP_LANGUAGE = 2;
private static final int REQUEST_CODE_CHANGE_TARGET_LANGUAGE = 3;
// The keys for each preference shown on the languages page.
static final String APP_LANGUAGE_SECTION_KEY = "app_language_section";
static final String APP_LANGUAGE_PREFERENCE_KEY = "app_language_preference";
static final String PREFERRED_LANGUAGES_KEY = "preferred_languages";
static final String CONTENT_LANGUAGES_KEY = "content_languages_preference";
static final String TRANSLATE_SWITCH_KEY = "translate_switch";
static final String TARGET_LANGUAGE_KEY = "translate_settings_target_language";
static final String AUTOMATIC_LANGUAGES_KEY = "translate_settings_automatic_languages";
static final String NO_PROMPT_LANGUAGES_KEY = "translate_settings_no_prompt_languages";
static final String NO_PROMPT_SITES_KEY = "translate_settings_no_prompt_sites";
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
getActivity().setTitle(R.string.language_settings);
......@@ -50,12 +64,14 @@ public class LanguageSettings
LanguagesManager.recordImpression(LanguagesManager.LanguageSettingsPageType.PAGE_MAIN);
}
public void createDetailedPreferences(Bundle savedInstanceState, String rootKey) {
SettingsUtils.addPreferencesFromResource(this, R.xml.languages_detailed_preferences);
DetailedLanguageListPreference mLanguageListPref =
(DetailedLanguageListPreference) findPreference(PREFERRED_LANGUAGES_KEY);
/**
* Create the old language and translate settings page. Delete once no longer used.
*/
private void createBasicPreferences(Bundle savedInstanceState, String rootKey) {
SettingsUtils.addPreferencesFromResource(this, R.xml.languages_preferences);
LanguageListPreference mLanguageListPref =
(LanguageListPreference) findPreference(PREFERRED_LANGUAGES_KEY);
mLanguageListPref.registerActivityLauncher(this);
ChromeSwitchPreference translateSwitch =
......@@ -80,25 +96,63 @@ public class LanguageSettings
-> getPrefService().isManagedPreference(Pref.OFFER_TRANSLATE_ENABLED));
}
public void createBasicPreferences(Bundle savedInstanceState, String rootKey) {
SettingsUtils.addPreferencesFromResource(this, R.xml.languages_preferences);
/**
* Create the new language and translate settings page. With options to change the app language,
* translate target language, and detailed translate preferences.
*/
private void createDetailedPreferences(Bundle savedInstanceState, String rootKey) {
SettingsUtils.addPreferencesFromResource(this, R.xml.languages_detailed_preferences);
LanguageListPreference mLanguageListPref =
(LanguageListPreference) findPreference(PREFERRED_LANGUAGES_KEY);
setupAppLanguageSection();
LanguageListPreference mLanguageListPref =
(LanguageListPreference) findPreference(CONTENT_LANGUAGES_KEY);
mLanguageListPref.registerActivityLauncher(this);
setupTranslateSection(mLanguageListPref);
}
/**
* Setup the App Language section with a title and preference to choose the app language.
*/
private void setupAppLanguageSection() {
// Set title to include current app name.
PreferenceCategory mAppLanguageTitle =
(PreferenceCategory) findPreference(APP_LANGUAGE_SECTION_KEY);
String mAppName = BuildInfo.getInstance().hostPackageLabel;
mAppLanguageTitle.setTitle(getResources().getString(R.string.app_language_title, mAppName));
LanguageItemPickerPreference appLanguagePreference =
(LanguageItemPickerPreference) findPreference(APP_LANGUAGE_PREFERENCE_KEY);
appLanguagePreference.setLanguageItem(AppLocaleUtils.getAppLanguagePref());
appLanguagePreference.useLanguageItemForTitle(true);
setSelectLanguageLauncher(appLanguagePreference,
AddLanguageFragment.LANGUAGE_OPTIONS_UI_LANGUAGES,
REQUEST_CODE_CHANGE_APP_LANGUAGE);
}
/**
* Setup the translate preferences section. A switch preferences controls if translate is
* enabled/disabled and will hide all advanced settings when disabled.
* @param languageListPreference LanguageListPreference reference to update about state changes.
*/
private void setupTranslateSection(LanguageListPreference languageListPreference) {
ChromeSwitchPreference translateSwitch =
(ChromeSwitchPreference) findPreference(TRANSLATE_SWITCH_KEY);
boolean isTranslateEnabled = getPrefService().getBoolean(Pref.OFFER_TRANSLATE_ENABLED);
translateSwitch.setChecked(isTranslateEnabled);
// Get advanced section preference items
LanguageItemPickerPreference targetLanguagePreference =
(LanguageItemPickerPreference) findPreference(TARGET_LANGUAGE_KEY);
translateSwitch.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
boolean enabled = (boolean) newValue;
getPrefService().setBoolean(Pref.OFFER_TRANSLATE_ENABLED, enabled);
mLanguageListPref.notifyPrefChanged();
languageListPreference.notifyPrefChanged();
targetLanguagePreference.setVisible(enabled);
LanguagesManager.recordAction(enabled ? LanguagesManager.LanguageSettingsActionType
.ENABLE_TRANSLATE_GLOBALLY
: LanguagesManager.LanguageSettingsActionType
......@@ -108,6 +162,11 @@ public class LanguageSettings
});
translateSwitch.setManagedPreferenceDelegate((ChromeManagedPreferenceDelegate) preference
-> getPrefService().isManagedPreference(Pref.OFFER_TRANSLATE_ENABLED));
targetLanguagePreference.setLanguageItem(TranslateBridge.getTargetLanguage());
setSelectLanguageLauncher(targetLanguagePreference,
AddLanguageFragment.LANGUAGE_OPTIONS_TRANSLATE_LANGUAGES,
REQUEST_CODE_CHANGE_TARGET_LANGUAGE);
}
@Override
......@@ -119,21 +178,65 @@ public class LanguageSettings
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_ADD_LANGUAGES && resultCode == Activity.RESULT_OK) {
String code = data.getStringExtra(AddLanguageFragment.INTENT_NEW_ACCEPT_LANGUAGE);
if (requestCode == REQUEST_CODE_ADD_ACCEPT_LANGUAGE && resultCode == Activity.RESULT_OK) {
String code = data.getStringExtra(AddLanguageFragment.INTENT_SELECTED_LANGUAGE);
LanguagesManager.getInstance().addToAcceptLanguages(code);
LanguagesManager.recordAction(
LanguagesManager.LanguageSettingsActionType.LANGUAGE_ADDED);
} else if (requestCode == REQUEST_CODE_CHANGE_APP_LANGUAGE
&& resultCode == Activity.RESULT_OK) {
String code = data.getStringExtra(AddLanguageFragment.INTENT_SELECTED_LANGUAGE);
LanguageItemPickerPreference appLanguagePreference =
(LanguageItemPickerPreference) findPreference(APP_LANGUAGE_PREFERENCE_KEY);
appLanguagePreference.setLanguageItem(code);
AppLocaleUtils.setAppLanguagePref(code);
} else if (requestCode == REQUEST_CODE_CHANGE_TARGET_LANGUAGE
&& resultCode == Activity.RESULT_OK) {
String code = data.getStringExtra(AddLanguageFragment.INTENT_SELECTED_LANGUAGE);
LanguageItemPickerPreference targetLanguagePreference =
(LanguageItemPickerPreference) findPreference(TARGET_LANGUAGE_KEY);
targetLanguagePreference.setLanguageItem(code);
TranslateBridge.setDefaultTargetLanguage(code);
}
}
/**
* Overrides AddLanguageFragment.Launcher.launchAddLanguage to handle click events on the
* Add Language button inside the LanguageListPreference.
*/
@Override
public void launchAddLanguage() {
// Launch preference activity with AddLanguageFragment.
launchSelectLanguage(AddLanguageFragment.LANGUAGE_OPTIONS_ACCEPT_LANGUAGES,
REQUEST_CODE_ADD_ACCEPT_LANGUAGE);
}
/**
* Set preference's OnPreferenceClickListener to launch the Select Language Fragment.
* @param Preference preference The Preference to set listener on.
* @param int launchCode The language options code to filter selectable languages.
* @param int requestCode The code to return from the select language fragment with.
*/
private void setSelectLanguageLauncher(Preference preference, int launchCode, int requestCode) {
preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
launchSelectLanguage(launchCode, requestCode);
return true;
}
});
}
/**
* Launch the AddLanguageFragment with launch and request codes to select a single language.
* @param int launchCode The language options code to filter selectable languages.
* @param int requestCode The code to return from the select language fragment with.
*/
private void launchSelectLanguage(int launchCode, int requestCode) {
SettingsLauncher settingsLauncher = new SettingsLauncherImpl();
Intent intent = settingsLauncher.createSettingsActivityIntent(
getActivity(), AddLanguageFragment.class.getName());
startActivityForResult(intent, REQUEST_CODE_ADD_LANGUAGES);
intent.putExtra(AddLanguageFragment.INTENT_LANGUAGE_OPTIONS, launchCode);
startActivityForResult(intent, requestCode);
}
@VisibleForTesting
......
......@@ -6,6 +6,7 @@ package org.chromium.chrome.browser.language.settings;
import androidx.annotation.IntDef;
import org.chromium.base.LocaleUtils;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.chrome.browser.translate.TranslateBridge;
......@@ -123,6 +124,43 @@ public class LanguagesManager {
return results;
}
/**
* Get a list of LanguageItems that can be Chrome UI languages.
* @return List of LanguageItems.
*/
public List<LanguageItem> getAvailableUiLanguageItems() {
List<LanguageItem> results = new ArrayList<>();
for (LanguageItem item : mLanguagesMap.values()) {
if (item.isUISupported()) results.add(item);
}
return results;
}
/**
* Get a list of LanguageItems that are translatable.
* @return List of LanguageItems.
*/
public List<LanguageItem> getTranslateLanguageItems() {
List<LanguageItem> results = new ArrayList<>();
for (LanguageItem item : mLanguagesMap.values()) {
if (item.isSupported()) results.add(item);
}
return results;
}
/**
* Get a LanguageItem given the iso639 locale code (e.g. en-US). If no direct match is found
* only the language is checked. If there is still no match null is returned.
* @return LanguageItem or null if none found
*/
public LanguageItem getLanguageItem(String localeCode) {
LanguageItem result = mLanguagesMap.get(localeCode);
if (result != null) return result;
String baseLanguage = LocaleUtils.toLanguage(localeCode);
return mLanguagesMap.get(baseLanguage);
}
/**
* Add a language to the current user's accept languages.
* @param code The language code to remove.
......
......@@ -81,6 +81,14 @@ public class TranslateBridge {
return TranslateBridgeJni.get().getTargetLanguage();
}
/**
* Set the default target language the Translate Service will use.
* @param String targetLanguage Language code of new target language.
*/
public static void setDefaultTargetLanguage(String targetLanguage) {
TranslateBridgeJni.get().setDefaultTargetLanguage(targetLanguage);
}
/** @return whether the given string is blocked for translation. */
public static boolean isBlockedLanguage(String language) {
return TranslateBridgeJni.get().isBlockedLanguage(language);
......@@ -224,6 +232,7 @@ public class TranslateBridge {
String getOriginalLanguage(WebContents webContents);
String getCurrentLanguage(WebContents webContents);
String getTargetLanguage();
void setDefaultTargetLanguage(String targetLanguage);
boolean isBlockedLanguage(String language);
void getModelLanguages(LinkedHashSet<String> set);
void resetAcceptLanguages(String defaultLocale);
......
......@@ -184,6 +184,16 @@ JNI_TranslateBridge_GetTargetLanguage(JNIEnv* env) {
return j_target_language;
}
// Set the default target language to translate into for this user.
static void JNI_TranslateBridge_SetDefaultTargetLanguage(
JNIEnv* env,
const JavaParamRef<jstring>& j_target_language) {
std::unique_ptr<translate::TranslatePrefs> translate_prefs =
ChromeTranslateClient::CreateTranslatePrefs(GetPrefService());
std::string target_language(ConvertJavaStringToUTF8(env, j_target_language));
translate_prefs->SetRecentTargetLanguage(target_language);
}
// Determines whether the given language is blocked for translation.
static jboolean JNI_TranslateBridge_IsBlockedLanguage(
JNIEnv* env,
......
......@@ -1187,12 +1187,6 @@ Your Google account may have other forms of browsing history like searches and a
<message name="IDS_LANGUAGES_ITEM_OPTION_OFFER_TO_TRANSLATE" desc="Option in language item menu. User can click the 'Offer to translate' option to toggle whether they want Chrome to translate pages in this language. [CHAR-LIMIT=32]">
Offer to translate
</message>
<message name="IDS_LANGUAGES_SET_APPLICATION_LANGUAGE_PROMPT" desc="Option in language item menu. User can click the 'App Language' option to toggle whether or not the Chrome user interface should be displayed in this language. [CHAR-LIMIT=32]">
Use as Chrome’s language
</message>
<message name="IDS_LANGUAGES_SET_AS_APPLICATION_LANGUAGE" desc="Toast to display after selecting language to use for Chrome's user interface.">
<ph name="APP_NAME">%1$s<ex>Chrome</ex></ph> will use <ph name="language">%2$s<ex>Hindi</ex></ph> on restart.
</message>
<message name="IDS_LANGUAGES_EXPLICIT_ASK_TITLE" desc="Title of the dialog that explicitly asks the user which languages they can read.">
What languages do you read?
</message>
......
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