diff --git a/res/values/strings.xml b/res/values/strings.xml index eb8f75b4d62..c30524328e5 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -8042,15 +8042,15 @@ Change to alarms only indefinitely - - Change to alarms only for one minute until %2$s - Change to alarms only for %1$d minutes (until %2$s) - + {count, plural, + =1 {Change to alarms only for one minute until {time}} + other {Change to alarms only for # minutes (until {time})} + } - - Change to alarms only for one hour until %2$s - Change to alarms only for %1$d hours until %2$s - + {count, plural, + =1 {Change to alarms only for one hour until {time}} + other {Change to alarms only for # hours until {time}} + } Change to alarms only until %1$s @@ -8241,14 +8241,14 @@ An app can verify links to automatically open in the app. - - %d verified link - %d verified links - - - This link is verified and automatically opens in this app. - These links are verified and automatically open in this app. - + {count, plural, + =1 {# verified link} + other {# verified links} + } + {count, plural, + =1 {This link is verified and automatically opens in this app.} + other {These links are verified and automatically open in this app.} + } OK @@ -8260,10 +8260,10 @@ Cancel - - %d supported link - %d supported links - + {count, plural, + =1 {# supported link} + other {# supported links} + } Add @@ -8294,16 +8294,16 @@ %1$s / %2$s - - %d category turned off - %d categories turned off - + {count, plural, + =1 {# category turned off} + other {# categories turned off} + } - - %d additional permission - %d additional permissions - + {count, plural, + =1 {# additional permission} + other {# additional permissions} + } No permissions granted @@ -8324,10 +8324,10 @@ Unused apps - - %d unused app - %d unused apps - + {count, plural, + =1 {# unused app} + other {# unused apps} + } Unused app settings @@ -8382,10 +8382,10 @@ Don’t allow app to open links - - App claims to handle %d link - App claims to handle %d links - + {count, plural, + =1 {App claims to handle # link} + other {App claims to handle # links} + } App claims to handle following links: @@ -8645,10 +8645,10 @@ Memory used by apps - - 1 app used memory in the last %2$s - %1$d apps used memory in the last %2$s - + {count, plural, + =1 {1 app used memory in the last {time}} + other {# apps used memory in the last {time}} + } Frequency @@ -9037,10 +9037,10 @@ Other apps included in usage - - 1 app allowed to use unrestricted data when Data Saver is on - %1$d apps allowed to use unrestricted data when Data Saver is on - + {count, plural, + =1 {1 app allowed to use unrestricted data when Data Saver is on} + other {# apps allowed to use unrestricted data when Data Saver is on} + } Primary data @@ -9064,10 +9064,10 @@ No data in this date range - - %d day left - %d days left - + {count, plural, + =1 {# day left} + other {# days left} + } No time remaining diff --git a/src/com/android/settings/applications/HibernatedAppsPreferenceController.java b/src/com/android/settings/applications/HibernatedAppsPreferenceController.java index 879903e1027..eb6edb27314 100644 --- a/src/com/android/settings/applications/HibernatedAppsPreferenceController.java +++ b/src/com/android/settings/applications/HibernatedAppsPreferenceController.java @@ -21,6 +21,7 @@ import static android.provider.DeviceConfig.NAMESPACE_APP_HIBERNATION; import static com.android.settings.Utils.PROPERTY_APP_HIBERNATION_ENABLED; import android.content.Context; +import android.icu.text.MessageFormat; import android.permission.PermissionControllerManager; import android.provider.DeviceConfig; @@ -35,6 +36,9 @@ import com.android.settings.core.BasePreferenceController; import com.google.common.annotations.VisibleForTesting; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; import java.util.concurrent.Executor; /** @@ -67,9 +71,13 @@ public final class HibernatedAppsPreferenceController extends BasePreferenceCont @Override public CharSequence getSummary() { + MessageFormat msgFormat = new MessageFormat( + mContext.getResources().getString(R.string.unused_apps_summary), + Locale.getDefault()); + Map arguments = new HashMap<>(); + arguments.put("count", mUnusedCount); return mLoadedUnusedCount - ? mContext.getResources().getQuantityString( - R.plurals.unused_apps_summary, mUnusedCount, mUnusedCount) + ? msgFormat.format(arguments) : mContext.getResources().getString(R.string.summary_placeholder); } diff --git a/src/com/android/settings/applications/OpenSupportedLinks.java b/src/com/android/settings/applications/OpenSupportedLinks.java index c4e478cefcb..2606a6cbca3 100644 --- a/src/com/android/settings/applications/OpenSupportedLinks.java +++ b/src/com/android/settings/applications/OpenSupportedLinks.java @@ -21,6 +21,7 @@ import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATIO import android.app.settings.SettingsEnums; import android.content.pm.PackageManager; +import android.icu.text.MessageFormat; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; @@ -35,6 +36,9 @@ import com.android.settings.Utils; import com.android.settingslib.widget.FooterPreference; import com.android.settingslib.widget.SelectorWithWidgetPreference; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; import java.util.Set; /** @@ -89,10 +93,14 @@ public class OpenSupportedLinks extends AppInfoWithHeader implements mPreferenceCategory = findPreference(RADIO_GROUP_KEY); mAllowOpening = makeRadioPreference(KEY_LINK_OPEN_ALWAYS, R.string.app_link_open_always); final int entriesNo = getEntriesNo(); + MessageFormat msgFormat = new MessageFormat( + getResources().getString(R.string.app_link_open_always_summary), + Locale.getDefault()); + Map arguments = new HashMap<>(); + arguments.put("count", entriesNo); //This to avoid the summary line wrap mAllowOpening.setAppendixVisibility(View.GONE); - mAllowOpening.setSummary(getResources().getQuantityString( - R.plurals.app_link_open_always_summary, entriesNo, entriesNo)); + mAllowOpening.setSummary(msgFormat.format(arguments)); mAskEveryTime = makeRadioPreference(KEY_LINK_OPEN_ASK, R.string.app_link_open_ask); mNotAllowed = makeRadioPreference(KEY_LINK_OPEN_NEVER, R.string.app_link_open_never); diff --git a/src/com/android/settings/applications/ProcessStatsSummary.java b/src/com/android/settings/applications/ProcessStatsSummary.java index a9f4ade7043..4044794e719 100644 --- a/src/com/android/settings/applications/ProcessStatsSummary.java +++ b/src/com/android/settings/applications/ProcessStatsSummary.java @@ -17,6 +17,7 @@ package com.android.settings.applications; import android.app.settings.SettingsEnums; import android.content.Context; +import android.icu.text.MessageFormat; import android.os.Bundle; import android.text.format.Formatter; import android.text.format.Formatter.BytesResult; @@ -30,6 +31,10 @@ import com.android.settings.Utils; import com.android.settings.applications.ProcStatsData.MemInfo; import com.android.settings.core.SubSettingLauncher; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + public class ProcessStatsSummary extends ProcessStatsBase implements OnPreferenceClickListener { private static final String KEY_STATUS_HEADER = "status_header"; @@ -94,8 +99,12 @@ public class ProcessStatsSummary extends ProcessStatsBase implements OnPreferenc mFree.setSummary(freeString); String durationString = getString(sDurationLabels[mDurationIndex]); int numApps = mStatsManager.getEntries().size(); - mAppListPreference.setSummary(getResources().getQuantityString( - R.plurals.memory_usage_apps_summary, numApps, numApps, durationString)); + MessageFormat msgFormat = new MessageFormat( + getResources().getString(R.string.memory_usage_apps_summary), Locale.getDefault()); + Map arguments = new HashMap<>(); + arguments.put("count", numApps); + arguments.put("time", durationString); + mAppListPreference.setSummary(msgFormat.format(arguments)); } @Override diff --git a/src/com/android/settings/applications/appinfo/AppNotificationPreferenceController.java b/src/com/android/settings/applications/appinfo/AppNotificationPreferenceController.java index df0d3549965..0f483554322 100644 --- a/src/com/android/settings/applications/appinfo/AppNotificationPreferenceController.java +++ b/src/com/android/settings/applications/appinfo/AppNotificationPreferenceController.java @@ -19,6 +19,7 @@ package com.android.settings.applications.appinfo; import static com.android.settings.SettingsActivity.EXTRA_FRAGMENT_ARG_KEY; import android.content.Context; +import android.icu.text.MessageFormat; import android.os.Bundle; import androidx.preference.Preference; @@ -31,6 +32,10 @@ import com.android.settings.notification.app.AppNotificationSettings; import com.android.settingslib.applications.AppUtils; import com.android.settingslib.applications.ApplicationsState; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + public class AppNotificationPreferenceController extends AppInfoPreferenceControllerBase { private String mChannelId = null; @@ -103,10 +108,14 @@ public class AppNotificationPreferenceController extends AppInfoPreferenceContro if (appRow.blockedChannelCount == 0) { return NotificationBackend.getSentSummary(context, appRow.sentByApp, false); } + MessageFormat msgFormat = new MessageFormat( + context.getString(R.string.notifications_categories_off), + Locale.getDefault()); + Map arguments = new HashMap<>(); + arguments.put("count", appRow.blockedChannelCount); return context.getString(R.string.notifications_enabled_with_info, NotificationBackend.getSentSummary(context, appRow.sentByApp, false), - context.getResources().getQuantityString(R.plurals.notifications_categories_off, - appRow.blockedChannelCount, appRow.blockedChannelCount)); + msgFormat.format(arguments)); } } } diff --git a/src/com/android/settings/applications/appinfo/AppPermissionPreferenceController.java b/src/com/android/settings/applications/appinfo/AppPermissionPreferenceController.java index 047101d522c..b7069d9df7f 100644 --- a/src/com/android/settings/applications/appinfo/AppPermissionPreferenceController.java +++ b/src/com/android/settings/applications/appinfo/AppPermissionPreferenceController.java @@ -23,6 +23,7 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.Resources; import android.icu.text.ListFormatter; +import android.icu.text.MessageFormat; import android.util.Log; import androidx.annotation.VisibleForTesting; @@ -35,7 +36,10 @@ import com.android.settingslib.core.lifecycle.events.OnStart; import com.android.settingslib.core.lifecycle.events.OnStop; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Locale; +import java.util.Map; import java.util.Random; /** @@ -70,9 +74,12 @@ public class AppPermissionPreferenceController extends AppInfoPreferenceControll final ArrayList list = new ArrayList<>(grantedGroupLabels); if (additionalGrantedPermissionCount > 0) { // N additional permissions. - list.add(res.getQuantityString( - R.plurals.runtime_permissions_additional_count, - additionalGrantedPermissionCount, additionalGrantedPermissionCount)); + MessageFormat msgFormat = new MessageFormat( + res.getString(R.string.runtime_permissions_additional_count), + Locale.getDefault()); + Map arguments = new HashMap<>(); + arguments.put("count", additionalGrantedPermissionCount); + list.add(msgFormat.format(arguments)); } if (list.size() == 0) { summary = res.getString( diff --git a/src/com/android/settings/applications/intentpicker/AppLaunchSettings.java b/src/com/android/settings/applications/intentpicker/AppLaunchSettings.java index cd360007fcf..b1ab1cc51bf 100644 --- a/src/com/android/settings/applications/intentpicker/AppLaunchSettings.java +++ b/src/com/android/settings/applications/intentpicker/AppLaunchSettings.java @@ -28,6 +28,7 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.verify.domain.DomainVerificationManager; import android.content.pm.verify.domain.DomainVerificationUserState; +import android.icu.text.MessageFormat; import android.net.Uri; import android.os.Bundle; import android.util.ArraySet; @@ -52,7 +53,10 @@ import com.android.settingslib.widget.FooterPreference; import com.android.settingslib.widget.MainSwitchPreference; import com.android.settingslib.widget.OnMainSwitchChangeListener; +import java.util.HashMap; import java.util.List; +import java.util.Locale; +import java.util.Map; import java.util.Set; import java.util.UUID; @@ -287,13 +291,21 @@ public class AppLaunchSettings extends AppInfoBase implements @VisibleForTesting String getVerifiedLinksTitle(int linksNo) { - return getResources().getQuantityString( - R.plurals.app_launch_verified_links_title, linksNo, linksNo); + MessageFormat msgFormat = new MessageFormat( + getResources().getString(R.string.app_launch_verified_links_title), + Locale.getDefault()); + Map arguments = new HashMap<>(); + arguments.put("count", linksNo); + return msgFormat.format(arguments); } private String getVerifiedLinksMessage(int linksNo) { - return getResources().getQuantityString( - R.plurals.app_launch_verified_links_message, linksNo, linksNo); + MessageFormat msgFormat = new MessageFormat( + getResources().getString(R.string.app_launch_verified_links_message), + Locale.getDefault()); + Map arguments = new HashMap<>(); + arguments.put("count", linksNo); + return msgFormat.format(arguments); } /** Add selected links items */ diff --git a/src/com/android/settings/applications/intentpicker/SupportedLinksDialogFragment.java b/src/com/android/settings/applications/intentpicker/SupportedLinksDialogFragment.java index e67fa049155..cc1241d8898 100644 --- a/src/com/android/settings/applications/intentpicker/SupportedLinksDialogFragment.java +++ b/src/com/android/settings/applications/intentpicker/SupportedLinksDialogFragment.java @@ -22,6 +22,7 @@ import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.verify.domain.DomainVerificationManager; import android.content.pm.verify.domain.DomainVerificationUserState; +import android.icu.text.MessageFormat; import android.os.Bundle; import android.util.ArraySet; import android.util.Log; @@ -34,7 +35,10 @@ import androidx.lifecycle.ViewModelProvider; import com.android.settings.R; import com.android.settings.core.instrumentation.InstrumentedDialogFragment; +import java.util.HashMap; import java.util.List; +import java.util.Locale; +import java.util.Map; import java.util.Set; import java.util.UUID; @@ -84,8 +88,12 @@ public class SupportedLinksDialogFragment extends InstrumentedDialogFragment { private String getSupportedLinksTitle() { final int supportedLinksNo = mSupportedLinkWrapperList.size(); - return getResources().getQuantityString( - R.plurals.app_launch_supported_links_title, supportedLinksNo, supportedLinksNo); + MessageFormat msgFormat = new MessageFormat( + getResources().getString(R.string.app_launch_supported_links_title), + Locale.getDefault()); + Map arguments = new HashMap<>(); + arguments.put("count", supportedLinksNo); + return msgFormat.format(arguments); } private void doSelectedAction() { diff --git a/src/com/android/settings/datausage/DataSaverSummary.java b/src/com/android/settings/datausage/DataSaverSummary.java index 17299751501..9bd862aa219 100644 --- a/src/com/android/settings/datausage/DataSaverSummary.java +++ b/src/com/android/settings/datausage/DataSaverSummary.java @@ -17,6 +17,7 @@ package com.android.settings.datausage; import android.app.Application; import android.app.settings.SettingsEnums; import android.content.Context; +import android.icu.text.MessageFormat; import android.os.Bundle; import android.telephony.SubscriptionManager; import android.widget.Switch; @@ -38,6 +39,9 @@ import com.android.settingslib.search.SearchIndexable; import com.android.settingslib.widget.OnMainSwitchChangeListener; import java.util.ArrayList; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; @SearchIndexable public class DataSaverSummary extends SettingsPreferenceFragment @@ -207,8 +211,12 @@ public class DataSaverSummary extends SettingsPreferenceFragment count++; } } - mUnrestrictedAccess.setSummary(getResources().getQuantityString( - R.plurals.data_saver_unrestricted_summary, count, count)); + MessageFormat msgFormat = new MessageFormat( + getResources().getString(R.string.data_saver_unrestricted_summary), + Locale.getDefault()); + Map arguments = new HashMap<>(); + arguments.put("count", count); + mUnrestrictedAccess.setSummary(msgFormat.format(arguments)); } public static boolean isDataSaverVisible(Context context) { diff --git a/src/com/android/settings/datausage/DataUsageSummaryPreference.java b/src/com/android/settings/datausage/DataUsageSummaryPreference.java index b6e533b2f7f..86e01ed2688 100644 --- a/src/com/android/settings/datausage/DataUsageSummaryPreference.java +++ b/src/com/android/settings/datausage/DataUsageSummaryPreference.java @@ -21,6 +21,7 @@ import android.app.settings.SettingsEnums; import android.content.Context; import android.content.Intent; import android.graphics.Typeface; +import android.icu.text.MessageFormat; import android.net.ConnectivityManager; import android.net.NetworkTemplate; import android.os.Bundle; @@ -46,6 +47,9 @@ import com.android.settingslib.Utils; import com.android.settingslib.net.DataUsageController; import com.android.settingslib.utils.StringUtil; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; import java.util.Objects; import java.util.concurrent.TimeUnit; @@ -290,10 +294,14 @@ public class DataUsageSummaryPreference extends Preference { cycleTime.setText(getContext().getString(R.string.billing_cycle_none_left)); } else { int daysLeft = (int) (millisLeft / MILLIS_IN_A_DAY); + MessageFormat msgFormat = new MessageFormat( + getContext().getResources().getString(R.string.billing_cycle_days_left), + Locale.getDefault()); + Map arguments = new HashMap<>(); + arguments.put("count", daysLeft); cycleTime.setText(daysLeft < 1 ? getContext().getString(R.string.billing_cycle_less_than_one_day_left) - : getContext().getResources().getQuantityString( - R.plurals.billing_cycle_days_left, daysLeft, daysLeft)); + : msgFormat.format(arguments)); } } diff --git a/src/com/android/settings/notification/zen/ZenModeVoiceActivity.java b/src/com/android/settings/notification/zen/ZenModeVoiceActivity.java index e107fdc3e75..af937d56735 100644 --- a/src/com/android/settings/notification/zen/ZenModeVoiceActivity.java +++ b/src/com/android/settings/notification/zen/ZenModeVoiceActivity.java @@ -22,7 +22,7 @@ import static android.provider.Settings.EXTRA_DO_NOT_DISTURB_MODE_MINUTES; import android.app.NotificationManager; import android.content.Context; import android.content.Intent; -import android.content.res.Resources; +import android.icu.text.MessageFormat; import android.media.AudioManager; import android.os.UserHandle; import android.provider.Settings.Global; @@ -34,7 +34,9 @@ import android.util.Log; import com.android.settings.R; import com.android.settings.utils.VoiceSettingsActivity; +import java.util.HashMap; import java.util.Locale; +import java.util.Map; /** * Activity for modifying the Zen mode (Do not disturb) by voice @@ -87,16 +89,10 @@ public class ZenModeVoiceActivity extends VoiceSettingsActivity { */ private CharSequence getChangeSummary(int mode, int minutes) { int indefinite = -1; - int byMinute = -1; - int byHour = -1; - int byTime = -1; switch (mode) { case Global.ZEN_MODE_ALARMS: indefinite = R.string.zen_mode_summary_alarms_only_indefinite; - byMinute = R.plurals.zen_mode_summary_alarms_only_by_minute; - byHour = R.plurals.zen_mode_summary_alarms_only_by_hour; - byTime = R.string.zen_mode_summary_alarms_only_by_time; break; case Global.ZEN_MODE_OFF: indefinite = R.string.zen_mode_summary_always; @@ -111,15 +107,23 @@ public class ZenModeVoiceActivity extends VoiceSettingsActivity { String skeleton = DateFormat.is24HourFormat(this, UserHandle.myUserId()) ? "Hm" : "hma"; String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton); CharSequence formattedTime = DateFormat.format(pattern, time); - Resources res = getResources(); if (minutes < 60) { - return res.getQuantityString(byMinute, minutes, minutes, formattedTime); + return buildMessage(R.string.zen_mode_summary_alarms_only_by_minute, minutes, formattedTime); } else if (minutes % 60 != 0) { - return res.getString(byTime, formattedTime); + return getResources().getString(R.string.zen_mode_summary_alarms_only_by_time, formattedTime); } else { int hours = minutes / 60; - return res.getQuantityString(byHour, hours, hours, formattedTime); + return buildMessage(R.string.zen_mode_summary_alarms_only_by_hour, hours, formattedTime); } } + + private CharSequence buildMessage(int resId, int count, CharSequence formattedTime) { + MessageFormat msgFormat = new MessageFormat( + getResources().getString(resId), Locale.getDefault()); + Map arguments = new HashMap<>(); + arguments.put("count", count); + arguments.put("time", formattedTime); + return msgFormat.format(arguments); + } } diff --git a/src/com/android/settings/spa/app/appinfo/AppPermissionSummary.kt b/src/com/android/settings/spa/app/appinfo/AppPermissionSummary.kt index 58edee6a2cc..9b8b0fd83d3 100644 --- a/src/com/android/settings/spa/app/appinfo/AppPermissionSummary.kt +++ b/src/com/android/settings/spa/app/appinfo/AppPermissionSummary.kt @@ -24,6 +24,7 @@ import androidx.lifecycle.LiveData import com.android.settings.R import com.android.settingslib.applications.PermissionsSummaryHelper import com.android.settingslib.applications.PermissionsSummaryHelper.PermissionsResultCallback +import com.android.settingslib.spa.framework.util.formatString import com.android.settingslib.spaprivileged.framework.common.asUser import com.android.settingslib.spaprivileged.model.app.userHandle @@ -91,10 +92,9 @@ class AppPermissionSummaryLiveData( else -> { grantedGroupLabels + // N additional permissions. - context.resources.getQuantityString( - R.plurals.runtime_permissions_additional_count, - additionalGrantedPermissionCount, - additionalGrantedPermissionCount, + context.formatString( + R.string.runtime_permissions_additional_count, + "count" to additionalGrantedPermissionCount, ) } } diff --git a/tests/robotests/src/com/android/settings/applications/OpenSupportedLinksTest.java b/tests/robotests/src/com/android/settings/applications/OpenSupportedLinksTest.java index ea2c4ecf50d..7712ae81025 100644 --- a/tests/robotests/src/com/android/settings/applications/OpenSupportedLinksTest.java +++ b/tests/robotests/src/com/android/settings/applications/OpenSupportedLinksTest.java @@ -36,6 +36,7 @@ import android.util.ArraySet; import androidx.preference.Preference; import androidx.preference.PreferenceCategory; +import com.android.settings.R; import com.android.settings.testutils.shadow.ShadowUtils; import com.android.settingslib.widget.FooterPreference; @@ -144,8 +145,9 @@ public class OpenSupportedLinksTest { anyInt()); doReturn(mCategory).when(mSettings).findPreference(any(CharSequence.class)); doReturn(mResources).when(mSettings).getResources(); - when(mResources.getQuantityString(anyInt(), anyInt(), anyInt())).thenReturn(TEST_SUMMARY); doReturn(true).when(mCategory).addPreference(any(Preference.class)); + when(mResources.getString(R.string.app_link_open_always_summary)) + .thenReturn("App claims to handle # links"); } public static class TestFragment extends OpenSupportedLinks {