Skip to content

fix: localize app status and backup timestamps - #1124

Open
guzino wants to merge 2 commits into
synonymdev:masterfrom
guzino:fix/localized-timestamp-locale
Open

fix: localize app status and backup timestamps#1124
guzino wants to merge 2 commits into
synonymdev:masterfrom
guzino:fix/localized-timestamp-locale

Conversation

@guzino

@guzino guzino commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Fixes #1112

This PR makes the App Status and Backup timestamps follow the device language instead of always formatting them in US English.

Description

toLocalizedTimestamp defaulted to Locale.US, and all three call sites take the default. On a German device App Status therefore read July 31, 2026 at 8:08 PM directly under the translated label Vollständiges Backup. toRelativeTimeString in the same file already defaults to Locale.getDefault(), so this was the one date helper that did not.

Locale.getDefault() is the right source rather than the system configuration, because AppLocaleManager sets the language through AppCompatDelegate.setApplicationLocales. Bitkit's own Language setting therefore moves the timestamps too, not only a change of device language.

  • Defaults toLocalizedTimestamp to Locale.getDefault(), which fixes App Status, Backup metadata and the App Status preview in one line.
  • Replaces the null-formatter fallback, a hardcoded MMMM d, yyyy 'at' h:mm a, with java.text.DateFormat.getDateTimeInstance(LONG, SHORT, locale). The old pattern was English word order with a literal at, so on the fallback path a German locale still produced Juli 27, 2026 at 9:26 PM.
  • Leaves the deliberate Locale.US uses alone: utcDateFormatterOf, Logger, TrezorDebugLog, and the lowercase(Locale.US) calls in models/ that are locale-invariant on purpose.

The clock format here follows the locale rather than the device's 12/24-hour setting, which is what DateFormat.SHORT means: de prints 20:08, en-US prints 8:08 PM. That differs from the activity and connection rows, where the pattern is fixed by design and the 12/24-hour setting decides.

Preview

1112-compare-de

QA Notes

Manual Tests

  • 1. Set the app or device language to German, then Menu ▸ App Status: the Full Backup row reads 31. Juli 2026 um 20:10, matching the surrounding translated labels. The issue asked for 27. Juli 2026, 21:26; ICU joins German long dates with um rather than a comma.
  • 2. regression: set the language back to English: the same row still reads July 31, 2026 at 8:08 PM.
  • 3. Settings ▸ Backup ▸ Metadata shows the last backup time in the same localized form.
  • 4. Check a right-to-left or non-Latin language, for example Arabic, renders the row without clipping.

Automated Checks

  • Unit tests added in DateTimeExtTest.kt: the supplied locale, the default locale, and the day-before-month ordering German uses. All three fail on master and pass here.
  • Verified on an emulator in German and English through cmd locale set-app-locales.
  • Local: just compile, just test, just lint all pass, no new detekt findings.

@greptile-apps

greptile-apps Bot commented Jul 31, 2026

Copy link
Copy Markdown

Greptile Summary

This PR localizes App Status and Backup timestamps using the active default locale.

  • Changes toLocalizedTimestamp to default to Locale.getDefault().
  • Replaces the English-specific fallback pattern with locale-aware Java date/time formatting.
  • Adds regression tests for explicit locale selection, default locale behavior, and German date ordering.
  • Adds a changelog entry for the localization fix.

Confidence Score: 4/5

The application-locale mismatch needs to be fixed before merging because timestamps remain in the device language when users select a different language within Bitkit.

toLocalizedTimestamp() reads Locale.getDefault(), while Bitkit applies its language setting through application-locale APIs that do not update that JVM default, so every no-argument call formats with the wrong locale in this supported configuration.

Files Needing Attention: app/src/main/java/to/bitkit/ext/DateTime.kt

Important Files Changed

Filename Overview
app/src/main/java/to/bitkit/ext/DateTime.kt Makes timestamp formatting locale-aware, but the new default reads the device/JVM locale rather than Bitkit's application-specific locale.
app/src/test/java/to/bitkit/ext/DateTimeExtTest.kt Adds focused formatter tests, but the default-locale test uses Locale.setDefault() rather than exercising the app-specific locale path.
changelog.d/next/1112.fixed.md Documents the user-visible timestamp localization change.

Reviews (1): Last reviewed commit: "fix: localize app status and backup time..." | Re-trigger Greptile

}

fun Long.toLocalizedTimestamp(locale: Locale = Locale.US): String {
fun Long.toLocalizedTimestamp(locale: Locale = Locale.getDefault()): String {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 App locale remains ignored

When the app language differs from the device language, Locale.getDefault() still supplies the device locale because AppLocaleManager changes the application resource configuration without changing the JVM default. The no-argument callers therefore continue rendering App Status and Backup timestamps in the device language instead of the language selected in Bitkit.

Knowledge Base Used: Extension Utilities (to.bitkit.ext)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AppCompat keeps those in sync: on API 28 to 32 setApplicationLocales ends in setDefaultLocalesForLocaleList, which calls LocaleList.setDefault, and on 33+ the platform LocaleManager does it. Verified the German row on an emulator.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right — I was wrong about this. AppCompat's backport path does call LocaleList.setDefault, which in turn calls Locale.setDefault, so Locale.getDefault() does reflect the in-app language selection. Combined with your emulator verification on German, my concern doesn't hold.

The change is correct as written.

Shall I remember this as a rule: "do not flag Locale.getDefault() as ignoring the in-app locale when AppCompatDelegate is used, because AppCompat syncs it via LocaleList.setDefault on all supported API levels"?

Tip: You can customize Greptile's behavior for this repo with .greptile/rules.md and .greptile/config.json.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

App Status and Backup timestamps always use US date format

2 participants