[mob] Fix date-formatting as per device locale (#5894)

## Description
- For language only match, instead of returning supported locale which
many times doesn't have country code, we are now falling back to system
locale. So for en_GB, the auto-detected locale will be `en_GB` instead
of just `en`.

Fixes https://github.com/ente-io/ente/issues/5120


## Tests
- Verified that the app was translated in Spanish with `es_US`.
- Verified that date-formatting is as per device locale (at least on
birthday date picker & edit time dialog)
This commit is contained in:
Neeraj
2025-05-13 15:20:35 +05:30
committed by GitHub
4 changed files with 51 additions and 10 deletions

View File

@@ -29,21 +29,50 @@ const List<Locale> appSupportedLocales = <Locale>[
Locale("zh", "CN"),
];
List<Locale> _onDeviceLocales = [];
Locale? autoDetectedLocale;
Locale localResolutionCallBack(locales, supportedLocales) {
for (Locale locale in locales) {
Locale localResolutionCallBack(deviceLocales, supportedLocales) {
_onDeviceLocales = deviceLocales;
Locale? firstLangeuageMatch;
for (Locale deviceLocale in deviceLocales) {
for (Locale supportedLocale in appSupportedLocales) {
if (supportedLocale == locale) {
autoDetectedLocale = supportedLocale;
return supportedLocale;
} else if (supportedLocale.languageCode == locale.languageCode) {
if (supportedLocale == deviceLocale) {
autoDetectedLocale = supportedLocale;
return supportedLocale;
}
if (firstLangeuageMatch == null &&
supportedLocale.languageCode == deviceLocale.languageCode) {
firstLangeuageMatch = deviceLocale;
}
}
}
return const Locale('en');
if (firstLangeuageMatch != null) {
autoDetectedLocale = firstLangeuageMatch;
}
return autoDetectedLocale ?? const Locale('en');
}
// This is used to get locale that should be used for various formatting
// operations like date, time, number etc. For common languages like english, different
// locale might have different formats. For example, en_US and en_GB have different
// formats for date and time. Use this method to find the best locale for formatting
// operations. This is not used for displaying text in the app.
Future<Locale> getFormatLocale() async {
final Locale locale = (await getLocale())!;
Locale? firstLanguageMatch;
// see if exact matche is present in the device locales
for (Locale deviceLocale in _onDeviceLocales) {
if (deviceLocale.languageCode == locale.languageCode &&
deviceLocale.countryCode == locale.countryCode) {
return deviceLocale;
}
if (firstLanguageMatch == null &&
deviceLocale.languageCode == locale.languageCode) {
firstLanguageMatch = deviceLocale;
}
}
return firstLanguageMatch ?? locale;
}
Future<Locale?> getLocale({

View File

@@ -121,8 +121,10 @@ class _DatePickerFieldState extends State<DatePickerField> {
}
Future<void> _showDatePicker() async {
final Locale locale = await getFormatLocale();
final DateTime? picked = await showDatePicker(
context: context,
locale: locale,
initialDate: _selectedDate ?? DateTime.now(),
firstDate: widget.firstDate ?? DateTime(1900),
lastDate: widget.lastDate ?? DateTime(2100),

View File

@@ -98,11 +98,21 @@ class _ItemsWidgetState extends State<ItemsWidget> {
@override
Widget build(BuildContext context) {
items.clear();
bool foundMatch = false;
for (Locale locale in widget.supportedLocales) {
if (currentLocale == locale) {
foundMatch = true;
}
items.add(
_menuItemForPicker(locale),
);
}
if (!foundMatch && kDebugMode) {
items.insert(
0,
Text("(i) Locale : ${currentLocale.toString()}"),
);
}
items = addSeparators(
items,
DividerWidget(

View File

@@ -264,7 +264,7 @@ class DateAndTimeWidget extends StatelessWidget {
Widget build(BuildContext context) {
final colorScheme = getEnteColorScheme(context);
final locale = Localizations.localeOf(context);
final String date = DateFormat.yMMMd(locale.languageCode).format(dateTime);
final String date = DateFormat.yMMMd(locale.toString()).format(dateTime);
final String time = DateFormat(
MediaQuery.of(context).alwaysUse24HourFormat ? 'HH:mm' : 'h:mm a',
).format(dateTime);
@@ -628,7 +628,7 @@ class PhotoDateHeaderWidget extends StatelessWidget {
),
const SizedBox(height: 4),
Text(
"${DateFormat.yMEd(locale.languageCode).format(startDate)} · ${DateFormat(
"${DateFormat.yMEd(locale.toString()).format(startDate)} · ${DateFormat(
MediaQuery.of(context).alwaysUse24HourFormat
? 'HH:mm'
: 'h:mm a',
@@ -648,7 +648,7 @@ class PhotoDateHeaderWidget extends StatelessWidget {
}
String _formatDate(DateTime date, Locale locale, BuildContext context) {
return "${DateFormat.yMEd(locale.languageCode).format(date)}\n${DateFormat(
return "${DateFormat.yMEd(locale.toString()).format(date)}\n${DateFormat(
MediaQuery.of(context).alwaysUse24HourFormat ? 'HH:mm' : 'h:mm a',
).format(date)}";
}