From 07b2924305066e39c271c67e04f2a20993639bc6 Mon Sep 17 00:00:00 2001 From: wellorbetter <1419919418@qq.com> Date: Wed, 25 Mar 2026 02:58:56 +0800 Subject: [PATCH 1/9] fix #289: add localized date format Use string resource for date format to adapt to different locales. --- .../main/kotlin/org/fossify/clock/extensions/Context.kt | 7 ++++++- app/src/main/res/values-ja/strings.xml | 1 + app/src/main/res/values-ko/strings.xml | 1 + app/src/main/res/values-zh-rCN/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 5 files changed, 10 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/org/fossify/clock/extensions/Context.kt b/app/src/main/kotlin/org/fossify/clock/extensions/Context.kt index de9312736..d0c16c328 100644 --- a/app/src/main/kotlin/org/fossify/clock/extensions/Context.kt +++ b/app/src/main/kotlin/org/fossify/clock/extensions/Context.kt @@ -113,7 +113,12 @@ fun Context.getFormattedDate(calendar: Calendar): String { val dayString = resources.getStringArray(org.fossify.commons.R.array.week_days_short)[dayOfWeek] val monthString = resources.getStringArray(org.fossify.commons.R.array.months)[month] - return "$dayString, $dayOfMonth $monthString" + + return formatDateString(monthString, dayOfMonth, dayString) +} + +private fun Context.formatDateString(month: String, day: Int, weekday: String): String { + return getString(R.string.date_format_md, weekday, day, month) } fun Context.getEditedTimeZonesMap(): HashMap { diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index db309b2a8..d7a71c01b 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -11,6 +11,7 @@ リマインダーの最大再生時間 時間切れ 時計と日付 + %1$s%2$d日(%3$s) 文字に影を付ける 右にスワイプして終了、または左にスワイプしてスヌーズ。 作成順 diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 2add7b783..bbf3b17e6 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -8,6 +8,7 @@ 알림 최대 지속시간 시간 만료 시계 및 날짜 + %1$s %2$d일 %3$s 텍스트 그림자 사용 생성된 순서 아날로그 시계 diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index f3e1ddc5a..dc74acab6 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -14,6 +14,7 @@ 最长提醒持续时间 时间结束 时钟和日期 + %1$s%2$d日 %3$s 使用文字阴影 向右滑动可关闭,向左滑动可暂停。 创建顺序 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b129f5c3c..754c1d41b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -14,6 +14,7 @@ Max reminder duration Time expired Clock and date + %1$s, %2$d %3$s Use text shadow Swipe right to Dismiss, or left to Snooze. Creation order From b6521a5a6e3617a19935735d3ccabfb6c770759c Mon Sep 17 00:00:00 2001 From: wellorbetter <1419919418@qq.com> Date: Wed, 25 Mar 2026 02:58:56 +0800 Subject: [PATCH 2/9] fix #289: add localized date format Use string resource for date format to adapt to different locales. --- .../main/kotlin/org/fossify/clock/extensions/Context.kt | 7 ++++++- app/src/main/res/values-ja/strings.xml | 1 + app/src/main/res/values-ko/strings.xml | 1 + app/src/main/res/values-zh-rCN/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 5 files changed, 10 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/org/fossify/clock/extensions/Context.kt b/app/src/main/kotlin/org/fossify/clock/extensions/Context.kt index de9312736..d0c16c328 100644 --- a/app/src/main/kotlin/org/fossify/clock/extensions/Context.kt +++ b/app/src/main/kotlin/org/fossify/clock/extensions/Context.kt @@ -113,7 +113,12 @@ fun Context.getFormattedDate(calendar: Calendar): String { val dayString = resources.getStringArray(org.fossify.commons.R.array.week_days_short)[dayOfWeek] val monthString = resources.getStringArray(org.fossify.commons.R.array.months)[month] - return "$dayString, $dayOfMonth $monthString" + + return formatDateString(monthString, dayOfMonth, dayString) +} + +private fun Context.formatDateString(month: String, day: Int, weekday: String): String { + return getString(R.string.date_format_md, weekday, day, month) } fun Context.getEditedTimeZonesMap(): HashMap { diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index db309b2a8..480f0958a 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -11,6 +11,7 @@ リマインダーの最大再生時間 時間切れ 時計と日付 + %3$s%2$d日(%1$s) 文字に影を付ける 右にスワイプして終了、または左にスワイプしてスヌーズ。 作成順 diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 2add7b783..f00d27f7e 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -8,6 +8,7 @@ 알림 최대 지속시간 시간 만료 시계 및 날짜 + %3$s %2$d일 %1$s 텍스트 그림자 사용 생성된 순서 아날로그 시계 diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index f3e1ddc5a..48f02b8b5 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -14,6 +14,7 @@ 最长提醒持续时间 时间结束 时钟和日期 + %3$s%2$d日 %1$s 使用文字阴影 向右滑动可关闭,向左滑动可暂停。 创建顺序 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b129f5c3c..754c1d41b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -14,6 +14,7 @@ Max reminder duration Time expired Clock and date + %1$s, %2$d %3$s Use text shadow Swipe right to Dismiss, or left to Snooze. Creation order From c81328a9f2ea2cdb846092280482112dc9b53d4a Mon Sep 17 00:00:00 2001 From: wellorbetter <1419919418@qq.com> Date: Wed, 25 Mar 2026 03:26:42 +0800 Subject: [PATCH 3/9] fix #289: add localized date format Use string resource for date format to adapt to different locales. Let main clock use this time format. --- .../main/kotlin/org/fossify/clock/fragments/ClockFragment.kt | 1 + app/src/main/res/layout/fragment_clock.xml | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/src/main/kotlin/org/fossify/clock/fragments/ClockFragment.kt b/app/src/main/kotlin/org/fossify/clock/fragments/ClockFragment.kt index 6e5985a46..f7ff54482 100644 --- a/app/src/main/kotlin/org/fossify/clock/fragments/ClockFragment.kt +++ b/app/src/main/kotlin/org/fossify/clock/fragments/ClockFragment.kt @@ -109,6 +109,7 @@ class ClockFragment : Fragment() { private fun updateDate() { calendar = Calendar.getInstance() val formattedDate = requireContext().getFormattedDate(calendar) + binding.clockDate.text = formattedDate (binding.timeZonesList.adapter as? TimeZonesAdapter)?.todayDateString = formattedDate } diff --git a/app/src/main/res/layout/fragment_clock.xml b/app/src/main/res/layout/fragment_clock.xml index b6affe50b..58c6066c7 100644 --- a/app/src/main/res/layout/fragment_clock.xml +++ b/app/src/main/res/layout/fragment_clock.xml @@ -28,13 +28,11 @@ android:textSize="@dimen/clock_text_size" tools:text="00:00:00" /> - From 15b65d56a706e9f2a5ecfc13df3a6f47e9cdc215 Mon Sep 17 00:00:00 2001 From: wellorbetter <1419919418@qq.com> Date: Wed, 25 Mar 2026 03:48:45 +0800 Subject: [PATCH 4/9] fix #289: add localized date format Use string resource for date format to adapt to different locales. Let main clock use this time format. --- .../org/fossify/clock/views/MyTextClock.kt | 25 ++++++++++++++++--- app/src/main/res/layout/fragment_clock.xml | 3 ++- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/app/src/main/kotlin/org/fossify/clock/views/MyTextClock.kt b/app/src/main/kotlin/org/fossify/clock/views/MyTextClock.kt index 63477eb73..c9ae1d313 100644 --- a/app/src/main/kotlin/org/fossify/clock/views/MyTextClock.kt +++ b/app/src/main/kotlin/org/fossify/clock/views/MyTextClock.kt @@ -7,9 +7,13 @@ import android.text.style.RelativeSizeSpan import android.util.AttributeSet import android.widget.TextClock import androidx.annotation.AttrRes +import org.fossify.clock.R import org.fossify.clock.extensions.config +import org.fossify.clock.extensions.getFormattedDate import org.fossify.commons.extensions.applyFontToTextView import java.text.DateFormatSymbols +import java.util.Calendar +import androidx.core.content.withStyledAttributes private const val AM_PM_SCALE = 0.4f @@ -19,9 +23,8 @@ class MyTextClock @JvmOverloads constructor( @AttrRes defStyleAttr: Int = android.R.attr.textViewStyle, ) : TextClock(context, attrs, defStyleAttr) { - init { - if (!isInEditMode) context.applyFontToTextView(this) - } + private var useLocalizedDateFormat = false + private var reenter = false private val amPmStrings by lazy { DateFormatSymbols.getInstance( @@ -29,7 +32,15 @@ class MyTextClock @JvmOverloads constructor( ).amPmStrings } - private var reenter = false + init { + if (!isInEditMode) context.applyFontToTextView(this) + + attrs?.let { + context.withStyledAttributes(it, R.styleable.MyTextClock, defStyleAttr, 0) { + useLocalizedDateFormat = getBoolean(R.styleable.MyTextClock_useLocalizedDateFormat, false) + } + } + } override fun setText(text: CharSequence?, type: BufferType?) { if (reenter) { @@ -37,6 +48,12 @@ class MyTextClock @JvmOverloads constructor( return } + if (useLocalizedDateFormat) { + val formattedDate = context.getFormattedDate(Calendar.getInstance()) + super.setText(formattedDate, type) + return + } + if (context.config.use24HourFormat || text.isNullOrEmpty()) { super.setText(text, type) return diff --git a/app/src/main/res/layout/fragment_clock.xml b/app/src/main/res/layout/fragment_clock.xml index 58c6066c7..6900a9ef1 100644 --- a/app/src/main/res/layout/fragment_clock.xml +++ b/app/src/main/res/layout/fragment_clock.xml @@ -28,13 +28,14 @@ android:textSize="@dimen/clock_text_size" tools:text="00:00:00" /> - Date: Wed, 25 Mar 2026 03:55:36 +0800 Subject: [PATCH 5/9] fix #289: add localized date format remove excessive editing --- app/src/main/kotlin/org/fossify/clock/fragments/ClockFragment.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/kotlin/org/fossify/clock/fragments/ClockFragment.kt b/app/src/main/kotlin/org/fossify/clock/fragments/ClockFragment.kt index f7ff54482..6e5985a46 100644 --- a/app/src/main/kotlin/org/fossify/clock/fragments/ClockFragment.kt +++ b/app/src/main/kotlin/org/fossify/clock/fragments/ClockFragment.kt @@ -109,7 +109,6 @@ class ClockFragment : Fragment() { private fun updateDate() { calendar = Calendar.getInstance() val formattedDate = requireContext().getFormattedDate(calendar) - binding.clockDate.text = formattedDate (binding.timeZonesList.adapter as? TimeZonesAdapter)?.todayDateString = formattedDate } From 9703335c1e529f725c442704629fd85b513c453a Mon Sep 17 00:00:00 2001 From: wellorbetter <1419919418@qq.com> Date: Wed, 25 Mar 2026 04:03:10 +0800 Subject: [PATCH 6/9] fix #289: add localized date format Adjust the position and modify the code to the minimum extent. --- .../org/fossify/clock/views/MyTextClock.kt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/app/src/main/kotlin/org/fossify/clock/views/MyTextClock.kt b/app/src/main/kotlin/org/fossify/clock/views/MyTextClock.kt index c9ae1d313..c70d0b983 100644 --- a/app/src/main/kotlin/org/fossify/clock/views/MyTextClock.kt +++ b/app/src/main/kotlin/org/fossify/clock/views/MyTextClock.kt @@ -23,15 +23,6 @@ class MyTextClock @JvmOverloads constructor( @AttrRes defStyleAttr: Int = android.R.attr.textViewStyle, ) : TextClock(context, attrs, defStyleAttr) { - private var useLocalizedDateFormat = false - private var reenter = false - - private val amPmStrings by lazy { - DateFormatSymbols.getInstance( - resources.configuration.locales[0] - ).amPmStrings - } - init { if (!isInEditMode) context.applyFontToTextView(this) @@ -42,6 +33,15 @@ class MyTextClock @JvmOverloads constructor( } } + private val amPmStrings by lazy { + DateFormatSymbols.getInstance( + resources.configuration.locales[0] + ).amPmStrings + } + + private var reenter = false + private var useLocalizedDateFormat = false + override fun setText(text: CharSequence?, type: BufferType?) { if (reenter) { super.setText(text, type) From dd86b5fa097d016735a52e16df5d73bbcbc1640e Mon Sep 17 00:00:00 2001 From: wellorbetter <1419919418@qq.com> Date: Wed, 25 Mar 2026 04:11:54 +0800 Subject: [PATCH 7/9] Add missing attrs.xml with useLocalizedDateFormat attribute --- app/src/main/res/values/attrs.xml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 app/src/main/res/values/attrs.xml diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml new file mode 100644 index 000000000..ccdc3bf4c --- /dev/null +++ b/app/src/main/res/values/attrs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file From 0e2a47bd7c73b6f8833541c75c7839ebcacd3f1c Mon Sep 17 00:00:00 2001 From: wellorbetter <1419919418@qq.com> Date: Wed, 25 Mar 2026 04:14:51 +0800 Subject: [PATCH 8/9] Refactor MyTextClock to reduce cyclomatic complexity --- .../org/fossify/clock/views/MyTextClock.kt | 69 ++++++++++--------- 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/app/src/main/kotlin/org/fossify/clock/views/MyTextClock.kt b/app/src/main/kotlin/org/fossify/clock/views/MyTextClock.kt index c70d0b983..f46a07c6b 100644 --- a/app/src/main/kotlin/org/fossify/clock/views/MyTextClock.kt +++ b/app/src/main/kotlin/org/fossify/clock/views/MyTextClock.kt @@ -59,46 +59,51 @@ class MyTextClock @JvmOverloads constructor( return } - val full = text.toString() - var amPmPosition = -1 - var amPmString: String? = null + val amPmInfo = findAmPmInfo(text.toString()) + if (amPmInfo != null) { + setTextWithAmPmScaled(text, amPmInfo, type) + } else { + super.setText(text, type) + } + } + + private fun findAmPmInfo(fullText: String): AmPmInfo? { for (s in amPmStrings) { if (s.isNotEmpty()) { - val i = full.indexOf(s, ignoreCase = true) + val i = fullText.indexOf(s, ignoreCase = true) if (i != -1) { - amPmPosition = i - amPmString = s - break + return AmPmInfo(i, s) } } } + return null + } - if (amPmPosition != -1 && amPmString != null) { - val spannable = SpannableString(text) - val startIndex = if (amPmPosition > 0 && full[amPmPosition - 1].isWhitespace()) { - amPmPosition - 1 - } else { - amPmPosition - } - val endIndex = amPmPosition + amPmString.length - if (startIndex < endIndex) { - spannable.setSpan( - RelativeSizeSpan(AM_PM_SCALE), - startIndex, - endIndex, - Spanned.SPAN_EXCLUSIVE_EXCLUSIVE - ) - } - - reenter = true - - try { - super.setText(spannable, type ?: BufferType.SPANNABLE) - } finally { - reenter = false - } + private fun setTextWithAmPmScaled(text: CharSequence?, amPmInfo: AmPmInfo, type: BufferType?) { + val full = text.toString() + val spannable = SpannableString(text) + val startIndex = if (amPmInfo.position > 0 && full[amPmInfo.position - 1].isWhitespace()) { + amPmInfo.position - 1 } else { - super.setText(text, type) + amPmInfo.position + } + val endIndex = amPmInfo.position + amPmInfo.string.length + if (startIndex < endIndex) { + spannable.setSpan( + RelativeSizeSpan(AM_PM_SCALE), + startIndex, + endIndex, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE + ) + } + + reenter = true + try { + super.setText(spannable, type ?: BufferType.SPANNABLE) + } finally { + reenter = false } } + + private data class AmPmInfo(val position: Int, val string: String) } From a2ddbe8c9796d9a5f032588d7dd285d2cc074fad Mon Sep 17 00:00:00 2001 From: wellorbetter <1419919418@qq.com> Date: Wed, 25 Mar 2026 04:26:48 +0800 Subject: [PATCH 9/9] fix #289: add localized date format Adjust the position and modify the code to the minimum extent & reduce cyclomatic complexity. --- .../org/fossify/clock/views/MyTextClock.kt | 69 +++++++++---------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/app/src/main/kotlin/org/fossify/clock/views/MyTextClock.kt b/app/src/main/kotlin/org/fossify/clock/views/MyTextClock.kt index f46a07c6b..d35ef7a33 100644 --- a/app/src/main/kotlin/org/fossify/clock/views/MyTextClock.kt +++ b/app/src/main/kotlin/org/fossify/clock/views/MyTextClock.kt @@ -59,51 +59,50 @@ class MyTextClock @JvmOverloads constructor( return } - val amPmInfo = findAmPmInfo(text.toString()) - if (amPmInfo != null) { - setTextWithAmPmScaled(text, amPmInfo, type) - } else { - super.setText(text, type) - } + setTextWithAmPmScaled(text, type); } - private fun findAmPmInfo(fullText: String): AmPmInfo? { + private fun setTextWithAmPmScaled(text: CharSequence?, type: BufferType?) { + val full = text.toString() + var amPmPosition = -1 + var amPmString: String? = null for (s in amPmStrings) { if (s.isNotEmpty()) { - val i = fullText.indexOf(s, ignoreCase = true) + val i = full.indexOf(s, ignoreCase = true) if (i != -1) { - return AmPmInfo(i, s) + amPmPosition = i + amPmString = s + break } } } - return null - } - private fun setTextWithAmPmScaled(text: CharSequence?, amPmInfo: AmPmInfo, type: BufferType?) { - val full = text.toString() - val spannable = SpannableString(text) - val startIndex = if (amPmInfo.position > 0 && full[amPmInfo.position - 1].isWhitespace()) { - amPmInfo.position - 1 - } else { - amPmInfo.position - } - val endIndex = amPmInfo.position + amPmInfo.string.length - if (startIndex < endIndex) { - spannable.setSpan( - RelativeSizeSpan(AM_PM_SCALE), - startIndex, - endIndex, - Spanned.SPAN_EXCLUSIVE_EXCLUSIVE - ) - } + if (amPmPosition != -1 && amPmString != null) { + val spannable = SpannableString(text) + val startIndex = if (amPmPosition > 0 && full[amPmPosition - 1].isWhitespace()) { + amPmPosition - 1 + } else { + amPmPosition + } + val endIndex = amPmPosition + amPmString.length + if (startIndex < endIndex) { + spannable.setSpan( + RelativeSizeSpan(AM_PM_SCALE), + startIndex, + endIndex, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE + ) + } + + reenter = true - reenter = true - try { - super.setText(spannable, type ?: BufferType.SPANNABLE) - } finally { - reenter = false + try { + super.setText(spannable, type ?: BufferType.SPANNABLE) + } finally { + reenter = false + } + } else { + super.setText(text, type) } } - - private data class AmPmInfo(val position: Int, val string: String) }