From 7ca8534b1b43541cc3d1e4fa909696b257851f8b Mon Sep 17 00:00:00 2001 From: Al-Mothafar Al-Hasan Date: Sun, 19 Jul 2026 03:04:41 +0300 Subject: [PATCH] i18n: localize legacy channel names/descriptions + ringtone "None" (#165) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The three oldest notification channels (critical/warning/full) had their names/descriptions hard-coded in English in NotificationService, so an Arabic user saw English rows in system Settings → Notifications. Move the six strings to resources with values-ar translations and wire them up. To make translated names reach *upgraded* installs (not just fresh ones), the channel helpers no longer early-return when the channel already exists: re-calling createNotificationChannel with the same ID updates only name/description/group (Android ignores importance/vibration/lights/sound), so the #153 versioning and user customizations are preserved. Renamed to createOrUpdateAlertChannel / createOrUpdateSilentChannel to match. Ringtone fallback summary now reuses the existing (previously orphaned) pref_ringtone_silent string instead of a hard-coded "None", matching the system picker's own "Silent" option. Debug-only literals in BatteryInsightsActivity are commented as deliberately untranslated so future i18n sweeps skip them knowingly. Co-Authored-By: Claude Opus 4.8 --- .../service/NotificationService.java | 51 ++++++++++--------- .../ui/BatteryInsightsActivity.java | 4 ++ .../ui/preference/RingtonePreference.java | 6 ++- app/src/main/res/values-ar/strings.xml | 8 +++ app/src/main/res/values/strings.xml | 9 ++++ 5 files changed, 53 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/com/almothafar/simplebatterynotifier/service/NotificationService.java b/app/src/main/java/com/almothafar/simplebatterynotifier/service/NotificationService.java index 6a7c6be..3879e42 100644 --- a/app/src/main/java/com/almothafar/simplebatterynotifier/service/NotificationService.java +++ b/app/src/main/java/com/almothafar/simplebatterynotifier/service/NotificationService.java @@ -654,49 +654,52 @@ private static void createNotificationChannels(final Context context) { final boolean vibrate = prefs.getBoolean(context.getString(R.string._pref_key_notifications_vibrate), true); final int version = alertChannelVersion(prefs); - createChannelIfNotExists(manager, versionedChannelId(CHANNEL_ID_CRITICAL, version), - "Battery Critical Alerts", "Critical battery level alerts", Color.RED, vibrate); - createChannelIfNotExists(manager, versionedChannelId(CHANNEL_ID_WARNING, version), - "Battery Warnings", "Battery warning notifications", Color.rgb(0xff, 0x66, 0x00), vibrate); - createChannelIfNotExists(manager, versionedChannelId(CHANNEL_ID_FULL, version), - "Battery Full", "Battery fully charged notifications", Color.GREEN, vibrate); - createChannelIfNotExists(manager, versionedChannelId(CHANNEL_ID_TEMPERATURE, version), + createOrUpdateAlertChannel(manager, versionedChannelId(CHANNEL_ID_CRITICAL, version), + context.getString(R.string.notification_critical_channel_name), + context.getString(R.string.notification_critical_channel_description), Color.RED, vibrate); + createOrUpdateAlertChannel(manager, versionedChannelId(CHANNEL_ID_WARNING, version), + context.getString(R.string.notification_warning_channel_name), + context.getString(R.string.notification_warning_channel_description), Color.rgb(0xff, 0x66, 0x00), vibrate); + createOrUpdateAlertChannel(manager, versionedChannelId(CHANNEL_ID_FULL, version), + context.getString(R.string.notification_full_channel_name), + context.getString(R.string.notification_full_channel_description), Color.GREEN, vibrate); + createOrUpdateAlertChannel(manager, versionedChannelId(CHANNEL_ID_TEMPERATURE, version), context.getString(R.string.notification_temperature_channel_name), context.getString(R.string.notification_temperature_channel_description), Color.RED, vibrate); - createChannelIfNotExists(manager, versionedChannelId(CHANNEL_ID_FAST_DRAIN, version), + createOrUpdateAlertChannel(manager, versionedChannelId(CHANNEL_ID_FAST_DRAIN, version), context.getString(R.string.notification_fast_drain_channel_name), context.getString(R.string.notification_fast_drain_channel_description), Color.rgb(0xff, 0x66, 0x00), vibrate); - createChannelIfNotExists(manager, versionedChannelId(CHANNEL_ID_SLOW_CHARGE, version), + createOrUpdateAlertChannel(manager, versionedChannelId(CHANNEL_ID_SLOW_CHARGE, version), context.getString(R.string.notification_slow_charge_channel_name), context.getString(R.string.notification_slow_charge_channel_description), Color.rgb(0xff, 0x66, 0x00), vibrate); - createSilentChannelIfNotExists(manager, CHANNEL_ID_STATUS, + createOrUpdateSilentChannel(manager, CHANNEL_ID_STATUS, context.getString(R.string.notification_status_channel_name), context.getString(R.string.notification_status_channel_description)); - createSilentChannelIfNotExists(manager, CHANNEL_ID_ALERTS_SILENT, + createOrUpdateSilentChannel(manager, CHANNEL_ID_ALERTS_SILENT, context.getString(R.string.notification_quiet_channel_name), context.getString(R.string.notification_quiet_channel_description)); } /** - * Create a low-importance, fully silent channel (no sound, vibration, lights or badge). + * Create a low-importance, fully silent channel (no sound, vibration, lights or badge), or update + * its name/description if it already exists. *

* Used both by the persistent status notification and, during the user's quiet hours, to deliver * an alert quietly so it stays visible without disturbing the user (issue #111). + *

+ * As with the alert channels, re-calling for an existing ID updates only name/description, so + * translated names reach upgraded installs (#165) without disturbing the silent behaviour. * * @param manager The NotificationManager * @param channelId The channel ID to create * @param name The channel name * @param description The channel description */ - private static void createSilentChannelIfNotExists( + private static void createOrUpdateSilentChannel( final NotificationManager manager, final String channelId, final String name, final String description) { - if (nonNull(manager.getNotificationChannel(channelId))) { - return; - } - final NotificationChannel channel = new NotificationChannel(channelId, name, NotificationManager.IMPORTANCE_LOW); channel.setDescription(description); channel.enableLights(false); @@ -707,7 +710,13 @@ private static void createSilentChannelIfNotExists( } /** - * Create a notification channel if it doesn't already exist + * Create an alert channel, or update its name/description if it already exists. + *

+ * Re-calling {@code createNotificationChannel} with an existing ID updates only the name, + * description and group — Android ignores importance, vibration, lights and sound so the user's + * (and the versioned #153) settings are preserved. This is how translated channel names reach + * upgraded installs, not just fresh ones (#165): the channel already exists, so we still + * re-apply the current locale's name and description. * * @param manager The NotificationManager * @param channelId The channel ID @@ -716,17 +725,13 @@ private static void createSilentChannelIfNotExists( * @param ledColor The LED color for notifications * @param vibrate Whether the channel should vibrate (from the user's Vibrate preference) */ - private static void createChannelIfNotExists( + private static void createOrUpdateAlertChannel( final NotificationManager manager, final String channelId, final String name, final String description, final int ledColor, final boolean vibrate) { - if (nonNull(manager.getNotificationChannel(channelId))) { - return; - } - final NotificationChannel channel = new NotificationChannel(channelId, name, NotificationManager.IMPORTANCE_HIGH); channel.setDescription(description); channel.enableLights(true); diff --git a/app/src/main/java/com/almothafar/simplebatterynotifier/ui/BatteryInsightsActivity.java b/app/src/main/java/com/almothafar/simplebatterynotifier/ui/BatteryInsightsActivity.java index 7d0d28e..2a3fb00 100644 --- a/app/src/main/java/com/almothafar/simplebatterynotifier/ui/BatteryInsightsActivity.java +++ b/app/src/main/java/com/almothafar/simplebatterynotifier/ui/BatteryInsightsActivity.java @@ -213,6 +213,8 @@ private void showDebugMenu() { return; } + // Debug-only strings: this block runs only in debuggable builds, so its literals are + // deliberately left untranslated (no values-ar). Skip them in i18n sweeps (#165). final String[] options = { "Show Debug Info", "Add 50 Test Cycles", @@ -388,6 +390,8 @@ private void lookUpBatteryModel() { * Resets all health tracking data, including the first-use date and real charge cycles. */ private void resetHealthData() { + // Reached only from the debuggable-only debug menu, so these literals are deliberately + // left untranslated (no values-ar). Skip them in i18n sweeps (#165). new MaterialAlertDialogBuilder(this) .setTitle("Reset ALL health data?") .setMessage("This deletes ALL tracked battery health data, including the first-use date " diff --git a/app/src/main/java/com/almothafar/simplebatterynotifier/ui/preference/RingtonePreference.java b/app/src/main/java/com/almothafar/simplebatterynotifier/ui/preference/RingtonePreference.java index 4b45e1d..47b6358 100644 --- a/app/src/main/java/com/almothafar/simplebatterynotifier/ui/preference/RingtonePreference.java +++ b/app/src/main/java/com/almothafar/simplebatterynotifier/ui/preference/RingtonePreference.java @@ -10,6 +10,8 @@ import android.util.Log; import androidx.preference.Preference; +import com.almothafar.simplebatterynotifier.R; + import static java.util.Objects.nonNull; /** @@ -203,7 +205,7 @@ private void updateSummary() { Log.e(TAG, "Error loading ringtone for " + currentRingtoneUri, e); } } - // Empty or null URI means no ringtone selected (silent/none) - setSummary("None"); + // Empty or null URI means no ringtone selected — matches the picker's own "Silent" option (#165) + setSummary(getContext().getString(R.string.pref_ringtone_silent)); } } diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index c17ea7c..9ea78ee 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -152,6 +152,14 @@ + + تنبيهات البطارية الحرجة + تنبيهات مستوى البطارية الحرج + تحذيرات البطارية + إشعارات تحذير البطارية + اكتمال شحن البطارية + إشعارات اكتمال شحن البطارية + حالة البطارية حالة البطارية المستمرة أثناء تفعيل المراقبة diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 14eac8b..108db80 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -129,6 +129,15 @@ You can unplug your charger now Charge complete — you can unplug now. Batteries age fastest when kept at 100%, so unplugging soon (and staying roughly between 20% and 80% day to day) helps the battery last longer. + + Battery Critical Alerts + Critical battery level alerts + Battery Warnings + Battery warning notifications + Battery Full + Battery fully charged notifications + Charging started