[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:
@@ -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({
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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)}";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user