From 79d7500e5fea3c720b8dd91833ec833efb0cad40 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 22 Jun 2022 15:14:28 +0200 Subject: [PATCH 01/23] Add i18n framework to mobile app and write simple translation generator --- i18n/gen_lang_files.py | 50 ++++++++++++++ i18n/translations/de-DE.csv | 4 ++ i18n/translations/en-US.csv | 4 ++ mobile/assets/i18n/de-DE.json | 6 ++ mobile/assets/i18n/en-US.json | 6 ++ mobile/lib/main.dart | 22 +++++- mobile/lib/modules/login/ui/login_form.dart | 15 +++-- mobile/pubspec.lock | 75 +++++++++++++++++++++ mobile/pubspec.yaml | 2 + 9 files changed, 176 insertions(+), 8 deletions(-) create mode 100644 i18n/gen_lang_files.py create mode 100644 i18n/translations/de-DE.csv create mode 100644 i18n/translations/en-US.csv create mode 100644 mobile/assets/i18n/de-DE.json create mode 100644 mobile/assets/i18n/en-US.json diff --git a/i18n/gen_lang_files.py b/i18n/gen_lang_files.py new file mode 100644 index 0000000000000..df6f8798b82bc --- /dev/null +++ b/i18n/gen_lang_files.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +import csv +import glob +import os +import logging +import json + + +class Translation: + def __init__(self, translation_tuple): + self.key, self.translation = translation_tuple + + def __repr__(self): + return f'{self.key} => {self.translation}' + + def get_key(self): + return self.key + + def get_translation(self): + return self.translation + + +def parse_language_csv(filename): + with open(filename, 'r') as file: + return [Translation(t) for t in csv.reader(file, delimiter=',', quotechar='"')] + + +def generate_mobile_translations(lang, translations): + with open(os.path.join('..', 'mobile', 'assets', 'i18n', f'{lang}.json'), 'w') as file: + translations_obj = {} + for t in translations: + translations_obj[t.get_key()] = t.get_translation() + + file.write(json.dumps(translations_obj, indent=2)) + + +def generate_language_files(): + for file in glob.glob(os.path.join('translations', '*.csv'), recursive=False): + language_code = os.path.basename(file)[:-4] + logging.info('Language Code: %s', language_code) + + translations = parse_language_csv(file) + logging.debug(translations) + + generate_mobile_translations(language_code, translations) + + +if __name__ == '__main__': + logging.basicConfig(format='%(levelname)s : %(message)s', level=logging.DEBUG) + generate_language_files() diff --git a/i18n/translations/de-DE.csv b/i18n/translations/de-DE.csv new file mode 100644 index 0000000000000..8bf7ac0c2ccb8 --- /dev/null +++ b/i18n/translations/de-DE.csv @@ -0,0 +1,4 @@ +login_button_text,Anmelden +save_login,Angemeldet bleiben +login_endpoint_url,Server URL +login_endpoint_hint,http://dein-server:port \ No newline at end of file diff --git a/i18n/translations/en-US.csv b/i18n/translations/en-US.csv new file mode 100644 index 0000000000000..237b76a82d0c7 --- /dev/null +++ b/i18n/translations/en-US.csv @@ -0,0 +1,4 @@ +login_button_text,Login +save_login,Save Login +login_endpoint_url,Server Endpoint URL +login_endpoint_hint,http://your-server-ip:port \ No newline at end of file diff --git a/mobile/assets/i18n/de-DE.json b/mobile/assets/i18n/de-DE.json new file mode 100644 index 0000000000000..d622cdbe15c28 --- /dev/null +++ b/mobile/assets/i18n/de-DE.json @@ -0,0 +1,6 @@ +{ + "login_button_text": "Anmelden", + "save_login": "Angemeldet bleiben", + "login_endpoint_url": "Server URL", + "login_endpoint_hint": "http://dein-server:port" +} \ No newline at end of file diff --git a/mobile/assets/i18n/en-US.json b/mobile/assets/i18n/en-US.json new file mode 100644 index 0000000000000..98db3084ae88a --- /dev/null +++ b/mobile/assets/i18n/en-US.json @@ -0,0 +1,6 @@ +{ + "login_button_text": "Login", + "save_login": "Save Login", + "login_endpoint_url": "Server Endpoint URL", + "login_endpoint_hint": "http://your-server-ip:port" +} \ No newline at end of file diff --git a/mobile/lib/main.dart b/mobile/lib/main.dart index 0cdc0df67f46e..8b688a22e06f0 100644 --- a/mobile/lib/main.dart +++ b/mobile/lib/main.dart @@ -1,3 +1,5 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:easy_localization_loader/easy_localization_loader.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:hive_flutter/hive_flutter.dart'; @@ -35,7 +37,22 @@ void main() async { ), ); - runApp(const ProviderScope(child: ImmichApp())); + await EasyLocalization.ensureInitialized(); + + var locales = const [ + // Default locale + Locale('en', 'US'), + // Additional locales + Locale('de', 'DE') + ]; + + runApp(EasyLocalization( + supportedLocales: locales, + path: 'assets/i18n', + useFallbackTranslations: true, + fallbackLocale: locales.first, + child: const ProviderScope(child: ImmichApp()) + )); } class ImmichApp extends ConsumerStatefulWidget { @@ -110,6 +127,9 @@ class _ImmichAppState extends ConsumerState with WidgetsBindingObserv ref.watch(releaseInfoProvider.notifier).checkGithubReleaseInfo(); return MaterialApp( + localizationsDelegates: context.localizationDelegates, + supportedLocales: context.supportedLocales, + locale: context.locale, debugShowCheckedModeBanner: false, home: Stack( children: [ diff --git a/mobile/lib/modules/login/ui/login_form.dart b/mobile/lib/modules/login/ui/login_form.dart index 0a0e84ea9a5c7..1c834095a99fe 100644 --- a/mobile/lib/modules/login/ui/login_form.dart +++ b/mobile/lib/modules/login/ui/login_form.dart @@ -1,4 +1,5 @@ import 'package:auto_route/auto_route.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hive/hive.dart'; @@ -67,9 +68,9 @@ class LoginForm extends HookConsumerWidget { shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)), enableFeedback: true, title: const Text( - "Save login", + "save_login", style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: Colors.grey), - ), + ).tr(), value: isSaveLoginInfo.value, onChanged: (switchValue) { if (switchValue != null) { @@ -106,8 +107,8 @@ class ServerEndpointInput extends StatelessWidget { Widget build(BuildContext context) { return TextFormField( controller: controller, - decoration: const InputDecoration( - labelText: 'Server Endpoint URL', border: OutlineInputBorder(), hintText: 'http://your-server-ip:port'), + decoration: InputDecoration( + labelText: 'login_endpoint_url'.tr(), border: OutlineInputBorder(), hintText: 'login_endpoint_hint'.tr()), validator: _validateInput, autovalidateMode: AutovalidateMode.always, ); @@ -193,14 +194,14 @@ class LoginButton extends ConsumerWidget { } else { ImmichToast.show( context: context, - msg: "Error logging you in, check server url, email and password!", + msg: "login_failed".tr(), toastType: ToastType.error, ); } }, child: const Text( - "Login", + "login_button_text", style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold), - )); + ).tr()); } } diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index d06aedafea4d4..2995d8f2e2010 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -253,6 +253,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.0.6" + easy_localization: + dependency: "direct main" + description: + name: easy_localization + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" + easy_logger: + dependency: transitive + description: + name: easy_logger + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.2" equatable: dependency: "direct main" description: @@ -335,6 +349,11 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.4" + flutter_localizations: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" flutter_map: dependency: "direct main" description: @@ -842,6 +861,62 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.27.3" + shared_preferences: + dependency: transitive + description: + name: shared_preferences + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.15" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.12" + shared_preferences_ios: + dependency: transitive + description: + name: shared_preferences_ios + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + shared_preferences_macos: + dependency: transitive + description: + name: shared_preferences_macos + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.4" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.4" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" shelf: dependency: transitive description: diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index 46a1787fa384c..da9ed2de1e1b0 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -42,6 +42,7 @@ dependencies: url_launcher: ^6.1.3 http: 0.13.4 cancellation_token_http: ^1.1.0 + easy_localization: ^3.0.1 dev_dependencies: flutter_test: @@ -55,6 +56,7 @@ flutter: uses-material-design: true assets: - assets/ + - assets/i18n/ fonts: - family: WorkSans fonts: From 8ccd8999bb2ef48981d9ff50382f0616a30d4114 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 22 Jun 2022 16:02:14 +0200 Subject: [PATCH 02/23] Replace all texts in login_form with i18n keys --- i18n/translations/de-DE.csv | 10 +++++++++- i18n/translations/en-US.csv | 10 +++++++++- mobile/assets/i18n/de-DE.json | 10 +++++++++- mobile/assets/i18n/en-US.json | 10 +++++++++- mobile/lib/main.dart | 1 - mobile/lib/modules/login/ui/login_form.dart | 14 +++++++------- 6 files changed, 43 insertions(+), 12 deletions(-) diff --git a/i18n/translations/de-DE.csv b/i18n/translations/de-DE.csv index 8bf7ac0c2ccb8..0b16025162a32 100644 --- a/i18n/translations/de-DE.csv +++ b/i18n/translations/de-DE.csv @@ -1,4 +1,12 @@ login_button_text,Anmelden save_login,Angemeldet bleiben login_endpoint_url,Server URL -login_endpoint_hint,http://dein-server:port \ No newline at end of file +login_endpoint_hint,http://dein-server:port +login_err_trailing_whitespace,Abschließendes Leerzeichen +login_err_leading_whitespace,Führendes Leerzeichen +login_err_invalid_email,Ungültige Email-Adresse +login_err_http,Muss mit http:// oder https:// starten +login_label_email,Email-Adresse +login_email_hint,deine@email.com +login_label_password,Passwort +login_password_hint,passwort \ No newline at end of file diff --git a/i18n/translations/en-US.csv b/i18n/translations/en-US.csv index 237b76a82d0c7..01a889c219626 100644 --- a/i18n/translations/en-US.csv +++ b/i18n/translations/en-US.csv @@ -1,4 +1,12 @@ login_button_text,Login save_login,Save Login login_endpoint_url,Server Endpoint URL -login_endpoint_hint,http://your-server-ip:port \ No newline at end of file +login_endpoint_hint,http://your-server-ip:port +login_err_trailing_whitespace,Trailing whitespace +login_err_leading_whitespace,Leading whitespace +login_err_invalid_email,Invalid Email +login_err_http,Please specify http:// or https:// +login_label_email,Email +login_email_hint,youremail@email.com +login_label_password,Password +login_password_hint,password \ No newline at end of file diff --git a/mobile/assets/i18n/de-DE.json b/mobile/assets/i18n/de-DE.json index d622cdbe15c28..424c2a84ce1ef 100644 --- a/mobile/assets/i18n/de-DE.json +++ b/mobile/assets/i18n/de-DE.json @@ -2,5 +2,13 @@ "login_button_text": "Anmelden", "save_login": "Angemeldet bleiben", "login_endpoint_url": "Server URL", - "login_endpoint_hint": "http://dein-server:port" + "login_endpoint_hint": "http://dein-server:port", + "login_err_trailing_whitespace": "Abschlie\u00dfendes Leerzeichen", + "login_err_leading_whitespace": "F\u00fchrendes Leerzeichen", + "login_err_invalid_email": "Ung\u00fcltige Email-Adresse", + "login_err_http": "Muss mit http:// oder https:// starten", + "login_label_email": "Email-Adresse", + "login_email_hint": "deine@email.com", + "login_label_password": "Passwort", + "login_password_hint": "passwort" } \ No newline at end of file diff --git a/mobile/assets/i18n/en-US.json b/mobile/assets/i18n/en-US.json index 98db3084ae88a..ea19ff8e2b3ff 100644 --- a/mobile/assets/i18n/en-US.json +++ b/mobile/assets/i18n/en-US.json @@ -2,5 +2,13 @@ "login_button_text": "Login", "save_login": "Save Login", "login_endpoint_url": "Server Endpoint URL", - "login_endpoint_hint": "http://your-server-ip:port" + "login_endpoint_hint": "http://your-server-ip:port", + "login_err_trailing_whitespace": "Trailing whitespace", + "login_err_leading_whitespace": "Leading whitespace", + "login_err_invalid_email": "Invalid Email", + "login_err_http": "Please specify http:// or https://", + "login_label_email": "Email", + "login_email_hint": "youremail@email.com", + "login_label_password": "Password", + "login_password_hint": "password" } \ No newline at end of file diff --git a/mobile/lib/main.dart b/mobile/lib/main.dart index 8b688a22e06f0..998b043ba34f7 100644 --- a/mobile/lib/main.dart +++ b/mobile/lib/main.dart @@ -1,5 +1,4 @@ import 'package:easy_localization/easy_localization.dart'; -import 'package:easy_localization_loader/easy_localization_loader.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:hive_flutter/hive_flutter.dart'; diff --git a/mobile/lib/modules/login/ui/login_form.dart b/mobile/lib/modules/login/ui/login_form.dart index 1c834095a99fe..f89dbfc0e5b58 100644 --- a/mobile/lib/modules/login/ui/login_form.dart +++ b/mobile/lib/modules/login/ui/login_form.dart @@ -18,7 +18,7 @@ class LoginForm extends HookConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final usernameController = useTextEditingController.fromValue(TextEditingValue.empty); final passwordController = useTextEditingController.fromValue(TextEditingValue.empty); - final serverEndpointController = useTextEditingController(text: 'http://your-server-ip:2283'); + final serverEndpointController = useTextEditingController(text: 'login_endpoint_hint'.tr()); final isSaveLoginInfo = useState(false); useEffect(() { @@ -99,7 +99,7 @@ class ServerEndpointInput extends StatelessWidget { String? _validateInput(String? url) { if (url == null) return null; - if (!url.startsWith(RegExp(r'https?://'))) return 'Please specify http:// or https://'; + if (!url.startsWith(RegExp(r'https?://'))) return 'login_err_http'.tr(); return null; } @@ -122,9 +122,9 @@ class EmailInput extends StatelessWidget { String? _validateInput(String? email) { if (email == null || email == '') return null; - if (email.endsWith(' ')) return 'Trailing whitespace'; - if (email.startsWith(' ')) return 'Leading whitespace'; - if (email.contains(' ') || !email.contains('@')) return 'Invalid Email'; + if (email.endsWith(' ')) return 'login_err_trailing_whitespace'.tr(); + if (email.startsWith(' ')) return 'login_err_leading_whitespace'.tr(); + if (email.contains(' ') || !email.contains('@')) return 'login_err_invalid_email'.tr(); return null; } @@ -133,7 +133,7 @@ class EmailInput extends StatelessWidget { return TextFormField( controller: controller, decoration: - const InputDecoration(labelText: 'Email', border: OutlineInputBorder(), hintText: 'youremail@email.com'), + InputDecoration(labelText: 'login_label_email'.tr(), border: OutlineInputBorder(), hintText: 'login_email_hint'.tr()), validator: _validateInput, autovalidateMode: AutovalidateMode.always, ); @@ -150,7 +150,7 @@ class PasswordInput extends StatelessWidget { return TextFormField( obscureText: true, controller: controller, - decoration: const InputDecoration(labelText: 'Password', border: OutlineInputBorder(), hintText: 'password'), + decoration: InputDecoration(labelText: 'login_label_password'.tr(), border: OutlineInputBorder(), hintText: 'login_password_hint'.tr()), ); } } From b88dcafe7e7a3178f7e6f7ea02c6be8fb4e77367 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 22 Jun 2022 17:31:06 +0200 Subject: [PATCH 03/23] Localization of sharing section --- i18n/translations/de-DE.csv | 25 ++++++++++++++++++- i18n/translations/en-US.csv | 25 ++++++++++++++++++- mobile/assets/i18n/de-DE.json | 25 ++++++++++++++++++- mobile/assets/i18n/en-US.json | 25 ++++++++++++++++++- .../sharing/ui/album_title_text_field.dart | 3 ++- .../sharing/ui/album_viewer_appbar.dart | 21 ++++++++-------- .../ui/album_viewer_editable_title.dart | 3 ++- .../sharing/ui/sharing_sliver_appbar.dart | 9 ++++--- .../sharing/views/album_viewer_page.dart | 5 ++-- .../sharing/views/asset_selection_page.dart | 9 ++++--- .../views/create_shared_album_page.dart | 21 ++++++++-------- ...lect_additional_user_for_sharing_page.dart | 13 +++++----- .../views/select_user_for_sharing_page.dart | 17 +++++++------ .../modules/sharing/views/sharing_page.dart | 15 +++++------ 14 files changed, 159 insertions(+), 57 deletions(-) diff --git a/i18n/translations/de-DE.csv b/i18n/translations/de-DE.csv index 0b16025162a32..2983518737a43 100644 --- a/i18n/translations/de-DE.csv +++ b/i18n/translations/de-DE.csv @@ -9,4 +9,27 @@ login_err_http,Muss mit http:// oder https:// starten login_label_email,Email-Adresse login_email_hint,deine@email.com login_label_password,Passwort -login_password_hint,passwort \ No newline at end of file +login_password_hint,passwort +share_add_title,Titel hinzufügen +share_err_delete,Fehler beim Löschen des Albums +share_err_leave,Fehler beim Verlassen des Albums +share_err_remove,Einträge konnten nicht aus dem Album gelöscht werden +share_err_title,Fehler beim Ändern des Titels +share_remove,Aus Album entfernen +share_delete,Album löschen +share_leave,Album verlassen +create_shared_album,Geteiltes Album erstellen +share_partner,Mit Partner teilen +share_add_photos,Fotos hinzufügen +share_add_users,Nutzer hinzufügen +share_add,Hinzufügen +share_add_assets,EINTRÄGE HINZUFÜGEN +share_select_photos,Fotos auswählen +share_create_album,Album erstellen +share_share,Teilen +share_suggestions,Vorschläge +share_invite,Zu Album einladen +share_err_album,Fehler beim Erstellen des Albums +share_empty_list,LEERE LISTE +share_description,Erstelle geteilte Alben um Fotos und Videos mit Menschen aus deinem Netzwerk zu teilen. +share_album,Geteilte Alben \ No newline at end of file diff --git a/i18n/translations/en-US.csv b/i18n/translations/en-US.csv index 01a889c219626..51d5377efecf5 100644 --- a/i18n/translations/en-US.csv +++ b/i18n/translations/en-US.csv @@ -9,4 +9,27 @@ login_err_http,Please specify http:// or https:// login_label_email,Email login_email_hint,youremail@email.com login_label_password,Password -login_password_hint,password \ No newline at end of file +login_password_hint,password +share_add_title,Add a title +share_err_delete,Failed to delete album +share_err_leave,Failed to leave album +share_err_remove,There are problems in removing assets from album +share_err_title,Failed to change album title +share_remove,Remove from album +share_delete,Delete album +share_leave,Leave album +create_shared_album,Create shared album +share_partner,Share with partner +share_add_photos,Add photos +share_add_users,Add users +share_add,Add +share_add_assets,ADD ASSETS +share_select_photos,Select Photos +share_create_album,Create album +share_share,Share +share_suggestions,Suggestions +share_invite,Invite to album +share_err_album,Failed to create album +share_empty_list,EMPTY LIST +share_description,Create shared albums to share photos and videos with people in your network. +share_album,Shared albums \ No newline at end of file diff --git a/mobile/assets/i18n/de-DE.json b/mobile/assets/i18n/de-DE.json index 424c2a84ce1ef..d832c67f99b96 100644 --- a/mobile/assets/i18n/de-DE.json +++ b/mobile/assets/i18n/de-DE.json @@ -10,5 +10,28 @@ "login_label_email": "Email-Adresse", "login_email_hint": "deine@email.com", "login_label_password": "Passwort", - "login_password_hint": "passwort" + "login_password_hint": "passwort", + "share_add_title": "Titel hinzuf\u00fcgen", + "share_err_delete": "Fehler beim L\u00f6schen des Albums", + "share_err_leave": "Fehler beim Verlassen des Albums", + "share_err_remove": "Eintr\u00e4ge konnten nicht aus dem Album gel\u00f6scht werden", + "share_err_title": "Fehler beim \u00c4ndern des Titels", + "share_remove": "Aus Album entfernen", + "share_delete": "Album l\u00f6schen", + "share_leave": "Album verlassen", + "create_shared_album": "Geteiltes Album erstellen", + "share_partner": "Mit Partner teilen", + "share_add_photos": "Fotos hinzuf\u00fcgen", + "share_add_users": "Nutzer hinzuf\u00fcgen", + "share_add": "Hinzuf\u00fcgen", + "share_add_assets": "EINTR\u00c4GE HINZUF\u00dcGEN", + "share_select_photos": "Fotos ausw\u00e4hlen", + "share_create_album": "Album erstellen", + "share_share": "Teilen", + "share_suggestions": "Vorschl\u00e4ge", + "share_invite": "Zu Album einladen", + "share_err_album": "Fehler beim Erstellen des Albums", + "share_empty_list": "LEERE LISTE", + "share_description": "Erstelle geteilte Alben um Fotos und Videos mit Menschen aus deinem Netzwerk zu teilen.", + "share_album": "Geteilte Alben" } \ No newline at end of file diff --git a/mobile/assets/i18n/en-US.json b/mobile/assets/i18n/en-US.json index ea19ff8e2b3ff..4a4188072d8b8 100644 --- a/mobile/assets/i18n/en-US.json +++ b/mobile/assets/i18n/en-US.json @@ -10,5 +10,28 @@ "login_label_email": "Email", "login_email_hint": "youremail@email.com", "login_label_password": "Password", - "login_password_hint": "password" + "login_password_hint": "password", + "share_add_title": "Add a title", + "share_err_delete": "Failed to delete album", + "share_err_leave": "Failed to leave album", + "share_err_remove": "There are problems in removing assets from album", + "share_err_title": "Failed to change album title", + "share_remove": "Remove from album", + "share_delete": "Delete album", + "share_leave": "Leave album", + "create_shared_album": "Create shared album", + "share_partner": "Share with partner", + "share_add_photos": "Add photos", + "share_add_users": "Add users", + "share_add": "Add", + "share_add_assets": "ADD ASSETS", + "share_select_photos": "Select Photos", + "share_create_album": "Create album", + "share_share": "Share", + "share_suggestions": "Suggestions", + "share_invite": "Invite to album", + "share_err_album": "Failed to create album", + "share_empty_list": "EMPTY LIST", + "share_description": "Create shared albums to share photos and videos with people in your network.", + "share_album": "Shared albums" } \ No newline at end of file diff --git a/mobile/lib/modules/sharing/ui/album_title_text_field.dart b/mobile/lib/modules/sharing/ui/album_title_text_field.dart index f777e2863fadd..d06c19e8af624 100644 --- a/mobile/lib/modules/sharing/ui/album_title_text_field.dart +++ b/mobile/lib/modules/sharing/ui/album_title_text_field.dart @@ -1,3 +1,4 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/modules/sharing/providers/album_title.provider.dart'; @@ -58,7 +59,7 @@ class AlbumTitleTextField extends ConsumerWidget { borderSide: const BorderSide(color: Colors.transparent), borderRadius: BorderRadius.circular(10), ), - hintText: 'Add a title', + hintText: 'share_add_title'.tr(), focusColor: Colors.grey[300], fillColor: Colors.grey[200], filled: isAlbumTitleTextFieldFocus.value, diff --git a/mobile/lib/modules/sharing/ui/album_viewer_appbar.dart b/mobile/lib/modules/sharing/ui/album_viewer_appbar.dart index e3ec43ba192f9..3a7a3f3278e82 100644 --- a/mobile/lib/modules/sharing/ui/album_viewer_appbar.dart +++ b/mobile/lib/modules/sharing/ui/album_viewer_appbar.dart @@ -1,4 +1,5 @@ import 'package:auto_route/auto_route.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -41,7 +42,7 @@ class AlbumViewerAppbar extends HookConsumerWidget with PreferredSizeWidget { } else { ImmichToast.show( context: context, - msg: "Failed to delete album", + msg: "share_err_delete".tr(), toastType: ToastType.error, gravity: ToastGravity.BOTTOM, ); @@ -61,7 +62,7 @@ class AlbumViewerAppbar extends HookConsumerWidget with PreferredSizeWidget { Navigator.pop(context); ImmichToast.show( context: context, - msg: "Failed to leave album", + msg: "share_err_leave".tr(), toastType: ToastType.error, gravity: ToastGravity.BOTTOM, ); @@ -86,7 +87,7 @@ class AlbumViewerAppbar extends HookConsumerWidget with PreferredSizeWidget { Navigator.pop(context); ImmichToast.show( context: context, - msg: "There are problems in removing assets from album", + msg: "share_err_remove".tr(), toastType: ToastType.error, gravity: ToastGravity.BOTTOM, ); @@ -101,9 +102,9 @@ class AlbumViewerAppbar extends HookConsumerWidget with PreferredSizeWidget { return ListTile( leading: const Icon(Icons.delete_sweep_rounded), title: const Text( - 'Remove from album', + 'share_remove', style: TextStyle(fontWeight: FontWeight.bold), - ), + ).tr(), onTap: () => _onRemoveFromAlbumPressed(albumId), ); } else { @@ -114,18 +115,18 @@ class AlbumViewerAppbar extends HookConsumerWidget with PreferredSizeWidget { return ListTile( leading: const Icon(Icons.delete_forever_rounded), title: const Text( - 'Delete album', + 'share_delete', style: TextStyle(fontWeight: FontWeight.bold), - ), + ).tr(), onTap: () => _onDeleteAlbumPressed(albumId), ); } else { return ListTile( leading: const Icon(Icons.person_remove_rounded), title: const Text( - 'Leave album', + 'share_leave', style: TextStyle(fontWeight: FontWeight.bold), - ), + ).tr(), onTap: () => _onLeaveAlbumPressed(albumId), ); } @@ -166,7 +167,7 @@ class AlbumViewerAppbar extends HookConsumerWidget with PreferredSizeWidget { if (!isSuccess) { ImmichToast.show( context: context, - msg: "Failed to change album title", + msg: "share_err_title".tr(), gravity: ToastGravity.BOTTOM, toastType: ToastType.error, ); diff --git a/mobile/lib/modules/sharing/ui/album_viewer_editable_title.dart b/mobile/lib/modules/sharing/ui/album_viewer_editable_title.dart index 191b5de1a4c29..d0a219982d96a 100644 --- a/mobile/lib/modules/sharing/ui/album_viewer_editable_title.dart +++ b/mobile/lib/modules/sharing/ui/album_viewer_editable_title.dart @@ -1,3 +1,4 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -69,7 +70,7 @@ class AlbumViewerEditableTitle extends HookConsumerWidget { focusColor: Colors.grey[300], fillColor: Colors.grey[200], filled: titleFocusNode.hasFocus, - hintText: 'Add a title', + hintText: 'share_add_title'.tr(), ), ); } diff --git a/mobile/lib/modules/sharing/ui/sharing_sliver_appbar.dart b/mobile/lib/modules/sharing/ui/sharing_sliver_appbar.dart index 60ffd929111d9..0bdfc88ef7036 100644 --- a/mobile/lib/modules/sharing/ui/sharing_sliver_appbar.dart +++ b/mobile/lib/modules/sharing/ui/sharing_sliver_appbar.dart @@ -1,4 +1,5 @@ import 'package:auto_route/auto_route.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:immich_mobile/routing/router.dart'; @@ -48,9 +49,9 @@ class SharingSliverAppBar extends StatelessWidget { size: 20, ), label: const Text( - "Create shared album", + "create_shared_album", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 12), - ), + ).tr(), ), ), ), @@ -68,9 +69,9 @@ class SharingSliverAppBar extends StatelessWidget { size: 20, ), label: const Text( - "Share with partner", + "share_partner", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 12), - ), + ).tr(), ), ), ) diff --git a/mobile/lib/modules/sharing/views/album_viewer_page.dart b/mobile/lib/modules/sharing/views/album_viewer_page.dart index 653f66021be62..d5ce4a9a84b84 100644 --- a/mobile/lib/modules/sharing/views/album_viewer_page.dart +++ b/mobile/lib/modules/sharing/views/album_viewer_page.dart @@ -1,4 +1,5 @@ import 'package:auto_route/auto_route.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -195,13 +196,13 @@ class AlbumViewerPage extends HookConsumerWidget { AlbumActionOutlinedButton( iconData: Icons.add_photo_alternate_outlined, onPressed: () => _onAddPhotosPressed(albumInfo), - labelText: "Add photos", + labelText: "share_add_photos".tr(), ), userId == albumInfo.ownerId ? AlbumActionOutlinedButton( iconData: Icons.person_add_alt_rounded, onPressed: () => _onAddUsersPressed(albumInfo), - labelText: "Add users", + labelText: "share_add_users".tr(), ) : Container(), ], diff --git a/mobile/lib/modules/sharing/views/asset_selection_page.dart b/mobile/lib/modules/sharing/views/asset_selection_page.dart index 5147e71f1fdf5..f52716d1ccde2 100644 --- a/mobile/lib/modules/sharing/views/asset_selection_page.dart +++ b/mobile/lib/modules/sharing/views/asset_selection_page.dart @@ -1,4 +1,5 @@ import 'package:auto_route/auto_route.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -62,9 +63,9 @@ class AssetSelectionPage extends HookConsumerWidget { ), title: selectedAssets.isEmpty ? const Text( - 'Add photos', + 'share_add_photos', style: TextStyle(fontSize: 18), - ) + ).tr() : Text( _buildAssetCountText(), style: const TextStyle(fontSize: 18), @@ -82,9 +83,9 @@ class AssetSelectionPage extends HookConsumerWidget { AutoRouter.of(context).pop(payload); }, child: const Text( - "Add", + "share_add", style: TextStyle(fontWeight: FontWeight.bold), - ), + ).tr(), ) : Container() ], diff --git a/mobile/lib/modules/sharing/views/create_shared_album_page.dart b/mobile/lib/modules/sharing/views/create_shared_album_page.dart index 1da6312ed2e98..8d510653f3d18 100644 --- a/mobile/lib/modules/sharing/views/create_shared_album_page.dart +++ b/mobile/lib/modules/sharing/views/create_shared_album_page.dart @@ -1,4 +1,5 @@ import 'package:auto_route/auto_route.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -62,13 +63,13 @@ class CreateSharedAlbumPage extends HookConsumerWidget { _buildTitle() { if (selectedAssets.isEmpty) { - return const SliverToBoxAdapter( + return SliverToBoxAdapter( child: Padding( padding: EdgeInsets.only(top: 200, left: 18), child: Text( - 'ADD ASSETS', + 'share_add_assets', style: TextStyle(fontSize: 12), - ), + ).tr(), ), ); } @@ -92,9 +93,9 @@ class CreateSharedAlbumPage extends HookConsumerWidget { label: Padding( padding: const EdgeInsets.only(left: 8.0), child: Text( - 'Select Photos', + 'share_select_photos', style: TextStyle(fontSize: 16, color: Colors.grey[700], fontWeight: FontWeight.bold), - ), + ).tr(), ), ), ), @@ -116,7 +117,7 @@ class CreateSharedAlbumPage extends HookConsumerWidget { AlbumActionOutlinedButton( iconData: Icons.add_photo_alternate_outlined, onPressed: _onSelectPhotosButtonPressed, - labelText: "Add photos", + labelText: "share_add_photos".tr(), ), ], ), @@ -164,14 +165,14 @@ class CreateSharedAlbumPage extends HookConsumerWidget { }, icon: const Icon(Icons.close_rounded)), title: const Text( - 'Create album', + 'share_create_album', style: TextStyle(color: Colors.black), - ), + ).tr(), actions: [ TextButton( onPressed: albumTitleController.text.isNotEmpty ? _showSelectUserPage : null, - child: const Text( - 'Share', + child: Text( + 'share_share'.tr(), style: TextStyle( fontWeight: FontWeight.bold, ), diff --git a/mobile/lib/modules/sharing/views/select_additional_user_for_sharing_page.dart b/mobile/lib/modules/sharing/views/select_additional_user_for_sharing_page.dart index d01693aae6a8e..81e5227d14cc3 100644 --- a/mobile/lib/modules/sharing/views/select_additional_user_for_sharing_page.dart +++ b/mobile/lib/modules/sharing/views/select_additional_user_for_sharing_page.dart @@ -1,4 +1,5 @@ import 'package:auto_route/auto_route.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -61,10 +62,10 @@ class SelectAdditionalUserForSharingPage extends HookConsumerWidget { Wrap( children: [...usersChip], ), - const Padding( + Padding( padding: EdgeInsets.all(16.0), child: Text( - 'Suggestions', + 'share_suggestions'.tr(), style: TextStyle(fontSize: 14, color: Colors.grey, fontWeight: FontWeight.bold), ), ), @@ -96,9 +97,9 @@ class SelectAdditionalUserForSharingPage extends HookConsumerWidget { return Scaffold( appBar: AppBar( title: const Text( - 'Invite to album', + 'share_invite', style: TextStyle(color: Colors.black), - ), + ).tr(), elevation: 0, centerTitle: false, leading: IconButton( @@ -111,9 +112,9 @@ class SelectAdditionalUserForSharingPage extends HookConsumerWidget { TextButton( onPressed: sharedUsersList.value.isEmpty ? null : _addNewUsersHandler, child: const Text( - "Add", + "share_add", style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold), - ), + ).tr(), ) ], ), diff --git a/mobile/lib/modules/sharing/views/select_user_for_sharing_page.dart b/mobile/lib/modules/sharing/views/select_user_for_sharing_page.dart index 91d7971badfc6..bb379d55bb370 100644 --- a/mobile/lib/modules/sharing/views/select_user_for_sharing_page.dart +++ b/mobile/lib/modules/sharing/views/select_user_for_sharing_page.dart @@ -1,4 +1,5 @@ import 'package:auto_route/auto_route.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -33,7 +34,7 @@ class SelectUserForSharingPage extends HookConsumerWidget { AutoRouter.of(context).navigate(const TabControllerRoute(children: [SharingRoute()])); } - const ScaffoldMessenger(child: SnackBar(content: Text('Failed to create album'))); + ScaffoldMessenger(child: SnackBar(content: Text('share_err_album').tr())); } _buildTileIcon(User user) { @@ -76,12 +77,12 @@ class SelectUserForSharingPage extends HookConsumerWidget { Wrap( children: [...usersChip], ), - const Padding( + Padding( padding: EdgeInsets.all(16.0), child: Text( - 'Suggestions', + 'share_suggestions', style: TextStyle(fontSize: 14, color: Colors.grey, fontWeight: FontWeight.bold), - ), + ).tr(), ), ListView.builder( shrinkWrap: true, @@ -111,9 +112,9 @@ class SelectUserForSharingPage extends HookConsumerWidget { return Scaffold( appBar: AppBar( title: const Text( - 'Invite to album', + 'share_invite', style: TextStyle(color: Colors.black), - ), + ).tr(), elevation: 0, centerTitle: false, leading: IconButton( @@ -126,9 +127,9 @@ class SelectUserForSharingPage extends HookConsumerWidget { TextButton( onPressed: sharedUsersList.value.isEmpty ? null : _createSharedAlbum, child: const Text( - "Create Album", + "share_create_album", style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold), - )) + ).tr()) ], ), body: suggestedShareUsers.when( diff --git a/mobile/lib/modules/sharing/views/sharing_page.dart b/mobile/lib/modules/sharing/views/sharing_page.dart index cad49e4ad954b..7a935dcec2184 100644 --- a/mobile/lib/modules/sharing/views/sharing_page.dart +++ b/mobile/lib/modules/sharing/views/sharing_page.dart @@ -1,4 +1,5 @@ import 'package:auto_route/auto_route.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hive/hive.dart'; @@ -96,20 +97,20 @@ class SharingPage extends HookConsumerWidget { Padding( padding: const EdgeInsets.all(8.0), child: Text( - 'EMPTY LIST', + 'share_empty_list', style: TextStyle( fontSize: 12, color: Theme.of(context).primaryColor, fontWeight: FontWeight.bold, ), - ), + ).tr(), ), Padding( padding: const EdgeInsets.all(8.0), child: Text( - 'Create shared albums to share photos and videos with people in your network.', + 'share_description', style: TextStyle(fontSize: 12, color: Colors.grey[700]), - ), + ).tr(), ), ], ), @@ -123,15 +124,15 @@ class SharingPage extends HookConsumerWidget { body: CustomScrollView( slivers: [ const SharingSliverAppBar(), - const SliverPadding( + SliverPadding( padding: EdgeInsets.symmetric(horizontal: 12, vertical: 12), sliver: SliverToBoxAdapter( child: Text( - "Shared albums", + "share_album", style: TextStyle( fontWeight: FontWeight.bold, ), - ), + ).tr(), ), ), sharedAlbums.isNotEmpty ? _buildAlbumList() : _buildEmptyListIndication() From 50c0847edea493b2e465b5a56673f698f3082d18 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 22 Jun 2022 17:55:39 +0200 Subject: [PATCH 04/23] Localization of asset viewer section --- i18n/translations/de-DE.csv | 7 ++++++- i18n/translations/en-US.csv | 7 ++++++- mobile/assets/i18n/de-DE.json | 7 ++++++- mobile/assets/i18n/en-US.json | 7 ++++++- .../asset_viewer/ui/exif_bottom_sheet.dart | 15 ++++++++------- .../asset_viewer/views/image_viewer_page.dart | 5 +++-- 6 files changed, 35 insertions(+), 13 deletions(-) diff --git a/i18n/translations/de-DE.csv b/i18n/translations/de-DE.csv index 2983518737a43..e419a50183b8e 100644 --- a/i18n/translations/de-DE.csv +++ b/i18n/translations/de-DE.csv @@ -1,3 +1,4 @@ +date_format,"E, LLL d, y • HH:mm" login_button_text,Anmelden save_login,Angemeldet bleiben login_endpoint_url,Server URL @@ -32,4 +33,8 @@ share_invite,Zu Album einladen share_err_album,Fehler beim Erstellen des Albums share_empty_list,LEERE LISTE share_description,Erstelle geteilte Alben um Fotos und Videos mit Menschen aus deinem Netzwerk zu teilen. -share_album,Geteilte Alben \ No newline at end of file +share_album,Geteilte Alben +asset_description,Beschreibung hinzufügen... +asset_location,STANDORT +asset_details,DETAILS +asset_err_corrupted,Fehler bei der Darstellung - Daten sind beschädigt \ No newline at end of file diff --git a/i18n/translations/en-US.csv b/i18n/translations/en-US.csv index 51d5377efecf5..de5444c586db7 100644 --- a/i18n/translations/en-US.csv +++ b/i18n/translations/en-US.csv @@ -1,3 +1,4 @@ +date_format,"E, LLL d, y • h:mm a" login_button_text,Login save_login,Save Login login_endpoint_url,Server Endpoint URL @@ -32,4 +33,8 @@ share_invite,Invite to album share_err_album,Failed to create album share_empty_list,EMPTY LIST share_description,Create shared albums to share photos and videos with people in your network. -share_album,Shared albums \ No newline at end of file +share_album,Shared albums +asset_description,Add Description... +asset_location,LOCATION +asset_details,DETAILS +asset_err_corrupted,Failed To Render Image - Possibly Corrupted Data \ No newline at end of file diff --git a/mobile/assets/i18n/de-DE.json b/mobile/assets/i18n/de-DE.json index d832c67f99b96..18bee87f637d7 100644 --- a/mobile/assets/i18n/de-DE.json +++ b/mobile/assets/i18n/de-DE.json @@ -1,4 +1,5 @@ { + "date_format": "E, LLL d, y \u2022 HH:mm", "login_button_text": "Anmelden", "save_login": "Angemeldet bleiben", "login_endpoint_url": "Server URL", @@ -33,5 +34,9 @@ "share_err_album": "Fehler beim Erstellen des Albums", "share_empty_list": "LEERE LISTE", "share_description": "Erstelle geteilte Alben um Fotos und Videos mit Menschen aus deinem Netzwerk zu teilen.", - "share_album": "Geteilte Alben" + "share_album": "Geteilte Alben", + "asset_description": "Beschreibung hinzuf\u00fcgen...", + "asset_location": "STANDORT", + "asset_details": "DETAILS", + "asset_err_corrupted": "Fehler bei der Darstellung - Daten sind besch\u00e4digt" } \ No newline at end of file diff --git a/mobile/assets/i18n/en-US.json b/mobile/assets/i18n/en-US.json index 4a4188072d8b8..aa6dcdce39350 100644 --- a/mobile/assets/i18n/en-US.json +++ b/mobile/assets/i18n/en-US.json @@ -1,4 +1,5 @@ { + "date_format": "E, LLL d, y \u2022 h:mm a", "login_button_text": "Login", "save_login": "Save Login", "login_endpoint_url": "Server Endpoint URL", @@ -33,5 +34,9 @@ "share_err_album": "Failed to create album", "share_empty_list": "EMPTY LIST", "share_description": "Create shared albums to share photos and videos with people in your network.", - "share_album": "Shared albums" + "share_album": "Shared albums", + "asset_description": "Add Description...", + "asset_location": "LOCATION", + "asset_details": "DETAILS", + "asset_err_corrupted": "Failed To Render Image - Possibly Corrupted Data" } \ No newline at end of file diff --git a/mobile/lib/modules/asset_viewer/ui/exif_bottom_sheet.dart b/mobile/lib/modules/asset_viewer/ui/exif_bottom_sheet.dart index c22843b69ad09..0ab5e961d37a3 100644 --- a/mobile/lib/modules/asset_viewer/ui/exif_bottom_sheet.dart +++ b/mobile/lib/modules/asset_viewer/ui/exif_bottom_sheet.dart @@ -1,3 +1,4 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_map/flutter_map.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -70,7 +71,7 @@ class ExifBottomSheet extends ConsumerWidget { children: [ assetDetail.exifInfo?.dateTimeOriginal != null ? Text( - DateFormat('E, LLL d, y • h:mm a').format( + DateFormat('date_format'.tr()).format( DateTime.parse(assetDetail.exifInfo!.dateTimeOriginal!), ), style: TextStyle( @@ -83,12 +84,12 @@ class ExifBottomSheet extends ConsumerWidget { Padding( padding: const EdgeInsets.only(top: 16.0), child: Text( - "Add Description...", + "asset_description", style: TextStyle( color: Colors.grey[500], fontSize: 11, ), - ), + ).tr(), ), // Location @@ -103,9 +104,9 @@ class ExifBottomSheet extends ConsumerWidget { color: Colors.grey[600], ), Text( - "LOCATION", + "asset_location", style: TextStyle(fontSize: 11, color: Colors.grey[400]), - ), + ).tr(), _buildMap(), _buildLocationText(), Text( @@ -130,9 +131,9 @@ class ExifBottomSheet extends ConsumerWidget { Padding( padding: const EdgeInsets.only(bottom: 8.0), child: Text( - "DETAILS", + "asset_details", style: TextStyle(fontSize: 11, color: Colors.grey[400]), - ), + ).tr(), ), ListTile( contentPadding: const EdgeInsets.all(0), diff --git a/mobile/lib/modules/asset_viewer/views/image_viewer_page.dart b/mobile/lib/modules/asset_viewer/views/image_viewer_page.dart index 6dd7fd1457357..05e1af3a290e7 100644 --- a/mobile/lib/modules/asset_viewer/views/image_viewer_page.dart +++ b/mobile/lib/modules/asset_viewer/views/image_viewer_page.dart @@ -1,5 +1,6 @@ import 'package:auto_route/auto_route.dart'; import 'package:cached_network_image/cached_network_image.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_swipe_detector/flutter_swipe_detector.dart'; @@ -89,10 +90,10 @@ class ImageViewerPage extends HookConsumerWidget { alignment: WrapAlignment.center, children: [ const Text( - "Failed To Render Image - Possibly Corrupted Data", + "asset_err_corrupted", textAlign: TextAlign.center, style: TextStyle(fontSize: 16, color: Colors.white), - ), + ).tr(), SingleChildScrollView( child: Text( error.toString(), From 067c9e3f1b08b6ca4177251d5653e186e1f751bc Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 22 Jun 2022 23:21:29 +0200 Subject: [PATCH 05/23] Use JSON as base translation format --- i18n/gen_lang_files.py | 17 +++++++++------ i18n/translations/de-DE.csv | 40 ---------------------------------- i18n/translations/de-DE.json | 42 ++++++++++++++++++++++++++++++++++++ i18n/translations/en-US.csv | 40 ---------------------------------- i18n/translations/en-US.json | 42 ++++++++++++++++++++++++++++++++++++ 5 files changed, 94 insertions(+), 87 deletions(-) delete mode 100644 i18n/translations/de-DE.csv create mode 100644 i18n/translations/de-DE.json delete mode 100644 i18n/translations/en-US.csv create mode 100644 i18n/translations/en-US.json diff --git a/i18n/gen_lang_files.py b/i18n/gen_lang_files.py index df6f8798b82bc..ea505685f2c69 100644 --- a/i18n/gen_lang_files.py +++ b/i18n/gen_lang_files.py @@ -1,9 +1,9 @@ #!/usr/bin/env python3 -import csv import glob import os import logging import json +import sys class Translation: @@ -20,9 +20,9 @@ def get_translation(self): return self.translation -def parse_language_csv(filename): +def parse_language_json(filename): with open(filename, 'r') as file: - return [Translation(t) for t in csv.reader(file, delimiter=',', quotechar='"')] + return [Translation(t) for t in json.load(file).items()] def generate_mobile_translations(lang, translations): @@ -35,11 +35,11 @@ def generate_mobile_translations(lang, translations): def generate_language_files(): - for file in glob.glob(os.path.join('translations', '*.csv'), recursive=False): - language_code = os.path.basename(file)[:-4] + for file in glob.glob(os.path.join('translations', '*.json'), recursive=False): + language_code = os.path.basename(file)[:-5] logging.info('Language Code: %s', language_code) - translations = parse_language_csv(file) + translations = parse_language_json(file) logging.debug(translations) generate_mobile_translations(language_code, translations) @@ -47,4 +47,7 @@ def generate_language_files(): if __name__ == '__main__': logging.basicConfig(format='%(levelname)s : %(message)s', level=logging.DEBUG) - generate_language_files() + + if len(sys.argv) < 2: + generate_language_files() + diff --git a/i18n/translations/de-DE.csv b/i18n/translations/de-DE.csv deleted file mode 100644 index e419a50183b8e..0000000000000 --- a/i18n/translations/de-DE.csv +++ /dev/null @@ -1,40 +0,0 @@ -date_format,"E, LLL d, y • HH:mm" -login_button_text,Anmelden -save_login,Angemeldet bleiben -login_endpoint_url,Server URL -login_endpoint_hint,http://dein-server:port -login_err_trailing_whitespace,Abschließendes Leerzeichen -login_err_leading_whitespace,Führendes Leerzeichen -login_err_invalid_email,Ungültige Email-Adresse -login_err_http,Muss mit http:// oder https:// starten -login_label_email,Email-Adresse -login_email_hint,deine@email.com -login_label_password,Passwort -login_password_hint,passwort -share_add_title,Titel hinzufügen -share_err_delete,Fehler beim Löschen des Albums -share_err_leave,Fehler beim Verlassen des Albums -share_err_remove,Einträge konnten nicht aus dem Album gelöscht werden -share_err_title,Fehler beim Ändern des Titels -share_remove,Aus Album entfernen -share_delete,Album löschen -share_leave,Album verlassen -create_shared_album,Geteiltes Album erstellen -share_partner,Mit Partner teilen -share_add_photos,Fotos hinzufügen -share_add_users,Nutzer hinzufügen -share_add,Hinzufügen -share_add_assets,EINTRÄGE HINZUFÜGEN -share_select_photos,Fotos auswählen -share_create_album,Album erstellen -share_share,Teilen -share_suggestions,Vorschläge -share_invite,Zu Album einladen -share_err_album,Fehler beim Erstellen des Albums -share_empty_list,LEERE LISTE -share_description,Erstelle geteilte Alben um Fotos und Videos mit Menschen aus deinem Netzwerk zu teilen. -share_album,Geteilte Alben -asset_description,Beschreibung hinzufügen... -asset_location,STANDORT -asset_details,DETAILS -asset_err_corrupted,Fehler bei der Darstellung - Daten sind beschädigt \ No newline at end of file diff --git a/i18n/translations/de-DE.json b/i18n/translations/de-DE.json new file mode 100644 index 0000000000000..74ea5f3bd8a49 --- /dev/null +++ b/i18n/translations/de-DE.json @@ -0,0 +1,42 @@ +{ + "date_format": "E, LLL d, y • HH:mm", + "login_button_text": "Anmelden", + "save_login": "Angemeldet bleiben", + "login_endpoint_url": "Server URL", + "login_endpoint_hint": "http://dein-server:port", + "login_err_trailing_whitespace": "Abschließendes Leerzeichen", + "login_err_leading_whitespace": "Führendes Leerzeichen", + "login_err_invalid_email": "Ungültige Email-Adresse", + "login_err_http": "Muss mit http:// oder https:// starten", + "login_label_email": "Email-Adresse", + "login_email_hint": "deine@email.com", + "login_label_password": "Passwort", + "login_password_hint": "passwort", + "share_add_title": "Titel hinzufügen", + "share_err_delete": "Fehler beim Löschen des Albums", + "share_err_leave": "Fehler beim Verlassen des Albums", + "share_err_remove": "Einträge konnten nicht aus dem Album gelöscht werden", + "share_err_title": "Fehler beim Ändern des Titels", + "share_remove": "Aus Album entfernen", + "share_delete": "Album löschen", + "share_leave": "Album verlassen", + "create_shared_album": "Geteiltes Album erstellen", + "share_partner": "Mit Partner teilen", + "share_add_photos": "Fotos hinzufügen", + "share_add_users": "Nutzer hinzufügen", + "share_add": "Hinzufügen", + "share_add_assets": "EINTRÄGE HINZUFÜGEN", + "share_select_photos": "Fotos auswählen", + "share_create_album": "Album erstellen", + "share_share": "Teilen", + "share_suggestions": "Vorschläge", + "share_invite": "Zu Album einladen", + "share_err_album": "Fehler beim Erstellen des Albums", + "share_empty_list": "LEERE LISTE", + "share_description": "Erstelle geteilte Alben um Fotos und Videos mit Menschen aus deinem Netzwerk zu teilen.", + "share_album": "Geteilte Alben", + "asset_description": "Beschreibung hinzufügen...", + "asset_location": "STANDORT", + "asset_details": "DETAILS", + "asset_err_corrupted": "Fehler bei der Darstellung - Daten sind beschädigt" +} \ No newline at end of file diff --git a/i18n/translations/en-US.csv b/i18n/translations/en-US.csv deleted file mode 100644 index de5444c586db7..0000000000000 --- a/i18n/translations/en-US.csv +++ /dev/null @@ -1,40 +0,0 @@ -date_format,"E, LLL d, y • h:mm a" -login_button_text,Login -save_login,Save Login -login_endpoint_url,Server Endpoint URL -login_endpoint_hint,http://your-server-ip:port -login_err_trailing_whitespace,Trailing whitespace -login_err_leading_whitespace,Leading whitespace -login_err_invalid_email,Invalid Email -login_err_http,Please specify http:// or https:// -login_label_email,Email -login_email_hint,youremail@email.com -login_label_password,Password -login_password_hint,password -share_add_title,Add a title -share_err_delete,Failed to delete album -share_err_leave,Failed to leave album -share_err_remove,There are problems in removing assets from album -share_err_title,Failed to change album title -share_remove,Remove from album -share_delete,Delete album -share_leave,Leave album -create_shared_album,Create shared album -share_partner,Share with partner -share_add_photos,Add photos -share_add_users,Add users -share_add,Add -share_add_assets,ADD ASSETS -share_select_photos,Select Photos -share_create_album,Create album -share_share,Share -share_suggestions,Suggestions -share_invite,Invite to album -share_err_album,Failed to create album -share_empty_list,EMPTY LIST -share_description,Create shared albums to share photos and videos with people in your network. -share_album,Shared albums -asset_description,Add Description... -asset_location,LOCATION -asset_details,DETAILS -asset_err_corrupted,Failed To Render Image - Possibly Corrupted Data \ No newline at end of file diff --git a/i18n/translations/en-US.json b/i18n/translations/en-US.json new file mode 100644 index 0000000000000..b1fdd8144c7b5 --- /dev/null +++ b/i18n/translations/en-US.json @@ -0,0 +1,42 @@ +{ + "date_format": "E, LLL d, y • h:mm a", + "login_button_text": "Login", + "save_login": "Save Login", + "login_endpoint_url": "Server Endpoint URL", + "login_endpoint_hint": "http://your-server-ip:port", + "login_err_trailing_whitespace": "Trailing whitespace", + "login_err_leading_whitespace": "Leading whitespace", + "login_err_invalid_email": "Invalid Email", + "login_err_http": "Please specify http:// or https://", + "login_label_email": "Email", + "login_email_hint": "youremail@email.com", + "login_label_password": "Password", + "login_password_hint": "password", + "share_add_title": "Add a title", + "share_err_delete": "Failed to delete album", + "share_err_leave": "Failed to leave album", + "share_err_remove": "There are problems in removing assets from album", + "share_err_title": "Failed to change album title", + "share_remove": "Remove from album", + "share_delete": "Delete album", + "share_leave": "Leave album", + "create_shared_album": "Create shared album", + "share_partner": "Share with partner", + "share_add_photos": "Add photos", + "share_add_users": "Add users", + "share_add": "Add", + "share_add_assets": "ADD ASSETS", + "share_select_photos": "Select Photos", + "share_create_album": "Create album", + "share_share": "Share", + "share_suggestions": "Suggestions", + "share_invite": "Invite to album", + "share_err_album": "Failed to create album", + "share_empty_list": "EMPTY LIST", + "share_description": "Create shared albums to share photos and videos with people in your network.", + "share_album": "Shared albums", + "asset_description": "Add Description...", + "asset_location": "LOCATION", + "asset_details": "DETAILS", + "asset_err_corrupted": "Failed To Render Image - Possibly Corrupted Data" +} \ No newline at end of file From ca62000fb30990c323a004a0ee85cab27f2b1349 Mon Sep 17 00:00:00 2001 From: Matthias Date: Wed, 22 Jun 2022 23:36:39 +0200 Subject: [PATCH 06/23] Add check for missing/unused translation keys --- i18n/gen_lang_files.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/i18n/gen_lang_files.py b/i18n/gen_lang_files.py index ea505685f2c69..110a08af43f50 100644 --- a/i18n/gen_lang_files.py +++ b/i18n/gen_lang_files.py @@ -45,9 +45,40 @@ def generate_language_files(): generate_mobile_translations(language_code, translations) +def get_translation_keys(translations): + return [i.get_key() for i in translations] + + +def check_keys(): + en_us_keys = get_translation_keys(parse_language_json(os.path.join('translations', 'en-US.json'))) + + ok = True + + for file in glob.glob(os.path.join('translations', '*.json'), recursive=False): + keys = get_translation_keys(parse_language_json(file)) + + for k in en_us_keys: + if k not in keys: + logging.error('File %s: missing key %s', file, k) + ok = False + + for k in keys: + if k not in en_us_keys: + logging.error('File %s: contains unused key %s', file, k) + ok = False + + if ok: + logging.info('No key errors found!') + + return ok + + if __name__ == '__main__': logging.basicConfig(format='%(levelname)s : %(message)s', level=logging.DEBUG) if len(sys.argv) < 2: generate_language_files() + elif sys.argv[1] == 'check-keys': + sys.exit(0 if check_keys() else 1) + From 2dd1df80c203d68b8d72b2cb9c1ecdb1171d1205 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 23 Jun 2022 14:58:26 +0200 Subject: [PATCH 07/23] Add localizely --- localizely.yml | 15 +++++++++++++++ mobile/assets/i18n/de-DE.json | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 localizely.yml diff --git a/localizely.yml b/localizely.yml new file mode 100644 index 0000000000000..648b1ad1ad4cc --- /dev/null +++ b/localizely.yml @@ -0,0 +1,15 @@ +config_version: 1.0 +project_id: 4fda40f2-8e20-48cf-97e8-0062c2b93ffc +file_type: flutter_arb +upload: + files: + - file: mobile/assets/i18n/en-US.json + locale_code: en + - file: mobile/assets/i18n/de-DE.json + locale_code: de +download: + files: + - file: mobile/assets/i18n/en-US.json + locale_code: en + - file: mobile/assets/i18n/de-DE.json + locale_code: de diff --git a/mobile/assets/i18n/de-DE.json b/mobile/assets/i18n/de-DE.json index 18bee87f637d7..bbb3b8ea3d540 100644 --- a/mobile/assets/i18n/de-DE.json +++ b/mobile/assets/i18n/de-DE.json @@ -39,4 +39,4 @@ "asset_location": "STANDORT", "asset_details": "DETAILS", "asset_err_corrupted": "Fehler bei der Darstellung - Daten sind besch\u00e4digt" -} \ No newline at end of file +} From a249e371b690a6dee1ba5cabc2b347ad222bf7a7 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 23 Jun 2022 17:27:08 +0200 Subject: [PATCH 08/23] Remove i18n directory in favour of localizely --- i18n/gen_lang_files.py | 84 ------------------------------------ i18n/translations/de-DE.json | 42 ------------------ i18n/translations/en-US.json | 42 ------------------ 3 files changed, 168 deletions(-) delete mode 100644 i18n/gen_lang_files.py delete mode 100644 i18n/translations/de-DE.json delete mode 100644 i18n/translations/en-US.json diff --git a/i18n/gen_lang_files.py b/i18n/gen_lang_files.py deleted file mode 100644 index 110a08af43f50..0000000000000 --- a/i18n/gen_lang_files.py +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/env python3 -import glob -import os -import logging -import json -import sys - - -class Translation: - def __init__(self, translation_tuple): - self.key, self.translation = translation_tuple - - def __repr__(self): - return f'{self.key} => {self.translation}' - - def get_key(self): - return self.key - - def get_translation(self): - return self.translation - - -def parse_language_json(filename): - with open(filename, 'r') as file: - return [Translation(t) for t in json.load(file).items()] - - -def generate_mobile_translations(lang, translations): - with open(os.path.join('..', 'mobile', 'assets', 'i18n', f'{lang}.json'), 'w') as file: - translations_obj = {} - for t in translations: - translations_obj[t.get_key()] = t.get_translation() - - file.write(json.dumps(translations_obj, indent=2)) - - -def generate_language_files(): - for file in glob.glob(os.path.join('translations', '*.json'), recursive=False): - language_code = os.path.basename(file)[:-5] - logging.info('Language Code: %s', language_code) - - translations = parse_language_json(file) - logging.debug(translations) - - generate_mobile_translations(language_code, translations) - - -def get_translation_keys(translations): - return [i.get_key() for i in translations] - - -def check_keys(): - en_us_keys = get_translation_keys(parse_language_json(os.path.join('translations', 'en-US.json'))) - - ok = True - - for file in glob.glob(os.path.join('translations', '*.json'), recursive=False): - keys = get_translation_keys(parse_language_json(file)) - - for k in en_us_keys: - if k not in keys: - logging.error('File %s: missing key %s', file, k) - ok = False - - for k in keys: - if k not in en_us_keys: - logging.error('File %s: contains unused key %s', file, k) - ok = False - - if ok: - logging.info('No key errors found!') - - return ok - - -if __name__ == '__main__': - logging.basicConfig(format='%(levelname)s : %(message)s', level=logging.DEBUG) - - if len(sys.argv) < 2: - generate_language_files() - - elif sys.argv[1] == 'check-keys': - sys.exit(0 if check_keys() else 1) - diff --git a/i18n/translations/de-DE.json b/i18n/translations/de-DE.json deleted file mode 100644 index 74ea5f3bd8a49..0000000000000 --- a/i18n/translations/de-DE.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "date_format": "E, LLL d, y • HH:mm", - "login_button_text": "Anmelden", - "save_login": "Angemeldet bleiben", - "login_endpoint_url": "Server URL", - "login_endpoint_hint": "http://dein-server:port", - "login_err_trailing_whitespace": "Abschließendes Leerzeichen", - "login_err_leading_whitespace": "Führendes Leerzeichen", - "login_err_invalid_email": "Ungültige Email-Adresse", - "login_err_http": "Muss mit http:// oder https:// starten", - "login_label_email": "Email-Adresse", - "login_email_hint": "deine@email.com", - "login_label_password": "Passwort", - "login_password_hint": "passwort", - "share_add_title": "Titel hinzufügen", - "share_err_delete": "Fehler beim Löschen des Albums", - "share_err_leave": "Fehler beim Verlassen des Albums", - "share_err_remove": "Einträge konnten nicht aus dem Album gelöscht werden", - "share_err_title": "Fehler beim Ändern des Titels", - "share_remove": "Aus Album entfernen", - "share_delete": "Album löschen", - "share_leave": "Album verlassen", - "create_shared_album": "Geteiltes Album erstellen", - "share_partner": "Mit Partner teilen", - "share_add_photos": "Fotos hinzufügen", - "share_add_users": "Nutzer hinzufügen", - "share_add": "Hinzufügen", - "share_add_assets": "EINTRÄGE HINZUFÜGEN", - "share_select_photos": "Fotos auswählen", - "share_create_album": "Album erstellen", - "share_share": "Teilen", - "share_suggestions": "Vorschläge", - "share_invite": "Zu Album einladen", - "share_err_album": "Fehler beim Erstellen des Albums", - "share_empty_list": "LEERE LISTE", - "share_description": "Erstelle geteilte Alben um Fotos und Videos mit Menschen aus deinem Netzwerk zu teilen.", - "share_album": "Geteilte Alben", - "asset_description": "Beschreibung hinzufügen...", - "asset_location": "STANDORT", - "asset_details": "DETAILS", - "asset_err_corrupted": "Fehler bei der Darstellung - Daten sind beschädigt" -} \ No newline at end of file diff --git a/i18n/translations/en-US.json b/i18n/translations/en-US.json deleted file mode 100644 index b1fdd8144c7b5..0000000000000 --- a/i18n/translations/en-US.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "date_format": "E, LLL d, y • h:mm a", - "login_button_text": "Login", - "save_login": "Save Login", - "login_endpoint_url": "Server Endpoint URL", - "login_endpoint_hint": "http://your-server-ip:port", - "login_err_trailing_whitespace": "Trailing whitespace", - "login_err_leading_whitespace": "Leading whitespace", - "login_err_invalid_email": "Invalid Email", - "login_err_http": "Please specify http:// or https://", - "login_label_email": "Email", - "login_email_hint": "youremail@email.com", - "login_label_password": "Password", - "login_password_hint": "password", - "share_add_title": "Add a title", - "share_err_delete": "Failed to delete album", - "share_err_leave": "Failed to leave album", - "share_err_remove": "There are problems in removing assets from album", - "share_err_title": "Failed to change album title", - "share_remove": "Remove from album", - "share_delete": "Delete album", - "share_leave": "Leave album", - "create_shared_album": "Create shared album", - "share_partner": "Share with partner", - "share_add_photos": "Add photos", - "share_add_users": "Add users", - "share_add": "Add", - "share_add_assets": "ADD ASSETS", - "share_select_photos": "Select Photos", - "share_create_album": "Create album", - "share_share": "Share", - "share_suggestions": "Suggestions", - "share_invite": "Invite to album", - "share_err_album": "Failed to create album", - "share_empty_list": "EMPTY LIST", - "share_description": "Create shared albums to share photos and videos with people in your network.", - "share_album": "Shared albums", - "asset_description": "Add Description...", - "asset_location": "LOCATION", - "asset_details": "DETAILS", - "asset_err_corrupted": "Failed To Render Image - Possibly Corrupted Data" -} \ No newline at end of file From 821eca66e086bb1a3ff9457b92b178a8fa8898b7 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 23 Jun 2022 19:01:05 +0200 Subject: [PATCH 09/23] Backup Translation --- mobile/assets/i18n/en-US.json | 37 ++++++++- .../modules/backup/ui/album_info_card.dart | 15 ++-- .../modules/backup/ui/backup_info_card.dart | 3 +- .../views/backup_album_selection_page.dart | 35 +++++---- .../backup/views/backup_controller_page.dart | 77 ++++++++++--------- 5 files changed, 103 insertions(+), 64 deletions(-) diff --git a/mobile/assets/i18n/en-US.json b/mobile/assets/i18n/en-US.json index aa6dcdce39350..2ed6cd364f59a 100644 --- a/mobile/assets/i18n/en-US.json +++ b/mobile/assets/i18n/en-US.json @@ -38,5 +38,40 @@ "asset_description": "Add Description...", "asset_location": "LOCATION", "asset_details": "DETAILS", - "asset_err_corrupted": "Failed To Render Image - Possibly Corrupted Data" + "asset_err_corrupted": "Failed To Render Image - Possibly Corrupted Data", + "backup_err_only_album": "Cannot remove the only album", + "backup_server_storage": "Server Storage", + "backup_status_on": "Backup is on", + "backup_status_off": "Backup is off", + "backup_turn_off": "Turn off Backup", + "backup_turn_on": "Turn on Backup", + "desc_backup": "Turn on backup to automatically upload new assets to the server.", + "backup_selected": "Selected: ", + "backup_all": "All", + "backup_none_selected": "None selected", + "backup_excluded": "Excluded: ", + "backup_albums": "Backup Albums", + "backup_to_backup": "Albums to be backup", + "backup_select": "Select", + "backup_backup": "Backup", + "backup_info": "Backup Information", + "backup_total": "Total", + "backup_total_sub": "All unique photos and videos from selected albums", + "backup_backup_sub": "Photos and videos from selected albums that are backup", + "backup_remainder": "Remainder", + "backup_remainder_sub": "Photos and videos that has not been backing up from selected albums", + "backup_assets": "Asset that were being backup: ", + "backup_progress": "Backup Progress:", + "backup_done": "Done", + "backup_cancel": "Cancel", + "start_backup": "Start Backup", + "backup_album_included": "INCLUDED", + "backup_album_excluded": "EXCLUDED", + "backup_info_assets": "assets", + "backup_select_albums": "Select Albums", + "backup_selection_info": "Selection Info", + "backup_total_assets": "Total unique assets", + "backup_albums_device": "Albums on device ", + "backup_albums_tap": "Tap to include, double tap to exclude", + "backup_info_assets_scatter": "Assets can scatter across multiple albums. Thus, albums can be included or excluded during the backup process." } \ No newline at end of file diff --git a/mobile/lib/modules/backup/ui/album_info_card.dart b/mobile/lib/modules/backup/ui/album_info_card.dart index f983f43e32236..8e87f7711c3e1 100644 --- a/mobile/lib/modules/backup/ui/album_info_card.dart +++ b/mobile/lib/modules/backup/ui/album_info_card.dart @@ -1,6 +1,7 @@ import 'dart:typed_data'; import 'package:auto_route/auto_route.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:fluttertoast/fluttertoast.dart'; @@ -31,9 +32,9 @@ class AlbumInfoCard extends HookConsumerWidget { visualDensity: VisualDensity.compact, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)), label: const Text( - "INCLUDED", + "backup_album_included", style: TextStyle(fontSize: 10, color: Colors.white, fontWeight: FontWeight.bold), - ), + ).tr(), backgroundColor: Theme.of(context).primaryColor, ); } else if (isExcluded) { @@ -41,9 +42,9 @@ class AlbumInfoCard extends HookConsumerWidget { visualDensity: VisualDensity.compact, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)), label: const Text( - "EXCLUDED", + "backup_album_excluded", style: TextStyle(fontSize: 10, color: Colors.white, fontWeight: FontWeight.bold), - ), + ).tr(), backgroundColor: Colors.red[300], ); } @@ -69,7 +70,7 @@ class AlbumInfoCard extends HookConsumerWidget { if (ref.watch(backupProvider).selectedBackupAlbums.length == 1) { ImmichToast.show( context: context, - msg: "Cannot remove the only album", + msg: "backup_err_only_album".tr(), toastType: ToastType.error, gravity: ToastGravity.BOTTOM, ); @@ -91,7 +92,7 @@ class AlbumInfoCard extends HookConsumerWidget { ref.watch(backupProvider).selectedBackupAlbums.contains(albumInfo)) { ImmichToast.show( context: context, - msg: "Cannot exclude the only album", + msg: "backup_err_only_album".tr(), toastType: ToastType.error, gravity: ToastGravity.BOTTOM, ); @@ -155,7 +156,7 @@ class AlbumInfoCard extends HookConsumerWidget { Padding( padding: const EdgeInsets.only(top: 2.0), child: Text( - albumInfo.assetCount.toString() + (albumInfo.isAll ? " (ALL)" : ""), + albumInfo.assetCount.toString() + (albumInfo.isAll ? " (${'backup_all'.tr()})" : ""), style: TextStyle(fontSize: 12, color: Colors.grey[600]), ), ) diff --git a/mobile/lib/modules/backup/ui/backup_info_card.dart b/mobile/lib/modules/backup/ui/backup_info_card.dart index d6f52fd354516..f1e87c2a3b317 100644 --- a/mobile/lib/modules/backup/ui/backup_info_card.dart +++ b/mobile/lib/modules/backup/ui/backup_info_card.dart @@ -1,3 +1,4 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; class BackupInfoCard extends StatelessWidget { @@ -39,7 +40,7 @@ class BackupInfoCard extends StatelessWidget { info, style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold), ), - const Text("assets"), + const Text("backup_info_assets").tr(), ], ), ), diff --git a/mobile/lib/modules/backup/views/backup_album_selection_page.dart b/mobile/lib/modules/backup/views/backup_album_selection_page.dart index 100c61057a794..3e65d506b1221 100644 --- a/mobile/lib/modules/backup/views/backup_album_selection_page.dart +++ b/mobile/lib/modules/backup/views/backup_album_selection_page.dart @@ -1,4 +1,5 @@ import 'package:auto_route/auto_route.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:fluttertoast/fluttertoast.dart'; @@ -51,7 +52,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { if (ref.watch(backupProvider).selectedBackupAlbums.length == 1) { ImmichToast.show( context: context, - msg: "Cannot remove the only album", + msg: "backup_err_only_album".tr(), toastType: ToastType.error, gravity: ToastGravity.BOTTOM, ); @@ -122,20 +123,20 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { icon: const Icon(Icons.arrow_back_ios_rounded), ), title: const Text( - "Select Albums", + "backup_select_albums", style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), - ), + ).tr(), elevation: 0, ), body: ListView( physics: const ClampingScrollPhysics(), children: [ - const Padding( - padding: EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0), - child: Text( - "Selection Info", + Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0), + child: const Text( + "backup_selection_info", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14), - ), + ).tr(), ), // Selected Album Chips @@ -164,9 +165,9 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { ListTile( visualDensity: VisualDensity.compact, title: Text( - "Total unique assets", + "backup_total_assets", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14, color: Colors.grey[700]), - ), + ).tr(), trailing: Text( ref.watch(backupProvider).allUniqueAssets.length.toString(), style: const TextStyle(fontWeight: FontWeight.bold), @@ -179,19 +180,19 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { ListTile( title: Text( - "Albums on device (${availableAlbums.length.toString()})", + "backup_albums_device".tr() + "(${availableAlbums.length.toString()})", style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 14), ), subtitle: Padding( padding: const EdgeInsets.symmetric(vertical: 8.0), child: Text( - "Tap to include, double tap to exclude", + "backup_albums_tap", style: TextStyle( fontSize: 12, color: Theme.of(context).primaryColor, fontWeight: FontWeight.bold, ), - ), + ).tr(), ), trailing: IconButton( splashRadius: 16, @@ -209,20 +210,20 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), elevation: 5, title: Text( - 'Selection Info', + 'backup_selection_info', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Theme.of(context).primaryColor, ), - ), + ).tr(), content: SingleChildScrollView( child: ListBody( children: [ Text( - 'Assets can scatter across multiple albums. Thus, albums can be included or excluded during the backup process.', + 'backup_info_assets_scatter', style: TextStyle(fontSize: 14, color: Colors.grey[700]), - ), + ).tr(), ], ), ), diff --git a/mobile/lib/modules/backup/views/backup_controller_page.dart b/mobile/lib/modules/backup/views/backup_controller_page.dart index 4c8db78a97f53..84ae649aa8a7f 100644 --- a/mobile/lib/modules/backup/views/backup_controller_page.dart +++ b/mobile/lib/modules/backup/views/backup_controller_page.dart @@ -1,4 +1,5 @@ import 'package:auto_route/auto_route.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -37,9 +38,9 @@ class BackupControllerPage extends HookConsumerWidget { color: Theme.of(context).primaryColor, ), title: const Text( - "Server Storage", + "backup_server_storage", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14), - ), + ).tr(), subtitle: Padding( padding: const EdgeInsets.only(top: 8.0), child: Column( @@ -67,9 +68,9 @@ class BackupControllerPage extends HookConsumerWidget { } ListTile _buildBackupController() { - var backUpOption = _authenticationState.deviceInfo.isAutoBackup ? "on" : "off"; + var backUpOption = _authenticationState.deviceInfo.isAutoBackup ? "backup_status_on".tr() : "backup_status_off".tr(); var isAutoBackup = _authenticationState.deviceInfo.isAutoBackup; - var backupBtnText = _authenticationState.deviceInfo.isAutoBackup ? "off" : "on"; + var backupBtnText = _authenticationState.deviceInfo.isAutoBackup ? "backup_turn_off".tr() : "backup_turn_on".tr(); return ListTile( isThreeLine: true, leading: isAutoBackup @@ -79,7 +80,7 @@ class BackupControllerPage extends HookConsumerWidget { ) : const Icon(Icons.cloud_off_rounded), title: Text( - "Back up is $backUpOption", + backUpOption, style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 14), ), subtitle: Padding( @@ -89,9 +90,9 @@ class BackupControllerPage extends HookConsumerWidget { children: [ !isAutoBackup ? const Text( - "Turn on backup to automatically upload new assets to the server.", + "desc_backup", style: TextStyle(fontSize: 14), - ) + ).tr() : Container(), Padding( padding: const EdgeInsets.only(top: 8.0), @@ -107,7 +108,7 @@ class BackupControllerPage extends HookConsumerWidget { ? ref.watch(authenticationProvider.notifier).setAutoBackup(false) : ref.watch(authenticationProvider.notifier).setAutoBackup(true); }, - child: Text("Turn $backupBtnText Backup", style: const TextStyle(fontWeight: FontWeight.bold)), + child: Text(backupBtnText, style: const TextStyle(fontWeight: FontWeight.bold)), ), ) ], @@ -117,13 +118,13 @@ class BackupControllerPage extends HookConsumerWidget { } Widget _buildSelectedAlbumName() { - var text = "Selected: "; + var text = "backup_selected".tr(); var albums = ref.watch(backupProvider).selectedBackupAlbums; if (albums.isNotEmpty) { for (var album in albums) { if (album.name == "Recent" || album.name == "Recents") { - text += "${album.name} (All), "; + text += "${album.name} (${'backup_all'.tr()}), "; } else { text += "${album.name}, "; } @@ -140,7 +141,7 @@ class BackupControllerPage extends HookConsumerWidget { return Padding( padding: const EdgeInsets.only(top: 8.0), child: Text( - "None selected", + "backup_none_selected".tr(), style: TextStyle(color: Theme.of(context).primaryColor, fontSize: 12, fontWeight: FontWeight.bold), ), ); @@ -148,7 +149,7 @@ class BackupControllerPage extends HookConsumerWidget { } Widget _buildExcludedAlbumName() { - var text = "Excluded: "; + var text = "backup_excluded".tr(); var albums = ref.watch(backupProvider).excludedBackupAlbums; if (albums.isNotEmpty) { @@ -181,16 +182,16 @@ class BackupControllerPage extends HookConsumerWidget { borderOnForeground: false, child: ListTile( minVerticalPadding: 15, - title: const Text("Backup Albums", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)), + title: const Text("backup_albums", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)).tr(), subtitle: Padding( padding: const EdgeInsets.only(top: 8.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( - "Albums to be backup", + "backup_to_backup", style: TextStyle(color: Color(0xFF808080), fontSize: 12), - ), + ).tr(), _buildSelectedAlbumName(), _buildExcludedAlbumName() ], @@ -207,14 +208,14 @@ class BackupControllerPage extends HookConsumerWidget { onPressed: () { AutoRouter.of(context).push(const BackupAlbumSelectionRoute()); }, - child: const Padding( - padding: EdgeInsets.symmetric( + child: Padding( + padding: const EdgeInsets.symmetric( vertical: 16.0, ), - child: Text( - "Select", + child: const Text( + "backup_select", style: TextStyle(fontWeight: FontWeight.bold), - ), + ).tr(), ), ), ), @@ -225,9 +226,9 @@ class BackupControllerPage extends HookConsumerWidget { appBar: AppBar( elevation: 0, title: const Text( - "Backup", + "backup_backup", style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), - ), + ).tr(), leading: IconButton( onPressed: () { ref.watch(websocketProvider.notifier).listenUploadEvent(); @@ -243,27 +244,27 @@ class BackupControllerPage extends HookConsumerWidget { child: ListView( // crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Padding( - padding: EdgeInsets.all(8.0), - child: Text( - "Backup Information", + Padding( + padding: const EdgeInsets.all(8.0), + child: const Text( + "backup_info", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16), - ), + ).tr(), ), _buildFolderSelectionTile(), BackupInfoCard( - title: "Total", - subtitle: "All unique photos and videos from selected albums", + title: "backup_total".tr(), + subtitle: "backup_total_sub".tr(), info: "${backupState.allUniqueAssets.length}", ), BackupInfoCard( - title: "Backup", - subtitle: "Photos and videos from selected albums that are backup", + title: "backup_backup".tr(), + subtitle: "backup_backup_sub".tr(), info: "${backupState.selectedAlbumsBackupAssetsIds.length}", ), BackupInfoCard( - title: "Remainder", - subtitle: "Photos and videos that has not been backing up from selected albums", + title: "backup_remainder".tr(), + subtitle: "backup_remainder_sub".tr(), info: "${backupState.allUniqueAssets.length - backupState.selectedAlbumsBackupAssetsIds.length}", ), const Divider(), @@ -274,16 +275,16 @@ class BackupControllerPage extends HookConsumerWidget { Padding( padding: const EdgeInsets.all(8.0), child: Text( - "Asset that were being backup: ${backupState.allUniqueAssets.length - backupState.selectedAlbumsBackupAssetsIds.length} [${backupState.progressInPercentage.toStringAsFixed(0)}%]"), + "backup_assets".tr() + "${backupState.allUniqueAssets.length - backupState.selectedAlbumsBackupAssetsIds.length} [${backupState.progressInPercentage.toStringAsFixed(0)}%]"), ), Padding( padding: const EdgeInsets.only(left: 8.0), child: Row(children: [ - const Text("Backup Progress:"), + const Text("backup_progress").tr(), const Padding(padding: EdgeInsets.symmetric(horizontal: 2)), backupState.backupProgress == BackUpProgressEnum.inProgress ? const CircularProgressIndicator.adaptive() - : const Text("Done"), + : const Text("backup_done").tr(), ]), ), Padding( @@ -298,7 +299,7 @@ class BackupControllerPage extends HookConsumerWidget { onPressed: () { ref.read(backupProvider.notifier).cancelBackup(); }, - child: const Text("Cancel"), + child: const Text("backup_cancel").tr(), ) : ElevatedButton( style: ElevatedButton.styleFrom( @@ -310,7 +311,7 @@ class BackupControllerPage extends HookConsumerWidget { ref.read(backupProvider.notifier).startBackupProcess(); } : null, - child: const Text("Start Backup"), + child: const Text("start_backup").tr(), ), ), ) From f08ec5294fba43e048e4be3a638f74ad07a87604 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 23 Jun 2022 20:20:51 +0200 Subject: [PATCH 10/23] More translations --- mobile/assets/i18n/de-DE.json | 101 ++++++++++++------ mobile/assets/i18n/en-US.json | 10 +- .../views/backup_album_selection_page.dart | 2 +- .../backup/views/backup_controller_page.dart | 4 +- .../lib/shared/views/tab_controller_page.dart | 9 +- 5 files changed, 85 insertions(+), 41 deletions(-) diff --git a/mobile/assets/i18n/de-DE.json b/mobile/assets/i18n/de-DE.json index bbb3b8ea3d540..b20896d76f881 100644 --- a/mobile/assets/i18n/de-DE.json +++ b/mobile/assets/i18n/de-DE.json @@ -1,42 +1,81 @@ { - "date_format": "E, LLL d, y \u2022 HH:mm", + "asset_description": "Beschreibung hinzufügen...", + "asset_details": "DETAILS", + "asset_err_corrupted": "Fehler bei der Darstellung - Daten sind beschädigt", + "asset_location": "STANDORT", + "backup_album_excluded": "AUSGESCHLOSSEN", + "backup_album_included": "EINGESCHLOSSEN", + "backup_albums": "Gesicherte Alben", + "backup_albums_device": "Alben auf dem Gerät", + "backup_albums_tap": "Tippe um hinzuzufügen, tippe doppelt um zu entfernen", + "backup_all": "Alle", + "backup_assets": "Gesicherte Einträge: ", + "backup_backup": "Sicherung", + "backup_backup_sub": "Gesicherte Fotos und Videos", + "backup_cancel": "Abbrechen", + "backup_done": "Fertig", + "backup_err_only_album": "Kann das einzige Album nicht löschen", + "backup_excluded": "Ausgeschlossen: ", + "backup_info": "Über die Sicherung", + "backup_info_assets": "Einträge", + "backup_info_assets_scatter": "Dateien können sich über mehrere Alben verteilen.Daher können Alben während des Backup Prozesses inkludiert oder exkludiert werden.", + "backup_none_selected": "Nichts ausgewählt", + "backup_progress": "Backup Fortschritt: ", + "backup_remainder": "Übrig: ", + "backup_remainder_sub": "Noch nicht gesicherte Fotos und Videos aus gewählten Alben ", + "backup_select": "Auswählen", + "backup_select_albums": "Wähle Alben aus", + "backup_selected": "Ausgewählt: ", + "backup_selection_info": "Auswahl Informationen", + "backup_server_storage": "Speicherplatz auf dem Server", + "backup_status_off": "Sicherung deaktiviert", + "backup_status_on": "Sicherung aktiviert", + "backup_storage_format": "{} von {} genutzt", + "backup_to_backup": "Zu sichernde Alben", + "backup_total": "Gesamt", + "backup_total_assets": "Gesamtzahl", + "backup_total_sub": "Alle Fotos und Videos aus gewählten Alben", + "backup_turn_off": "Sicherung deaktivieren", + "backup_turn_on": "Sicherung aktivieren", + "create_shared_album": "Geteiltes Album erstellen", + "date_format": "E, LLL d, y • HH:mm", + "desc_backup": "Aktiviere automatische Sicherung auf den Server.", "login_button_text": "Anmelden", - "save_login": "Angemeldet bleiben", - "login_endpoint_url": "Server URL", + "login_email_hint": "deine@email.com", "login_endpoint_hint": "http://dein-server:port", - "login_err_trailing_whitespace": "Abschlie\u00dfendes Leerzeichen", - "login_err_leading_whitespace": "F\u00fchrendes Leerzeichen", - "login_err_invalid_email": "Ung\u00fcltige Email-Adresse", + "login_endpoint_url": "Server URL", "login_err_http": "Muss mit http:// oder https:// starten", + "login_err_invalid_email": "Ungültige Email-Adresse", + "login_err_leading_whitespace": "Führendes Leerzeichen", + "login_err_trailing_whitespace": "Abschließendes Leerzeichen", "login_label_email": "Email-Adresse", - "login_email_hint": "deine@email.com", "login_label_password": "Passwort", "login_password_hint": "passwort", - "share_add_title": "Titel hinzuf\u00fcgen", - "share_err_delete": "Fehler beim L\u00f6schen des Albums", + "nav_photos": "Fotos", + "nav_search": "Suche", + "nav_sharing": "Freigabe", + "save_login": "Angemeldet bleiben", + "share_add": "Hinzufügen", + "share_add_assets": "EINTRÄGE HINZUFÜGEN", + "share_add_photos": "Fotos hinzufügen", + "share_add_title": "Titel hinzufügen", + "share_add_users": "Nutzer hinzufügen", + "share_album": "Geteilte Alben", + "share_create_album": "Album erstellen", + "share_delete": "Album löschen", + "share_description": "Erstelle geteilte Alben um Fotos und Videos mit Menschen aus deinem Netzwerk zu teilen.", + "share_empty_list": "LEERE LISTE", + "share_err_album": "Fehler beim Erstellen des Albums", + "share_err_delete": "Fehler beim Löschen des Albums", "share_err_leave": "Fehler beim Verlassen des Albums", - "share_err_remove": "Eintr\u00e4ge konnten nicht aus dem Album gel\u00f6scht werden", - "share_err_title": "Fehler beim \u00c4ndern des Titels", - "share_remove": "Aus Album entfernen", - "share_delete": "Album l\u00f6schen", + "share_err_remove": "Einträge konnten nicht aus dem Album gelöscht werden", + "share_err_title": "Fehler beim Ändern des Titels", + "share_invite": "Zum Album einladen", "share_leave": "Album verlassen", - "create_shared_album": "Geteiltes Album erstellen", "share_partner": "Mit Partner teilen", - "share_add_photos": "Fotos hinzuf\u00fcgen", - "share_add_users": "Nutzer hinzuf\u00fcgen", - "share_add": "Hinzuf\u00fcgen", - "share_add_assets": "EINTR\u00c4GE HINZUF\u00dcGEN", - "share_select_photos": "Fotos ausw\u00e4hlen", - "share_create_album": "Album erstellen", + "share_remove": "Aus Album entfernen", + "share_select_photos": "Fotos auswählen", "share_share": "Teilen", - "share_suggestions": "Vorschl\u00e4ge", - "share_invite": "Zu Album einladen", - "share_err_album": "Fehler beim Erstellen des Albums", - "share_empty_list": "LEERE LISTE", - "share_description": "Erstelle geteilte Alben um Fotos und Videos mit Menschen aus deinem Netzwerk zu teilen.", - "share_album": "Geteilte Alben", - "asset_description": "Beschreibung hinzuf\u00fcgen...", - "asset_location": "STANDORT", - "asset_details": "DETAILS", - "asset_err_corrupted": "Fehler bei der Darstellung - Daten sind besch\u00e4digt" -} + "share_suggestions": "Vorschläge", + "start_backup": "Starte Backup" +} \ No newline at end of file diff --git a/mobile/assets/i18n/en-US.json b/mobile/assets/i18n/en-US.json index 2ed6cd364f59a..f17f29e96ec39 100644 --- a/mobile/assets/i18n/en-US.json +++ b/mobile/assets/i18n/en-US.json @@ -60,7 +60,7 @@ "backup_backup_sub": "Photos and videos from selected albums that are backup", "backup_remainder": "Remainder", "backup_remainder_sub": "Photos and videos that has not been backing up from selected albums", - "backup_assets": "Asset that were being backup: ", + "backup_assets": "Asset that were being backup: {}", "backup_progress": "Backup Progress:", "backup_done": "Done", "backup_cancel": "Cancel", @@ -71,7 +71,11 @@ "backup_select_albums": "Select Albums", "backup_selection_info": "Selection Info", "backup_total_assets": "Total unique assets", - "backup_albums_device": "Albums on device ", + "backup_albums_device": "Albums on device ({})", "backup_albums_tap": "Tap to include, double tap to exclude", - "backup_info_assets_scatter": "Assets can scatter across multiple albums. Thus, albums can be included or excluded during the backup process." + "backup_info_assets_scatter": "Assets can scatter across multiple albums. Thus, albums can be included or excluded during the backup process.", + "backup_storage_format": "{} of {} used", + "nav_photos": "Photos", + "nav_search": "Search", + "nav_sharing": "Sharing" } \ No newline at end of file diff --git a/mobile/lib/modules/backup/views/backup_album_selection_page.dart b/mobile/lib/modules/backup/views/backup_album_selection_page.dart index 3e65d506b1221..94720370a48fd 100644 --- a/mobile/lib/modules/backup/views/backup_album_selection_page.dart +++ b/mobile/lib/modules/backup/views/backup_album_selection_page.dart @@ -180,7 +180,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { ListTile( title: Text( - "backup_albums_device".tr() + "(${availableAlbums.length.toString()})", + "backup_albums_device".tr(args: [availableAlbums.length.toString()]), style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 14), ), subtitle: Padding( diff --git a/mobile/lib/modules/backup/views/backup_controller_page.dart b/mobile/lib/modules/backup/views/backup_controller_page.dart index 84ae649aa8a7f..b6ec892c2657b 100644 --- a/mobile/lib/modules/backup/views/backup_controller_page.dart +++ b/mobile/lib/modules/backup/views/backup_controller_page.dart @@ -59,7 +59,7 @@ class BackupControllerPage extends HookConsumerWidget { ), Padding( padding: const EdgeInsets.only(top: 12.0), - child: Text('${backupState.serverInfo.diskUse} of ${backupState.serverInfo.diskSize} used'), + child: Text('backup_storage_format').tr(args: [backupState.serverInfo.diskUse, backupState.serverInfo.diskSize]), ), ], ), @@ -275,7 +275,7 @@ class BackupControllerPage extends HookConsumerWidget { Padding( padding: const EdgeInsets.all(8.0), child: Text( - "backup_assets".tr() + "${backupState.allUniqueAssets.length - backupState.selectedAlbumsBackupAssetsIds.length} [${backupState.progressInPercentage.toStringAsFixed(0)}%]"), + "backup_assets".tr(args: ["${backupState.allUniqueAssets.length - backupState.selectedAlbumsBackupAssetsIds.length} [${backupState.progressInPercentage.toStringAsFixed(0)}%]"])), ), Padding( padding: const EdgeInsets.only(left: 8.0), diff --git a/mobile/lib/shared/views/tab_controller_page.dart b/mobile/lib/shared/views/tab_controller_page.dart index 2c303c39af029..dea326b256754 100644 --- a/mobile/lib/shared/views/tab_controller_page.dart +++ b/mobile/lib/shared/views/tab_controller_page.dart @@ -1,4 +1,5 @@ import 'package:auto_route/auto_route.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/modules/home/providers/home_page_state.provider.dart'; @@ -38,10 +39,10 @@ class TabControllerPage extends ConsumerWidget { onTap: (index) { tabsRouter.setActiveIndex(index); }, - items: const [ - BottomNavigationBarItem(label: 'Photos', icon: Icon(Icons.photo)), - BottomNavigationBarItem(label: 'Search', icon: Icon(Icons.search)), - BottomNavigationBarItem(label: 'Sharing', icon: Icon(Icons.group_outlined)), + items: [ + BottomNavigationBarItem(label: 'nav_photos'.tr(), icon: const Icon(Icons.photo)), + BottomNavigationBarItem(label: 'nav_search'.tr(), icon: const Icon(Icons.search)), + BottomNavigationBarItem(label: 'nav_sharing'.tr(), icon: const Icon(Icons.group_outlined)), ], ), ), From cb158a0d0647421e510bebaac60785f5bf41aa99 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 27 Jun 2022 15:15:18 +0200 Subject: [PATCH 11/23] Translate home page --- mobile/assets/i18n/de-DE.json | 12 +++++++++++- mobile/assets/i18n/en-US.json | 12 +++++++++++- .../lib/modules/home/ui/control_bottom_app_bar.dart | 3 ++- mobile/lib/modules/home/ui/daily_title_text.dart | 3 ++- mobile/lib/modules/home/ui/delete_diaglog.dart | 13 +++++++------ mobile/lib/modules/home/ui/monthly_title_text.dart | 3 ++- mobile/lib/modules/home/ui/profile_drawer.dart | 7 ++++--- 7 files changed, 39 insertions(+), 14 deletions(-) diff --git a/mobile/assets/i18n/de-DE.json b/mobile/assets/i18n/de-DE.json index b20896d76f881..7ca94acae04b6 100644 --- a/mobile/assets/i18n/de-DE.json +++ b/mobile/assets/i18n/de-DE.json @@ -77,5 +77,15 @@ "share_select_photos": "Fotos auswählen", "share_share": "Teilen", "share_suggestions": "Vorschläge", - "start_backup": "Starte Backup" + "start_backup": "Starte Backup", + "home_delete": "Löschen", + "home_delete_alert_title": "Endgültig löschen", + "home_delete_alert": "Diese Elemente werden für immer von deinem Gerät und vom Server gelöscht!", + "home_delete_alert_cancel": "Abbrechen", + "home_delete_alert_ok": "Löschen", + "home_sign_out": "Abmelden", + "home_client_server_up_to_date": "Client und Server sind aktuell", + "home_date": "E, dd MMM", + "home_date_year": "E, dd MMM, yyyy", + "month_title_date_format": "MMMM y" } \ No newline at end of file diff --git a/mobile/assets/i18n/en-US.json b/mobile/assets/i18n/en-US.json index f17f29e96ec39..6c7321705832c 100644 --- a/mobile/assets/i18n/en-US.json +++ b/mobile/assets/i18n/en-US.json @@ -1,5 +1,8 @@ { "date_format": "E, LLL d, y \u2022 h:mm a", + "home_date": "E, MMM dd", + "home_date_year": "E, MMM dd, yyyy", + "month_title_date_format": "MMMM y", "login_button_text": "Login", "save_login": "Save Login", "login_endpoint_url": "Server Endpoint URL", @@ -77,5 +80,12 @@ "backup_storage_format": "{} of {} used", "nav_photos": "Photos", "nav_search": "Search", - "nav_sharing": "Sharing" + "nav_sharing": "Sharing", + "home_delete": "Delete", + "home_delete_alert_title": "Delete Permanently", + "home_delete_alert": "These items will be permanently deleted from Immich and from your device", + "home_delete_alert_cancel": "Cancel", + "home_delete_alert_ok": "Delete", + "home_sign_out": "Sign Out", + "home_client_server_up_to_date": "Client and Server are up-to-date" } \ No newline at end of file diff --git a/mobile/lib/modules/home/ui/control_bottom_app_bar.dart b/mobile/lib/modules/home/ui/control_bottom_app_bar.dart index 7ad8f4119a6e5..4f020dd941e9a 100644 --- a/mobile/lib/modules/home/ui/control_bottom_app_bar.dart +++ b/mobile/lib/modules/home/ui/control_bottom_app_bar.dart @@ -1,3 +1,4 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:immich_mobile/modules/home/ui/delete_diaglog.dart'; @@ -25,7 +26,7 @@ class ControlBottomAppBar extends StatelessWidget { children: [ ControlBoxButton( iconData: Icons.delete_forever_rounded, - label: "Delete", + label: "home_delete".tr(), onPressed: () { showDialog( context: context, diff --git a/mobile/lib/modules/home/ui/daily_title_text.dart b/mobile/lib/modules/home/ui/daily_title_text.dart index bffe496b8c88f..d2f9015832afb 100644 --- a/mobile/lib/modules/home/ui/daily_title_text.dart +++ b/mobile/lib/modules/home/ui/daily_title_text.dart @@ -1,3 +1,4 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/modules/home/providers/home_page_state.provider.dart'; @@ -18,7 +19,7 @@ class DailyTitleText extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { var currentYear = DateTime.now().year; var groupYear = DateTime.parse(isoDate).year; - var formatDateTemplate = currentYear == groupYear ? 'E, MMM dd' : 'E, MMM dd, yyyy'; + var formatDateTemplate = currentYear == groupYear ? "home_date".tr() : "home_date_year".tr(); var dateText = DateFormat(formatDateTemplate).format(DateTime.parse(isoDate)); var isMultiSelectEnable = ref.watch(homePageStateProvider).isMultiSelectEnable; var selectedDateGroup = ref.watch(homePageStateProvider).selectedDateGroup; diff --git a/mobile/lib/modules/home/ui/delete_diaglog.dart b/mobile/lib/modules/home/ui/delete_diaglog.dart index af6040da83683..645b2dc452767 100644 --- a/mobile/lib/modules/home/ui/delete_diaglog.dart +++ b/mobile/lib/modules/home/ui/delete_diaglog.dart @@ -1,3 +1,4 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/shared/providers/asset.provider.dart'; @@ -13,17 +14,17 @@ class DeleteDialog extends ConsumerWidget { return AlertDialog( backgroundColor: Colors.grey[200], shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), - title: const Text("Delete Permanently"), - content: const Text("These items will be permanently deleted from Immich and from your device"), + title: const Text("home_delete_alert_title").tr(), + content: const Text("home_delete_alert").tr(), actions: [ TextButton( onPressed: () { Navigator.of(context).pop(); }, child: const Text( - "Cancel", + "home_delete_alert_cancel", style: TextStyle(color: Colors.blueGrey), - ), + ).tr(), ), TextButton( onPressed: () { @@ -33,9 +34,9 @@ class DeleteDialog extends ConsumerWidget { Navigator.of(context).pop(); }, child: Text( - "Delete", + "home_delete_alert_ok", style: TextStyle(color: Colors.red[400]), - ), + ).tr(), ), ], ); diff --git a/mobile/lib/modules/home/ui/monthly_title_text.dart b/mobile/lib/modules/home/ui/monthly_title_text.dart index 8df0334317d80..a00b8bae03002 100644 --- a/mobile/lib/modules/home/ui/monthly_title_text.dart +++ b/mobile/lib/modules/home/ui/monthly_title_text.dart @@ -1,3 +1,4 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; @@ -11,7 +12,7 @@ class MonthlyTitleText extends StatelessWidget { @override Widget build(BuildContext context) { - var monthTitleText = DateFormat('MMMM y').format(DateTime.parse(isoDate)); + var monthTitleText = DateFormat("month_title_date_format".tr()).format(DateTime.parse(isoDate)); return SliverToBoxAdapter( child: Padding( diff --git a/mobile/lib/modules/home/ui/profile_drawer.dart b/mobile/lib/modules/home/ui/profile_drawer.dart index 46866605c7047..25b48efed0dad 100644 --- a/mobile/lib/modules/home/ui/profile_drawer.dart +++ b/mobile/lib/modules/home/ui/profile_drawer.dart @@ -1,4 +1,5 @@ import 'package:auto_route/auto_route.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hive_flutter/hive_flutter.dart'; @@ -175,9 +176,9 @@ class ProfileDrawer extends HookConsumerWidget { color: Colors.black54, ), title: const Text( - "Sign Out", + "home_sign_out", style: TextStyle(color: Colors.black54, fontSize: 14, fontWeight: FontWeight.bold), - ), + ).tr(), onTap: () async { bool res = await ref.read(authenticationProvider.notifier).logout(); @@ -213,7 +214,7 @@ class ProfileDrawer extends HookConsumerWidget { child: Text( _serverInfoState.isVersionMismatch ? _serverInfoState.versionMismatchErrorMessage - : "Client and Server are up-to-date", + : "home_client_server_up_to_date".tr(), textAlign: TextAlign.center, style: TextStyle(fontSize: 11, color: Theme.of(context).primaryColor, fontWeight: FontWeight.w600), From 07a4fde7c9e8cb384f046f25db6e9a03af0c9b83 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 27 Jun 2022 15:27:16 +0200 Subject: [PATCH 12/23] Translation of search page --- mobile/assets/i18n/de-DE.json | 8 ++++++- mobile/assets/i18n/en-US.json | 8 ++++++- mobile/lib/modules/search/ui/search_bar.dart | 5 +++-- .../search/ui/thumbnail_with_info.dart | 2 +- .../lib/modules/search/views/search_page.dart | 21 ++++++++++--------- .../search/views/search_result_page.dart | 5 +++-- 6 files changed, 32 insertions(+), 17 deletions(-) diff --git a/mobile/assets/i18n/de-DE.json b/mobile/assets/i18n/de-DE.json index 7ca94acae04b6..c9c8fb039035a 100644 --- a/mobile/assets/i18n/de-DE.json +++ b/mobile/assets/i18n/de-DE.json @@ -87,5 +87,11 @@ "home_client_server_up_to_date": "Client und Server sind aktuell", "home_date": "E, dd MMM", "home_date_year": "E, dd MMM, yyyy", - "month_title_date_format": "MMMM y" + "month_title_date_format": "MMMM y", + "search_hint": "Durchsuche deine Fotos", + "search_places": "Orte", + "search_things": "Dinge", + "search_new_search_hint": "Neue Suche", + "search_no_objects": "Keine Informationen über Dinge verfügbar", + "search_no_places": "Keine Informationen über Orte verfügbar" } \ No newline at end of file diff --git a/mobile/assets/i18n/en-US.json b/mobile/assets/i18n/en-US.json index 6c7321705832c..a8ab0d16ccc03 100644 --- a/mobile/assets/i18n/en-US.json +++ b/mobile/assets/i18n/en-US.json @@ -87,5 +87,11 @@ "home_delete_alert_cancel": "Cancel", "home_delete_alert_ok": "Delete", "home_sign_out": "Sign Out", - "home_client_server_up_to_date": "Client and Server are up-to-date" + "home_client_server_up_to_date": "Client and Server are up-to-date", + "search_hint": "Search your photos", + "search_places": "Places", + "search_things": "Things", + "search_new_search_hint": "New Search", + "search_no_objects": "No Object Info Available", + "search_no_places": "No Places Info Available" } \ No newline at end of file diff --git a/mobile/lib/modules/search/ui/search_bar.dart b/mobile/lib/modules/search/ui/search_bar.dart index b3af1af4e22bf..4634ff42e8a49 100644 --- a/mobile/lib/modules/search/ui/search_bar.dart +++ b/mobile/lib/modules/search/ui/search_bar.dart @@ -1,3 +1,4 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -45,8 +46,8 @@ class SearchBar extends HookConsumerWidget with PreferredSizeWidget { onChanged: (value) { ref.watch(searchPageStateProvider.notifier).setSearchTerm(value); }, - decoration: const InputDecoration( - hintText: 'Search your photos', + decoration: InputDecoration( + hintText: 'search_hint'.tr(), enabledBorder: UnderlineInputBorder( borderSide: BorderSide(color: Colors.transparent), ), diff --git a/mobile/lib/modules/search/ui/thumbnail_with_info.dart b/mobile/lib/modules/search/ui/thumbnail_with_info.dart index fe6912526bc06..579850aa75ee4 100644 --- a/mobile/lib/modules/search/ui/thumbnail_with_info.dart +++ b/mobile/lib/modules/search/ui/thumbnail_with_info.dart @@ -49,7 +49,7 @@ class ThumbnailWithInfo extends StatelessWidget { child: SizedBox( width: MediaQuery.of(context).size.width / 3, child: Text( - textInfo.capitalizeFirstLetter(), + textInfo, style: const TextStyle( color: Colors.white, fontWeight: FontWeight.bold, diff --git a/mobile/lib/modules/search/views/search_page.dart b/mobile/lib/modules/search/views/search_page.dart index 59866b6056f59..fd2b262c4f242 100644 --- a/mobile/lib/modules/search/views/search_page.dart +++ b/mobile/lib/modules/search/views/search_page.dart @@ -1,4 +1,5 @@ import 'package:auto_route/auto_route.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart'; @@ -83,7 +84,7 @@ class SearchPage extends HookConsumerWidget { return ThumbnailWithInfo( imageUrl: 'https://images.unsplash.com/photo-1612178537253-bccd437b730e?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8NXx8Ymxhbmt8ZW58MHx8MHx8&auto=format&fit=crop&w=700&q=60', - textInfo: 'No Places Info Available', + textInfo: 'search_no_places'.tr(), onTap: () {}, ); }), @@ -135,7 +136,7 @@ class SearchPage extends HookConsumerWidget { return ThumbnailWithInfo( imageUrl: 'https://images.unsplash.com/photo-1612178537253-bccd437b730e?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8NXx8Ymxhbmt8ZW58MHx8MHx8&auto=format&fit=crop&w=700&q=60', - textInfo: 'No Object Info Available', + textInfo: 'sarch_no_objects'.tr(), onTap: () {}, ); }), @@ -159,20 +160,20 @@ class SearchPage extends HookConsumerWidget { children: [ ListView( children: [ - const Padding( + Padding( padding: EdgeInsets.all(16.0), - child: Text( - "Places", + child: const Text( + "search_places", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16), - ), + ).tr(), ), _buildPlaces(), - const Padding( + Padding( padding: EdgeInsets.all(16.0), - child: Text( - "Things", + child: const Text( + "search_things", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16), - ), + ).tr(), ), _buildThings() ], diff --git a/mobile/lib/modules/search/views/search_result_page.dart b/mobile/lib/modules/search/views/search_result_page.dart index 38c859542170f..475314b542f89 100644 --- a/mobile/lib/modules/search/views/search_result_page.dart +++ b/mobile/lib/modules/search/views/search_result_page.dart @@ -1,4 +1,5 @@ import 'package:auto_route/auto_route.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart'; @@ -63,8 +64,8 @@ class SearchResultPage extends HookConsumerWidget { onChanged: (value) { ref.watch(searchPageStateProvider.notifier).setSearchTerm(value); }, - decoration: const InputDecoration( - hintText: 'New Search', + decoration: InputDecoration( + hintText: 'search_new_search_hint'.tr(), enabledBorder: UnderlineInputBorder( borderSide: BorderSide(color: Colors.transparent), ), From e769483add5a234dceee5a26558c07b800db7bf1 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 27 Jun 2022 15:42:25 +0200 Subject: [PATCH 13/23] Translate new server version announcement --- mobile/assets/i18n/de-DE.json | 8 ++++++- mobile/assets/i18n/en-US.json | 8 ++++++- .../views/version_announcement_overlay.dart | 23 ++++++++++--------- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/mobile/assets/i18n/de-DE.json b/mobile/assets/i18n/de-DE.json index c9c8fb039035a..f53172bd322a9 100644 --- a/mobile/assets/i18n/de-DE.json +++ b/mobile/assets/i18n/de-DE.json @@ -93,5 +93,11 @@ "search_things": "Dinge", "search_new_search_hint": "Neue Suche", "search_no_objects": "Keine Informationen über Dinge verfügbar", - "search_no_places": "Keine Informationen über Orte verfügbar" + "search_no_places": "Keine Informationen über Orte verfügbar", + "version_announcement_title": "Eine neue Server-Version ist verfügbar \uD83C\uDF89", + "version_announcement_text_1": "Hallo mein Freund, es gibt eine neue Version von", + "version_announcement_text_2": "- Bitte nehme dir Zeit und lese die ", + "version_announcement_release_notes": "Release-Notes", + "version_announcement_text_3": " und stelle sicher, dass deine docker-compose und .env Dateien aktuell sind. So kannst du Fehler vermeiden, besonders wenn du WatchTower oder einen ähnlichen Mechanismus für automatische Updates benutzt.", + "version_announcement_ack": "Ich habe verstanden" } \ No newline at end of file diff --git a/mobile/assets/i18n/en-US.json b/mobile/assets/i18n/en-US.json index a8ab0d16ccc03..973fa7933a348 100644 --- a/mobile/assets/i18n/en-US.json +++ b/mobile/assets/i18n/en-US.json @@ -93,5 +93,11 @@ "search_things": "Things", "search_new_search_hint": "New Search", "search_no_objects": "No Object Info Available", - "search_no_places": "No Places Info Available" + "search_no_places": "No Places Info Available", + "version_announcement_title": "New Server Version Available \uD83C\uDF89", + "version_announcement_text_1": "Hi friend, there is a new release of", + "version_announcement_text_2": "please take your time to visit the ", + "version_announcement_release_notes": "release notes", + "version_announcement_text_3": " and ensure your docker-compose and .env setup is up-to-date to prevent any misconfigurations, especially if you use WatchTower or any mechanism that handles updating your server application automatically.", + "version_announcement_ack": "Acknowledge" } \ No newline at end of file diff --git a/mobile/lib/shared/views/version_announcement_overlay.dart b/mobile/lib/shared/views/version_announcement_overlay.dart index 474a1340866cf..819811cf6ce52 100644 --- a/mobile/lib/shared/views/version_announcement_overlay.dart +++ b/mobile/lib/shared/views/version_announcement_overlay.dart @@ -1,3 +1,4 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -38,14 +39,14 @@ class VersionAnnouncementOverlay extends HookConsumerWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( - "New Server Version Available 🎉", + "version_announcement_title", style: TextStyle( fontSize: 16, fontFamily: 'WorkSans', fontWeight: FontWeight.bold, color: Colors.indigo, ), - ), + ).tr(), Padding( padding: const EdgeInsets.only(top: 16.0), child: RichText( @@ -53,8 +54,8 @@ class VersionAnnouncementOverlay extends HookConsumerWidget { style: const TextStyle( fontSize: 14, fontFamily: 'WorkSans', color: Colors.black87, height: 1.2), children: [ - const TextSpan( - text: 'Hi friend, there is a new release of', + TextSpan( + text: 'version_announcement_text_1'.tr(), ), const TextSpan( text: ' Immich ', @@ -64,19 +65,19 @@ class VersionAnnouncementOverlay extends HookConsumerWidget { fontWeight: FontWeight.bold, ), ), - const TextSpan( - text: "please take your time to visit the ", + TextSpan( + text: "version_announcement_text_2".tr(), ), TextSpan( - text: "release note", + text: "version_announcement_release_notes".tr(), style: const TextStyle( decoration: TextDecoration.underline, ), recognizer: TapGestureRecognizer()..onTap = goToReleaseNote, ), - const TextSpan( + TextSpan( text: - " and ensure your docker-compose and .env setup is up-to-date to prevent any misconfigurations, especially if you use WatchTower or any mechanism that handles updating your server application automatically.", + "version_announcement_text_3".tr(), ) ], ), @@ -95,11 +96,11 @@ class VersionAnnouncementOverlay extends HookConsumerWidget { ), onPressed: onAcknowledgeTapped, child: const Text( - "Acknowledge", + "version_announcement_ack", style: TextStyle( fontSize: 14, ), - )), + ).tr()), ) ], ), From f675b9ab8672120c7e453cb0441c74d0b64faf1c Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 27 Jun 2022 16:52:12 +0200 Subject: [PATCH 14/23] Reformat code --- mobile/lib/main.dart | 11 ++- .../asset_viewer/ui/exif_bottom_sheet.dart | 3 +- .../modules/backup/ui/album_info_card.dart | 14 +++- .../views/backup_album_selection_page.dart | 14 +++- .../backup/views/backup_controller_page.dart | 82 +++++++++++-------- .../lib/modules/home/ui/daily_title_text.dart | 9 +- .../lib/modules/home/ui/profile_drawer.dart | 5 +- mobile/lib/modules/login/ui/login_form.dart | 32 ++++++-- .../sharing/ui/sharing_sliver_appbar.dart | 6 +- .../views/create_shared_album_page.dart | 9 +- ...lect_additional_user_for_sharing_page.dart | 5 +- .../views/select_user_for_sharing_page.dart | 5 +- .../lib/shared/views/tab_controller_page.dart | 12 ++- .../views/version_announcement_overlay.dart | 9 +- 14 files changed, 143 insertions(+), 73 deletions(-) diff --git a/mobile/lib/main.dart b/mobile/lib/main.dart index ead7a623cbcb8..5e0e51a77d0d7 100644 --- a/mobile/lib/main.dart +++ b/mobile/lib/main.dart @@ -47,12 +47,11 @@ void main() async { ]; runApp(EasyLocalization( - supportedLocales: locales, - path: 'assets/i18n', - useFallbackTranslations: true, - fallbackLocale: locales.first, - child: const ProviderScope(child: ImmichApp()) - )); + supportedLocales: locales, + path: 'assets/i18n', + useFallbackTranslations: true, + fallbackLocale: locales.first, + child: const ProviderScope(child: ImmichApp()))); } class ImmichApp extends ConsumerStatefulWidget { diff --git a/mobile/lib/modules/asset_viewer/ui/exif_bottom_sheet.dart b/mobile/lib/modules/asset_viewer/ui/exif_bottom_sheet.dart index 4d22eced395f7..379e8db316982 100644 --- a/mobile/lib/modules/asset_viewer/ui/exif_bottom_sheet.dart +++ b/mobile/lib/modules/asset_viewer/ui/exif_bottom_sheet.dart @@ -142,7 +142,8 @@ class ExifBottomSheet extends ConsumerWidget { padding: const EdgeInsets.only(bottom: 8.0), child: Text( "asset_details", - style: TextStyle(fontSize: 11, color: Colors.grey[400]), + style: + TextStyle(fontSize: 11, color: Colors.grey[400]), ).tr(), ), ListTile( diff --git a/mobile/lib/modules/backup/ui/album_info_card.dart b/mobile/lib/modules/backup/ui/album_info_card.dart index 2e37588ca23c3..4056f2a5a7396 100644 --- a/mobile/lib/modules/backup/ui/album_info_card.dart +++ b/mobile/lib/modules/backup/ui/album_info_card.dart @@ -39,7 +39,8 @@ class AlbumInfoCard extends HookConsumerWidget { shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)), label: const Text( "backup_album_included", - style: TextStyle(fontSize: 10, color: Colors.white, fontWeight: FontWeight.bold), + style: TextStyle( + fontSize: 10, color: Colors.white, fontWeight: FontWeight.bold), ).tr(), backgroundColor: Theme.of(context).primaryColor, ); @@ -49,7 +50,8 @@ class AlbumInfoCard extends HookConsumerWidget { shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)), label: const Text( "backup_album_excluded", - style: TextStyle(fontSize: 10, color: Colors.white, fontWeight: FontWeight.bold), + style: TextStyle( + fontSize: 10, color: Colors.white, fontWeight: FontWeight.bold), ).tr(), backgroundColor: Colors.red[300], ); @@ -175,8 +177,12 @@ class AlbumInfoCard extends HookConsumerWidget { Padding( padding: const EdgeInsets.only(top: 2.0), child: Text( - albumInfo.assetCount.toString() + (albumInfo.isAll ? " (${'backup_all'.tr()})" : ""), - style: TextStyle(fontSize: 12, color: Colors.grey[600]), + albumInfo.assetCount.toString() + + (albumInfo.isAll + ? " (${'backup_all'.tr()})" + : ""), + style: TextStyle( + fontSize: 12, color: Colors.grey[600]), ), ) ], diff --git a/mobile/lib/modules/backup/views/backup_album_selection_page.dart b/mobile/lib/modules/backup/views/backup_album_selection_page.dart index 40d86402649bd..c6ce5777930a0 100644 --- a/mobile/lib/modules/backup/views/backup_album_selection_page.dart +++ b/mobile/lib/modules/backup/views/backup_album_selection_page.dart @@ -146,7 +146,8 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { physics: const ClampingScrollPhysics(), children: [ Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0), + padding: + const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0), child: const Text( "backup_selection_info", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14), @@ -183,7 +184,10 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { visualDensity: VisualDensity.compact, title: Text( "backup_total_assets", - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14, color: Colors.grey[700]), + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 14, + color: Colors.grey[700]), ).tr(), trailing: Text( ref @@ -201,7 +205,8 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { ListTile( title: Text( - "backup_albums_device".tr(args: [availableAlbums.length.toString()]), + "backup_albums_device" + .tr(args: [availableAlbums.length.toString()]), style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 14), ), subtitle: Padding( @@ -244,7 +249,8 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { children: [ Text( 'backup_info_assets_scatter', - style: TextStyle(fontSize: 14, color: Colors.grey[700]), + style: TextStyle( + fontSize: 14, color: Colors.grey[700]), ).tr(), ], ), diff --git a/mobile/lib/modules/backup/views/backup_controller_page.dart b/mobile/lib/modules/backup/views/backup_controller_page.dart index 4ee18af03660c..1e6fbbb78047d 100644 --- a/mobile/lib/modules/backup/views/backup_controller_page.dart +++ b/mobile/lib/modules/backup/views/backup_controller_page.dart @@ -65,7 +65,10 @@ class BackupControllerPage extends HookConsumerWidget { ), Padding( padding: const EdgeInsets.only(top: 12.0), - child: Text('backup_storage_format').tr(args: [backupState.serverInfo.diskUse, backupState.serverInfo.diskSize]), + child: Text('backup_storage_format').tr(args: [ + backupState.serverInfo.diskUse, + backupState.serverInfo.diskSize + ]), ), ], ), @@ -74,9 +77,13 @@ class BackupControllerPage extends HookConsumerWidget { } ListTile _buildBackupController() { - var backUpOption = authenticationState.deviceInfo.isAutoBackup ? "backup_status_on".tr() : "backup_status_off".tr(); + var backUpOption = authenticationState.deviceInfo.isAutoBackup + ? "backup_status_on".tr() + : "backup_status_off".tr(); var isAutoBackup = authenticationState.deviceInfo.isAutoBackup; - var backupBtnText = authenticationState.deviceInfo.isAutoBackup ? "backup_turn_off".tr() : "backup_turn_on".tr(); + var backupBtnText = authenticationState.deviceInfo.isAutoBackup + ? "backup_turn_off".tr() + : "backup_turn_on".tr(); return ListTile( isThreeLine: true, leading: isAutoBackup @@ -120,7 +127,8 @@ class BackupControllerPage extends HookConsumerWidget { .setAutoBackup(true); } }, - child: Text(backupBtnText, style: const TextStyle(fontWeight: FontWeight.bold)), + child: Text(backupBtnText, + style: const TextStyle(fontWeight: FontWeight.bold)), ), ) ], @@ -157,7 +165,10 @@ class BackupControllerPage extends HookConsumerWidget { padding: const EdgeInsets.only(top: 8.0), child: Text( "backup_none_selected".tr(), - style: TextStyle(color: Theme.of(context).primaryColor, fontSize: 12, fontWeight: FontWeight.bold), + style: TextStyle( + color: Theme.of(context).primaryColor, + fontSize: 12, + fontWeight: FontWeight.bold), ), ); } @@ -200,7 +211,9 @@ class BackupControllerPage extends HookConsumerWidget { borderOnForeground: false, child: ListTile( minVerticalPadding: 15, - title: const Text("backup_albums", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)).tr(), + title: const Text("backup_albums", + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)) + .tr(), subtitle: Padding( padding: const EdgeInsets.only(top: 8.0), child: Column( @@ -283,7 +296,8 @@ class BackupControllerPage extends HookConsumerWidget { BackupInfoCard( title: "backup_remainder".tr(), subtitle: "backup_remainder_sub".tr(), - info: "${backupState.allUniqueAssets.length - backupState.selectedAlbumsBackupAssetsIds.length}", + info: + "${backupState.allUniqueAssets.length - backupState.selectedAlbumsBackupAssetsIds.length}", ), const Divider(), _buildBackupController(), @@ -292,8 +306,9 @@ class BackupControllerPage extends HookConsumerWidget { const Divider(), Padding( padding: const EdgeInsets.all(8.0), - child: Text( - "backup_assets".tr(args: ["${backupState.allUniqueAssets.length - backupState.selectedAlbumsBackupAssetsIds.length} [${backupState.progressInPercentage.toStringAsFixed(0)}%]"])), + child: Text("backup_assets".tr(args: [ + "${backupState.allUniqueAssets.length - backupState.selectedAlbumsBackupAssetsIds.length} [${backupState.progressInPercentage.toStringAsFixed(0)}%]" + ])), ), Padding( padding: const EdgeInsets.only(left: 8.0), @@ -308,29 +323,32 @@ class BackupControllerPage extends HookConsumerWidget { Padding( padding: const EdgeInsets.all(8.0), child: Container( - child: backupState.backupProgress == BackUpProgressEnum.inProgress - ? ElevatedButton( - style: ElevatedButton.styleFrom( - primary: Colors.red[300], - onPrimary: Colors.grey[50], - ), - onPressed: () { - ref.read(backupProvider.notifier).cancelBackup(); - }, - child: const Text("backup_cancel").tr(), - ) - : ElevatedButton( - style: ElevatedButton.styleFrom( - primary: Theme.of(context).primaryColor, - onPrimary: Colors.grey[50], - ), - onPressed: shouldBackup - ? () { - ref.read(backupProvider.notifier).startBackupProcess(); - } - : null, - child: const Text("start_backup").tr(), - ), + child: + backupState.backupProgress == BackUpProgressEnum.inProgress + ? ElevatedButton( + style: ElevatedButton.styleFrom( + primary: Colors.red[300], + onPrimary: Colors.grey[50], + ), + onPressed: () { + ref.read(backupProvider.notifier).cancelBackup(); + }, + child: const Text("backup_cancel").tr(), + ) + : ElevatedButton( + style: ElevatedButton.styleFrom( + primary: Theme.of(context).primaryColor, + onPrimary: Colors.grey[50], + ), + onPressed: shouldBackup + ? () { + ref + .read(backupProvider.notifier) + .startBackupProcess(); + } + : null, + child: const Text("start_backup").tr(), + ), ), ) ], diff --git a/mobile/lib/modules/home/ui/daily_title_text.dart b/mobile/lib/modules/home/ui/daily_title_text.dart index 71d0aa0b1cb6f..0af5bf6a5861f 100644 --- a/mobile/lib/modules/home/ui/daily_title_text.dart +++ b/mobile/lib/modules/home/ui/daily_title_text.dart @@ -19,9 +19,12 @@ class DailyTitleText extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { var currentYear = DateTime.now().year; var groupYear = DateTime.parse(isoDate).year; - var formatDateTemplate = currentYear == groupYear ? "home_date".tr() : "home_date_year".tr(); - var dateText = DateFormat(formatDateTemplate).format(DateTime.parse(isoDate)); - var isMultiSelectEnable = ref.watch(homePageStateProvider).isMultiSelectEnable; + var formatDateTemplate = + currentYear == groupYear ? "home_date".tr() : "home_date_year".tr(); + var dateText = + DateFormat(formatDateTemplate).format(DateTime.parse(isoDate)); + var isMultiSelectEnable = + ref.watch(homePageStateProvider).isMultiSelectEnable; var selectedDateGroup = ref.watch(homePageStateProvider).selectedDateGroup; var selectedItems = ref.watch(homePageStateProvider).selectedItems; diff --git a/mobile/lib/modules/home/ui/profile_drawer.dart b/mobile/lib/modules/home/ui/profile_drawer.dart index 94feb8ad44a2d..a1ab9e49759a4 100644 --- a/mobile/lib/modules/home/ui/profile_drawer.dart +++ b/mobile/lib/modules/home/ui/profile_drawer.dart @@ -185,7 +185,10 @@ class ProfileDrawer extends HookConsumerWidget { ), title: const Text( "home_sign_out", - style: TextStyle(color: Colors.black54, fontSize: 14, fontWeight: FontWeight.bold), + style: TextStyle( + color: Colors.black54, + fontSize: 14, + fontWeight: FontWeight.bold), ).tr(), onTap: () async { bool res = diff --git a/mobile/lib/modules/login/ui/login_form.dart b/mobile/lib/modules/login/ui/login_form.dart index f0c518c45596f..3f0152d7b721c 100644 --- a/mobile/lib/modules/login/ui/login_form.dart +++ b/mobile/lib/modules/login/ui/login_form.dart @@ -16,9 +16,12 @@ class LoginForm extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final usernameController = useTextEditingController.fromValue(TextEditingValue.empty); - final passwordController = useTextEditingController.fromValue(TextEditingValue.empty); - final serverEndpointController = useTextEditingController(text: 'login_endpoint_hint'.tr()); + final usernameController = + useTextEditingController.fromValue(TextEditingValue.empty); + final passwordController = + useTextEditingController.fromValue(TextEditingValue.empty); + final serverEndpointController = + useTextEditingController(text: 'login_endpoint_hint'.tr()); final isSaveLoginInfo = useState(false); useEffect(() { @@ -71,7 +74,10 @@ class LoginForm extends HookConsumerWidget { enableFeedback: true, title: const Text( "save_login", - style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: Colors.grey), + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: Colors.grey), ).tr(), value: isSaveLoginInfo.value, onChanged: (switchValue) { @@ -111,7 +117,9 @@ class ServerEndpointInput extends StatelessWidget { return TextFormField( controller: controller, decoration: InputDecoration( - labelText: 'login_endpoint_url'.tr(), border: OutlineInputBorder(), hintText: 'login_endpoint_hint'.tr()), + labelText: 'login_endpoint_url'.tr(), + border: OutlineInputBorder(), + hintText: 'login_endpoint_hint'.tr()), validator: _validateInput, autovalidateMode: AutovalidateMode.always, ); @@ -127,7 +135,8 @@ class EmailInput extends StatelessWidget { if (email == null || email == '') return null; if (email.endsWith(' ')) return 'login_err_trailing_whitespace'.tr(); if (email.startsWith(' ')) return 'login_err_leading_whitespace'.tr(); - if (email.contains(' ') || !email.contains('@')) return 'login_err_invalid_email'.tr(); + if (email.contains(' ') || !email.contains('@')) + return 'login_err_invalid_email'.tr(); return null; } @@ -135,8 +144,10 @@ class EmailInput extends StatelessWidget { Widget build(BuildContext context) { return TextFormField( controller: controller, - decoration: - InputDecoration(labelText: 'login_label_email'.tr(), border: OutlineInputBorder(), hintText: 'login_email_hint'.tr()), + decoration: InputDecoration( + labelText: 'login_label_email'.tr(), + border: OutlineInputBorder(), + hintText: 'login_email_hint'.tr()), validator: _validateInput, autovalidateMode: AutovalidateMode.always, ); @@ -153,7 +164,10 @@ class PasswordInput extends StatelessWidget { return TextFormField( obscureText: true, controller: controller, - decoration: InputDecoration(labelText: 'login_label_password'.tr(), border: OutlineInputBorder(), hintText: 'login_password_hint'.tr()), + decoration: InputDecoration( + labelText: 'login_label_password'.tr(), + border: OutlineInputBorder(), + hintText: 'login_password_hint'.tr()), ); } } diff --git a/mobile/lib/modules/sharing/ui/sharing_sliver_appbar.dart b/mobile/lib/modules/sharing/ui/sharing_sliver_appbar.dart index 43ae14c57b067..a43a3edffdc2e 100644 --- a/mobile/lib/modules/sharing/ui/sharing_sliver_appbar.dart +++ b/mobile/lib/modules/sharing/ui/sharing_sliver_appbar.dart @@ -52,7 +52,8 @@ class SharingSliverAppBar extends StatelessWidget { ), label: const Text( "create_shared_album", - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 12), + style: + TextStyle(fontWeight: FontWeight.bold, fontSize: 12), ).tr(), ), ), @@ -73,7 +74,8 @@ class SharingSliverAppBar extends StatelessWidget { ), label: const Text( "share_partner", - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 12), + style: + TextStyle(fontWeight: FontWeight.bold, fontSize: 12), ).tr(), ), ), diff --git a/mobile/lib/modules/sharing/views/create_shared_album_page.dart b/mobile/lib/modules/sharing/views/create_shared_album_page.dart index 4bcb6bde2ada3..c47a79894c24c 100644 --- a/mobile/lib/modules/sharing/views/create_shared_album_page.dart +++ b/mobile/lib/modules/sharing/views/create_shared_album_page.dart @@ -99,7 +99,10 @@ class CreateSharedAlbumPage extends HookConsumerWidget { padding: const EdgeInsets.only(left: 8.0), child: Text( 'share_select_photos', - style: TextStyle(fontSize: 16, color: Colors.grey[700], fontWeight: FontWeight.bold), + style: TextStyle( + fontSize: 16, + color: Colors.grey[700], + fontWeight: FontWeight.bold), ).tr(), ), ), @@ -176,7 +179,9 @@ class CreateSharedAlbumPage extends HookConsumerWidget { ).tr(), actions: [ TextButton( - onPressed: albumTitleController.text.isNotEmpty ? _showSelectUserPage : null, + onPressed: albumTitleController.text.isNotEmpty + ? _showSelectUserPage + : null, child: Text( 'share_share'.tr(), style: TextStyle( diff --git a/mobile/lib/modules/sharing/views/select_additional_user_for_sharing_page.dart b/mobile/lib/modules/sharing/views/select_additional_user_for_sharing_page.dart index e5cbe74ec74c9..1108407b47b63 100644 --- a/mobile/lib/modules/sharing/views/select_additional_user_for_sharing_page.dart +++ b/mobile/lib/modules/sharing/views/select_additional_user_for_sharing_page.dart @@ -73,7 +73,10 @@ class SelectAdditionalUserForSharingPage extends HookConsumerWidget { padding: EdgeInsets.all(16.0), child: Text( 'share_suggestions'.tr(), - style: TextStyle(fontSize: 14, color: Colors.grey, fontWeight: FontWeight.bold), + style: TextStyle( + fontSize: 14, + color: Colors.grey, + fontWeight: FontWeight.bold), ), ), ListView.builder( diff --git a/mobile/lib/modules/sharing/views/select_user_for_sharing_page.dart b/mobile/lib/modules/sharing/views/select_user_for_sharing_page.dart index 2a170dd565c62..7a40ddfab9395 100644 --- a/mobile/lib/modules/sharing/views/select_user_for_sharing_page.dart +++ b/mobile/lib/modules/sharing/views/select_user_for_sharing_page.dart @@ -88,7 +88,10 @@ class SelectUserForSharingPage extends HookConsumerWidget { padding: EdgeInsets.all(16.0), child: Text( 'share_suggestions', - style: TextStyle(fontSize: 14, color: Colors.grey, fontWeight: FontWeight.bold), + style: TextStyle( + fontSize: 14, + color: Colors.grey, + fontWeight: FontWeight.bold), ).tr(), ), ListView.builder( diff --git a/mobile/lib/shared/views/tab_controller_page.dart b/mobile/lib/shared/views/tab_controller_page.dart index 1226cde95aadd..83e5cb617bd7d 100644 --- a/mobile/lib/shared/views/tab_controller_page.dart +++ b/mobile/lib/shared/views/tab_controller_page.dart @@ -43,9 +43,15 @@ class TabControllerPage extends ConsumerWidget { tabsRouter.setActiveIndex(index); }, items: [ - BottomNavigationBarItem(label: 'nav_photos'.tr(), icon: const Icon(Icons.photo)), - BottomNavigationBarItem(label: 'nav_search'.tr(), icon: const Icon(Icons.search)), - BottomNavigationBarItem(label: 'nav_sharing'.tr(), icon: const Icon(Icons.group_outlined)), + BottomNavigationBarItem( + label: 'nav_photos'.tr(), + icon: const Icon(Icons.photo)), + BottomNavigationBarItem( + label: 'nav_search'.tr(), + icon: const Icon(Icons.search)), + BottomNavigationBarItem( + label: 'nav_sharing'.tr(), + icon: const Icon(Icons.group_outlined)), ], ), ), diff --git a/mobile/lib/shared/views/version_announcement_overlay.dart b/mobile/lib/shared/views/version_announcement_overlay.dart index cc67ebbea9f8c..05c50bbb43853 100644 --- a/mobile/lib/shared/views/version_announcement_overlay.dart +++ b/mobile/lib/shared/views/version_announcement_overlay.dart @@ -74,7 +74,8 @@ class VersionAnnouncementOverlay extends HookConsumerWidget { text: "version_announcement_text_2".tr(), ), TextSpan( - text: "version_announcement_release_notes".tr(), + text: "version_announcement_release_notes" + .tr(), style: const TextStyle( decoration: TextDecoration.underline, ), @@ -82,8 +83,7 @@ class VersionAnnouncementOverlay extends HookConsumerWidget { ..onTap = goToReleaseNote, ), TextSpan( - text: - "version_announcement_text_3".tr(), + text: "version_announcement_text_3".tr(), ) ], ), @@ -98,7 +98,8 @@ class VersionAnnouncementOverlay extends HookConsumerWidget { primary: Colors.indigo, onPrimary: Colors.grey[50], elevation: 2, - padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 25), + padding: const EdgeInsets.symmetric( + vertical: 10, horizontal: 25), ), onPressed: onAcknowledgeTapped, child: const Text( From e4c722326328f9717a488d78676fc1a3cf3f3168 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 27 Jun 2022 16:54:14 +0200 Subject: [PATCH 15/23] Fix typo in german translation --- mobile/assets/i18n/de-DE.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/assets/i18n/de-DE.json b/mobile/assets/i18n/de-DE.json index f53172bd322a9..33c09fbf68f49 100644 --- a/mobile/assets/i18n/de-DE.json +++ b/mobile/assets/i18n/de-DE.json @@ -21,7 +21,7 @@ "backup_info_assets_scatter": "Dateien können sich über mehrere Alben verteilen.Daher können Alben während des Backup Prozesses inkludiert oder exkludiert werden.", "backup_none_selected": "Nichts ausgewählt", "backup_progress": "Backup Fortschritt: ", - "backup_remainder": "Übrig: ", + "backup_remainder": "Übrig", "backup_remainder_sub": "Noch nicht gesicherte Fotos und Videos aus gewählten Alben ", "backup_select": "Auswählen", "backup_select_albums": "Wähle Alben aus", From f9bbcaf511811ebe160f21dfacdb19424b9e7c67 Mon Sep 17 00:00:00 2001 From: Matthias Date: Mon, 27 Jun 2022 16:57:42 +0200 Subject: [PATCH 16/23] Update englisch translations --- mobile/assets/i18n/en-US.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mobile/assets/i18n/en-US.json b/mobile/assets/i18n/en-US.json index 973fa7933a348..026660bac6ef0 100644 --- a/mobile/assets/i18n/en-US.json +++ b/mobile/assets/i18n/en-US.json @@ -4,7 +4,7 @@ "home_date_year": "E, MMM dd, yyyy", "month_title_date_format": "MMMM y", "login_button_text": "Login", - "save_login": "Save Login", + "save_login": "Stay logged in", "login_endpoint_url": "Server Endpoint URL", "login_endpoint_hint": "http://your-server-ip:port", "login_err_trailing_whitespace": "Trailing whitespace", @@ -60,9 +60,9 @@ "backup_info": "Backup Information", "backup_total": "Total", "backup_total_sub": "All unique photos and videos from selected albums", - "backup_backup_sub": "Photos and videos from selected albums that are backup", + "backup_backup_sub": "Backed up photos and videos", "backup_remainder": "Remainder", - "backup_remainder_sub": "Photos and videos that has not been backing up from selected albums", + "backup_remainder_sub": "Remaining photos and albums to back up from selection", "backup_assets": "Asset that were being backup: {}", "backup_progress": "Backup Progress:", "backup_done": "Done", From 842c6ab53999fb8cadda7b81ed71cf9ca4ed9815 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 5 Jul 2022 14:28:08 +0200 Subject: [PATCH 17/23] Change translation keys to match dart filenames --- mobile/assets/i18n/de-DE.json | 194 +++++++++--------- mobile/assets/i18n/en-US.json | 184 ++++++++--------- .../asset_viewer/ui/exif_bottom_sheet.dart | 6 +- .../modules/backup/ui/album_info_card.dart | 4 +- .../modules/backup/ui/backup_info_card.dart | 2 +- .../views/backup_album_selection_page.dart | 14 +- .../backup/views/backup_controller_page.dart | 52 ++--- .../home/ui/control_bottom_app_bar.dart | 2 +- .../lib/modules/home/ui/daily_title_text.dart | 2 +- .../lib/modules/home/ui/delete_diaglog.dart | 8 +- .../modules/home/ui/monthly_title_text.dart | 2 +- .../lib/modules/home/ui/profile_drawer.dart | 4 +- mobile/lib/modules/login/ui/login_form.dart | 24 +-- mobile/lib/modules/search/ui/search_bar.dart | 2 +- .../lib/modules/search/views/search_page.dart | 6 +- .../search/views/search_result_page.dart | 2 +- .../sharing/ui/album_viewer_appbar.dart | 14 +- .../sharing/ui/sharing_sliver_appbar.dart | 4 +- .../sharing/views/album_viewer_page.dart | 2 +- .../views/create_shared_album_page.dart | 6 +- ...lect_additional_user_for_sharing_page.dart | 2 +- .../views/select_user_for_sharing_page.dart | 2 +- .../modules/sharing/views/sharing_page.dart | 6 +- .../lib/shared/views/tab_controller_page.dart | 6 +- .../views/version_announcement_overlay.dart | 12 +- mobile/scripts/check_i18n_keys.py | 18 ++ 26 files changed, 297 insertions(+), 283 deletions(-) create mode 100644 mobile/scripts/check_i18n_keys.py diff --git a/mobile/assets/i18n/de-DE.json b/mobile/assets/i18n/de-DE.json index 33c09fbf68f49..6c2e4cec24b38 100644 --- a/mobile/assets/i18n/de-DE.json +++ b/mobile/assets/i18n/de-DE.json @@ -1,103 +1,101 @@ { - "asset_description": "Beschreibung hinzufügen...", - "asset_details": "DETAILS", - "asset_err_corrupted": "Fehler bei der Darstellung - Daten sind beschädigt", - "asset_location": "STANDORT", - "backup_album_excluded": "AUSGESCHLOSSEN", - "backup_album_included": "EINGESCHLOSSEN", - "backup_albums": "Gesicherte Alben", - "backup_albums_device": "Alben auf dem Gerät", - "backup_albums_tap": "Tippe um hinzuzufügen, tippe doppelt um zu entfernen", - "backup_all": "Alle", - "backup_assets": "Gesicherte Einträge: ", - "backup_backup": "Sicherung", - "backup_backup_sub": "Gesicherte Fotos und Videos", - "backup_cancel": "Abbrechen", - "backup_done": "Fertig", - "backup_err_only_album": "Kann das einzige Album nicht löschen", - "backup_excluded": "Ausgeschlossen: ", - "backup_info": "Über die Sicherung", - "backup_info_assets": "Einträge", - "backup_info_assets_scatter": "Dateien können sich über mehrere Alben verteilen.Daher können Alben während des Backup Prozesses inkludiert oder exkludiert werden.", - "backup_none_selected": "Nichts ausgewählt", - "backup_progress": "Backup Fortschritt: ", - "backup_remainder": "Übrig", - "backup_remainder_sub": "Noch nicht gesicherte Fotos und Videos aus gewählten Alben ", - "backup_select": "Auswählen", - "backup_select_albums": "Wähle Alben aus", - "backup_selected": "Ausgewählt: ", - "backup_selection_info": "Auswahl Informationen", - "backup_server_storage": "Speicherplatz auf dem Server", - "backup_status_off": "Sicherung deaktiviert", - "backup_status_on": "Sicherung aktiviert", - "backup_storage_format": "{} von {} genutzt", - "backup_to_backup": "Zu sichernde Alben", - "backup_total": "Gesamt", - "backup_total_assets": "Gesamtzahl", - "backup_total_sub": "Alle Fotos und Videos aus gewählten Alben", - "backup_turn_off": "Sicherung deaktivieren", - "backup_turn_on": "Sicherung aktivieren", - "create_shared_album": "Geteiltes Album erstellen", - "date_format": "E, LLL d, y • HH:mm", - "desc_backup": "Aktiviere automatische Sicherung auf den Server.", - "login_button_text": "Anmelden", - "login_email_hint": "deine@email.com", - "login_endpoint_hint": "http://dein-server:port", - "login_endpoint_url": "Server URL", - "login_err_http": "Muss mit http:// oder https:// starten", - "login_err_invalid_email": "Ungültige Email-Adresse", - "login_err_leading_whitespace": "Führendes Leerzeichen", - "login_err_trailing_whitespace": "Abschließendes Leerzeichen", - "login_label_email": "Email-Adresse", - "login_label_password": "Passwort", - "login_password_hint": "passwort", - "nav_photos": "Fotos", - "nav_search": "Suche", - "nav_sharing": "Freigabe", - "save_login": "Angemeldet bleiben", - "share_add": "Hinzufügen", - "share_add_assets": "EINTRÄGE HINZUFÜGEN", - "share_add_photos": "Fotos hinzufügen", + "date_format": "E d. LLL y \u2022 hh:mm", + "daily_title_text_date": "E, dd MMM", + "daily_title_text_date_year": "E, dd MMM, yyyy", + "monthly_title_text_date_format": "MMMM y", + "login_form_button_text": "Anmelden", + "login_form_save_login": "Angemeldet bleiben", + "login_form_endpoint_url": "Server URL", + "login_form_endpoint_hint": "http://deine-server-ip:port", + "login_form_err_trailing_whitespace": "Folgendes Leerzeichen", + "login_form_err_leading_whitespace": "Führendes Leerzichen", + "login_form_err_invalid_email": "Ungültige E-Mail", + "login_form_err_http": "Bitte gebe http:// oder https:// an", + "login_form_label_email": "E-Mail", + "login_form_email_hint": "deine@email.de", + "login_form_label_password": "Passwort", + "login_form_password_hint": "password", "share_add_title": "Titel hinzufügen", - "share_add_users": "Nutzer hinzufügen", - "share_album": "Geteilte Alben", + "album_viewer_appbar_share_err_delete": "Album konnte nicht gelöscht werden", + "album_viewer_appbar_share_err_leave": "Album konnte nicht verlassen werden", + "album_viewer_appbar_share_err_remove": "Beim Löschen von Elementen aus dem Album ist ein Problem aufgetreten", + "album_viewer_appbar_share_err_title": "Der Titel konnte nicht geändert werden", + "album_viewer_appbar_share_remove": "Entferne vom Album", + "album_viewer_appbar_share_delete": "Album löschen", + "album_viewer_appbar_share_leave": "Album verlassen", + "sharing_silver_appbar_create_shared_album": "Neues geteiltes Album", + "sharing_silver_appbar_share_partner": "Teile mit Partner", + "share_add_photos": "Fotos hinzufügen", + "album_viewer_page_share_add_users": "Nutzer hinzufügen", + "share_add": "Hinzufügen", + "create_shared_album_page_share_add_assets": "ELEMENTE HINZUFÜGEN", + "create_shared_album_page_share_select_photos": "Fotos auswählen", "share_create_album": "Album erstellen", - "share_delete": "Album löschen", - "share_description": "Erstelle geteilte Alben um Fotos und Videos mit Menschen aus deinem Netzwerk zu teilen.", - "share_empty_list": "LEERE LISTE", - "share_err_album": "Fehler beim Erstellen des Albums", - "share_err_delete": "Fehler beim Löschen des Albums", - "share_err_leave": "Fehler beim Verlassen des Albums", - "share_err_remove": "Einträge konnten nicht aus dem Album gelöscht werden", - "share_err_title": "Fehler beim Ändern des Titels", + "create_shared_album_page_share": "Teilen", + "select_additional_user_for_sharing_page_suggestions": "Vorschläge", "share_invite": "Zum Album einladen", - "share_leave": "Album verlassen", - "share_partner": "Mit Partner teilen", - "share_remove": "Aus Album entfernen", - "share_select_photos": "Fotos auswählen", - "share_share": "Teilen", - "share_suggestions": "Vorschläge", - "start_backup": "Starte Backup", - "home_delete": "Löschen", - "home_delete_alert_title": "Endgültig löschen", - "home_delete_alert": "Diese Elemente werden für immer von deinem Gerät und vom Server gelöscht!", - "home_delete_alert_cancel": "Abbrechen", - "home_delete_alert_ok": "Löschen", - "home_sign_out": "Abmelden", - "home_client_server_up_to_date": "Client und Server sind aktuell", - "home_date": "E, dd MMM", - "home_date_year": "E, dd MMM, yyyy", - "month_title_date_format": "MMMM y", - "search_hint": "Durchsuche deine Fotos", - "search_places": "Orte", - "search_things": "Dinge", - "search_new_search_hint": "Neue Suche", - "search_no_objects": "Keine Informationen über Dinge verfügbar", - "search_no_places": "Keine Informationen über Orte verfügbar", - "version_announcement_title": "Eine neue Server-Version ist verfügbar \uD83C\uDF89", - "version_announcement_text_1": "Hallo mein Freund, es gibt eine neue Version von", - "version_announcement_text_2": "- Bitte nehme dir Zeit und lese die ", - "version_announcement_release_notes": "Release-Notes", - "version_announcement_text_3": " und stelle sicher, dass deine docker-compose und .env Dateien aktuell sind. So kannst du Fehler vermeiden, besonders wenn du WatchTower oder einen ähnlichen Mechanismus für automatische Updates benutzt.", - "version_announcement_ack": "Ich habe verstanden" + "select_user_for_sharing_page_err_album": "Album konnte nicht erstellt werden", + "sharing_page_empty_list": "LEERE LISTE", + "sharing_page_description": "Erstelle ein geteiltes Album um Fotos und Videos mit Personen in deinem Netzwerk zu teilen.", + "sharing_page_album": "Geteilte Alben", + "exif_bottom_sheet_description": "Beschreibung hinzufügen...", + "exif_bottom_sheet_location": "STANDORT", + "exif_bottom_sheet_details": "DETAILS", + "backup_err_only_album": "Das einzige Album kann nicht entfernt werden", + "backup_controller_page_server_storage": "Server Speicher", + "backup_controller_page_status_on": "Sicherung ist aktiv", + "backup_controller_page_status_off": "Sicherung ist inaktiv", + "backup_controller_page_turn_off": "Sicherung ausschalten", + "backup_controller_page_turn_on": "Sicherung einschalten", + "backup_controller_page_desc_backup": "Aktiviere die Sicherung um Elemente automatisch auf den Server zu laden.", + "backup_controller_page_backup_selected": "Ausgewählt: ", + "backup_all": "Alle", + "backup_controller_page_none_selected": "Keine ausgewählt", + "backup_controller_page_excluded": "Ausgeschlossen: ", + "backup_controller_page_albums": "Gesicherte Alben", + "backup_controller_page_to_backup": "Zu sichernde Alben", + "backup_controller_page_select": "Auswählen", + "backup_controller_page_backup": "Sicherung", + "backup_controller_page_info": "Informationen zur Sicherung", + "backup_controller_page_total": "Gesamt", + "backup_controller_page_total_sub": "Alle Fotos und Videos", + "backup_controller_page_backup_sub": "Gesicherte Fotos und Videos", + "backup_controller_page_remainder": "Übrig", + "backup_controller_page_remainder_sub": "Noch zu sichernde Fotos und Videos", + "backup_controller_page_assets": "Nicht gesicherte Elemente: {}", + "backup_controller_page_progress": "Sicherungsfortschritt:", + "backup_controller_page_done": "Fertig", + "backup_controller_page_cancel": "Abbrechen", + "backup_controller_page_start_backup": "Sicherung starten", + "album_info_card_backup_album_included": "EINGESCHLOSSEN", + "album_info_card_backup_album_excluded": "AUSGESCHLOSSEN", + "backup_info_card_assets": "Elemente", + "backup_album_selection_page_select_albums": "Alben auswählen", + "backup_album_selection_page_selection_info": "Auswahl", + "backup_album_selection_page_total_assets": "Elemente", + "backup_album_selection_page_albums_device": "Alben auf dem Gerät ({})", + "backup_album_selection_page_albums_tap": "Tippen um einzuschließen, doppelt tippen um zu entfernen", + "backup_album_selection_page_assets_scatter": "Elemente können sich über mehrere Alben verteilen. Daher können diese vor der Sicherung eingeschlossen oder ausgeschlossen werden", + "backup_controller_page_storage_format": "{} von {} genutzt", + "tab_controller_nav_photos": "Fotos", + "tab_controller_nav_search": "Suche", + "tab_controller_nav_sharing": "Teilen", + "control_bottom_app_bar_delete": "Löschen", + "delete_dialog_title": "Für immer löschen", + "delete_dialog_alert": "Diese Elemente werden unwiderruflich von Immich und dem Gerät entfernt", + "delete_dialog_cancel": "Abbrechen", + "delete_dialog_ok": "Löschen", + "profile_drawer_sign_out": "Abmelden", + "profile_drawer_client_server_up_to_date": "App und Server sind aktuell", + "search_bar_hint": "Durchsuche deine Fotos", + "search_page_places": "Orte", + "search_page_things": "Dinge", + "search_result_page_new_search_hint": "Neue Suche", + "search_page_no_places": "Keine Informationen über Orte verfügbar", + "version_announcement_overlay_title": "Neue Server-Version verfügbar \uD83C\uDF89", + "version_announcement_overlay_text_1": "Hallo mein Freund! Es gibt eine neue Version von", + "version_announcement_overlay_text_2": "Bitte nehm dir die Zeit und lese das ", + "version_announcement_overlay_release_notes": "Änderungsprotokoll", + "version_announcement_overlay_text_3": " und achte darauf, dass deine docker-compose und .env Dateien aktuell sind, vor allem wenn du ein System für automatische Updates benutzt (z.B. Watchtower).", + "version_announcement_overlay_ack": "Ich habe verstanden" } \ No newline at end of file diff --git a/mobile/assets/i18n/en-US.json b/mobile/assets/i18n/en-US.json index 026660bac6ef0..2d9ae211c9c24 100644 --- a/mobile/assets/i18n/en-US.json +++ b/mobile/assets/i18n/en-US.json @@ -1,103 +1,101 @@ { "date_format": "E, LLL d, y \u2022 h:mm a", - "home_date": "E, MMM dd", - "home_date_year": "E, MMM dd, yyyy", - "month_title_date_format": "MMMM y", - "login_button_text": "Login", - "save_login": "Stay logged in", - "login_endpoint_url": "Server Endpoint URL", - "login_endpoint_hint": "http://your-server-ip:port", - "login_err_trailing_whitespace": "Trailing whitespace", - "login_err_leading_whitespace": "Leading whitespace", - "login_err_invalid_email": "Invalid Email", - "login_err_http": "Please specify http:// or https://", - "login_label_email": "Email", - "login_email_hint": "youremail@email.com", - "login_label_password": "Password", - "login_password_hint": "password", + "daily_title_text_date": "E, MMM dd", + "daily_title_text_date_year": "E, MMM dd, yyyy", + "monthly_title_text_date_format": "MMMM y", + "login_form_button_text": "Login", + "login_form_save_login": "Stay logged in", + "login_form_endpoint_url": "Server Endpoint URL", + "login_form_endpoint_hint": "http://your-server-ip:port", + "login_form_err_trailing_whitespace": "Trailing whitespace", + "login_form_err_leading_whitespace": "Leading whitespace", + "login_form_err_invalid_email": "Invalid Email", + "login_form_err_http": "Please specify http:// or https://", + "login_form_label_email": "Email", + "login_form_email_hint": "youremail@email.com", + "login_form_label_password": "Password", + "login_form_password_hint": "password", "share_add_title": "Add a title", - "share_err_delete": "Failed to delete album", - "share_err_leave": "Failed to leave album", - "share_err_remove": "There are problems in removing assets from album", - "share_err_title": "Failed to change album title", - "share_remove": "Remove from album", - "share_delete": "Delete album", - "share_leave": "Leave album", - "create_shared_album": "Create shared album", - "share_partner": "Share with partner", + "album_viewer_appbar_share_err_delete": "Failed to delete album", + "album_viewer_appbar_share_err_leave": "Failed to leave album", + "album_viewer_appbar_share_err_remove": "There are problems in removing assets from album", + "album_viewer_appbar_share_err_title": "Failed to change album title", + "album_viewer_appbar_share_remove": "Remove from album", + "album_viewer_appbar_share_delete": "Delete album", + "album_viewer_appbar_share_leave": "Leave album", + "sharing_silver_appbar_create_shared_album": "Create shared album", + "sharing_silver_appbar_share_partner": "Share with partner", "share_add_photos": "Add photos", - "share_add_users": "Add users", + "album_viewer_page_share_add_users": "Add users", "share_add": "Add", - "share_add_assets": "ADD ASSETS", - "share_select_photos": "Select Photos", + "create_shared_album_page_share_add_assets": "ADD ASSETS", + "create_shared_album_page_share_select_photos": "Select Photos", "share_create_album": "Create album", - "share_share": "Share", - "share_suggestions": "Suggestions", + "create_shared_album_page_share": "Share", + "select_additional_user_for_sharing_page_suggestions": "Suggestions", "share_invite": "Invite to album", - "share_err_album": "Failed to create album", - "share_empty_list": "EMPTY LIST", - "share_description": "Create shared albums to share photos and videos with people in your network.", - "share_album": "Shared albums", - "asset_description": "Add Description...", - "asset_location": "LOCATION", - "asset_details": "DETAILS", - "asset_err_corrupted": "Failed To Render Image - Possibly Corrupted Data", + "select_user_for_sharing_page_err_album": "Failed to create album", + "sharing_page_empty_list": "EMPTY LIST", + "sharing_page_description": "Create shared albums to share photos and videos with people in your network.", + "sharing_page_album": "Shared albums", + "exif_bottom_sheet_description": "Add Description...", + "exif_bottom_sheet_location": "LOCATION", + "exif_bottom_sheet_details": "DETAILS", "backup_err_only_album": "Cannot remove the only album", - "backup_server_storage": "Server Storage", - "backup_status_on": "Backup is on", - "backup_status_off": "Backup is off", - "backup_turn_off": "Turn off Backup", - "backup_turn_on": "Turn on Backup", - "desc_backup": "Turn on backup to automatically upload new assets to the server.", - "backup_selected": "Selected: ", + "backup_controller_page_server_storage": "Server Storage", + "backup_controller_page_status_on": "Backup is on", + "backup_controller_page_status_off": "Backup is off", + "backup_controller_page_turn_off": "Turn off Backup", + "backup_controller_page_turn_on": "Turn on Backup", + "backup_controller_page_desc_backup": "Turn on backup to automatically upload new assets to the server.", + "backup_controller_page_backup_selected": "Selected: ", "backup_all": "All", - "backup_none_selected": "None selected", - "backup_excluded": "Excluded: ", - "backup_albums": "Backup Albums", - "backup_to_backup": "Albums to be backup", - "backup_select": "Select", - "backup_backup": "Backup", - "backup_info": "Backup Information", - "backup_total": "Total", - "backup_total_sub": "All unique photos and videos from selected albums", - "backup_backup_sub": "Backed up photos and videos", - "backup_remainder": "Remainder", - "backup_remainder_sub": "Remaining photos and albums to back up from selection", - "backup_assets": "Asset that were being backup: {}", - "backup_progress": "Backup Progress:", - "backup_done": "Done", - "backup_cancel": "Cancel", - "start_backup": "Start Backup", - "backup_album_included": "INCLUDED", - "backup_album_excluded": "EXCLUDED", - "backup_info_assets": "assets", - "backup_select_albums": "Select Albums", - "backup_selection_info": "Selection Info", - "backup_total_assets": "Total unique assets", - "backup_albums_device": "Albums on device ({})", - "backup_albums_tap": "Tap to include, double tap to exclude", - "backup_info_assets_scatter": "Assets can scatter across multiple albums. Thus, albums can be included or excluded during the backup process.", - "backup_storage_format": "{} of {} used", - "nav_photos": "Photos", - "nav_search": "Search", - "nav_sharing": "Sharing", - "home_delete": "Delete", - "home_delete_alert_title": "Delete Permanently", - "home_delete_alert": "These items will be permanently deleted from Immich and from your device", - "home_delete_alert_cancel": "Cancel", - "home_delete_alert_ok": "Delete", - "home_sign_out": "Sign Out", - "home_client_server_up_to_date": "Client and Server are up-to-date", - "search_hint": "Search your photos", - "search_places": "Places", - "search_things": "Things", - "search_new_search_hint": "New Search", - "search_no_objects": "No Object Info Available", - "search_no_places": "No Places Info Available", - "version_announcement_title": "New Server Version Available \uD83C\uDF89", - "version_announcement_text_1": "Hi friend, there is a new release of", - "version_announcement_text_2": "please take your time to visit the ", - "version_announcement_release_notes": "release notes", - "version_announcement_text_3": " and ensure your docker-compose and .env setup is up-to-date to prevent any misconfigurations, especially if you use WatchTower or any mechanism that handles updating your server application automatically.", - "version_announcement_ack": "Acknowledge" + "backup_controller_page_none_selected": "None selected", + "backup_controller_page_excluded": "Excluded: ", + "backup_controller_page_albums": "Backup Albums", + "backup_controller_page_to_backup": "Albums to be backup", + "backup_controller_page_select": "Select", + "backup_controller_page_backup": "Backup", + "backup_controller_page_info": "Backup Information", + "backup_controller_page_total": "Total", + "backup_controller_page_total_sub": "All unique photos and videos from selected albums", + "backup_controller_page_backup_sub": "Backed up photos and videos", + "backup_controller_page_remainder": "Remainder", + "backup_controller_page_remainder_sub": "Remaining photos and albums to back up from selection", + "backup_controller_page_assets": "Asset that were being backup: {}", + "backup_controller_page_progress": "Backup Progress:", + "backup_controller_page_done": "Done", + "backup_controller_page_cancel": "Cancel", + "backup_controller_page_start_backup": "Start Backup", + "album_info_card_backup_album_included": "INCLUDED", + "album_info_card_backup_album_excluded": "EXCLUDED", + "backup_info_card_assets": "assets", + "backup_album_selection_page_select_albums": "Select Albums", + "backup_album_selection_page_selection_info": "Selection Info", + "backup_album_selection_page_total_assets": "Total unique assets", + "backup_album_selection_page_albums_device": "Albums on device ({})", + "backup_album_selection_page_albums_tap": "Tap to include, double tap to exclude", + "backup_album_selection_page_assets_scatter": "Assets can scatter across multiple albums. Thus, albums can be included or excluded during the backup process.", + "backup_controller_page_storage_format": "{} of {} used", + "tab_controller_nav_photos": "Photos", + "tab_controller_nav_search": "Search", + "tab_controller_nav_sharing": "Sharing", + "control_bottom_app_bar_delete": "Delete", + "delete_dialog_title": "Delete Permanently", + "delete_dialog_alert": "These items will be permanently deleted from Immich and from your device", + "delete_dialog_cancel": "Cancel", + "delete_dialog_ok": "Delete", + "profile_drawer_sign_out": "Sign Out", + "profile_drawer_client_server_up_to_date": "Client and Server are up-to-date", + "search_bar_hint": "Search your photos", + "search_page_places": "Places", + "search_page_things": "Things", + "search_result_page_new_search_hint": "New Search", + "search_page_no_places": "No Places Info Available", + "version_announcement_overlay_title": "New Server Version Available \uD83C\uDF89", + "version_announcement_overlay_text_1": "Hi friend, there is a new release of", + "version_announcement_overlay_text_2": "please take your time to visit the ", + "version_announcement_overlay_release_notes": "release notes", + "version_announcement_overlay_text_3": " and ensure your docker-compose and .env setup is up-to-date to prevent any misconfigurations, especially if you use WatchTower or any mechanism that handles updating your server application automatically.", + "version_announcement_overlay_ack": "Acknowledge" } \ No newline at end of file diff --git a/mobile/lib/modules/asset_viewer/ui/exif_bottom_sheet.dart b/mobile/lib/modules/asset_viewer/ui/exif_bottom_sheet.dart index 379e8db316982..9ec8edda1ccf1 100644 --- a/mobile/lib/modules/asset_viewer/ui/exif_bottom_sheet.dart +++ b/mobile/lib/modules/asset_viewer/ui/exif_bottom_sheet.dart @@ -94,7 +94,7 @@ class ExifBottomSheet extends ConsumerWidget { Padding( padding: const EdgeInsets.only(top: 16.0), child: Text( - "asset_description", + "exif_bottom_sheet_description", style: TextStyle( color: Colors.grey[500], fontSize: 11, @@ -114,7 +114,7 @@ class ExifBottomSheet extends ConsumerWidget { color: Colors.grey[600], ), Text( - "asset_location", + "exif_bottom_sheet_location", style: TextStyle(fontSize: 11, color: Colors.grey[400]), ).tr(), _buildMap(), @@ -141,7 +141,7 @@ class ExifBottomSheet extends ConsumerWidget { Padding( padding: const EdgeInsets.only(bottom: 8.0), child: Text( - "asset_details", + "exif_bottom_sheet_details", style: TextStyle(fontSize: 11, color: Colors.grey[400]), ).tr(), diff --git a/mobile/lib/modules/backup/ui/album_info_card.dart b/mobile/lib/modules/backup/ui/album_info_card.dart index 4056f2a5a7396..1a8c489f849d8 100644 --- a/mobile/lib/modules/backup/ui/album_info_card.dart +++ b/mobile/lib/modules/backup/ui/album_info_card.dart @@ -38,7 +38,7 @@ class AlbumInfoCard extends HookConsumerWidget { visualDensity: VisualDensity.compact, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)), label: const Text( - "backup_album_included", + "album_info_card_backup_album_included", style: TextStyle( fontSize: 10, color: Colors.white, fontWeight: FontWeight.bold), ).tr(), @@ -49,7 +49,7 @@ class AlbumInfoCard extends HookConsumerWidget { visualDensity: VisualDensity.compact, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)), label: const Text( - "backup_album_excluded", + "album_info_card_backup_album_excluded", style: TextStyle( fontSize: 10, color: Colors.white, fontWeight: FontWeight.bold), ).tr(), diff --git a/mobile/lib/modules/backup/ui/backup_info_card.dart b/mobile/lib/modules/backup/ui/backup_info_card.dart index 3f481cef984d8..300fa1febadbb 100644 --- a/mobile/lib/modules/backup/ui/backup_info_card.dart +++ b/mobile/lib/modules/backup/ui/backup_info_card.dart @@ -45,7 +45,7 @@ class BackupInfoCard extends StatelessWidget { info, style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold), ), - const Text("backup_info_assets").tr(), + const Text("backup_info_card_assets").tr(), ], ), ), diff --git a/mobile/lib/modules/backup/views/backup_album_selection_page.dart b/mobile/lib/modules/backup/views/backup_album_selection_page.dart index c6ce5777930a0..27cf556842697 100644 --- a/mobile/lib/modules/backup/views/backup_album_selection_page.dart +++ b/mobile/lib/modules/backup/views/backup_album_selection_page.dart @@ -137,7 +137,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { icon: const Icon(Icons.arrow_back_ios_rounded), ), title: const Text( - "backup_select_albums", + "backup_album_selection_page_select_albums", style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ).tr(), elevation: 0, @@ -149,7 +149,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0), child: const Text( - "backup_selection_info", + "backup_album_selection_page_selection_info", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14), ).tr(), ), @@ -183,7 +183,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { ListTile( visualDensity: VisualDensity.compact, title: Text( - "backup_total_assets", + "backup_album_selection_page_total_assets", style: TextStyle( fontWeight: FontWeight.bold, fontSize: 14, @@ -205,14 +205,14 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { ListTile( title: Text( - "backup_albums_device" + "backup_album_selection_page_albums_device" .tr(args: [availableAlbums.length.toString()]), style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 14), ), subtitle: Padding( padding: const EdgeInsets.symmetric(vertical: 8.0), child: Text( - "backup_albums_tap", + "backup_album_selection_page_albums_tap", style: TextStyle( fontSize: 12, color: Theme.of(context).primaryColor, @@ -237,7 +237,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { borderRadius: BorderRadius.circular(12)), elevation: 5, title: Text( - 'backup_selection_info', + 'backup_album_selection_page_selection_info', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, @@ -248,7 +248,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { child: ListBody( children: [ Text( - 'backup_info_assets_scatter', + 'backup_album_selection_page_assets_scatter', style: TextStyle( fontSize: 14, color: Colors.grey[700]), ).tr(), diff --git a/mobile/lib/modules/backup/views/backup_controller_page.dart b/mobile/lib/modules/backup/views/backup_controller_page.dart index 1e6fbbb78047d..a5f019985f339 100644 --- a/mobile/lib/modules/backup/views/backup_controller_page.dart +++ b/mobile/lib/modules/backup/views/backup_controller_page.dart @@ -43,7 +43,7 @@ class BackupControllerPage extends HookConsumerWidget { color: Theme.of(context).primaryColor, ), title: const Text( - "backup_server_storage", + "backup_controller_page_server_storage", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14), ).tr(), subtitle: Padding( @@ -65,7 +65,7 @@ class BackupControllerPage extends HookConsumerWidget { ), Padding( padding: const EdgeInsets.only(top: 12.0), - child: Text('backup_storage_format').tr(args: [ + child: Text('backup_controller_page_storage_format').tr(args: [ backupState.serverInfo.diskUse, backupState.serverInfo.diskSize ]), @@ -78,12 +78,12 @@ class BackupControllerPage extends HookConsumerWidget { ListTile _buildBackupController() { var backUpOption = authenticationState.deviceInfo.isAutoBackup - ? "backup_status_on".tr() - : "backup_status_off".tr(); + ? "backup_controller_page_status_on".tr() + : "backup_controller_page_status_off".tr(); var isAutoBackup = authenticationState.deviceInfo.isAutoBackup; var backupBtnText = authenticationState.deviceInfo.isAutoBackup - ? "backup_turn_off".tr() - : "backup_turn_on".tr(); + ? "backup_controller_page_turn_off".tr() + : "backup_controller_page_turn_on".tr(); return ListTile( isThreeLine: true, leading: isAutoBackup @@ -103,7 +103,7 @@ class BackupControllerPage extends HookConsumerWidget { children: [ !isAutoBackup ? const Text( - "desc_backup", + "backup_controller_page_desc_backup", style: TextStyle(fontSize: 14), ).tr() : Container(), @@ -138,7 +138,7 @@ class BackupControllerPage extends HookConsumerWidget { } Widget _buildSelectedAlbumName() { - var text = "backup_selected".tr(); + var text = "backup_controller_page_backup_selected".tr(); var albums = ref.watch(backupProvider).selectedBackupAlbums; if (albums.isNotEmpty) { @@ -164,7 +164,7 @@ class BackupControllerPage extends HookConsumerWidget { return Padding( padding: const EdgeInsets.only(top: 8.0), child: Text( - "backup_none_selected".tr(), + "backup_controller_page_none_selected".tr(), style: TextStyle( color: Theme.of(context).primaryColor, fontSize: 12, @@ -175,7 +175,7 @@ class BackupControllerPage extends HookConsumerWidget { } Widget _buildExcludedAlbumName() { - var text = "backup_excluded".tr(); + var text = "backup_controller_page_excluded".tr(); var albums = ref.watch(backupProvider).excludedBackupAlbums; if (albums.isNotEmpty) { @@ -211,7 +211,7 @@ class BackupControllerPage extends HookConsumerWidget { borderOnForeground: false, child: ListTile( minVerticalPadding: 15, - title: const Text("backup_albums", + title: const Text("backup_controller_page_albums", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)) .tr(), subtitle: Padding( @@ -220,7 +220,7 @@ class BackupControllerPage extends HookConsumerWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( - "backup_to_backup", + "backup_controller_page_to_backup", style: TextStyle(color: Color(0xFF808080), fontSize: 12), ).tr(), _buildSelectedAlbumName(), @@ -244,7 +244,7 @@ class BackupControllerPage extends HookConsumerWidget { vertical: 16.0, ), child: const Text( - "backup_select", + "backup_controller_page_select", style: TextStyle(fontWeight: FontWeight.bold), ).tr(), ), @@ -257,7 +257,7 @@ class BackupControllerPage extends HookConsumerWidget { appBar: AppBar( elevation: 0, title: const Text( - "backup_backup", + "backup_controller_page_backup", style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ).tr(), leading: IconButton( @@ -278,24 +278,24 @@ class BackupControllerPage extends HookConsumerWidget { Padding( padding: const EdgeInsets.all(8.0), child: const Text( - "backup_info", + "backup_controller_page_info", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16), ).tr(), ), _buildFolderSelectionTile(), BackupInfoCard( - title: "backup_total".tr(), - subtitle: "backup_total_sub".tr(), + title: "backup_controller_page_total".tr(), + subtitle: "backup_controller_page_total_sub".tr(), info: "${backupState.allUniqueAssets.length}", ), BackupInfoCard( - title: "backup_backup".tr(), - subtitle: "backup_backup_sub".tr(), + title: "backup_controller_page_backup".tr(), + subtitle: "backup_controller_page_backup_sub".tr(), info: "${backupState.selectedAlbumsBackupAssetsIds.length}", ), BackupInfoCard( - title: "backup_remainder".tr(), - subtitle: "backup_remainder_sub".tr(), + title: "backup_controller_page_remainder".tr(), + subtitle: "backup_controller_page_remainder_sub".tr(), info: "${backupState.allUniqueAssets.length - backupState.selectedAlbumsBackupAssetsIds.length}", ), @@ -306,18 +306,18 @@ class BackupControllerPage extends HookConsumerWidget { const Divider(), Padding( padding: const EdgeInsets.all(8.0), - child: Text("backup_assets".tr(args: [ + child: Text("backup_controller_page_assets".tr(args: [ "${backupState.allUniqueAssets.length - backupState.selectedAlbumsBackupAssetsIds.length} [${backupState.progressInPercentage.toStringAsFixed(0)}%]" ])), ), Padding( padding: const EdgeInsets.only(left: 8.0), child: Row(children: [ - const Text("backup_progress").tr(), + const Text("backup_controller_page_progress").tr(), const Padding(padding: EdgeInsets.symmetric(horizontal: 2)), backupState.backupProgress == BackUpProgressEnum.inProgress ? const CircularProgressIndicator.adaptive() - : const Text("backup_done").tr(), + : const Text("backup_controller_page_done").tr(), ]), ), Padding( @@ -333,7 +333,7 @@ class BackupControllerPage extends HookConsumerWidget { onPressed: () { ref.read(backupProvider.notifier).cancelBackup(); }, - child: const Text("backup_cancel").tr(), + child: const Text("backup_controller_page_cancel").tr(), ) : ElevatedButton( style: ElevatedButton.styleFrom( @@ -347,7 +347,7 @@ class BackupControllerPage extends HookConsumerWidget { .startBackupProcess(); } : null, - child: const Text("start_backup").tr(), + child: const Text("backup_controller_page_start_backup").tr(), ), ), ) diff --git a/mobile/lib/modules/home/ui/control_bottom_app_bar.dart b/mobile/lib/modules/home/ui/control_bottom_app_bar.dart index 73f234b40f26e..2ff56fb997fa5 100644 --- a/mobile/lib/modules/home/ui/control_bottom_app_bar.dart +++ b/mobile/lib/modules/home/ui/control_bottom_app_bar.dart @@ -27,7 +27,7 @@ class ControlBottomAppBar extends StatelessWidget { children: [ ControlBoxButton( iconData: Icons.delete_forever_rounded, - label: "home_delete".tr(), + label: "control_bottom_app_bar_delete".tr(), onPressed: () { showDialog( context: context, diff --git a/mobile/lib/modules/home/ui/daily_title_text.dart b/mobile/lib/modules/home/ui/daily_title_text.dart index 0af5bf6a5861f..15e941f9a06ea 100644 --- a/mobile/lib/modules/home/ui/daily_title_text.dart +++ b/mobile/lib/modules/home/ui/daily_title_text.dart @@ -20,7 +20,7 @@ class DailyTitleText extends ConsumerWidget { var currentYear = DateTime.now().year; var groupYear = DateTime.parse(isoDate).year; var formatDateTemplate = - currentYear == groupYear ? "home_date".tr() : "home_date_year".tr(); + currentYear == groupYear ? "daily_title_text_date".tr() : "daily_title_text_date_year".tr(); var dateText = DateFormat(formatDateTemplate).format(DateTime.parse(isoDate)); var isMultiSelectEnable = diff --git a/mobile/lib/modules/home/ui/delete_diaglog.dart b/mobile/lib/modules/home/ui/delete_diaglog.dart index 5408b67fb07a1..3adef135a8ee6 100644 --- a/mobile/lib/modules/home/ui/delete_diaglog.dart +++ b/mobile/lib/modules/home/ui/delete_diaglog.dart @@ -14,15 +14,15 @@ class DeleteDialog extends ConsumerWidget { return AlertDialog( backgroundColor: Colors.grey[200], shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), - title: const Text("home_delete_alert_title").tr(), - content: const Text("home_delete_alert").tr(), + title: const Text("delete_dialog_title").tr(), + content: const Text("delete_dialog_alert").tr(), actions: [ TextButton( onPressed: () { Navigator.of(context).pop(); }, child: const Text( - "home_delete_alert_cancel", + "delete_dialog_cancel", style: TextStyle(color: Colors.blueGrey), ).tr(), ), @@ -36,7 +36,7 @@ class DeleteDialog extends ConsumerWidget { Navigator.of(context).pop(); }, child: Text( - "home_delete_alert_ok", + "delete_dialog_ok", style: TextStyle(color: Colors.red[400]), ).tr(), ), diff --git a/mobile/lib/modules/home/ui/monthly_title_text.dart b/mobile/lib/modules/home/ui/monthly_title_text.dart index a00b8bae03002..ad9998c8f2c22 100644 --- a/mobile/lib/modules/home/ui/monthly_title_text.dart +++ b/mobile/lib/modules/home/ui/monthly_title_text.dart @@ -12,7 +12,7 @@ class MonthlyTitleText extends StatelessWidget { @override Widget build(BuildContext context) { - var monthTitleText = DateFormat("month_title_date_format".tr()).format(DateTime.parse(isoDate)); + var monthTitleText = DateFormat("monthly_title_text_date_format".tr()).format(DateTime.parse(isoDate)); return SliverToBoxAdapter( child: Padding( diff --git a/mobile/lib/modules/home/ui/profile_drawer.dart b/mobile/lib/modules/home/ui/profile_drawer.dart index a1ab9e49759a4..bd85f7fd0acc8 100644 --- a/mobile/lib/modules/home/ui/profile_drawer.dart +++ b/mobile/lib/modules/home/ui/profile_drawer.dart @@ -184,7 +184,7 @@ class ProfileDrawer extends HookConsumerWidget { color: Colors.black54, ), title: const Text( - "home_sign_out", + "profile_drawer_sign_out", style: TextStyle( color: Colors.black54, fontSize: 14, @@ -228,7 +228,7 @@ class ProfileDrawer extends HookConsumerWidget { child: Text( serverInfoState.isVersionMismatch ? serverInfoState.versionMismatchErrorMessage - : "home_client_server_up_to_date".tr(), + : "profile_drawer_client_server_up_to_date".tr(), textAlign: TextAlign.center, style: TextStyle( fontSize: 11, diff --git a/mobile/lib/modules/login/ui/login_form.dart b/mobile/lib/modules/login/ui/login_form.dart index 3f0152d7b721c..ef69ec4b7eb88 100644 --- a/mobile/lib/modules/login/ui/login_form.dart +++ b/mobile/lib/modules/login/ui/login_form.dart @@ -73,7 +73,7 @@ class LoginForm extends HookConsumerWidget { borderRadius: BorderRadius.circular(5)), enableFeedback: true, title: const Text( - "save_login", + "login_form_save_login", style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, @@ -108,7 +108,7 @@ class ServerEndpointInput extends StatelessWidget { String? _validateInput(String? url) { if (url == null) return null; - if (!url.startsWith(RegExp(r'https?://'))) return 'login_err_http'.tr(); + if (!url.startsWith(RegExp(r'https?://'))) return 'login_form_err_http'.tr(); return null; } @@ -117,9 +117,9 @@ class ServerEndpointInput extends StatelessWidget { return TextFormField( controller: controller, decoration: InputDecoration( - labelText: 'login_endpoint_url'.tr(), + labelText: 'login_form_endpoint_url'.tr(), border: OutlineInputBorder(), - hintText: 'login_endpoint_hint'.tr()), + hintText: 'login_form_endpoint_hint'.tr()), validator: _validateInput, autovalidateMode: AutovalidateMode.always, ); @@ -133,10 +133,10 @@ class EmailInput extends StatelessWidget { String? _validateInput(String? email) { if (email == null || email == '') return null; - if (email.endsWith(' ')) return 'login_err_trailing_whitespace'.tr(); - if (email.startsWith(' ')) return 'login_err_leading_whitespace'.tr(); + if (email.endsWith(' ')) return 'login_form_err_trailing_whitespace'.tr(); + if (email.startsWith(' ')) return 'login_form_err_leading_whitespace'.tr(); if (email.contains(' ') || !email.contains('@')) - return 'login_err_invalid_email'.tr(); + return 'login_form_err_invalid_email'.tr(); return null; } @@ -145,9 +145,9 @@ class EmailInput extends StatelessWidget { return TextFormField( controller: controller, decoration: InputDecoration( - labelText: 'login_label_email'.tr(), + labelText: 'login_form_label_email'.tr(), border: OutlineInputBorder(), - hintText: 'login_email_hint'.tr()), + hintText: 'login_form_email_hint'.tr()), validator: _validateInput, autovalidateMode: AutovalidateMode.always, ); @@ -165,9 +165,9 @@ class PasswordInput extends StatelessWidget { obscureText: true, controller: controller, decoration: InputDecoration( - labelText: 'login_label_password'.tr(), + labelText: 'login_form_label_password'.tr(), border: OutlineInputBorder(), - hintText: 'login_password_hint'.tr()), + hintText: 'login_form_password_hint'.tr()), ); } } @@ -218,7 +218,7 @@ class LoginButton extends ConsumerWidget { } }, child: const Text( - "login_button_text", + "login_form_button_text", style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold), ).tr()); } diff --git a/mobile/lib/modules/search/ui/search_bar.dart b/mobile/lib/modules/search/ui/search_bar.dart index 65ed42663f498..f1b67749af74f 100644 --- a/mobile/lib/modules/search/ui/search_bar.dart +++ b/mobile/lib/modules/search/ui/search_bar.dart @@ -49,7 +49,7 @@ class SearchBar extends HookConsumerWidget with PreferredSizeWidget { ref.watch(searchPageStateProvider.notifier).setSearchTerm(value); }, decoration: InputDecoration( - hintText: 'search_hint'.tr(), + hintText: 'search_bar_hint'.tr(), enabledBorder: UnderlineInputBorder( borderSide: BorderSide(color: Colors.transparent), ), diff --git a/mobile/lib/modules/search/views/search_page.dart b/mobile/lib/modules/search/views/search_page.dart index 2f4935e9805ad..793000fd8bfc9 100644 --- a/mobile/lib/modules/search/views/search_page.dart +++ b/mobile/lib/modules/search/views/search_page.dart @@ -83,7 +83,7 @@ class SearchPage extends HookConsumerWidget { return ThumbnailWithInfo( imageUrl: 'https://images.unsplash.com/photo-1612178537253-bccd437b730e?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8NXx8Ymxhbmt8ZW58MHx8MHx8&auto=format&fit=crop&w=700&q=60', - textInfo: 'search_no_places'.tr(), + textInfo: 'search_page_no_places'.tr(), onTap: () {}, ); }), @@ -162,7 +162,7 @@ class SearchPage extends HookConsumerWidget { Padding( padding: EdgeInsets.all(16.0), child: const Text( - "search_places", + "search_page_places", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16), ).tr(), ), @@ -170,7 +170,7 @@ class SearchPage extends HookConsumerWidget { Padding( padding: EdgeInsets.all(16.0), child: const Text( - "search_things", + "search_page_things", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16), ).tr(), ), diff --git a/mobile/lib/modules/search/views/search_result_page.dart b/mobile/lib/modules/search/views/search_result_page.dart index af390588befd8..428bf33d08cda 100644 --- a/mobile/lib/modules/search/views/search_result_page.dart +++ b/mobile/lib/modules/search/views/search_result_page.dart @@ -68,7 +68,7 @@ class SearchResultPage extends HookConsumerWidget { ref.watch(searchPageStateProvider.notifier).setSearchTerm(value); }, decoration: InputDecoration( - hintText: 'search_new_search_hint'.tr(), + hintText: 'search_result_page_new_search_hint'.tr(), enabledBorder: UnderlineInputBorder( borderSide: BorderSide(color: Colors.transparent), ), diff --git a/mobile/lib/modules/sharing/ui/album_viewer_appbar.dart b/mobile/lib/modules/sharing/ui/album_viewer_appbar.dart index 303be33b40f46..50aaed0643501 100644 --- a/mobile/lib/modules/sharing/ui/album_viewer_appbar.dart +++ b/mobile/lib/modules/sharing/ui/album_viewer_appbar.dart @@ -46,7 +46,7 @@ class AlbumViewerAppbar extends HookConsumerWidget with PreferredSizeWidget { } else { ImmichToast.show( context: context, - msg: "share_err_delete".tr(), + msg: "album_viewer_appbar_share_err_delete".tr(), toastType: ToastType.error, gravity: ToastGravity.BOTTOM, ); @@ -68,7 +68,7 @@ class AlbumViewerAppbar extends HookConsumerWidget with PreferredSizeWidget { Navigator.pop(context); ImmichToast.show( context: context, - msg: "share_err_leave".tr(), + msg: "album_viewer_appbar_share_err_leave".tr(), toastType: ToastType.error, gravity: ToastGravity.BOTTOM, ); @@ -94,7 +94,7 @@ class AlbumViewerAppbar extends HookConsumerWidget with PreferredSizeWidget { Navigator.pop(context); ImmichToast.show( context: context, - msg: "share_err_remove".tr(), + msg: "album_viewer_appbar_share_err_remove".tr(), toastType: ToastType.error, gravity: ToastGravity.BOTTOM, ); @@ -109,7 +109,7 @@ class AlbumViewerAppbar extends HookConsumerWidget with PreferredSizeWidget { return ListTile( leading: const Icon(Icons.delete_sweep_rounded), title: const Text( - 'share_remove', + 'album_viewer_appbar_share_remove', style: TextStyle(fontWeight: FontWeight.bold), ).tr(), onTap: () => _onRemoveFromAlbumPressed(albumId), @@ -122,7 +122,7 @@ class AlbumViewerAppbar extends HookConsumerWidget with PreferredSizeWidget { return ListTile( leading: const Icon(Icons.delete_forever_rounded), title: const Text( - 'share_delete', + 'album_viewer_appbar_share_delete', style: TextStyle(fontWeight: FontWeight.bold), ).tr(), onTap: () => _onDeleteAlbumPressed(albumId), @@ -131,7 +131,7 @@ class AlbumViewerAppbar extends HookConsumerWidget with PreferredSizeWidget { return ListTile( leading: const Icon(Icons.person_remove_rounded), title: const Text( - 'share_leave', + 'album_viewer_appbar_share_leave', style: TextStyle(fontWeight: FontWeight.bold), ).tr(), onTap: () => _onLeaveAlbumPressed(albumId), @@ -177,7 +177,7 @@ class AlbumViewerAppbar extends HookConsumerWidget with PreferredSizeWidget { if (!isSuccess) { ImmichToast.show( context: context, - msg: "share_err_title".tr(), + msg: "album_viewer_appbar_share_err_title".tr(), gravity: ToastGravity.BOTTOM, toastType: ToastType.error, ); diff --git a/mobile/lib/modules/sharing/ui/sharing_sliver_appbar.dart b/mobile/lib/modules/sharing/ui/sharing_sliver_appbar.dart index a43a3edffdc2e..57243a9460235 100644 --- a/mobile/lib/modules/sharing/ui/sharing_sliver_appbar.dart +++ b/mobile/lib/modules/sharing/ui/sharing_sliver_appbar.dart @@ -51,7 +51,7 @@ class SharingSliverAppBar extends StatelessWidget { size: 20, ), label: const Text( - "create_shared_album", + "sharing_silver_appbar_create_shared_album", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 12), ).tr(), @@ -73,7 +73,7 @@ class SharingSliverAppBar extends StatelessWidget { size: 20, ), label: const Text( - "share_partner", + "sharing_silver_appbar_share_partner", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 12), ).tr(), diff --git a/mobile/lib/modules/sharing/views/album_viewer_page.dart b/mobile/lib/modules/sharing/views/album_viewer_page.dart index 54a8844c6f458..4db972e08fc12 100644 --- a/mobile/lib/modules/sharing/views/album_viewer_page.dart +++ b/mobile/lib/modules/sharing/views/album_viewer_page.dart @@ -214,7 +214,7 @@ class AlbumViewerPage extends HookConsumerWidget { ? AlbumActionOutlinedButton( iconData: Icons.person_add_alt_rounded, onPressed: () => _onAddUsersPressed(albumInfo), - labelText: "share_add_users".tr(), + labelText: "album_viewer_page_share_add_users".tr(), ) : Container(), ], diff --git a/mobile/lib/modules/sharing/views/create_shared_album_page.dart b/mobile/lib/modules/sharing/views/create_shared_album_page.dart index c47a79894c24c..35840a26b6381 100644 --- a/mobile/lib/modules/sharing/views/create_shared_album_page.dart +++ b/mobile/lib/modules/sharing/views/create_shared_album_page.dart @@ -69,7 +69,7 @@ class CreateSharedAlbumPage extends HookConsumerWidget { child: Padding( padding: EdgeInsets.only(top: 200, left: 18), child: Text( - 'share_add_assets', + 'create_shared_album_page_share_add_assets', style: TextStyle(fontSize: 12), ).tr(), ), @@ -98,7 +98,7 @@ class CreateSharedAlbumPage extends HookConsumerWidget { label: Padding( padding: const EdgeInsets.only(left: 8.0), child: Text( - 'share_select_photos', + 'create_shared_album_page_share_select_photos', style: TextStyle( fontSize: 16, color: Colors.grey[700], @@ -183,7 +183,7 @@ class CreateSharedAlbumPage extends HookConsumerWidget { ? _showSelectUserPage : null, child: Text( - 'share_share'.tr(), + 'create_shared_album_page_share'.tr(), style: TextStyle( fontWeight: FontWeight.bold, ), diff --git a/mobile/lib/modules/sharing/views/select_additional_user_for_sharing_page.dart b/mobile/lib/modules/sharing/views/select_additional_user_for_sharing_page.dart index 1108407b47b63..59ebc7e009a8e 100644 --- a/mobile/lib/modules/sharing/views/select_additional_user_for_sharing_page.dart +++ b/mobile/lib/modules/sharing/views/select_additional_user_for_sharing_page.dart @@ -72,7 +72,7 @@ class SelectAdditionalUserForSharingPage extends HookConsumerWidget { Padding( padding: EdgeInsets.all(16.0), child: Text( - 'share_suggestions'.tr(), + 'select_additional_user_for_sharing_page_suggestions'.tr(), style: TextStyle( fontSize: 14, color: Colors.grey, diff --git a/mobile/lib/modules/sharing/views/select_user_for_sharing_page.dart b/mobile/lib/modules/sharing/views/select_user_for_sharing_page.dart index 7a40ddfab9395..0e0efc4878fa3 100644 --- a/mobile/lib/modules/sharing/views/select_user_for_sharing_page.dart +++ b/mobile/lib/modules/sharing/views/select_user_for_sharing_page.dart @@ -37,7 +37,7 @@ class SelectUserForSharingPage extends HookConsumerWidget { .navigate(const TabControllerRoute(children: [SharingRoute()])); } - ScaffoldMessenger(child: SnackBar(content: Text('share_err_album').tr())); + ScaffoldMessenger(child: SnackBar(content: Text('select_user_for_sharing_page_err_album').tr())); } _buildTileIcon(User user) { diff --git a/mobile/lib/modules/sharing/views/sharing_page.dart b/mobile/lib/modules/sharing/views/sharing_page.dart index aa25545c041ba..616b55b4b9583 100644 --- a/mobile/lib/modules/sharing/views/sharing_page.dart +++ b/mobile/lib/modules/sharing/views/sharing_page.dart @@ -105,7 +105,7 @@ class SharingPage extends HookConsumerWidget { Padding( padding: const EdgeInsets.all(8.0), child: Text( - 'share_empty_list', + 'sharing_page_empty_list', style: TextStyle( fontSize: 12, color: Theme.of(context).primaryColor, @@ -116,7 +116,7 @@ class SharingPage extends HookConsumerWidget { Padding( padding: const EdgeInsets.all(8.0), child: Text( - 'share_description', + 'sharing_page_description', style: TextStyle(fontSize: 12, color: Colors.grey[700]), ).tr(), ), @@ -136,7 +136,7 @@ class SharingPage extends HookConsumerWidget { padding: EdgeInsets.symmetric(horizontal: 12, vertical: 12), sliver: SliverToBoxAdapter( child: Text( - "share_album", + "sharing_page_album", style: TextStyle( fontWeight: FontWeight.bold, ), diff --git a/mobile/lib/shared/views/tab_controller_page.dart b/mobile/lib/shared/views/tab_controller_page.dart index 83e5cb617bd7d..b32baf33bf154 100644 --- a/mobile/lib/shared/views/tab_controller_page.dart +++ b/mobile/lib/shared/views/tab_controller_page.dart @@ -44,13 +44,13 @@ class TabControllerPage extends ConsumerWidget { }, items: [ BottomNavigationBarItem( - label: 'nav_photos'.tr(), + label: 'tab_controller_nav_photos'.tr(), icon: const Icon(Icons.photo)), BottomNavigationBarItem( - label: 'nav_search'.tr(), + label: 'tab_controller_nav_search'.tr(), icon: const Icon(Icons.search)), BottomNavigationBarItem( - label: 'nav_sharing'.tr(), + label: 'tab_controller_nav_sharing'.tr(), icon: const Icon(Icons.group_outlined)), ], ), diff --git a/mobile/lib/shared/views/version_announcement_overlay.dart b/mobile/lib/shared/views/version_announcement_overlay.dart index 05c50bbb43853..d0286b0df0b5d 100644 --- a/mobile/lib/shared/views/version_announcement_overlay.dart +++ b/mobile/lib/shared/views/version_announcement_overlay.dart @@ -41,7 +41,7 @@ class VersionAnnouncementOverlay extends HookConsumerWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( - "version_announcement_title", + "version_announcement_overlay_title", style: TextStyle( fontSize: 16, fontFamily: 'WorkSans', @@ -60,7 +60,7 @@ class VersionAnnouncementOverlay extends HookConsumerWidget { height: 1.2), children: [ TextSpan( - text: 'version_announcement_text_1'.tr(), + text: 'version_announcement_overlay_text_1'.tr(), ), const TextSpan( text: ' Immich ', @@ -71,10 +71,10 @@ class VersionAnnouncementOverlay extends HookConsumerWidget { ), ), TextSpan( - text: "version_announcement_text_2".tr(), + text: "version_announcement_overlay_text_2".tr(), ), TextSpan( - text: "version_announcement_release_notes" + text: "version_announcement_overlay_release_notes" .tr(), style: const TextStyle( decoration: TextDecoration.underline, @@ -83,7 +83,7 @@ class VersionAnnouncementOverlay extends HookConsumerWidget { ..onTap = goToReleaseNote, ), TextSpan( - text: "version_announcement_text_3".tr(), + text: "version_announcement_overlay_text_3".tr(), ) ], ), @@ -103,7 +103,7 @@ class VersionAnnouncementOverlay extends HookConsumerWidget { ), onPressed: onAcknowledgeTapped, child: const Text( - "version_announcement_ack", + "version_announcement_overlay_ack", style: TextStyle( fontSize: 14, ), diff --git a/mobile/scripts/check_i18n_keys.py b/mobile/scripts/check_i18n_keys.py new file mode 100644 index 0000000000000..8d748ceb06e4a --- /dev/null +++ b/mobile/scripts/check_i18n_keys.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +import json +import subprocess + +def main(): + with open('assets/i18n/en-US.json', 'r') as f: + data = json.load(f) + + for k in data.keys(): + print(k) + sp = subprocess.run(['sh', '-c', f'grep -r --include="*.dart" "{k}"']) + + if sp.returncode != 0: + print("Not found in source code!") + return 1 + +if __name__ == '__main__': + main() \ No newline at end of file From 715f646ace0abd193f4d8e3b6f2aad019fd12e29 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 5 Jul 2022 14:50:14 +0200 Subject: [PATCH 18/23] Add /api to translated endpoint_urls --- mobile/assets/i18n/de-DE.json | 2 +- mobile/assets/i18n/en-US.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mobile/assets/i18n/de-DE.json b/mobile/assets/i18n/de-DE.json index 6c2e4cec24b38..a5434922ecd5c 100644 --- a/mobile/assets/i18n/de-DE.json +++ b/mobile/assets/i18n/de-DE.json @@ -6,7 +6,7 @@ "login_form_button_text": "Anmelden", "login_form_save_login": "Angemeldet bleiben", "login_form_endpoint_url": "Server URL", - "login_form_endpoint_hint": "http://deine-server-ip:port", + "login_form_endpoint_hint": "http://deine-server-ip:port/api", "login_form_err_trailing_whitespace": "Folgendes Leerzeichen", "login_form_err_leading_whitespace": "Führendes Leerzichen", "login_form_err_invalid_email": "Ungültige E-Mail", diff --git a/mobile/assets/i18n/en-US.json b/mobile/assets/i18n/en-US.json index 2d9ae211c9c24..69c97e4557212 100644 --- a/mobile/assets/i18n/en-US.json +++ b/mobile/assets/i18n/en-US.json @@ -6,7 +6,7 @@ "login_form_button_text": "Login", "login_form_save_login": "Stay logged in", "login_form_endpoint_url": "Server Endpoint URL", - "login_form_endpoint_hint": "http://your-server-ip:port", + "login_form_endpoint_hint": "http://your-server-ip:port/api", "login_form_err_trailing_whitespace": "Trailing whitespace", "login_form_err_leading_whitespace": "Leading whitespace", "login_form_err_invalid_email": "Invalid Email", From cf6c7d0e0e17690c4da752e530fe43f23986c217 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 5 Jul 2022 21:14:38 +0200 Subject: [PATCH 19/23] Update localizely.yml --- localizely.yml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/localizely.yml b/localizely.yml index 648b1ad1ad4cc..ab124ac126ac0 100644 --- a/localizely.yml +++ b/localizely.yml @@ -1,5 +1,5 @@ config_version: 1.0 -project_id: 4fda40f2-8e20-48cf-97e8-0062c2b93ffc +project_id: ead34689-ec52-41d9-b675-09bc85a6cbd7 file_type: flutter_arb upload: files: @@ -7,9 +7,3 @@ upload: locale_code: en - file: mobile/assets/i18n/de-DE.json locale_code: de -download: - files: - - file: mobile/assets/i18n/en-US.json - locale_code: en - - file: mobile/assets/i18n/de-DE.json - locale_code: de From 409c19e6c45057a056949cc1e0ac156158fa48e7 Mon Sep 17 00:00:00 2001 From: Matthias Date: Tue, 5 Jul 2022 21:47:03 +0200 Subject: [PATCH 20/23] Add languages to ios plist --- mobile/ios/Runner/Info.plist | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mobile/ios/Runner/Info.plist b/mobile/ios/Runner/Info.plist index ffdad9da735f8..0c0a5984c8bc0 100644 --- a/mobile/ios/Runner/Info.plist +++ b/mobile/ios/Runner/Info.plist @@ -82,5 +82,11 @@ https + + CFBundleLocalizations + + en + de + \ No newline at end of file From ac7a527cdbace522a64948d8e512d3adb703acc2 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 6 Jul 2022 16:33:06 -0500 Subject: [PATCH 21/23] Remove unused keys --- mobile/assets/i18n/en-US.json | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/mobile/assets/i18n/en-US.json b/mobile/assets/i18n/en-US.json index 69c97e4557212..d995acadb3508 100644 --- a/mobile/assets/i18n/en-US.json +++ b/mobile/assets/i18n/en-US.json @@ -62,9 +62,6 @@ "backup_controller_page_backup_sub": "Backed up photos and videos", "backup_controller_page_remainder": "Remainder", "backup_controller_page_remainder_sub": "Remaining photos and albums to back up from selection", - "backup_controller_page_assets": "Asset that were being backup: {}", - "backup_controller_page_progress": "Backup Progress:", - "backup_controller_page_done": "Done", "backup_controller_page_cancel": "Cancel", "backup_controller_page_start_backup": "Start Backup", "album_info_card_backup_album_included": "INCLUDED", @@ -98,4 +95,4 @@ "version_announcement_overlay_release_notes": "release notes", "version_announcement_overlay_text_3": " and ensure your docker-compose and .env setup is up-to-date to prevent any misconfigurations, especially if you use WatchTower or any mechanism that handles updating your server application automatically.", "version_announcement_overlay_ack": "Acknowledge" -} \ No newline at end of file +} From 389794a1c0d8c44b946761d960d39e74735ddf7d Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 6 Jul 2022 16:39:17 -0500 Subject: [PATCH 22/23] Added script to check outdated key in other translations --- mobile/assets/i18n/de-DE.json | 5 +---- mobile/scripts/check_key_uniform.py | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 mobile/scripts/check_key_uniform.py diff --git a/mobile/assets/i18n/de-DE.json b/mobile/assets/i18n/de-DE.json index a5434922ecd5c..bef961441f9fa 100644 --- a/mobile/assets/i18n/de-DE.json +++ b/mobile/assets/i18n/de-DE.json @@ -62,9 +62,6 @@ "backup_controller_page_backup_sub": "Gesicherte Fotos und Videos", "backup_controller_page_remainder": "Übrig", "backup_controller_page_remainder_sub": "Noch zu sichernde Fotos und Videos", - "backup_controller_page_assets": "Nicht gesicherte Elemente: {}", - "backup_controller_page_progress": "Sicherungsfortschritt:", - "backup_controller_page_done": "Fertig", "backup_controller_page_cancel": "Abbrechen", "backup_controller_page_start_backup": "Sicherung starten", "album_info_card_backup_album_included": "EINGESCHLOSSEN", @@ -98,4 +95,4 @@ "version_announcement_overlay_release_notes": "Änderungsprotokoll", "version_announcement_overlay_text_3": " und achte darauf, dass deine docker-compose und .env Dateien aktuell sind, vor allem wenn du ein System für automatische Updates benutzt (z.B. Watchtower).", "version_announcement_overlay_ack": "Ich habe verstanden" -} \ No newline at end of file +} diff --git a/mobile/scripts/check_key_uniform.py b/mobile/scripts/check_key_uniform.py new file mode 100644 index 0000000000000..3140f55a1249d --- /dev/null +++ b/mobile/scripts/check_key_uniform.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +import json +import subprocess + +def main(): + print("CHECK GERMAN TRANSLATIONS") + with open('assets/i18n/de-DE.json', 'r') as f: + data = json.load(f) + + for k in data.keys(): + print(k) + sp = subprocess.run(['sh', '-c', f'grep -r --include="./assets/i18n/en-US.json" "{k}"']) + + if sp.returncode != 0: + print(f"Outdated Key! {k}") + return 1 + +if __name__ == '__main__': + main() \ No newline at end of file From 7ad7b2bd814a4569abdc24b0a6812c23b60d2bc3 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 7 Jul 2022 16:04:42 +0200 Subject: [PATCH 23/23] Add download key to localizely.yml --- localizely.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/localizely.yml b/localizely.yml index ab124ac126ac0..c9ad629aa0478 100644 --- a/localizely.yml +++ b/localizely.yml @@ -7,3 +7,9 @@ upload: locale_code: en - file: mobile/assets/i18n/de-DE.json locale_code: de +download: + files: + - file: mobile/assets/i18n/en-US.json + locale_code: en + - file: mobile/assets/i18n/de-DE.json + locale_code: de \ No newline at end of file