1
0
Fork 0
mirror of https://github.com/immich-app/immich.git synced 2025-01-17 01:06:46 +01:00

feat(mobile): in app language selector (#8574)

* feat(mobile): select locale in the mobile app

* add additional locale

* use the same locale variable across the app

* using different data structure

* drop down with button

* update pull locales

* open app ios

* remove dependency

* format fix
This commit is contained in:
Alex 2024-04-06 21:58:35 -05:00 committed by GitHub
parent 335c03d0b8
commit 82aeb3292a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 584 additions and 489 deletions

View file

@ -66,8 +66,8 @@ download:
locale_code: es-MX locale_code: es-MX
- file: mobile/assets/i18n/sv-FI.json - file: mobile/assets/i18n/sv-FI.json
locale_code: sv-FI locale_code: sv-FI
- file: mobile/assets/i18n/ca.json - file: mobile/assets/i18n/ca-CA.json
locale_code: ca locale_code: ca-CA
- file: mobile/assets/i18n/hu-HU.json - file: mobile/assets/i18n/hu-HU.json
locale_code: hu-HU locale_code: hu-HU
- file: mobile/assets/i18n/lv-LV.json - file: mobile/assets/i18n/lv-LV.json
@ -76,3 +76,19 @@ download:
locale_code: zh-Hans locale_code: zh-Hans
- file: mobile/assets/i18n/th-TH.json - file: mobile/assets/i18n/th-TH.json
locale_code: th-TH locale_code: th-TH
- file: mobile/assets/i18n/lt-LT.json
locale_code: lt-LT
- file: mobile/assets/i18n/el-GR.json
locale_code: el-GR
- file: mobile/assets/i18n/fr-CA.json
locale_code: fr-CA
- file: mobile/assets/i18n/es-US.json
locale_code: es-US
- file: mobile/assets/i18n/sl-SI.json
locale_code: sl-SI
- file: mobile/assets/i18n/ar-JO.json
locale_code: ar-JO
- file: mobile/assets/i18n/he-IL.json
locale_code: he-IL
- file: mobile/assets/i18n/ro-RO.json
locale_code: ro-RO

View file

@ -400,7 +400,9 @@
"setting_notifications_total_progress_subtitle": "Overall upload progress (done/total assets)", "setting_notifications_total_progress_subtitle": "Overall upload progress (done/total assets)",
"setting_notifications_total_progress_title": "Show background backup total progress", "setting_notifications_total_progress_title": "Show background backup total progress",
"setting_pages_app_bar_settings": "Settings", "setting_pages_app_bar_settings": "Settings",
"setting_languages_title": "Languages",
"settings_require_restart": "Please restart Immich to apply this setting", "settings_require_restart": "Please restart Immich to apply this setting",
"setting_languages_apply": "Apply",
"share_add": "Add", "share_add": "Add",
"share_add_photos": "Add photos", "share_add_photos": "Add photos",
"share_add_title": "Add a title", "share_add_title": "Add a title",

View file

@ -22,33 +22,36 @@
<key>CFBundleLocalizations</key> <key>CFBundleLocalizations</key>
<array> <array>
<string>en</string> <string>en</string>
<string>de</string> <string>ar</string>
<string>da</string>
<string>it</string>
<string>es</string>
<string>vi</string>
<string>fr</string>
<string>ja</string>
<string>pl</string>
<string>fi</string>
<string>pt</string>
<string>cs</string>
<string>uk</string>
<string>ru</string>
<string>zh</string>
<string>sk</string>
<string>nl</string>
<string>nb</string>
<string>sv</string>
<string>mn</string>
<string>ko</string>
<string>sr</string>
<string>hi</string>
<string>ca</string> <string>ca</string>
<string>cs</string>
<string>da</string>
<string>de</string>
<string>es</string>
<string>fi</string>
<string>fr</string>
<string>he</string>
<string>hi</string>
<string>hu</string> <string>hu</string>
<string>it</string>
<string>ja</string>
<string>ko</string>
<string>lv</string> <string>lv</string>
<string>th</string> <string>mn</string>
<string>nb</string>
<string>nl</string>
<string>pl</string>
<string>pt</string>
<string>ro</string>
<string>ru</string>
<string>sk</string>
<string>sl</string> <string>sl</string>
<string>sr</string>
<string>sv</string>
<string>th</string>
<string>uk</string>
<string>vi</string>
<string>zh</string>
</array> </array>
<key>CFBundleName</key> <key>CFBundleName</key>
<string>immich_mobile</string> <string>immich_mobile</string>

View file

@ -1,43 +1,48 @@
import 'dart:ui'; import 'dart:ui';
const List<Locale> locales = [ const Map<String, Locale> locales = {
// Default locale // Default locale
Locale('en', 'US'), 'English (en_US)': Locale('en', 'US'),
// Additional locales // Additional locales
Locale('de', 'DE'), 'Arabic (ar_JO)': Locale('ar', 'JO'),
Locale('da', 'DK'), 'Catalan (ca_CA)': Locale('ca', 'CA'),
Locale('it', 'IT'), 'Chinese (zh_CN)': Locale('zh', 'CN'),
Locale('es', 'ES'), 'Chinese Simplified (zh_Hans)': Locale('zh', 'Hans'),
Locale('vi', 'VN'), 'Czech (cs_CZ)': Locale('cs', 'CZ'),
Locale('fr', 'CA'), 'Danish (da_DK)': Locale('da', 'DK'),
Locale('fr', 'FR'), 'Dutch (nl_NL)': Locale('nl', 'NL'),
Locale('ja', 'JP'), 'Finnish (fi_FI)': Locale('fi', 'FI'),
Locale('pl', 'PL'), 'French (fr_CA)': Locale('fr', 'CA'),
Locale('fi', 'FI'), 'French (fr_FR)': Locale('fr', 'FR'),
Locale('pt', 'PT'), 'German (de_DE)': Locale('de', 'DE'),
Locale('cs', 'CZ'), 'Greek (el_GR)': Locale('el', 'GR'),
Locale('uk', 'UA'), 'Hebrew (he_IL)': Locale('he', 'IL'),
Locale('ru', 'RU'), 'Hindi (hi_IN)': Locale('hi', 'IN'),
Locale('zh', 'CN'), 'Hungarian (hu_HU)': Locale('hu', 'HU'),
Locale('sk', 'SK'), 'Italian (it_IT)': Locale('it', 'IT'),
Locale('nl', 'NL'), 'Japanese (ja_JP)': Locale('ja', 'JP'),
Locale('nb', 'NO'), 'Korean (ko_KR)': Locale('ko', 'KR'),
Locale('sv', 'SE'), 'Latvian (lv_LV)': Locale('lv', 'LV'),
Locale('mn', 'MN'), 'Lithuanian (lt_LT)': Locale('lt', 'LT'),
Locale('ko', 'KR'), 'Mongolian (mn_MN)': Locale('mn', 'MN'),
Locale('sr', 'Latn'), 'Norwegian Bokmål (nb_NO)': Locale('nb', 'NO'),
Locale('sr', 'Cyrl'), 'Polish (pl_PL)': Locale('pl', 'PL'),
Locale('hi', 'IN'), 'Portuguese (pt_PT)': Locale('pt', 'PT'),
Locale('es', 'PE'), 'Romanian (ro_RO)': Locale('ro', 'RO'),
Locale('es', 'MX'), 'Russian (ru_RU)': Locale('ru', 'RU'),
Locale('es', 'US'), 'Serbian Cyrillic (sr_Cyrl)': Locale('sr', 'Cyrl'),
Locale('sv', 'FI'), 'Serbian Latin (sr_Latn)': Locale('sr', 'Latn'),
Locale('ca', 'CA'), 'Slovak (sk_SK)': Locale('sk', 'SK'),
Locale('hu', 'HU'), 'Slovenian (sl_SI)': Locale('sl', 'SI'),
Locale('lv', 'LV'), 'Spanish (es_ES)': Locale('es', 'ES'),
Locale('zh', 'Hans'), 'Spanish (es_MX)': Locale('es', 'MX'),
Locale('th', 'TH'), 'Spanish (es_PE)': Locale('es', 'PE'),
Locale('sl', 'SI'), 'Spanish (es_US)': Locale('es', 'US'),
]; 'Swedish (sv_FI)': Locale('sv', 'FI'),
'Swedish (sv_SE)': Locale('sv', 'SE'),
'Thai (th_TH)': Locale('th', 'TH'),
'Ukrainian (uk_UA)': Locale('uk', 'UA'),
'Vietnamese (vi_VN)': Locale('vi', 'VN'),
};
const String translationsPath = 'assets/i18n'; const String translationsPath = 'assets/i18n';

View file

@ -215,10 +215,10 @@ class MainWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return EasyLocalization( return EasyLocalization(
supportedLocales: locales, supportedLocales: locales.values.toList(),
path: translationsPath, path: translationsPath,
useFallbackTranslations: true, useFallbackTranslations: true,
fallbackLocale: locales.first, fallbackLocale: locales.values.first,
child: const ImmichApp(), child: const ImmichApp(),
); );
} }

View file

@ -11,14 +11,14 @@ Future<bool> loadTranslations() async {
await EasyLocalizationController.initEasyLocation(); await EasyLocalizationController.initEasyLocation();
final controller = EasyLocalizationController( final controller = EasyLocalizationController(
supportedLocales: locales, supportedLocales: locales.values.toList(),
useFallbackTranslations: true, useFallbackTranslations: true,
saveLocale: true, saveLocale: true,
assetLoader: const RootBundleAssetLoader(), assetLoader: const RootBundleAssetLoader(),
path: translationsPath, path: translationsPath,
useOnlyLangCode: false, useOnlyLangCode: false,
onLoadError: (e) => debugPrint(e.toString()), onLoadError: (e) => debugPrint(e.toString()),
fallbackLocale: locales.first, fallbackLocale: locales.values.first,
); );
await controller.loadTranslations(); await controller.loadTranslations();

View file

@ -2,7 +2,10 @@ import 'package:auto_route/auto_route.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/constants/locales.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/modules/backup/background_service/localization.dart';
import 'package:immich_mobile/modules/settings/ui/advanced_settings.dart'; import 'package:immich_mobile/modules/settings/ui/advanced_settings.dart';
import 'package:immich_mobile/modules/settings/ui/asset_list_settings/asset_list_settings.dart'; import 'package:immich_mobile/modules/settings/ui/asset_list_settings/asset_list_settings.dart';
import 'package:immich_mobile/modules/settings/ui/backup_settings/backup_settings.dart'; import 'package:immich_mobile/modules/settings/ui/backup_settings/backup_settings.dart';
@ -16,6 +19,7 @@ enum SettingSection {
'setting_notifications_title', 'setting_notifications_title',
Icons.notifications_none_rounded, Icons.notifications_none_rounded,
), ),
languages('setting_languages_title', Icons.language),
preferences('preferences_settings_title', Icons.interests_outlined), preferences('preferences_settings_title', Icons.interests_outlined),
backup('backup_controller_page_backup', Icons.cloud_upload_outlined), backup('backup_controller_page_backup', Icons.cloud_upload_outlined),
timeline('asset_list_settings_title', Icons.auto_awesome_mosaic_outlined), timeline('asset_list_settings_title', Icons.auto_awesome_mosaic_outlined),
@ -27,6 +31,7 @@ enum SettingSection {
Widget get widget => switch (this) { Widget get widget => switch (this) {
SettingSection.notifications => const NotificationSetting(), SettingSection.notifications => const NotificationSetting(),
SettingSection.languages => const LanguageSettings(),
SettingSection.preferences => const PreferenceSetting(), SettingSection.preferences => const PreferenceSetting(),
SettingSection.backup => const BackupSettings(), SettingSection.backup => const BackupSettings(),
SettingSection.timeline => const AssetListSettings(), SettingSection.timeline => const AssetListSettings(),
@ -37,6 +42,70 @@ enum SettingSection {
const SettingSection(this.title, this.icon); const SettingSection(this.title, this.icon);
} }
class LanguageSettings extends HookConsumerWidget {
const LanguageSettings({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final currentLocale = context.locale;
final textController = useTextEditingController(
text: locales.keys.firstWhere(
(countryName) => locales[countryName] == currentLocale,
),
);
final selectedLocale = useState<Locale>(currentLocale);
return ListView(
padding: const EdgeInsets.all(16),
children: [
DropdownMenu(
inputDecorationTheme: InputDecorationTheme(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
contentPadding: const EdgeInsets.only(left: 16),
),
menuStyle: MenuStyle(
shape: MaterialStatePropertyAll<OutlinedBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
),
),
menuHeight: context.height * 0.5,
hintText: "Languages",
label: const Text('Languages'),
dropdownMenuEntries: locales.keys
.map(
(countryName) => DropdownMenuEntry(
value: locales[countryName],
label: countryName,
),
)
.toList(),
controller: textController,
onSelected: (value) {
if (value != null) {
selectedLocale.value = value;
}
},
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: selectedLocale.value == currentLocale
? null
: () {
context.setLocale(selectedLocale.value);
loadTranslations();
},
child: const Text('setting_languages_apply').tr(),
),
],
);
}
}
@RoutePage() @RoutePage()
class SettingsPage extends StatelessWidget { class SettingsPage extends StatelessWidget {
const SettingsPage({super.key}); const SettingsPage({super.key});