refactor: implement localization for user interface

feature/issue-4/translation
Frédérik Benoist 2024-08-09 10:03:42 +02:00
parent aa88116123
commit 9da2f30417
19 changed files with 287 additions and 117 deletions

View File

@ -1,14 +1,70 @@
{ {
"i18n_label_hello" : "Hello", "i18n_label_ok":"OK",
"i18n_take_pictures" : "Take pictures", "i18n_label_yes":"Yes",
"i18n_menu_settings" : "Settings", "i18n_label_no":"No",
"i18n_menu_about" : "About", "i18n_label_cancel":"Cancel",
"i18n_menu_show_logs" : "Show logs", "i18n_label_delete":"Delete",
"i18n_menu_check_version" : "Check version", "i18n_label_hello":"Hello",
"i18n_menu_account" : "Account", "i18n_label_take_photos":"Take photos",
"i18n_label_sign_out" : "Sign Out", "i18n_menu_settings":"Settings",
"i18n_label_photo_quality" : "Photo quality", "i18n_menu_about":"About",
"i18n_label_photo_resizing" : "Photo resizing", "i18n_menu_show_logs":"Show logs",
"i18n_label_sound_photo" : "Play sound when taking photo", "i18n_menu_check_version":"Check version",
"i18n_label_language" : "Language" "i18n_menu_account":"Account",
"i18n_menu_notification":"Notification",
"i18n_label_sign_out":"Sign Out",
"i18n_label_photo_quality":"Photo quality",
"i18n_label_photo_resizing":"Photo resizing",
"i18n_label_sound_photo":"Play sound when taking photo",
"i18n_label_language":"Langage",
"i18n_label_copy_to_gallery":"Copy to gallery",
"i18n_label_edit_tag":"Edit tags",
"i18n_label_tags":"Tags",
"i18n_label_notag":"No tag",
"i18n_label_enter_tags":"Enter tag",
"i18n_label_competition":"Competition",
"i18n_label_choose_competitor":"Choose competitor",
"i18n_label_visibility":"Visibility",
"i18n_label_main_visibility":"Main",
"i18n_label_private_visibility":"Private",
"i18n_label_typology":"Typology",
"i18n_label_photo_added_to_gallery":"Photo has been added to gallery",
"i18n_label_image_rotated":"The image has been rotated",
"i18n_label_last_visit_access":"Last visit access",
"i18n_label_today_visits":"Today visits",
"i18n_label_previous_visits":"Previous visits",
"i18n_label_delete_photo":"Delete photo",
"i18n_label_confirm_delete_photo":"Are you sure you want to delete this photo ?",
"i18n_label_deleted_photo":"Photo has been deleted",
"i18n_label_data_synchronization":"Data synchronization",
"i18n_label_backoffice_synchronization":"Backoffice data synchronization",
"i18n_label_photos_synchronization":"Photos synchronization",
"i18n_label_sync_logs":"Sync logs",
"i18n_label_logs_synchronization":"Activity logs synchronization",
"i18n_label_confirmation":"Confirmation",
"i18n_label_confirm_delete_log":"Are you sure you want to delete logs ?",
"i18n_menu_check_update":"Checking for update",
"i18n_label_current_version":"Current version",
"i18n_label_available_version":"Available version",
"i18n_label_latest_version":"You have the latest version",
"i18n_label_release_notes":"Release notes",
"i18n_label_publication_date":"Publication date",
"i18n_label_update":"Update",
"i18n_label_choose_quality":"Choose quality",
"i18n_label_choose_language":"Choose language",
"i18n_label_synchronize":"Synchronize",
"i18n_label_new_version":"New version available",
"i18n_label_new_version_install":"A new version is available. Would you like to install it ?",
"i18n_label_never":"Never",
"i18n_label_no_internet":"No internet connection ...",
"i18n_menu_backoffice":"BackOffice",
"i18n_menu_photos":"Photos",
"i18n_menu_log":"Logs",
"i18n_label_photo_not_found":"Photo not found",
"i18n_label_photo":"Photo",
"i18n_label_save":"Save",
"i18n_label_error":"Error",
"i18n_label_app_version":"App Version",
"i18n_label_synchronization_error": "Synchronization error",
"i18n_label_synchronization_complete": "Synchronization complete"
} }

View File

@ -1,14 +1,70 @@
{ {
"i18n_label_hello": "Bonjour", "i18n_label_ok":"OK",
"i18n_take_pictures" : "Prendre des photos", "i18n_label_yes":"Oui",
"i18n_menu_settings" : "Paramètres", "i18n_label_no":"Non",
"i18n_menu_about" : "A propos", "i18n_label_cancel":"Annuler",
"i18n_menu_show_logs" : "Voir logs", "i18n_label_delete":"Supprimer",
"i18n_menu_check_version" : "Vérifier version", "i18n_label_hello":"Bonjour",
"i18n_menu_account" : "Profil", "i18n_label_take_photos":"Prendre des photos",
"i18n_label_sign_out" : "Déconnecter", "i18n_menu_settings":"Paramètres",
"i18n_label_photo_quality" : "Qualité photo", "i18n_menu_about":"A propos",
"i18n_label_photo_resizing" : "Redimensionnement photo", "i18n_menu_show_logs":"Voir logs",
"i18n_label_sound_photo" : "Jouer son quand prise photo", "i18n_menu_check_version":"Vérifier version",
"i18n_label_language" : "Langage" "i18n_menu_account":"Profil",
"i18n_menu_notification":"Notification",
"i18n_label_sign_out":"Déconnecter",
"i18n_label_photo_quality":"Qualité photo",
"i18n_label_photo_resizing":"Redimensionnement photo",
"i18n_label_sound_photo":"Jouer son quand prise photo",
"i18n_label_language":"Langage",
"i18n_label_copy_to_gallery":"Copier dans galerie",
"i18n_label_edit_tag":"Modifier les tags",
"i18n_label_tags":"Tags",
"i18n_label_notag":"Aucun tag",
"i18n_label_enter_tags":"Saisir tag",
"i18n_label_competition":"Concurrence",
"i18n_label_choose_competitor":"Choisir concurrent",
"i18n_label_visibility":"Visibilité",
"i18n_label_main_visibility":"Principale",
"i18n_label_private_visibility":"Privée",
"i18n_label_typology":"Typologie",
"i18n_label_photo_added_to_gallery":"Photo ajoutée à la galerie",
"i18n_label_image_rotated":"Image retournée",
"i18n_label_last_visit_access":"Dernières visites",
"i18n_label_today_visits":"Visites du jour",
"i18n_label_previous_visits":"Visites précédentes",
"i18n_label_delete_photo":"Supprimer la photo",
"i18n_label_confirm_delete_photo":"Confirmez-vous la suppression de la photo ?",
"i18n_label_deleted_photo":"La photo a été supprimée",
"i18n_label_data_synchronization":"Synchronisation données",
"i18n_label_backoffice_synchronization":"Synchronisation des données du backoffice",
"i18n_label_photos_synchronization":"Synchronisation des photos",
"i18n_label_sync_logs":"Sync logs",
"i18n_label_logs_synchronization":"Synchronisation des journaux d'activité",
"i18n_label_confirmation":"Confirmation",
"i18n_label_confirm_delete_log":"Confirmez-vous la suppression des logs ?",
"i18n_menu_check_update":"Vérification mise à jour",
"i18n_label_current_version":"Version actuelle",
"i18n_label_available_version":"Version disponible",
"i18n_label_latest_version":"Vous avez la dernière version",
"i18n_label_release_notes":"Notes de mise à jour",
"i18n_label_publication_date":"Date de sortie",
"i18n_label_update":"Mettre à jour",
"i18n_label_choose_quality":"Choisir qualité",
"i18n_label_choose_language":"Choisir langage",
"i18n_label_synchronize":"Synchronisation",
"i18n_label_new_version":"Nouvelle version disponible",
"i18n_label_new_version_install": "Une nouvelle version est disponible. Voulez-vous l'installer ?",
"i18n_label_never":"Jamais",
"i18n_label_no_internet":"Aucune connexion internet ...",
"i18n_menu_backoffice":"BackOffice",
"i18n_menu_photos":"Photos",
"i18n_menu_log":"Logs",
"i18n_label_photo_not_found":"Photo introuvable",
"i18n_label_photo":"Photo",
"i18n_label_save":"Sauvegarder",
"i18n_label_error":"Erreur",
"i18n_label_app_version":"App Version",
"i18n_label_synchronization_error": "Erreur de synchronisation",
"i18n_label_synchronization_complete": "Synchronisation terminée"
} }

View File

@ -20,7 +20,7 @@ PODS:
- FMDB (2.7.5): - FMDB (2.7.5):
- FMDB/standard (= 2.7.5) - FMDB/standard (= 2.7.5)
- FMDB/standard (2.7.5) - FMDB/standard (2.7.5)
- image_gallery_saver (2.0.1): - image_gallery_saver (2.0.2):
- Flutter - Flutter
- image_picker_ios (0.0.1): - image_picker_ios (0.0.1):
- Flutter - Flutter
@ -36,16 +36,16 @@ PODS:
- Mantle (2.2.0): - Mantle (2.2.0):
- Mantle/extobjc (= 2.2.0) - Mantle/extobjc (= 2.2.0)
- Mantle/extobjc (2.2.0) - Mantle/extobjc (2.2.0)
- ObjectBox (1.8.1) - ObjectBox (1.9.0)
- objectbox_flutter_libs (0.0.1): - objectbox_flutter_libs (0.0.1):
- Flutter - Flutter
- ObjectBox (= 1.8.1) - ObjectBox (= 1.9.0)
- package_info_plus (0.4.5): - package_info_plus (0.4.5):
- Flutter - Flutter
- path_provider_foundation (0.0.1): - path_provider_foundation (0.0.1):
- Flutter - Flutter
- FlutterMacOS - FlutterMacOS
- permission_handler_apple (9.1.0): - permission_handler_apple (9.1.1):
- Flutter - Flutter
- ReachabilitySwift (5.0.0) - ReachabilitySwift (5.0.0)
- SDWebImage (5.16.0): - SDWebImage (5.16.0):
@ -57,11 +57,11 @@ PODS:
- shared_preferences_foundation (0.0.1): - shared_preferences_foundation (0.0.1):
- Flutter - Flutter
- FlutterMacOS - FlutterMacOS
- sqflite (0.0.2): - sqflite (0.0.3):
- Flutter - Flutter
- FMDB (>= 2.7.5) - FMDB (>= 2.7.5)
- Toast (4.0.0) - Toast (4.0.0)
- wakelock (0.0.1): - wakelock_plus (0.0.1):
- Flutter - Flutter
- webview_flutter_wkwebview (0.0.1): - webview_flutter_wkwebview (0.0.1):
- Flutter - Flutter
@ -82,7 +82,7 @@ DEPENDENCIES:
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- sqflite (from `.symlinks/plugins/sqflite/ios`) - sqflite (from `.symlinks/plugins/sqflite/ios`)
- wakelock (from `.symlinks/plugins/wakelock/ios`) - wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`)
- webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/ios`) - webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/ios`)
SPEC REPOS: SPEC REPOS:
@ -127,38 +127,38 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/shared_preferences_foundation/darwin" :path: ".symlinks/plugins/shared_preferences_foundation/darwin"
sqflite: sqflite:
:path: ".symlinks/plugins/sqflite/ios" :path: ".symlinks/plugins/sqflite/ios"
wakelock: wakelock_plus:
:path: ".symlinks/plugins/wakelock/ios" :path: ".symlinks/plugins/wakelock_plus/ios"
webview_flutter_wkwebview: webview_flutter_wkwebview:
:path: ".symlinks/plugins/webview_flutter_wkwebview/ios" :path: ".symlinks/plugins/webview_flutter_wkwebview/ios"
SPEC CHECKSUMS: SPEC CHECKSUMS:
audioplayers_darwin: 877d9a4d06331c5c374595e46e16453ac7eafa40 audioplayers_darwin: 877d9a4d06331c5c374595e46e16453ac7eafa40
camera_avfoundation: 3125e8cd1a4387f6f31c6c63abb8a55892a9eeeb camera_avfoundation: 3125e8cd1a4387f6f31c6c63abb8a55892a9eeeb
connectivity_plus: 07c49e96d7fc92bc9920617b83238c4d178b446a connectivity_plus: bf0076dd84a130856aa636df1c71ccaff908fa1d
device_info_plus: e5c5da33f982a436e103237c0c85f9031142abed device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
flutter_image_compress_common: ec1d45c362c9d30a3f6a0426c297f47c52007e3e flutter_image_compress_common: ec1d45c362c9d30a3f6a0426c297f47c52007e3e
fluttertoast: eb263d302cc92e04176c053d2385237e9f43fad0 fluttertoast: 31b00dabfa7fb7bacd9e7dbee580d7a2ff4bf265
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
image_gallery_saver: 6eb11e5a866e9ac2c8a98c74ef99a04fc62878b2 image_gallery_saver: cb43cc43141711190510e92c460eb1655cd343cb
image_picker_ios: 4a8aadfbb6dc30ad5141a2ce3832af9214a705b5 image_picker_ios: 4a8aadfbb6dc30ad5141a2ce3832af9214a705b5
libwebp: f62cb61d0a484ba548448a4bd52aabf150ff6eef libwebp: f62cb61d0a484ba548448a4bd52aabf150ff6eef
Mantle: c5aa8794a29a022dfbbfc9799af95f477a69b62d Mantle: c5aa8794a29a022dfbbfc9799af95f477a69b62d
ObjectBox: a7900d5335218cd437cbc080b7ccc38a5211f7b4 ObjectBox: e7ff611291a0663380e0736b46786bcd077294ff
objectbox_flutter_libs: 61d74196d924fbc773da5f5757d1e9fab7b3cc78 objectbox_flutter_libs: 0948d6feb7de4f7edaebc7a898b9e85b7fc2bc89
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85
path_provider_foundation: c68054786f1b4f3343858c1e1d0caaded73f0be9 path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
permission_handler_apple: 8f116445eff3c0e7c65ad60f5fef5490aa94b4e4 permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825 ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
SDWebImage: 2aea163b50bfcb569a2726b6a754c54a4506fcf6 SDWebImage: 2aea163b50bfcb569a2726b6a754c54a4506fcf6
SDWebImageWebPCoder: 295a6573c512f54ad2dd58098e64e17dcf008499 SDWebImageWebPCoder: 295a6573c512f54ad2dd58098e64e17dcf008499
shared_preferences_foundation: 986fc17f3d3251412d18b0265f9c64113a8c2472 shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904 sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a
Toast: 91b396c56ee72a5790816f40d3a94dd357abc196 Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f wakelock_plus: 8b09852c8876491e4b6d179e17dfe2a0b5f60d47
webview_flutter_wkwebview: 2e2d318f21a5e036e2c3f26171342e95908bd60a webview_flutter_wkwebview: 2e2d318f21a5e036e2c3f26171342e95908bd60a
PODFILE CHECKSUM: b634fd49380cdd3837626153fb977533b1916433 PODFILE CHECKSUM: b634fd49380cdd3837626153fb977533b1916433
COCOAPODS: 1.11.3 COCOAPODS: 1.14.3

View File

@ -156,7 +156,7 @@
97C146E61CF9000F007C117D /* Project object */ = { 97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastUpgradeCheck = 1300; LastUpgradeCheck = 1430;
ORGANIZATIONNAME = ""; ORGANIZATIONNAME = "";
TargetAttributes = { TargetAttributes = {
97C146ED1CF9000F007C117D = { 97C146ED1CF9000F007C117D = {

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1300" LastUpgradeVersion = "1430"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

View File

@ -45,7 +45,7 @@ class _AboutPageState extends State<AboutPage> {
height: 50, height: 50,
), ),
Text( Text(
'App Version', AppLocalizations.of(context)!.translate('i18n_label_app_version'),
style: TextStyle(fontSize: 14, color: CHARCOAL), style: TextStyle(fontSize: 14, color: CHARCOAL),
), ),
SizedBox( SizedBox(

View File

@ -90,17 +90,19 @@ class _LogPageState extends State<LogPage> {
showDialog( showDialog(
context: context, context: context,
builder: (context) => AlertDialog( builder: (context) => AlertDialog(
title: Text('Confirmation'), title: Text(
content: Text('Are you sure you want to delete these logs ?'), AppLocalizations.of(context)!.translate('i18n_label_confirmation')),
content: Text(
AppLocalizations.of(context)!.translate('i18n_label_confirm_delete_log')),
actions: [ actions: [
TextButton( TextButton(
child: Text('Cancel'), child: Text(AppLocalizations.of(context)!.translate('i18n_label_cancel')),
onPressed: () { onPressed: () {
Navigator.of(context).pop(); Navigator.of(context).pop();
}, },
), ),
TextButton( TextButton(
child: Text('Delete'), child: Text(AppLocalizations.of(context)!.translate('i18n_label_delete')),
onPressed: () { onPressed: () {
// remove all log from db // remove all log from db
objectbox.logBox.removeAll(); objectbox.logBox.removeAll();

View File

@ -245,7 +245,8 @@ class _SettingsPageState extends State<SettingsPage> {
Container( Container(
margin: EdgeInsets.fromLTRB(16, 8, 16, 8), margin: EdgeInsets.fromLTRB(16, 8, 16, 8),
child: Text( child: Text(
'Choose Quality', AppLocalizations.of(context)!
.translate('i18n_label_choose_quality'),
style: GlobalStyle.chooseCourier, style: GlobalStyle.chooseCourier,
), ),
), ),
@ -300,7 +301,8 @@ class _SettingsPageState extends State<SettingsPage> {
Container( Container(
margin: EdgeInsets.fromLTRB(16, 8, 16, 8), margin: EdgeInsets.fromLTRB(16, 8, 16, 8),
child: Text( child: Text(
'Choose Language', AppLocalizations.of(context)!
.translate('i18n_label_choose_language'),
style: GlobalStyle.chooseCourier, style: GlobalStyle.chooseCourier,
), ),
), ),

View File

@ -5,6 +5,7 @@ import 'package:http/http.dart' as http;
import 'package:mobdr/service/shared_prefs.dart'; import 'package:mobdr/service/shared_prefs.dart';
import 'package:mobdr/config/constant.dart'; import 'package:mobdr/config/constant.dart';
import 'package:mobdr/cubit/language/app_localizations.dart';
class UpdateCheckPage extends StatefulWidget { class UpdateCheckPage extends StatefulWidget {
@override @override
@ -69,7 +70,8 @@ class _UpdateCheckPageState extends State<UpdateCheckPage> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text('Checking for update'), title: Text(AppLocalizations.of(context)!
.translate('i18n_menu_check_update')),
), ),
body: Center( body: Center(
child: currentEvent == null child: currentEvent == null
@ -77,7 +79,8 @@ class _UpdateCheckPageState extends State<UpdateCheckPage> {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Text( Text(
'Current version : ', AppLocalizations.of(context)!
.translate('i18n_label_current_version'),
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 16, fontSize: 16,
@ -93,7 +96,8 @@ class _UpdateCheckPageState extends State<UpdateCheckPage> {
), ),
SizedBox(height: 16), SizedBox(height: 16),
Text( Text(
'Version available : ', AppLocalizations.of(context)!
.translate('i18n_label_available_version'),
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 18, fontSize: 18,
@ -110,12 +114,13 @@ class _UpdateCheckPageState extends State<UpdateCheckPage> {
if (_currentVersion != _latestVersion) ...[ if (_currentVersion != _latestVersion) ...[
SizedBox(height: 16), SizedBox(height: 16),
Text( Text(
'Publication date : $_releaseDate', '${AppLocalizations.of(context)!.translate('i18n_label_publication_date')} : $_releaseDate',
style: TextStyle(fontWeight: FontWeight.bold), style: TextStyle(fontWeight: FontWeight.bold),
), ),
SizedBox(height: 8), SizedBox(height: 8),
Text( Text(
'Release notes :', AppLocalizations.of(context)!
.translate('i18n_label_release_notes') + ' :',
style: TextStyle(fontWeight: FontWeight.bold), style: TextStyle(fontWeight: FontWeight.bold),
), ),
for (String note in _releaseNotes) ...[ for (String note in _releaseNotes) ...[
@ -126,7 +131,8 @@ class _UpdateCheckPageState extends State<UpdateCheckPage> {
ElevatedButton( ElevatedButton(
onPressed: _doUpdate, onPressed: _doUpdate,
child: Text( child: Text(
'Update', AppLocalizations.of(context)!
.translate('i18n_label_update'),
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 18, fontSize: 18,
@ -139,7 +145,8 @@ class _UpdateCheckPageState extends State<UpdateCheckPage> {
] else ...[ ] else ...[
SizedBox(height: 32), SizedBox(height: 32),
Text( Text(
'You have the latest version', AppLocalizations.of(context)!
.translate('i18n_label_latest_version'),
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 18, fontSize: 18,

View File

@ -6,6 +6,7 @@ import 'package:mobdr/config/global_style.dart';
import 'package:mobdr/ui/reusable/reusable_widget.dart'; import 'package:mobdr/ui/reusable/reusable_widget.dart';
import 'package:mobdr/service/plausible.dart'; import 'package:mobdr/service/plausible.dart';
import 'package:mobdr/service/logger_util.dart'; import 'package:mobdr/service/logger_util.dart';
import 'package:mobdr/cubit/language/app_localizations.dart';
class NotificationPage extends StatefulWidget { class NotificationPage extends StatefulWidget {
@override @override
@ -39,8 +40,7 @@ class _NotificationPageState extends State<NotificationPage> {
color: GlobalStyle.appBarIconThemeColor, color: GlobalStyle.appBarIconThemeColor,
), ),
elevation: GlobalStyle.appBarElevation, elevation: GlobalStyle.appBarElevation,
title: Text( title: Text(AppLocalizations.of(context)!.translate('i18n_menu_notification'),
'Notification',
style: GlobalStyle.appBarTitle, style: GlobalStyle.appBarTitle,
), ),
backgroundColor: GlobalStyle.appBarBackgroundColor, backgroundColor: GlobalStyle.appBarBackgroundColor,

View File

@ -193,7 +193,9 @@ class _TabHomePageState extends State<TabHomePage>
padding: EdgeInsets.fromLTRB(16, 8, 0, 0), padding: EdgeInsets.fromLTRB(16, 8, 0, 0),
child: Row( child: Row(
children: [ children: [
Text('Last visit access', style: GlobalStyle.horizontalTitle), Text(
AppLocalizations.of(context)!
.translate('i18n_label_last_visit_access'), style: GlobalStyle.horizontalTitle),
], ],
), ),
), ),
@ -214,7 +216,9 @@ class _TabHomePageState extends State<TabHomePage>
padding: EdgeInsets.fromLTRB(16, 16, 16, 0), padding: EdgeInsets.fromLTRB(16, 16, 16, 0),
child: Row( child: Row(
children: [ children: [
Text('Today Visits', style: GlobalStyle.horizontalTitle), Text(
AppLocalizations.of(context)!
.translate('i18n_label_today_visits'), style: GlobalStyle.horizontalTitle),
Container( Container(
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
@ -247,7 +251,8 @@ class _TabHomePageState extends State<TabHomePage>
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Text( Text(
'Synchronize', AppLocalizations.of(context)!
.translate('i18n_label_synchronize'),
style: TextStyle( style: TextStyle(
color: Colors.blue, color: Colors.blue,
fontSize: 16, fontSize: 16,
@ -289,7 +294,7 @@ class _TabHomePageState extends State<TabHomePage>
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text('Previous Visits', style: GlobalStyle.horizontalTitle), Text(AppLocalizations.of(context)!.translate('i18n_label_previous_visits'), style: GlobalStyle.horizontalTitle),
], ],
), ),
), ),

View File

@ -34,8 +34,8 @@ class _OnBoardingPageState extends State<OnBoardingPage> {
PageModel( PageModel(
color: Colors.white, color: Colors.white,
imageFromUrl: GLOBAL_IMAGES_URL + '/onboarding-synchro.png', imageFromUrl: GLOBAL_IMAGES_URL + '/onboarding-synchro.png',
title: 'MP4 synchronisation', title: 'MP4 synchronization',
body: 'Synchronise your data quickly and easily with MP4 :)', body: 'Synchronize your data quickly and easily with MP4 :)',
doAnimateImage: true), doAnimateImage: true),
PageModel( PageModel(
color: Colors.white, color: Colors.white,

View File

@ -13,6 +13,7 @@ import 'package:mobdr/service/shared_prefs.dart';
import 'package:mobdr/network/api_provider.dart'; import 'package:mobdr/network/api_provider.dart';
import 'package:mobdr/db/box_visit_photo.dart'; import 'package:mobdr/db/box_visit_photo.dart';
import 'package:mobdr/service/logger_util.dart'; import 'package:mobdr/service/logger_util.dart';
import 'package:mobdr/cubit/language/app_localizations.dart';
class SynchronizationPage extends StatefulWidget { class SynchronizationPage extends StatefulWidget {
@override @override
@ -83,18 +84,18 @@ class _SynchronizationPageState extends State<SynchronizationPage>
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return AlertDialog( return AlertDialog(
title: Text("New version available"), title: Text(AppLocalizations.of(context)!.translate('i18n_label_new_version')),
content: Text( content: Text(AppLocalizations.of(context)!.translate('i18n_label_new_version_install')),
"A new version is available. Would you like to install it?"),
actions: [ actions: [
TextButton( TextButton(
child: Text("No"), child: Text(AppLocalizations.of(context)!.translate('i18n_label_no')),
onPressed: () { onPressed: () {
Navigator.pop(context); // Closes the dialog box Navigator.pop(context); // Closes the dialog box
}, },
), ),
TextButton( TextButton(
child: Text("Yes"), child: Text(AppLocalizations.of(context)!
.translate('i18n_label_yes')),
onPressed: () { onPressed: () {
Navigator.pop(context); // Closes the dialog box Navigator.pop(context); // Closes the dialog box
Navigator.push( Navigator.push(
@ -330,7 +331,7 @@ class _SynchronizationPageState extends State<SynchronizationPage>
), ),
elevation: GlobalStyle.appBarElevation, elevation: GlobalStyle.appBarElevation,
title: Text( title: Text(
'Data synchronization', AppLocalizations.of(context)!.translate('i18n_label_data_synchronization'),
style: GlobalStyle.appBarTitle, style: GlobalStyle.appBarTitle,
), ),
backgroundColor: GlobalStyle.appBarBackgroundColor, backgroundColor: GlobalStyle.appBarBackgroundColor,
@ -378,10 +379,11 @@ class _SynchronizationPageState extends State<SynchronizationPage>
SizedBox(height: 10), SizedBox(height: 10),
Text( Text(
!_isInternetConnexion !_isInternetConnexion
? "No internet connection ..." ? AppLocalizations.of(context)!
.translate('i18n_label_no_internet')
: (SharedPrefs().lastCalendarRefresh.isNotEmpty : (SharedPrefs().lastCalendarRefresh.isNotEmpty
? SharedPrefs().lastCalendarRefresh ? SharedPrefs().lastCalendarRefresh
: "Never"), : AppLocalizations.of(context)!.translate('i18n_label_never')),
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
color: !_isInternetConnexion color: !_isInternetConnexion
@ -397,7 +399,7 @@ class _SynchronizationPageState extends State<SynchronizationPage>
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
Text( Text(
'Sync Logs', AppLocalizations.of(context)!.translate('i18n_label_sync_logs'),
style: TextStyle(fontSize: 16), style: TextStyle(fontSize: 16),
), ),
Switch( Switch(
@ -413,8 +415,9 @@ class _SynchronizationPageState extends State<SynchronizationPage>
SizedBox(height: 20), SizedBox(height: 20),
SyncItem( SyncItem(
icon: Icons.business, icon: Icons.business,
title: 'Backoffice', title: AppLocalizations.of(context)!.translate('i18n_menu_backoffice'),
description: 'Synchronisation des données du backoffice', description: AppLocalizations.of(context)!
.translate('i18n_label_backoffice_synchronization'),
isSyncing: _isSyncing, isSyncing: _isSyncing,
syncCompleted: _syncCompleted, syncCompleted: _syncCompleted,
isError: _syncCompleted && !_backofficeSyncCompleted, isError: _syncCompleted && !_backofficeSyncCompleted,
@ -422,8 +425,9 @@ class _SynchronizationPageState extends State<SynchronizationPage>
SizedBox(height: 20), SizedBox(height: 20),
SyncItem( SyncItem(
icon: Icons.photo, icon: Icons.photo,
title: 'Photos', title: AppLocalizations.of(context)!.translate('i18n_menu_photos'),
description: 'Synchronisation des photos', description: AppLocalizations.of(context)!
.translate('i18n_label_photos_synchronization'),
isSyncing: _isSyncing, isSyncing: _isSyncing,
syncCompleted: _syncCompleted, syncCompleted: _syncCompleted,
isError: _syncCompleted && !_photosSyncCompleted, isError: _syncCompleted && !_photosSyncCompleted,
@ -431,8 +435,9 @@ class _SynchronizationPageState extends State<SynchronizationPage>
SizedBox(height: 20), SizedBox(height: 20),
SyncItem( SyncItem(
icon: Icons.warning, icon: Icons.warning,
title: 'Log', title: AppLocalizations.of(context)!.translate('i18n_menu_log'),
description: 'Synchronisation des journaux d\'activité', description: AppLocalizations.of(context)!
.translate('i18n_label_logs_synchronization'),
isSyncing: _isSyncing, isSyncing: _isSyncing,
syncCompleted: _syncCompleted, syncCompleted: _syncCompleted,
isError: _syncCompleted && !_logSyncCompleted, isError: _syncCompleted && !_logSyncCompleted,
@ -500,8 +505,10 @@ class SyncItem extends StatelessWidget {
SizedBox(width: 10), SizedBox(width: 10),
Text( Text(
isError isError
? 'Erreur de synchronisation' ? AppLocalizations.of(context)!
: 'Synchronisation terminée', .translate('i18n_label_synchronization_error')
: AppLocalizations.of(context)!
.translate('i18n_label_synchronization_complete'),
style: TextStyle( style: TextStyle(
color: isError ? Colors.red : Colors.green, color: isError ? Colors.red : Colors.green,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,

View File

@ -7,6 +7,7 @@ import 'package:mobdr/ui/reusable/reusable_widget.dart';
import 'package:super_tag_editor/tag_editor.dart'; import 'package:super_tag_editor/tag_editor.dart';
import 'package:super_tag_editor/widgets/rich_text_widget.dart'; import 'package:super_tag_editor/widgets/rich_text_widget.dart';
import 'package:mobdr/cubit/language/app_localizations.dart';
class PhotoTagPage extends StatefulWidget { class PhotoTagPage extends StatefulWidget {
// variables corresponding to the data parameters // variables corresponding to the data parameters
@ -70,7 +71,8 @@ class _PhotoTagPageState extends State<PhotoTagPage> {
), ),
elevation: GlobalStyle.appBarElevation, elevation: GlobalStyle.appBarElevation,
title: Text( title: Text(
'Edit tags ...', AppLocalizations.of(context)!.translate('i18n_label_edit_tag') +
' ...',
style: GlobalStyle.appBarTitle, style: GlobalStyle.appBarTitle,
), ),
backgroundColor: GlobalStyle.appBarBackgroundColor, backgroundColor: GlobalStyle.appBarBackgroundColor,
@ -96,9 +98,9 @@ class _PhotoTagPageState extends State<PhotoTagPage> {
_selectedTags.add(outstandingValue); _selectedTags.add(outstandingValue);
}); });
}, },
inputDecoration: const InputDecoration( inputDecoration: InputDecoration(
border: InputBorder.none, border: InputBorder.none,
hintText: 'Enter tag ...', hintText: AppLocalizations.of(context)!.translate('i18n_label_enter_tags') + ' ...',
), ),
onTagChanged: (newValue) { onTagChanged: (newValue) {
setState(() { setState(() {
@ -204,7 +206,8 @@ class _PhotoTagPageState extends State<PhotoTagPage> {
Navigator.pop( Navigator.pop(
context, _selectedTags.map((tag) => tag).toList()); context, _selectedTags.map((tag) => tag).toList());
}, },
child: const Text('Save'), child: new Text(
AppLocalizations.of(context)!.translate('i18n_label_save')),
), ),
], ],
), ),

View File

@ -19,6 +19,7 @@ import 'package:mobdr/db/box_photo_competitor.dart';
import 'package:mobdr/model/visit_model.dart'; import 'package:mobdr/model/visit_model.dart';
import 'package:mobdr/service/plausible.dart'; import 'package:mobdr/service/plausible.dart';
import 'package:mobdr/service/logger_util.dart'; import 'package:mobdr/service/logger_util.dart';
import 'package:mobdr/cubit/language/app_localizations.dart';
class VisitPhotoTypologyDetailPage extends StatefulWidget { class VisitPhotoTypologyDetailPage extends StatefulWidget {
final VisitModel pp_visitModel; final VisitModel pp_visitModel;
@ -124,11 +125,11 @@ class _VisitPhotoTypologyDetailPageState
} else if (_errorMessage.isNotEmpty) { } else if (_errorMessage.isNotEmpty) {
return Center( return Center(
child: AlertDialog( child: AlertDialog(
title: Text("Erreur"), title: Text(AppLocalizations.of(context)!.translate('i18n_label_error')),
content: Text("La photo est introuvable"), content: Text(AppLocalizations.of(context)!.translate('i18n_label_photo_not_found')),
actions: <Widget>[ actions: <Widget>[
TextButton( TextButton(
child: Text("OK"), child: Text(AppLocalizations.of(context)!.translate('i18n_label_ok')),
onPressed: () { onPressed: () {
Navigator.of(context).pop(); Navigator.of(context).pop();
}, },
@ -144,7 +145,7 @@ class _VisitPhotoTypologyDetailPageState
), ),
elevation: GlobalStyle.appBarElevation, elevation: GlobalStyle.appBarElevation,
title: Text( title: Text(
'Photo', AppLocalizations.of(context)!.translate('i18n_label_photo'),
style: GlobalStyle.appBarTitle, style: GlobalStyle.appBarTitle,
), ),
backgroundColor: GlobalStyle.appBarBackgroundColor, backgroundColor: GlobalStyle.appBarBackgroundColor,
@ -211,7 +212,7 @@ class _VisitPhotoTypologyDetailPageState
'LOG', 'MOBDR', 'Copier dans galerie', 0); 'LOG', 'MOBDR', 'Copier dans galerie', 0);
Fluttertoast.showToast( Fluttertoast.showToast(
msg: 'Photo has been added to gallery', msg: AppLocalizations.of(context)!.translate('i18n_label_photo_added_to_gallery'),
toastLength: Toast.LENGTH_LONG); toastLength: Toast.LENGTH_LONG);
} else { } else {
// log tracker // log tracker
@ -233,7 +234,9 @@ class _VisitPhotoTypologyDetailPageState
borderRadius: BorderRadius.all(Radius.circular( borderRadius: BorderRadius.all(Radius.circular(
10) // <--- border radius here 10) // <--- border radius here
)), )),
child: Text('Copier dans galerie', child: Text(
AppLocalizations.of(context)!
.translate('i18n_label_copy_to_gallery'),
style: TextStyle( style: TextStyle(
color: SOFT_BLUE, color: SOFT_BLUE,
fontWeight: FontWeight.bold)), fontWeight: FontWeight.bold)),
@ -295,7 +298,9 @@ class _VisitPhotoTypologyDetailPageState
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text('Typologie', style: GlobalStyle.sectionTitle), Text(
AppLocalizations.of(context)!
.translate('i18n_label_typology'), style: GlobalStyle.sectionTitle),
SizedBox( SizedBox(
height: 16, height: 16,
), ),
@ -402,16 +407,18 @@ class _VisitPhotoTypologyDetailPageState
children: [ children: [
Row( Row(
children: [ children: [
Text('Visibility', style: GlobalStyle.sectionTitle), Text(AppLocalizations.of(context)!.translate('i18n_label_visibility'), style: GlobalStyle.sectionTitle),
], ],
), ),
SizedBox(height: 16), SizedBox(height: 16),
_checkboxVisibility(value: 'private', primaryText: 'Privée'), _checkboxVisibility(value: 'private', primaryText: AppLocalizations.of(context)!
.translate('i18n_label_private_visibility')),
Divider( Divider(
height: 32, height: 32,
color: Colors.grey[400], color: Colors.grey[400],
), ),
_checkboxVisibility(value: 'principal', primaryText: 'Principale') _checkboxVisibility(value: 'principal', primaryText: AppLocalizations.of(context)!
.translate('i18n_label_main_visibility'))
], ],
), ),
); );
@ -448,7 +455,8 @@ class _VisitPhotoTypologyDetailPageState
children: [ children: [
Row( Row(
children: [ children: [
Text('Tags', style: GlobalStyle.sectionTitle), Text(AppLocalizations.of(context)!
.translate('i18n_label_tags'), style: GlobalStyle.sectionTitle),
], ],
), ),
Wrap( Wrap(
@ -476,7 +484,9 @@ class _VisitPhotoTypologyDetailPageState
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text('Competitor', Text(
AppLocalizations.of(context)!
.translate('i18n_label_competition'),
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
SizedBox( SizedBox(
height: 16, height: 16,
@ -509,7 +519,8 @@ class _VisitPhotoTypologyDetailPageState
children: [ children: [
Icon(Icons.thumb_down, color: SOFT_BLUE), Icon(Icons.thumb_down, color: SOFT_BLUE),
SizedBox(width: 12), SizedBox(width: 12),
Text('Choose Competitor', Text(AppLocalizations.of(context)!
.translate('i18n_label_choose_competitor'),
style: TextStyle( style: TextStyle(
color: CHARCOAL, color: CHARCOAL,
fontWeight: FontWeight.bold)), fontWeight: FontWeight.bold)),
@ -557,7 +568,8 @@ class _VisitPhotoTypologyDetailPageState
), ),
Container( Container(
margin: EdgeInsets.fromLTRB(16, 8, 16, 8), margin: EdgeInsets.fromLTRB(16, 8, 16, 8),
child: Text('Choose Competitor', style: GlobalStyle.chooseCourier), child: Text(AppLocalizations.of(context)!
.translate('i18n_label_choose_competitor'), style: GlobalStyle.chooseCourier),
), ),
Flexible( Flexible(
child: ListView.builder( child: ListView.builder(

View File

@ -24,6 +24,7 @@ import 'package:mobdr/ui/reusable/reusable_widget.dart';
import 'package:mobdr/events.dart'; import 'package:mobdr/events.dart';
import 'package:mobdr/service/plausible.dart'; import 'package:mobdr/service/plausible.dart';
import 'package:mobdr/service/logger_util.dart'; import 'package:mobdr/service/logger_util.dart';
import 'package:mobdr/cubit/language/app_localizations.dart';
extension FileNameExtension on File { extension FileNameExtension on File {
String getFileName() { String getFileName() {
@ -182,7 +183,8 @@ class _VisitPhotoTypologyListPageState
borderRadius: BorderRadius.all(Radius.circular( borderRadius: BorderRadius.all(Radius.circular(
10) // <--- border radius here 10) // <--- border radius here
)), )),
child: Text('Prendre des photos', child: Text(
AppLocalizations.of(context)!.translate('i18n_label_take_photos'),
style: TextStyle( style: TextStyle(
color: SOFT_BLUE, fontWeight: FontWeight.bold)), color: SOFT_BLUE, fontWeight: FontWeight.bold)),
), ),
@ -269,7 +271,8 @@ class _VisitPhotoTypologyListPageState
), ),
Container(height: 8), Container(height: 8),
Text( Text(
"Private : ${photoData.photo_privee == 1 ? 'Yes' : 'No'}", AppLocalizations.of(context)!.translate('i18n_label_private_visibility') + " : ${photoData.photo_privee == 1 ?
AppLocalizations.of(context)!.translate('i18n_label_yes') : AppLocalizations.of(context)!.translate('i18n_label_no')}",
style: TextStyle(fontSize: 13, color: _color2), style: TextStyle(fontSize: 13, color: _color2),
maxLines: 3, maxLines: 3,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
@ -277,7 +280,7 @@ class _VisitPhotoTypologyListPageState
Container( Container(
margin: EdgeInsets.only(top: 5), margin: EdgeInsets.only(top: 5),
child: Text( child: Text(
'${photoData.tags.isNotEmpty ? (photoData.tags.length > 53 ? '${photoData.tags.substring(0, 50)}...' : photoData.tags) : "notag"}', '${photoData.tags.isNotEmpty ? (photoData.tags.length > 53 ? '${photoData.tags.substring(0, 50)}...' : photoData.tags) : AppLocalizations.of(context)!.translate('i18n_label_notag')}',
style: TextStyle( style: TextStyle(
fontSize: 13, fontWeight: FontWeight.bold), fontSize: 13, fontWeight: FontWeight.bold),
), ),
@ -328,7 +331,7 @@ class _VisitPhotoTypologyListPageState
}); });
Fluttertoast.showToast( Fluttertoast.showToast(
msg: 'The image has been rotated'); msg: AppLocalizations.of(context)!.translate('i18n_label_image_rotated'));
}, },
child: Container( child: Container(
padding: EdgeInsets.fromLTRB(5, 0, 5, 0), padding: EdgeInsets.fromLTRB(5, 0, 5, 0),
@ -364,7 +367,7 @@ class _VisitPhotoTypologyListPageState
}); });
Fluttertoast.showToast( Fluttertoast.showToast(
msg: 'The image has been rotated'); msg: AppLocalizations.of(context)!.translate('i18n_label_image_rotated'));
}, },
child: Container( child: Container(
padding: EdgeInsets.fromLTRB(5, 0, 5, 0), padding: EdgeInsets.fromLTRB(5, 0, 5, 0),
@ -472,7 +475,9 @@ class _VisitPhotoTypologyListPageState
onPressed: () { onPressed: () {
Navigator.pop(context); Navigator.pop(context);
}, },
child: Text('No', style: TextStyle(color: SOFT_BLUE))); child: Text(
AppLocalizations.of(context)!
.translate('i18n_label_no'), style: TextStyle(color: SOFT_BLUE)));
Widget continueButton = TextButton( Widget continueButton = TextButton(
onPressed: () { onPressed: () {
int removeIndex = index; int removeIndex = index;
@ -508,10 +513,13 @@ class _VisitPhotoTypologyListPageState
LoggerUtil.dblog('LOG', 'MOBDR', 'Suppression photo', 0); LoggerUtil.dblog('LOG', 'MOBDR', 'Suppression photo', 0);
Fluttertoast.showToast( Fluttertoast.showToast(
msg: 'Photo has been deleted from your visit', msg: AppLocalizations.of(context)!
.translate('i18n_label_deleted_photo'),
toastLength: Toast.LENGTH_SHORT); toastLength: Toast.LENGTH_SHORT);
}, },
child: Text('Yes', style: TextStyle(color: SOFT_BLUE))); child: Text(
AppLocalizations.of(context)!
.translate('i18n_label_yes'), style: TextStyle(color: SOFT_BLUE)));
// set up the AlertDialog // set up the AlertDialog
AlertDialog alert = AlertDialog( AlertDialog alert = AlertDialog(
@ -519,10 +527,11 @@ class _VisitPhotoTypologyListPageState
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
), ),
title: Text( title: Text(
'Delete Photo', AppLocalizations.of(context)!.translate('i18n_label_delete_photo'),
style: TextStyle(fontSize: 18), style: TextStyle(fontSize: 18),
), ),
content: Text('Are you sure to delete this photo from your visit ?', content: Text(
AppLocalizations.of(context)!.translate('i18n_label_confirm_delete_photo'),
style: TextStyle(fontSize: 13, color: _color1)), style: TextStyle(fontSize: 13, color: _color1)),
actions: [ actions: [
cancelButton, cancelButton,

View File

@ -203,7 +203,7 @@
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastSwiftUpdateCheck = 0920; LastSwiftUpdateCheck = 0920;
LastUpgradeCheck = 1300; LastUpgradeCheck = 1430;
ORGANIZATIONNAME = ""; ORGANIZATIONNAME = "";
TargetAttributes = { TargetAttributes = {
33CC10EC2044A3C60003C045 = { 33CC10EC2044A3C60003C045 = {

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "1300" LastUpgradeVersion = "1430"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"

11
todo-list.md Normal file
View File

@ -0,0 +1,11 @@
# To-Do List
## Frontend Developer
- [ ] voir si des print() sont inutiles
- [ ] Dans les typologies pouvoir filtrer que les catégories avec prise de photos effectives
- [ ] vérifier si dblog tous en francais ou en anglais
## Backend Developer
- [ ]