From 83aee4a084161e4e1b24c2706867c22c8a439e57 Mon Sep 17 00:00:00 2001 From: Michelle Tang Date: Fri, 24 Jan 2025 10:46:46 -0500 Subject: [PATCH] Pluralize time strings. --- .../jobs/NewLinkedDeviceNotificationJob.kt | 2 +- .../securesms/megaphone/Megaphones.java | 2 +- .../thoughtcrime/securesms/util/DateUtils.kt | 33 +++++++++++++++++-- app/src/main/res/values/strings.xml | 18 +++++++--- 4 files changed, 45 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/NewLinkedDeviceNotificationJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/NewLinkedDeviceNotificationJob.kt index 7590a3e08e..952efe4750 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/NewLinkedDeviceNotificationJob.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/NewLinkedDeviceNotificationJob.kt @@ -74,7 +74,7 @@ class NewLinkedDeviceNotificationJob private constructor( val builder = NotificationCompat.Builder(context, NotificationChannels.getInstance().NEW_LINKED_DEVICE) .setSmallIcon(R.drawable.ic_notification) .setContentTitle(context.getString(R.string.NewLinkedDeviceNotification__you_linked_new_device)) - .setContentText(context.getString(R.string.NewLinkedDeviceNotification__a_new_device_was_linked, DateUtils.getOnlyTimeString(context, data.deviceCreatedAt))) + .setContentText(context.getString(R.string.NewLinkedDeviceNotification__a_new_device_was_linked, DateUtils.getOnlyTimeAtString(context, data.deviceCreatedAt))) .setContentIntent(pendingIntent) ServiceUtil.getNotificationManager(context).notify(NotificationIds.NEW_LINKED_DEVICE, builder.build()) diff --git a/app/src/main/java/org/thoughtcrime/securesms/megaphone/Megaphones.java b/app/src/main/java/org/thoughtcrime/securesms/megaphone/Megaphones.java index 9afa7e026b..42141c3228 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/megaphone/Megaphones.java +++ b/app/src/main/java/org/thoughtcrime/securesms/megaphone/Megaphones.java @@ -299,7 +299,7 @@ public final class Megaphones { } private static @NonNull Megaphone buildNewLinkedDeviceMegaphone(@NonNull Context context) { - String createdAt = DateUtils.getOnlyTimeString(context, SignalStore.misc().getNewLinkedDeviceCreatedTime()); + String createdAt = DateUtils.getOnlyTimeAtString(context, SignalStore.misc().getNewLinkedDeviceCreatedTime()); return new Megaphone.Builder(Event.NEW_LINKED_DEVICE, Megaphone.Style.BASIC) .setTitle(R.string.NewLinkedDeviceNotification__you_linked_new_device) .setBody(context.getString(R.string.NewLinkedDeviceMegaphone__a_new_device_was_linked, createdAt)) diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/DateUtils.kt b/app/src/main/java/org/thoughtcrime/securesms/util/DateUtils.kt index 13683604b0..f46b0c5b44 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/DateUtils.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/util/DateUtils.kt @@ -26,6 +26,7 @@ import org.thoughtcrime.securesms.conversation.v2.computed.FormattedDate import java.text.DateFormatSymbols import java.text.ParseException import java.text.SimpleDateFormat +import java.util.Calendar import java.util.Date import java.util.Locale import java.util.concurrent.TimeUnit @@ -182,14 +183,30 @@ object DateUtils : android.text.format.DateUtils() { } /** - * Formats the timestamp as a date, without the year, followed by the time - * eg. Jan 15 at 9:00pm + * Given a timestamp, formats as "at time". + * Pluralization allows for Romance languages to be translated correctly + * eg. at 7:23pm, at 13:20 + */ + @JvmStatic + fun getOnlyTimeAtString(context: Context, timestamp: Long): String { + val time = timestamp.toLocalTime().formatHours(context) + val hour = getHour(context, timestamp) + + return context.resources.getQuantityString(R.plurals.DateUtils_time_at, hour, time) + } + + /** + * Formats the timestamp as a date, without the year, followed by the time. + * Pluralization allows for Romance languages to be translated correctly + * eg. on Jan 15 at 9:00pm */ @JvmStatic fun getDateTimeString(context: Context, locale: Locale, timestamp: Long): String { val date = timestamp.toDateString("MMM d", locale) val time = timestamp.toLocalTime().formatHours(context) - return context.getString(R.string.DateUtils_date_at, date, time) + val hour = getHour(context, timestamp) + + return context.resources.getQuantityString(R.plurals.DateUtils_date_time_at, hour, date, time) } /** @@ -363,6 +380,16 @@ object DateUtils : android.text.format.DateUtils() { return isToday(time + TimeUnit.DAYS.toMillis(1)) } + private fun getHour(context: Context, timestamp: Long): Int { + val cal = Calendar.getInstance(Locale.getDefault()) + cal.timeInMillis = timestamp + return if (context.is24HourFormat()) { + cal[Calendar.HOUR_OF_DAY] + } else { + cal[Calendar.HOUR] + } + } + private fun Context.is24HourFormat(): Boolean { is24HourDateCache?.let { if (it.lastUpdated.isWithin(10.seconds)) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c20bbcaf6f..9af9501e46 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -927,8 +927,16 @@ Tomorrow Tonight - - %1$s at %2$s + + + on %1$s at %2$s + on %1$s at %2$s + + + + at %1$s + at %1$s + @@ -1037,7 +1045,7 @@ Device unlinked - The device that was linked on %1$s is no longer linked. + The device that was linked %1$s is no longer linked. OK @@ -1088,7 +1096,7 @@ You linked a new device - A new device was linked to your account at %1$s. Tap to view. + A new device was linked to your account %1$s. Tap to view. Unlink \"%s\"? @@ -1684,7 +1692,7 @@ Add a profile photo - A new device was linked to your account at %1$s. + A new device was linked to your account %1$s. View device