diff --git a/res/values/strings.xml b/res/values/strings.xml index d0ad58a0d80..51a581fb490 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -502,6 +502,9 @@ Your device will keep %s as a system language + + %1$s will replace %2$s in your preferred languages + Change system language to %s ? diff --git a/src/com/android/settings/localepicker/LocalePickerWithRegionActivity.java b/src/com/android/settings/localepicker/LocalePickerWithRegionActivity.java index 6069c43fd16..9f67251e6bb 100644 --- a/src/com/android/settings/localepicker/LocalePickerWithRegionActivity.java +++ b/src/com/android/settings/localepicker/LocalePickerWithRegionActivity.java @@ -28,6 +28,7 @@ import android.view.MenuItem; import android.window.OnBackInvokedCallback; import androidx.core.view.ViewCompat; +import androidx.fragment.app.FragmentManager; import com.android.internal.app.LocalePickerWithRegion; import com.android.internal.app.LocaleStore; @@ -49,10 +50,15 @@ public class LocalePickerWithRegionActivity extends SettingsBaseActivity private static final String TAG = LocalePickerWithRegionActivity.class.getSimpleName(); private static final String PARENT_FRAGMENT_NAME = "localeListEditor"; private static final String CHILD_FRAGMENT_NAME = "LocalePickerWithRegion"; - private static final int DIALOG_CHANGE_LOCALE_REGION = 1; + private static final int DIALOG_CHANGE_SYSTEM_LOCALE_REGION = 1; + private static final int DIALOG_CHANGE_PREFERRED_LOCALE_REGION = 2; private static final String ARG_DIALOG_TYPE = "arg_dialog_type"; private static final String ARG_TARGET_LOCALE = "arg_target_locale"; + private static final String ARG_REPLACED_TARGET_LOCALE = "arg_replaced_target_locale"; private static final String TAG_DIALOG_CHANGE_REGION = "dialog_change_region"; + private static final int DISPOSE = -1; + private static final int SHOW_DIALOG_FOR_SYSTEM_LANGUAGE = 0; + private static final int SHOW_DIALOG_FOR_PREFERRED_LANGUAGE = 1; private LocalePickerWithRegion mSelector; @@ -111,21 +117,67 @@ public class LocalePickerWithRegionActivity extends SettingsBaseActivity @Override public void onLocaleSelected(LocaleStore.LocaleInfo locale) { if (Flags.regionalPreferencesApiEnabled()) { - if (sameLanguageAndScript(locale.getLocale(), LocaleList.getDefault().get(0))) { - Bundle args = new Bundle(); - args.putInt(ARG_DIALOG_TYPE, DIALOG_CHANGE_LOCALE_REGION); - args.putSerializable(ARG_TARGET_LOCALE, locale); - RegionDialogFragment regionDialogFragment = RegionDialogFragment.newInstance(); - regionDialogFragment.setArguments(args); - regionDialogFragment.show(getSupportFragmentManager(), TAG_DIALOG_CHANGE_REGION); - } else { - dispose(locale); + int index = indexOfSameLanguageAndScript(locale.getLocale()); + switch(getDialogEvent(index)) { + case SHOW_DIALOG_FOR_SYSTEM_LANGUAGE: + showDialogForSystemLanguage(locale, getSupportFragmentManager()); + break; + case SHOW_DIALOG_FOR_PREFERRED_LANGUAGE: + Locale replacedLocale = LocaleList.getDefault().get(index); + showDialogForPreferredLanguage( + locale, replacedLocale, getSupportFragmentManager()); + break; + default: + dispose(locale); } } else { dispose(locale); } } + private static void showDialogForSystemLanguage( + LocaleStore.LocaleInfo locale, FragmentManager fragmentManager) { + Bundle args = new Bundle(); + args.putInt(ARG_DIALOG_TYPE, DIALOG_CHANGE_SYSTEM_LOCALE_REGION); + args.putSerializable(ARG_TARGET_LOCALE, locale); + RegionDialogFragment regionDialogFragment = RegionDialogFragment.newInstance(); + regionDialogFragment.setArguments(args); + regionDialogFragment.show(fragmentManager, TAG_DIALOG_CHANGE_REGION); + } + + private static void showDialogForPreferredLanguage( + LocaleStore.LocaleInfo locale, Locale replacedLocale, FragmentManager fragmentManager) { + Bundle args = new Bundle(); + args.putInt(ARG_DIALOG_TYPE, DIALOG_CHANGE_PREFERRED_LOCALE_REGION); + args.putSerializable(ARG_TARGET_LOCALE, locale); + args.putSerializable(ARG_REPLACED_TARGET_LOCALE, replacedLocale); + RegionDialogFragment regionDialogFragment = RegionDialogFragment.newInstance(); + regionDialogFragment.setArguments(args); + regionDialogFragment.show(fragmentManager, TAG_DIALOG_CHANGE_REGION); + } + + private static int getDialogEvent(int index) { + if (index == -1) { + return DISPOSE; + } + + return index == 0 + ? SHOW_DIALOG_FOR_SYSTEM_LANGUAGE + : SHOW_DIALOG_FOR_PREFERRED_LANGUAGE; + } + + private static int indexOfSameLanguageAndScript(Locale source) { + int index = -1; + LocaleList localeList = LocaleList.getDefault(); + for (int i = 0; i < localeList.size(); i++) { + Locale target = localeList.get(i); + if (sameLanguageAndScript(source, target)) { + index = i; + } + } + return index; + } + private static boolean sameLanguageAndScript(Locale source, Locale target) { String sourceLanguage = source.getLanguage(); String targetLanguage = target.getLanguage(); diff --git a/src/com/android/settings/regionalpreferences/RegionDialogFragment.java b/src/com/android/settings/regionalpreferences/RegionDialogFragment.java index 7bfc82801e6..df5c3ca54d9 100644 --- a/src/com/android/settings/regionalpreferences/RegionDialogFragment.java +++ b/src/com/android/settings/regionalpreferences/RegionDialogFragment.java @@ -47,9 +47,11 @@ import java.util.Set; */ public class RegionDialogFragment extends InstrumentedDialogFragment { private static final String TAG = "RegionDialogFragment"; - static final int DIALOG_CHANGE_LOCALE_REGION = 1; + static final int DIALOG_CHANGE_SYSTEM_LOCALE_REGION = 1; + static final int DIALOG_CHANGE_PREFERRED_LOCALE_REGION = 2; static final String ARG_DIALOG_TYPE = "arg_dialog_type"; static final String ARG_TARGET_LOCALE = "arg_target_locale"; + static final String ARG_REPLACED_TARGET_LOCALE = "arg_replaced_target_locale"; /** * Use this factory method to create a new instance of @@ -113,6 +115,7 @@ public class RegionDialogFragment extends InstrumentedDialogFragment { private final Context mContext; private final int mDialogType; private final LocaleStore.LocaleInfo mLocaleInfo; + private final Locale mReplacedLocale; private final MetricsFeatureProvider mMetricsFeatureProvider; RegionDialogController( @@ -121,23 +124,26 @@ public class RegionDialogFragment extends InstrumentedDialogFragment { Bundle arguments = dialogFragment.getArguments(); mDialogType = arguments.getInt(ARG_DIALOG_TYPE); mLocaleInfo = (LocaleStore.LocaleInfo) arguments.getSerializable(ARG_TARGET_LOCALE); + mReplacedLocale = (Locale) arguments.getSerializable(ARG_REPLACED_TARGET_LOCALE); mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider(); } @Override public void onClick(@NonNull DialogInterface dialog, int which) { - if (mDialogType == DIALOG_CHANGE_LOCALE_REGION) { + if (mDialogType == DIALOG_CHANGE_SYSTEM_LOCALE_REGION + || mDialogType == DIALOG_CHANGE_PREFERRED_LOCALE_REGION) { if (which == DialogInterface.BUTTON_POSITIVE) { updateRegion(mLocaleInfo.getLocale().toLanguageTag()); mMetricsFeatureProvider.action( mContext, SettingsEnums.ACTION_CHANGE_REGION_DIALOG_POSITIVE_BTN_CLICKED); - } - if (which == DialogInterface.BUTTON_NEGATIVE) { + // TODO: add new metrics for DIALOG_CHANGE_PREFERRED_LOCALE_REGION + } else { mMetricsFeatureProvider.action( mContext, SettingsEnums.ACTION_CHANGE_REGION_DIALOG_NEGATIVE_BTN_CLICKED); + // TODO: add new metrics for DIALOG_CHANGE_PREFERRED_LOCALE_REGION } dismiss(); if (getActivity() != null) { @@ -150,7 +156,7 @@ public class RegionDialogFragment extends InstrumentedDialogFragment { DialogContent getDialogContent() { DialogContent dialogContent = new DialogContent(); switch (mDialogType) { - case DIALOG_CHANGE_LOCALE_REGION: + case DIALOG_CHANGE_SYSTEM_LOCALE_REGION: dialogContent.mTitle = String.format(mContext.getString( R.string.title_change_system_region), mLocaleInfo.getLocale().getDisplayCountry()); @@ -161,6 +167,18 @@ public class RegionDialogFragment extends InstrumentedDialogFragment { R.string.button_label_confirmation_of_system_locale_change); dialogContent.mNegativeButton = mContext.getString(R.string.cancel); break; + case DIALOG_CHANGE_PREFERRED_LOCALE_REGION: + dialogContent.mTitle = String.format(mContext.getString( + R.string.title_change_system_region), + mLocaleInfo.getLocale().getDisplayCountry()); + dialogContent.mMessage = mContext.getString( + R.string.desc_notice_device_region_change_for_preferred_language, + mLocaleInfo.getFullNameNative(), + LocaleStore.getLocaleInfo(mReplacedLocale).getFullNameNative()); + dialogContent.mPositiveButton = mContext.getString( + R.string.button_label_confirmation_of_system_locale_change); + dialogContent.mNegativeButton = mContext.getString(R.string.cancel); + break; default: break; } @@ -168,10 +186,27 @@ public class RegionDialogFragment extends InstrumentedDialogFragment { } private void updateRegion(String selectedLanguageTag) { + Locale[] newLocales = getUpdatedLocales(Locale.forLanguageTag(selectedLanguageTag)); + LocalePicker.updateLocales(new LocaleList(newLocales)); + } + + private Locale[] getUpdatedLocales(Locale selectedLocale) { LocaleList localeList = LocaleList.getDefault(); + Locale[] newLocales = new Locale[localeList.size()]; + for (int i = 0; i < localeList.size(); i++) { + Locale target = localeList.get(i); + if (sameLanguageAndScript(selectedLocale, target)) { + newLocales[i] = appendLocaleExtension(selectedLocale); + } else { + newLocales[i] = localeList.get(i); + } + } + return newLocales; + } + + private Locale appendLocaleExtension(Locale selectedLocale) { Locale systemLocale = Locale.getDefault(); Set extensionKeys = systemLocale.getExtensionKeys(); - Locale selectedLocale = Locale.forLanguageTag(selectedLanguageTag); Locale.Builder builder = new Locale.Builder(); builder.setLocale(selectedLocale); if (!extensionKeys.isEmpty()) { @@ -179,13 +214,21 @@ public class RegionDialogFragment extends InstrumentedDialogFragment { builder.setExtension(extKey, systemLocale.getExtension(extKey)); } } - Locale newLocale = builder.build(); - Locale[] resultLocales = new Locale[localeList.size()]; - resultLocales[0] = newLocale; - for (int i = 1; i < localeList.size(); i++) { - resultLocales[i] = localeList.get(i); + return builder.build(); + } + + private static boolean sameLanguageAndScript(Locale source, Locale target) { + String sourceLanguage = source.getLanguage(); + String targetLanguage = target.getLanguage(); + String sourceLocaleScript = source.getScript(); + String targetLocaleScript = target.getScript(); + if (sourceLanguage.equals(targetLanguage)) { + if (!sourceLocaleScript.isEmpty() && !targetLocaleScript.isEmpty()) { + return sourceLocaleScript.equals(targetLocaleScript); + } + return true; } - LocalePicker.updateLocales(new LocaleList(resultLocales)); + return false; } @VisibleForTesting diff --git a/src/com/android/settings/regionalpreferences/RegionPickerBaseListPreferenceController.java b/src/com/android/settings/regionalpreferences/RegionPickerBaseListPreferenceController.java index c06c6695220..fc12d1baa3f 100644 --- a/src/com/android/settings/regionalpreferences/RegionPickerBaseListPreferenceController.java +++ b/src/com/android/settings/regionalpreferences/RegionPickerBaseListPreferenceController.java @@ -169,7 +169,7 @@ public abstract class RegionPickerBaseListPreferenceController extends BasePrefe mFragmentManager = mParent.getChildFragmentManager(); Bundle args = new Bundle(); args.putInt(RegionDialogFragment.ARG_DIALOG_TYPE, - RegionDialogFragment.DIALOG_CHANGE_LOCALE_REGION); + RegionDialogFragment.DIALOG_CHANGE_SYSTEM_LOCALE_REGION); args.putSerializable(RegionDialogFragment.ARG_TARGET_LOCALE, localeInfo); RegionDialogFragment regionDialogFragment = RegionDialogFragment.newInstance(); regionDialogFragment.setArguments(args);