Skip to content

Commit

Permalink
Localization preferences (#77)
Browse files Browse the repository at this point in the history
* locale implementation

* add localizations translates

* update changelogs

* update app version
  • Loading branch information
EdwynZN authored May 18, 2024
1 parent 042c286 commit f27b148
Show file tree
Hide file tree
Showing 15 changed files with 145 additions and 7 deletions.
4 changes: 4 additions & 0 deletions assets/text/Cambios.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## Version 2.1.10
- Ahora se puede cambiar el idioma en las opciones (Inglés, Francés o Español)
- Nueva funcionalidad para agregar amiibos en caja o abiertos y cuantos (experimental)

## Version 2.1.61
- Zelda edición Tears of the Kingdom agregado
- Ganondorf posando suavemente edición Tears of the Kingdom agregado
Expand Down
4 changes: 4 additions & 0 deletions assets/text/Changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## Version 2.1.10
- Now you can change the language of the app from settings (English, French or Spanish)
- New feature to add owned amiibos as boxed / unboxed (experimental)

## Version 2.1.61
- Zelda y Ganondorf (mid-suavemente) from Tears of the Kingdom added

Expand Down
4 changes: 4 additions & 0 deletions assets/text/Journal_des_Modifications.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## Version 2.1.10
- Vous pouvez désormais changer la langue de l'application depuis les paramètres (Anglais, Français ou Espagnol)
- Nouvelle fonctionnalité pour ajouter des amiibos possédés en boîte/sans boîte (expérimental)

## Version 2.1.61
- Ajout des figurines Zelda et Ganondorf (au milieu suavemente) de la série Tears of the Kingdom

Expand Down
4 changes: 4 additions & 0 deletions lib/l10n/intl_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@
"actionText": "Share",
"donate": "Donate",
"lockTooltip": "{choice, select, true {Locked} false {Unlocked} other {Unknown}}",
"language": "Language",
"languageSubtitle": "Choose a language or use it from the system",
"system": "System",
"localization": "{choice, select, en {English} es {Spanish} fr {French} other {Unknown}}",
"statTooltip": "{choice, select, true {Percentage} false {Fraction} other {Unknown}}",
"switch_platform": "Switch",
"wiiu_platform": "WiiU",
Expand Down
4 changes: 4 additions & 0 deletions lib/l10n/intl_es.arb
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@
"actionText": "Compartir",
"donate": "Donaciones",
"lockTooltip": "{choice, select, true {Bloqueado} false {Desbloqueado} other {Desconocido}}",
"language": "Idioma",
"languageSubtitle": "Escoja un idioma o use el del sistema",
"system": "Sistema",
"localization": "{choice, select, en {Inglés} es {Español} fr {Francés} other {Desconocido}}",
"statTooltip": "{choice, select, true {Porcentaje} false {Fracción} other {Unknown}}",
"switch_platform": "Switch",
"wiiu_platform": "WiiU",
Expand Down
4 changes: 4 additions & 0 deletions lib/l10n/intl_fr.arb
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@
"actionText": "Partager",
"donate": "Faire un don",
"lockTooltip": "{choice, select, true {Fermé à clé} false {Déverrouillé} other {inconnue}}",
"language": "Langue",
"languageSubtitle": "Choisissez une langue ou utilisez-la depuis le système",
"system": "Système",
"localization": "{choice, select, en {Anglais} es {Espagnol} fr {Français} other {Inconnu}}",
"statTooltip": "{choice, select, true {Pourcentage} false {Fraction} other {inconnue}}",
"switch_platform": "Switch",
"wiiu_platform": "WiiU",
Expand Down
8 changes: 5 additions & 3 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'dart:async';
import 'package:amiibo_network/data/remote_config/model/default_remote_config.dart';
import 'package:amiibo_network/firebase_options.dart';
import 'package:amiibo_network/riverpod/game_provider.dart';
import 'package:amiibo_network/riverpod/preferences_provider.dart';
import 'package:amiibo_network/riverpod/provider_observer.dart';
import 'package:amiibo_network/riverpod/router_provider.dart';
import 'package:amiibo_network/service/info_package.dart';
Expand Down Expand Up @@ -63,9 +64,8 @@ Future<void> main() async {
await remoteConfig.ensureInitialized();
await remoteConfig.setConfigSettings(RemoteConfigSettings(
fetchTimeout: const Duration(minutes: 1),
minimumFetchInterval: kDebugMode
? const Duration(minutes: 5)
: const Duration(days: 1),
minimumFetchInterval:
kDebugMode ? const Duration(minutes: 5) : const Duration(days: 1),
));
await remoteConfig.setDefaults(const DefaultRemoteConfig().toJson());
if (remoteConfig.lastFetchStatus == RemoteConfigFetchStatus.success) {
Expand Down Expand Up @@ -135,6 +135,7 @@ class AmiiboNetwork extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final ThemeProvider themeMode = ref.watch(themeProvider);
final router = ref.watch(routerProvider);
final Locale? locale = ref.watch(localeProvider);
return MaterialApp.router(
localizationsDelegates: [
S.delegate,
Expand All @@ -144,6 +145,7 @@ class AmiiboNetwork extends ConsumerWidget {
],
supportedLocales: S.delegate.supportedLocales,
debugShowCheckedModeBanner: false,
locale: locale,
theme: themeMode.light,
darkTheme: themeMode.dark,
themeMode: themeMode.preferredTheme,
Expand Down
1 change: 1 addition & 0 deletions lib/model/preferences.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class Preferences with _$Preferences {
required bool usePercentage,
required bool useGrid,
required bool ownTypes,
String? languageCode,
HiddenType? ignored,
}) = _Preferences;
}
9 changes: 9 additions & 0 deletions lib/model/result.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import 'package:freezed_annotation/freezed_annotation.dart';

part 'result.freezed.dart';

@freezed
class Result<T> with _$Result<T> {

const factory Result(T data) = _Result;
}
2 changes: 1 addition & 1 deletion lib/repository/theme_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1615,7 +1615,7 @@ class AmiiboTheme3 implements AmiiboTheme {
_textTheme.bodyLarge,
),
overlayColor: WidgetStateProperty.all<Color>(overlay),
visualDensity: const VisualDensity(vertical: 2.5),
visualDensity: const VisualDensity(vertical: 0),
),
),

Expand Down
31 changes: 30 additions & 1 deletion lib/riverpod/preferences_provider.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:ui';

import 'package:amiibo_network/enum/hidden_types.dart';
import 'package:amiibo_network/model/preferences.dart';
import 'package:amiibo_network/riverpod/repository_provider.dart';
Expand All @@ -14,18 +16,32 @@ final hiddenCategoryProvider = Provider<HiddenType?>(
final ownTypesCategoryProvider = Provider<bool>(
(ref) {
final ownedCategories = ref.watch(remoteOwnedCategoryProvider);
return ownedCategories && ref.watch(personalProvider.select((value) => value.ownTypes));
return ownedCategories &&
ref.watch(personalProvider.select((value) => value.ownTypes));
},
name: 'OwnerCategoriesFlagProvider',
);

final localeProvider = Provider<Locale?>(
(ref) {
final languageCode =
ref.watch(personalProvider.select((value) => value.languageCode));
if (languageCode == null || languageCode.isEmpty) {
return null;
}
return Locale.fromSubtags(languageCode: languageCode);
},
name: 'LocaleProvider',
);

final personalProvider =
StateNotifierProvider<UserPreferencessNotifier, Preferences>(
(ref) {
final sharedProvider = ref.watch(preferencesProvider);
final percent = sharedProvider.getBool(sharedStatMode) ?? false;
final grid = sharedProvider.getBool(sharedGridMode) ?? true;
final ignored = sharedProvider.getInt(sharedIgnored) ?? 0;
final languageCode = sharedProvider.getString(sharedLanguageCode);
final ownType = sharedProvider.getBool(sharedOwnType) ?? false;
final HiddenType? categoryIgnored;
switch (ignored) {
Expand All @@ -45,6 +61,7 @@ final personalProvider =
useGrid: grid,
ownTypes: ownType,
ignored: categoryIgnored,
languageCode: languageCode,
);
return UserPreferencessNotifier(initial, ref);
},
Expand All @@ -58,6 +75,18 @@ class UserPreferencessNotifier extends StateNotifier<Preferences> {

bool get isPercentage => state.usePercentage;

Future<void> forceLocale(String? newLanguageCode) async {
if (newLanguageCode != state.languageCode) {
final SharedPreferences preferences = ref.read(preferencesProvider);
if (newLanguageCode == null) {
await preferences.remove(sharedLanguageCode);
} else {
await preferences.setString(sharedLanguageCode, newLanguageCode);
}
state = state.copyWith(languageCode: newLanguageCode);
}
}

Future<void> toggleOwnType(bool newValue) async {
if (newValue != state.ownTypes) {
final SharedPreferences preferences = ref.read(preferencesProvider);
Expand Down
19 changes: 19 additions & 0 deletions lib/screen/settings_screen.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:amiibo_network/enum/hidden_types.dart';
import 'package:amiibo_network/model/result.dart';
import 'package:amiibo_network/resources/resources.dart';
import 'package:amiibo_network/riverpod/preferences_provider.dart';
import 'package:amiibo_network/riverpod/query_provider.dart';
Expand All @@ -7,6 +8,7 @@ import 'package:amiibo_network/riverpod/service_provider.dart';
import 'package:amiibo_network/riverpod/theme_provider.dart';
import 'package:amiibo_network/enum/amiibo_category_enum.dart';
import 'package:amiibo_network/utils/format_color_on_theme.dart';
import 'package:amiibo_network/widget/locale_selection_dialog.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
Expand Down Expand Up @@ -63,6 +65,23 @@ class SettingsPage extends ConsumerWidget {
icon: const Icon(Icons.color_lens),
onTap: () => ThemeButton.dialog(context),
),
_CardSettings(
title: translate.language,
subtitle: translate.languageSubtitle,
icon: const Icon(Icons.language),
onTap: () async {
final localeResult = await showDialog<Result<String?>>(
context: context,
builder: (context) => const LocaleDialog(),
);
if (localeResult == null) {
return;
}
ref
.read(personalProvider.notifier)
.forceLocale(localeResult.data);
},
),
_CardSettings(
title: translate.changelog,
subtitle: translate.changelogSubtitle,
Expand Down
4 changes: 3 additions & 1 deletion lib/utils/preferences_constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,7 @@ const String sharedGridMode = 'gridMode';
const String sharedIgnored = 'ignoredType';
/// if owned system should be enable (shows boxed/unboxed owned amiibos or just owned as a whole)
const String sharedOwnType = 'ownType';
/// locale index from S.delegate.supportedLocales or null
const String sharedLanguageCode = 'localeIndex';
/// Version of the App
const int versionApp = 58;
const int versionApp = 85;
52 changes: 52 additions & 0 deletions lib/widget/locale_selection_dialog.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import 'package:amiibo_network/generated/l10n.dart';
import 'package:amiibo_network/model/result.dart';
import 'package:amiibo_network/riverpod/preferences_provider.dart';
import 'package:amiibo_network/utils/string_extensions.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

class LocaleDialog extends HookConsumerWidget {
const LocaleDialog({super.key});

@override
Widget build(BuildContext context, WidgetRef ref) {
final localizations = MaterialLocalizations.of(context);
final S translate = S.of(context);
final selectedLocale = ref.watch(localeProvider);
final ValueNotifier<String?> state = useState(selectedLocale?.languageCode);
return AlertDialog(
title: Text(translate.language),
scrollable: true,
alignment: Alignment.center,
content: ListBody(
children: [
RadioListTile<String?>(
value: null,
groupValue: state.value,
title: Text(translate.system),
onChanged: (value) => state.value = value,
),
for (final locale in S.delegate.supportedLocales)
RadioListTile<String?>(
value: locale.languageCode,
groupValue: state.value,
title: Text(translate.localization(locale.languageCode)),
onChanged: (value) => state.value = value,
),
],
),
actions: [
TextButton(
child: Text(localizations.cancelButtonLabel.capitalize()),
onPressed: Navigator.of(context).pop,
),
ElevatedButton(
child: Text(localizations.saveButtonLabel.capitalize()),
onPressed: () async =>
Navigator.of(context).pop(Result<String?>(state.value)),
),
],
);
}
}
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ description: An Amiibo collection app designed to allow you to keep track of whi
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 2.1.91+84
version: 2.1.91+85

environment:
sdk: '>=3.4.0 <4.0.0'
Expand Down

0 comments on commit f27b148

Please sign in to comment.