diff --git a/lib/localization_delegates.dart b/lib/localization_delegates.dart new file mode 100644 index 0000000..55beb90 --- /dev/null +++ b/lib/localization_delegates.dart @@ -0,0 +1,222 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +import 'package:flutter_localizations/flutter_localizations.dart'; +// ignore: implementation_imports +import 'package:flutter_localizations/src/utils/date_localizations.dart' as util; +import 'package:intl/intl.dart' as intl; + +import 'package:fladder/l10n/generated/app_localizations.dart'; + +class FladderLocalizations { + static const List> localizationsDelegates = >[ + AppLocalizations.delegate, + FladderMaterialLocalizationsDelegate(), + FladderCupertinoLocalizationsDelegate(), + FladderWidgetsLocalizationsDelegate(), + ]; +} + +class FladderMaterialLocalizationsDelegate extends LocalizationsDelegate { + const FladderMaterialLocalizationsDelegate(); + + @override + bool isSupported(Locale locale) => true; + + static final Map> _loadedTranslations = + >{}; + + @override + Future load(Locale locale) { + Locale correctedLocale = locale; + if (!kMaterialSupportedLanguages.contains(locale.languageCode)) { + correctedLocale = const Locale("en"); + } + assert(isSupported(correctedLocale)); + return _loadedTranslations.putIfAbsent(correctedLocale, () { + util.loadDateIntlDataIfNotLoaded(); + + final String localeName = intl.Intl.canonicalizedLocale(correctedLocale.toString()); + assert( + correctedLocale.toString() == localeName, + 'Flutter does not support the non-standard locale form $correctedLocale (which ' + 'might be $localeName', + ); + + intl.DateFormat fullYearFormat; + intl.DateFormat compactDateFormat; + intl.DateFormat shortDateFormat; + intl.DateFormat mediumDateFormat; + intl.DateFormat longDateFormat; + intl.DateFormat yearMonthFormat; + intl.DateFormat shortMonthDayFormat; + if (intl.DateFormat.localeExists(localeName)) { + fullYearFormat = intl.DateFormat.y(localeName); + compactDateFormat = intl.DateFormat.yMd(localeName); + shortDateFormat = intl.DateFormat.yMMMd(localeName); + mediumDateFormat = intl.DateFormat.MMMEd(localeName); + longDateFormat = intl.DateFormat.yMMMMEEEEd(localeName); + yearMonthFormat = intl.DateFormat.yMMMM(localeName); + shortMonthDayFormat = intl.DateFormat.MMMd(localeName); + } else if (intl.DateFormat.localeExists(correctedLocale.languageCode)) { + fullYearFormat = intl.DateFormat.y(correctedLocale.languageCode); + compactDateFormat = intl.DateFormat.yMd(correctedLocale.languageCode); + shortDateFormat = intl.DateFormat.yMMMd(correctedLocale.languageCode); + mediumDateFormat = intl.DateFormat.MMMEd(correctedLocale.languageCode); + longDateFormat = intl.DateFormat.yMMMMEEEEd(correctedLocale.languageCode); + yearMonthFormat = intl.DateFormat.yMMMM(correctedLocale.languageCode); + shortMonthDayFormat = intl.DateFormat.MMMd(correctedLocale.languageCode); + } else { + fullYearFormat = intl.DateFormat.y(); + compactDateFormat = intl.DateFormat.yMd(); + shortDateFormat = intl.DateFormat.yMMMd(); + mediumDateFormat = intl.DateFormat.MMMEd(); + longDateFormat = intl.DateFormat.yMMMMEEEEd(); + yearMonthFormat = intl.DateFormat.yMMMM(); + shortMonthDayFormat = intl.DateFormat.MMMd(); + } + + intl.NumberFormat decimalFormat; + intl.NumberFormat twoDigitZeroPaddedFormat; + if (intl.NumberFormat.localeExists(localeName)) { + decimalFormat = intl.NumberFormat.decimalPattern(localeName); + twoDigitZeroPaddedFormat = intl.NumberFormat('00', localeName); + } else if (intl.NumberFormat.localeExists(correctedLocale.languageCode)) { + decimalFormat = intl.NumberFormat.decimalPattern(correctedLocale.languageCode); + twoDigitZeroPaddedFormat = intl.NumberFormat('00', correctedLocale.languageCode); + } else { + decimalFormat = intl.NumberFormat.decimalPattern(); + twoDigitZeroPaddedFormat = intl.NumberFormat('00'); + } + + return SynchronousFuture( + getMaterialTranslation( + correctedLocale, + fullYearFormat, + compactDateFormat, + shortDateFormat, + mediumDateFormat, + longDateFormat, + yearMonthFormat, + shortMonthDayFormat, + decimalFormat, + twoDigitZeroPaddedFormat, + )!, + ); + }); + } + + @override + bool shouldReload(FladderMaterialLocalizationsDelegate old) => false; + + @override + String toString() => 'GlobalMaterialLocalizations.delegate(${kMaterialSupportedLanguages.length} locales)'; +} + +class FladderWidgetsLocalizationsDelegate extends LocalizationsDelegate { + const FladderWidgetsLocalizationsDelegate(); + + @override + bool isSupported(Locale locale) => true; + + static final Map> _loadedTranslations = >{}; + + @override + Future load(Locale locale) { + Locale correctedLocale = locale; + if (!kMaterialSupportedLanguages.contains(locale.languageCode)) { + correctedLocale = const Locale("en"); + } + assert(isSupported(correctedLocale)); + return _loadedTranslations.putIfAbsent(correctedLocale, () { + return SynchronousFuture(getWidgetsTranslation(correctedLocale)!); + }); + } + + @override + bool shouldReload(covariant LocalizationsDelegate old) => false; +} + +class FladderCupertinoLocalizationsDelegate extends LocalizationsDelegate { + const FladderCupertinoLocalizationsDelegate(); + + @override + bool isSupported(Locale locale) => true; + + static final Map> _loadedTranslations = + >{}; + + @override + Future load(Locale locale) { + Locale correctedLocale = locale; + if (!kMaterialSupportedLanguages.contains(locale.languageCode)) { + correctedLocale = const Locale("en"); + } + assert(isSupported(correctedLocale)); + return _loadedTranslations.putIfAbsent(correctedLocale, () { + util.loadDateIntlDataIfNotLoaded(); + + final String localeName = intl.Intl.canonicalizedLocale(correctedLocale.toString()); + assert( + correctedLocale.toString() == localeName, + 'Flutter does not support the non-standard locale form $correctedLocale (which ' + 'might be $localeName', + ); + + late intl.DateFormat fullYearFormat; + late intl.DateFormat dayFormat; + late intl.DateFormat weekdayFormat; + late intl.DateFormat mediumDateFormat; + // We don't want any additional decoration here. The am/pm is handled in + // the date picker. We just want an hour number localized. + late intl.DateFormat singleDigitHourFormat; + late intl.DateFormat singleDigitMinuteFormat; + late intl.DateFormat doubleDigitMinuteFormat; + late intl.DateFormat singleDigitSecondFormat; + late intl.NumberFormat decimalFormat; + + void loadFormats(String? correctedLocale) { + fullYearFormat = intl.DateFormat.y(correctedLocale); + dayFormat = intl.DateFormat.d(correctedLocale); + weekdayFormat = intl.DateFormat.E(correctedLocale); + mediumDateFormat = intl.DateFormat.MMMEd(correctedLocale); + // TODO(xster): fix when https://github.com/dart-lang/intl/issues/207 is resolved. + singleDigitHourFormat = intl.DateFormat('HH', correctedLocale); + singleDigitMinuteFormat = intl.DateFormat.m(correctedLocale); + doubleDigitMinuteFormat = intl.DateFormat('mm', correctedLocale); + singleDigitSecondFormat = intl.DateFormat.s(correctedLocale); + decimalFormat = intl.NumberFormat.decimalPattern(correctedLocale); + } + + if (intl.DateFormat.localeExists(localeName)) { + loadFormats(localeName); + } else if (intl.DateFormat.localeExists(correctedLocale.languageCode)) { + loadFormats(correctedLocale.languageCode); + } else { + loadFormats(null); + } + + return SynchronousFuture( + getCupertinoTranslation( + correctedLocale, + fullYearFormat, + dayFormat, + weekdayFormat, + mediumDateFormat, + singleDigitHourFormat, + singleDigitMinuteFormat, + doubleDigitMinuteFormat, + singleDigitSecondFormat, + decimalFormat, + )!, + ); + }); + } + + @override + bool shouldReload(FladderCupertinoLocalizationsDelegate old) => false; + + @override + String toString() => 'GlobalCupertinoLocalizations.delegate(${kCupertinoSupportedLanguages.length} locales)'; +} diff --git a/lib/main.dart b/lib/main.dart index a48b71f..c1b1b34 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -16,6 +16,7 @@ import 'package:universal_html/html.dart' as html; import 'package:window_manager/window_manager.dart'; import 'package:fladder/l10n/generated/app_localizations.dart'; +import 'package:fladder/localization_delegates.dart'; import 'package:fladder/models/account_model.dart'; import 'package:fladder/models/settings/arguments_model.dart'; import 'package:fladder/providers/arguments_provider.dart'; @@ -271,7 +272,7 @@ class _MainState extends ConsumerState
with WindowListener, WidgetsBinding mouseDrag ? PointerDeviceKind.mouse : null, }.nonNulls.toSet(), ), - localizationsDelegates: AppLocalizations.localizationsDelegates, + localizationsDelegates: FladderLocalizations.localizationsDelegates, supportedLocales: AppLocalizations.supportedLocales, locale: language, localeResolutionCallback: (locale, supportedLocales) {