From 12d39a1132477b506198c5dad7567b1e262fc291 Mon Sep 17 00:00:00 2001 From: Saif Turki Date: Sun, 25 Jun 2023 02:44:40 +0100 Subject: [PATCH 1/5] Add l10n support --- lib/l10n.yaml | 3 + lib/l10n/app_en.arb | 100 ++++++ lib/l10n/app_fr.arb | 100 ++++++ lib/main.dart | 130 ++++---- .../booking_detail/booking_detail.dart | 24 +- .../booking_detail_accommodation.dart | 9 +- .../booking_detail_actions.dart | 13 +- .../booking_detail_customer.dart | 11 +- .../booking_detail/booking_detail_price.dart | 9 +- .../booking_detail_services.dart | 11 +- .../booking_detail/booking_detail_status.dart | 3 +- lib/screens/bookings.dart | 11 +- lib/screens/bookings/booking_list_item.dart | 3 +- lib/screens/bookings/bookings_filter.dart | 311 +++++++++--------- .../character_search_input_sliver.dart | 7 +- .../bookings/create/create_booking.dart | 13 +- .../create/create_booking_checkout.dart | 21 +- .../create/create_booking_complete.dart | 6 +- .../create/create_booking_search.dart | 7 +- .../create/search_availability_form.dart | 23 +- .../bookings/create/single_accommodation.dart | 9 +- lib/screens/calendar.dart | 19 +- lib/screens/calendar/booking_list_item.dart | 5 +- lib/screens/calendar/calendar_filter.dart | 29 +- lib/screens/form.dart | 195 +++++------ lib/screens/home.dart | 13 +- .../payment_detail/payment_detail.dart | 9 +- .../payment_detail_actions.dart | 13 +- .../payment_detail_booking.dart | 3 +- .../payment_detail_gateway.dart | 5 +- .../payment_detail/payment_detail_status.dart | 3 +- lib/screens/payments.dart | 9 +- lib/screens/payments/payments_filter.dart | 47 +-- lib/screens/scanner.dart | 5 +- lib/screens/settings.dart | 13 +- pubspec.lock | 7 + pubspec.yaml | 3 + 37 files changed, 704 insertions(+), 498 deletions(-) create mode 100644 lib/l10n.yaml create mode 100644 lib/l10n/app_en.arb create mode 100644 lib/l10n/app_fr.arb diff --git a/lib/l10n.yaml b/lib/l10n.yaml new file mode 100644 index 0000000..4e6692e --- /dev/null +++ b/lib/l10n.yaml @@ -0,0 +1,3 @@ +arb-dir: lib/l10n +template-arb-file: app_en.arb +output-localization-file: app_localizations.dart \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb new file mode 100644 index 0000000..f7a2748 --- /dev/null +++ b/lib/l10n/app_en.arb @@ -0,0 +1,100 @@ +{ + "@@locale": "en", + "textInstructions": "Navigate to Accommodation → Settings → Advanced to generate API keys and scan QR code. Or enter your data in the form below.", + "scanQRCodeButtonText": "Scan QR code", + "invalidQRCodeMessage": "QR code is not valid.", + "domainLabelText": "Domain", + "domainValidatorMessage": "Please enter domain", + "keyLabelText": "Key", + "keyValidatorMessage": "Please enter Key", + "secretLabelText": "Secret", + "secretValidatorMessage": "Please enter Secret", + "submitButtonText": "Submit", + "calendarLabelText": "Calendar", + "bookingsLabelText": "Bookings", + "paymentsLabelText": "Payments", + "settingsLabelText": "Settings", + "refreshTootlipText": "Refresh", + "filterTootlipText": "Filter", + "nothingFoundText": "Nothing Found", + "newBookingTooltipText": "New Booking", + "cancelButttonText": "Cancel", + "logoutButtonText": "Log out", + "confirmLogoutMessage": "Are you sure you want to log out?", + "consumerKeyEndingInLabelText": "Consumer key ending in", + "adultsLabelText": "Adults", + "childrenLabelText": "Children", + "rateLabelText": "Rate", + "servicesLabelText": "Services", + "bookingSetToConfirmedButtonText": "Set to Confirmed", + "bookingSetToCanceledButtonText": "Set to Canceled", + "bookingSetToPendingAdminButtonText": "Set to Pending Admin", + "bookingSetToPendingUserConfirmationButtonText": "Set to Pending User Confirmation", + "bookingSetToPendingPaymentButtonText": "Set to Pending Payment", + "deleteButtonText": "Delete", + "notSetLabelText": "not set", + "copiedLabelText": "copied", + "copyTooltipText": "Copy", + "totalLabelText": "Total", + "paidLabelText": "Paid", + "toPayLabelText": "To Pay", + "couponCodeUsedLabelText": "Coupon code used", + "guestsText": "guest(s)", + "timesText": "time(s)", + "onceText": "Once", + "dailyText": "Daily", + "bookingDeletedMessage": "Booking %d deleted", + "bookingLabelText": "Booking", + "actionsTooltipText": "Actions", + "errorText": "Error", + "reservationText": "Reservation", + "customerNoteText": "Customer Note", + "internalNotesText": "Internal Notes", + "customerInformationText": "Customer Information", + "firstnameLabelText": "First Name", + "lastnameLabelText": "Last Name", + "emailLabelText": "Email", + "phoneLabelText": "Phone", + "bookingCreatedMessage": "Booking %d created", + "basePriceText": "Base price", + "addBookingTitleText": "Add Booking", + "invalidRouteText": "Invalid route", + "continueButtonText": "Continue", + "bookNowButtonText": "Book Now", + "quitButtonText": "Quit", + "checkInLabelText": "Check-In", + "checkOutLabelText": "Check-Out", + "dateValidatorMessage": "Please enter date", + "searchButtonText": "Search", + "externalText": "External", + "bookingConfirmedOptionText": "Confirmed", + "bookingCanceledOptionText": "Canceled", + "bookingAbandonedOptionText": "Abandoned", + "bookingPendingAdminOptionText": "Pending Admin", + "bookingPendingUserOptionText": "Pending User", + "bookingPendingPaymentOptionText": "Pending Payment", + "todayOptionText": "Today", + "thisWeekOptionText": "This Week", + "thisMonthOptionText": "This Month", + "filtersTitleText": "Filters", + "resetButtonText": "Reset", + "bookingStatusLabelText": "Booking Status", + "dateCreatedLabelText": "Date created", + "searchHintText": "search...", + "displayExternalBookingsLabelText": "Display external bookings", + "paymentCompletedOptionText": "Completed", + "paymentCanceledOptionText": "Canceled", + "paymentAbandonedOptionText": "Abandoned", + "paymentPendingOptionText": "Pending", + "paymentFailedOptionText": "Failed", + "paymentRefundedOptionText": "Refunded", + "paymentOnHoldOptionText": "On Hold", + "paymentStatusLabelText": "Payment Status", + "paymentSetToCompletedButtonText": "Set to Completed", + "paymentSetToCanceledButtonText": "Set to Canceled", + "paymentSetToOnHoldButtonText": "Set to On Hold", + "paymentSetToPendingButtonText": "Set to Pending", + "paymentSetToFailedButtonText": "Set to Failed", + "paymentSetToRefundedButtonText": "Set to Refunded", + "paymentText": "Payment" +} diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb new file mode 100644 index 0000000..5b601be --- /dev/null +++ b/lib/l10n/app_fr.arb @@ -0,0 +1,100 @@ +{ + "@@locale": "fr", + "textInstructions": "Accédez à Hébergement → Paramètres → Avancé pour générer les clés API et scanner le code QR. Ou saisissez vos données dans le formulaire ci-dessous.", + "scanQRCodeButtonText": "Scanner le code QR", + "invalidQRCodeMessage": "Le code QR n'est pas valide.", + "domainLabelText": "Domaine", + "domainValidatorMessage": "Veuillez saisir le domaine", + "keyLabelText": "Clé", + "keyValidatorMessage": "Veuillez saisir la clé", + "secretLabelText": "Clé secrète", + "secretValidatorMessage": "Veuillez entrer la clé secrète", + "submitButtonText": "Soumettre", + "calendarLabelText": "Calendrier", + "bookingsLabelText": "Réservations", + "paymentsLabelText": "Paiements", + "settingsLabelText": "Paramètres", + "refreshTootlipText": "Rafraîchir", + "filterTootlipText": "Filtrer", + "nothingFoundText": "Rien n'a été trouvé", + "newBookingTooltipText": "Ajouter une Réservation", + "cancelButttonText": "Annuler", + "logoutButtonText": "Se déconnecter", + "confirmLogoutMessage": "Êtes-vous sûr(e) de vouloir vous déconnecter ?", + "consumerKeyEndingInLabelText": "Clé d'utilisateur se termine par", + "adultsLabelText": "Adultes", + "childrenLabelText": "Enfants", + "rateLabelText": "Tarif", + "servicesLabelText": "Services", + "bookingSetToConfirmedButtonText": "Définir en tant que: confirmée", + "bookingSetToCanceledButtonText": "Définir en tant que: annulée", + "bookingSetToPendingAdminButtonText": "Définir en tant que: en attente de la confirmation de l'admin", + "bookingSetToPendingUserConfirmationButtonText": "Définir en tant que: en attente de la confirmation de l'utilisateur", + "bookingSetToPendingPaymentButtonText": "Définir en tant que: paiement en attente", + "deleteButtonText": "Supprimer", + "notSetLabelText": "non défini", + "copiedLabelText": "copié", + "copyTooltipText": "Copier", + "totalLabelText": "Total", + "paidLabelText": "Payé", + "toPayLabelText": "À payer", + "couponCodeUsedLabelText": "Code coupon utilisé", + "guestsText": "pensionnaire(s)", + "timesText": "fois", + "onceText": "Une fois", + "dailyText": "Par jour", + "bookingDeletedMessage": "Réservation %d supprimée", + "bookingLabelText": "Réservation", + "actionsTooltipText": "Actions", + "errorText": "Erreur", + "reservationText": "Réservation", + "customerNoteText": "Remarque client", + "internalNotesText": "Remarques internes", + "customerInformationText": "Informations client", + "firstnameLabelText": "Prénom", + "lastnameLabelText": "Nom", + "emailLabelText": "Email", + "phoneLabelText": "N° Téléphone", + "bookingCreatedMessage": "Réservation %d créée", + "basePriceText": "Prix de base", + "addBookingTitleText": "Ajouter une Réservation", + "invalidRouteText": "Route invalide", + "continueButtonText": "Continuer", + "bookNowButtonText": "Réserver maintenant", + "quitButtonText": "Quitter", + "checkInLabelText": "Arrivée", + "checkOutLabelText": "Départ", + "dateValidatorMessage": "Veuillez entrer une date", + "searchButtonText": "Rechercher", + "externalText": "Externe", + "bookingConfirmedOptionText": "Confirmée", + "bookingCanceledOptionText": "Annulée", + "bookingAbandonedOptionText": "Abandonnée", + "bookingPendingAdminOptionText": "En attente de la confirmation de l'admin", + "bookingPendingUserOptionText": "En attente de la confirmation de l'utilisateur", + "bookingPendingPaymentOptionText": "Paiement en attente", + "todayOptionText": "Aujourd'hui", + "thisWeekOptionText": "Cette semaine", + "thisMonthOptionText": "Ce mois", + "filtersTitleText": "Filtres", + "resetButtonText": "Réinitialiser", + "bookingStatusLabelText": "Statut de la réservation", + "dateCreatedLabelText": "Date de création", + "searchHintText": "rechercher...", + "displayExternalBookingsLabelText": "Afficher les réservations externes", + "paymentCompletedOptionText": "Terminé", + "paymentCanceledOptionText": "Annulé", + "paymentAbandonedOptionText": "Abandonné", + "paymentPendingOptionText": "En attente", + "paymentFailedOptionText": "Échoué", + "paymentRefundedOptionText": "Remboursé", + "paymentOnHoldOptionText": "Suspendu", + "paymentStatusLabelText": "Statut du paiement", + "paymentSetToCompletedButtonText": "Définir en tant que: terminé", + "paymentSetToCanceledButtonText": "Définir en tant que: annulé", + "paymentSetToOnHoldButtonText": "Définir en tant que: suspendu", + "paymentSetToPendingButtonText": "Définir en tant que: en attente", + "paymentSetToFailedButtonText": "Définir en tant que: échoué", + "paymentSetToRefundedButtonText": "Définir en tant que: remboursé", + "paymentText": "Paiement" +} diff --git a/lib/main.dart b/lib/main.dart index dd37150..835a2e2 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,66 +1,64 @@ -import 'package:flutter/material.dart'; -import 'package:mphb_app/screens/form.dart'; -import 'package:mphb_app/screens/home.dart'; -import 'package:mphb_app/local_storage.dart'; -import 'package:shared_preferences/shared_preferences.dart'; -import 'package:flutter_localizations/flutter_localizations.dart'; - -void main() async { - - // Required for async calls in `main` - WidgetsFlutterBinding.ensureInitialized(); - - // Quick fix to initialize SharedPreferences - final prefs = await SharedPreferences.getInstance(); - - // Initialize SharedPrefs instance. - await LocalStorage(); - - runApp(MyApp()); -} - -class MyApp extends StatelessWidget { - - @override - Widget build(BuildContext context) { - return MaterialApp( - debugShowCheckedModeBanner: false, - localizationsDelegates: [ - GlobalMaterialLocalizations.delegate, - ], - supportedLocales: [ - Locale('en', 'US'), - Locale('en', 'GB'), - ], - theme: ThemeData( - primarySwatch: Colors.indigo, - scaffoldBackgroundColor: const Color(0xFFF4F5F8), - visualDensity: VisualDensity.adaptivePlatformDensity, - appBarTheme: AppBarTheme( - backgroundColor: Colors.white, - foregroundColor: Colors.black, - elevation: 0, - ), - elevatedButtonTheme: ElevatedButtonThemeData( - style: ElevatedButton.styleFrom( - primary: Colors.indigo.shade600, - ) - ), - chipTheme: ChipTheme.of(context).copyWith( - backgroundColor: Colors.white, - selectedColor: Colors.indigo.shade100, - secondarySelectedColor: Colors.indigo.shade100, - secondaryLabelStyle: TextStyle(color: Colors.black), - ), - - ), - initialRoute: LocalStorage().hasData() ? '/home' : '/login', - routes: { - '/home': (context) => const HomePage(), - '/login': (context) => const LoginForm(), - }, - ); - } -} - - +import 'package:flutter/material.dart'; +import 'package:mphb_app/screens/form.dart'; +import 'package:mphb_app/screens/home.dart'; +import 'package:mphb_app/local_storage.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +void main() async { + // Required for async calls in `main` + WidgetsFlutterBinding.ensureInitialized(); + + // Quick fix to initialize SharedPreferences + final prefs = await SharedPreferences.getInstance(); + + // Initialize SharedPrefs instance. + await LocalStorage(); + + runApp(MyApp()); +} + +class MyApp extends StatelessWidget { + @override + Widget build(BuildContext context) { + return MaterialApp( + debugShowCheckedModeBanner: false, + localizationsDelegates: [ + AppLocalizations.delegate, + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + ], + supportedLocales: [ + Locale('en'), // English + Locale('fr'), // French + ], + theme: ThemeData( + primarySwatch: Colors.indigo, + scaffoldBackgroundColor: const Color(0xFFF4F5F8), + visualDensity: VisualDensity.adaptivePlatformDensity, + appBarTheme: AppBarTheme( + backgroundColor: Colors.white, + foregroundColor: Colors.black, + elevation: 0, + ), + elevatedButtonTheme: ElevatedButtonThemeData( + style: ElevatedButton.styleFrom( + primary: Colors.indigo.shade600, + )), + chipTheme: ChipTheme.of(context).copyWith( + backgroundColor: Colors.white, + selectedColor: Colors.indigo.shade100, + secondarySelectedColor: Colors.indigo.shade100, + secondaryLabelStyle: TextStyle(color: Colors.black), + ), + ), + initialRoute: LocalStorage().hasData() ? '/home' : '/login', + routes: { + '/home': (context) => const HomePage(), + '/login': (context) => const LoginForm(), + }, + ); + } +} diff --git a/lib/screens/booking_detail/booking_detail.dart b/lib/screens/booking_detail/booking_detail.dart index 351b15d..65f7fdf 100644 --- a/lib/screens/booking_detail/booking_detail.dart +++ b/lib/screens/booking_detail/booking_detail.dart @@ -11,6 +11,8 @@ import 'package:mphb_app/screens/booking_detail/booking_detail_payment.dart'; import 'package:mphb_app/screens/booking_detail/booking_detail_ical.dart'; import 'package:mphb_app/screens/booking_detail/booking_detail_note.dart'; import 'package:mphb_app/screens/booking_detail/booking_detail_internal_notes.dart'; +import 'package:sprintf/sprintf.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class BookingDetailScreen extends StatefulWidget { @@ -73,11 +75,11 @@ class _BookingDetailScreenState extends State { void deleteBooking( Booking booking ) async { try { - + Booking deletedBooking = await _bookingController.wpDeleteBooking(booking.id); ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Booking ${deletedBooking.id} deleted.')) + SnackBar(content: Text(sprintf(AppLocalizations.of(context).bookingDeletedMessage, [deletedBooking.id]))) ); Navigator.maybePop(context); @@ -136,11 +138,11 @@ class _BookingDetailScreenState extends State { return WillPopScope( child: Scaffold( appBar: AppBar( - title: Text( 'Booking #$bookingID' ), + title: Text( AppLocalizations.of(context).bookingLabelText + ' #$bookingID' ), actions: [ IconButton( icon: const Icon(Icons.sync), - tooltip: 'Refresh', + tooltip: AppLocalizations.of(context).refreshTootlipText, onPressed: () { setState(() { _bookingFuture = _getBooking( bookingID ); @@ -172,7 +174,7 @@ class _BookingDetailScreenState extends State { return IconButton( icon: const Icon(Icons.more_vert), - tooltip: 'Actions', + tooltip: AppLocalizations.of(context).actionsTooltipText, onPressed: () => _showModalBottomSheet( context, booking ), ); } @@ -187,7 +189,7 @@ class _BookingDetailScreenState extends State { if (snapshot.hasError) { - return new Center(child: Text('Error: ${snapshot.error}') ); + return new Center(child: Text(AppLocalizations.of(context).errorText + ': ${snapshot.error}') ); } else { @@ -214,7 +216,7 @@ class _BookingDetailScreenState extends State { // customer if ( booking.imported == false ) BookingDetailCustomer( customer: booking.customer ), - + if ( booking.imported == true ) BookingDetailIcal( booking: booking ), @@ -224,7 +226,7 @@ class _BookingDetailScreenState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text('Reservation'), + Text(AppLocalizations.of(context).reservationText), for ( var reserved_accommodation in booking.reserved_accommodations @@ -251,7 +253,7 @@ class _BookingDetailScreenState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text('Payments'), + Text(AppLocalizations.of(context).paymentsLabelText), for ( var payment in booking.payments ) BookingDetailPayment( payment: payment ), ], @@ -264,7 +266,7 @@ class _BookingDetailScreenState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text('Customer Note'), + Text(AppLocalizations.of(context).customerNoteText), BookingDetailNote( booking: booking ), ], ), @@ -276,7 +278,7 @@ class _BookingDetailScreenState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text('Internal Notes'), + Text(AppLocalizations.of(context).internalNotesText), BookingDetailInternalNotes( booking: booking ), ], ), diff --git a/lib/screens/booking_detail/booking_detail_accommodation.dart b/lib/screens/booking_detail/booking_detail_accommodation.dart index 69e4363..f114d8b 100644 --- a/lib/screens/booking_detail/booking_detail_accommodation.dart +++ b/lib/screens/booking_detail/booking_detail_accommodation.dart @@ -4,6 +4,7 @@ import 'package:mphb_app/models/accommodation.dart'; import 'package:mphb_app/models/accommodation_type.dart'; import 'package:mphb_app/models/reserved_accommodation.dart'; import 'package:mphb_app/models/booking.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class BookingDetailAccommodation extends StatelessWidget { @@ -112,7 +113,7 @@ class BookingDetailAccommodation extends StatelessWidget { style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ), Text( - 'adults', + AppLocalizations.of(context).adultsLabelText, style: TextStyle(fontSize: 11), ), ] @@ -129,7 +130,7 @@ class BookingDetailAccommodation extends StatelessWidget { style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ), Text( - 'children', + AppLocalizations.of(context).childrenLabelText, style: TextStyle(fontSize: 11), ), ] @@ -150,7 +151,7 @@ class BookingDetailAccommodation extends StatelessWidget { tilePadding: EdgeInsets.zero, childrenPadding: EdgeInsets.zero, title: Text( - 'Rate: ' + (booking.getRateByID( + AppLocalizations.of(context).rateLabelText + ': ' + (booking.getRateByID( reserved_accommodation.rate )?.title ?? reserved_accommodation.rate.toString() ), style: DefaultTextStyle.of(context).style @@ -180,7 +181,7 @@ class BookingDetailAccommodation extends StatelessWidget { tilePadding: EdgeInsets.zero, childrenPadding: EdgeInsets.zero, title: Text( - 'Services (' + reserved_accommodation.services.length.toString() + ')', + AppLocalizations.of(context).servicesLabelText + ' (' + reserved_accommodation.services.length.toString() + ')', style: DefaultTextStyle.of(context).style ), children: List.generate(1,(index){ diff --git a/lib/screens/booking_detail/booking_detail_actions.dart b/lib/screens/booking_detail/booking_detail_actions.dart index 953be65..0c147dc 100644 --- a/lib/screens/booking_detail/booking_detail_actions.dart +++ b/lib/screens/booking_detail/booking_detail_actions.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:mphb_app/models/booking.dart'; import 'package:mphb_app/models/enum/booking_status.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class BookingDetailActions extends StatelessWidget { @@ -15,35 +16,35 @@ class BookingDetailActions extends StatelessWidget { children: [ ListTile( leading: Icon(Icons.done), - title: Text('Set to Confirmed'), + title: Text(AppLocalizations.of(context).bookingSetToConfirmedButtonText), onTap: () { Navigator.pop(context, BookingStatusEnum.CONFIRMED); }, ), ListTile( leading: Icon(Icons.block), - title: Text('Set to Cancelled'), + title: Text(AppLocalizations.of(context).bookingSetToCanceledButtonText), onTap: () { Navigator.pop(context, BookingStatusEnum.CANCELLED); }, ), ListTile( leading: Icon(Icons.hourglass_empty), - title: Text('Set to Pending Admin'), + title: Text(AppLocalizations.of(context).bookingSetToPendingAdminButtonText), onTap: () { Navigator.pop(context, BookingStatusEnum.PENDING); }, ), ListTile( leading: Icon(Icons.mail_outline), - title: Text('Set to Pending User Confirmation'), + title: Text(AppLocalizations.of(context).bookingSetToPendingUserConfirmationButtonText), onTap: () { Navigator.pop(context, BookingStatusEnum.PENDING_USER); }, ), ListTile( leading: Icon(Icons.payment), - title: Text('Set to Pending Payment'), + title: Text(AppLocalizations.of(context).bookingSetToPendingPaymentButtonText), onTap: () { Navigator.pop(context, BookingStatusEnum.PENDING_PAYMENT); }, @@ -51,7 +52,7 @@ class BookingDetailActions extends StatelessWidget { Divider(), ListTile( leading: Icon(Icons.delete), - title: Text('Delete'), + title: Text(AppLocalizations.of(context).deleteButtonText), onTap: () { Navigator.pop(context, 'delete'); }, diff --git a/lib/screens/booking_detail/booking_detail_customer.dart b/lib/screens/booking_detail/booking_detail_customer.dart index ab0b171..b1790bc 100644 --- a/lib/screens/booking_detail/booking_detail_customer.dart +++ b/lib/screens/booking_detail/booking_detail_customer.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:mphb_app/models/customer.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class BookingDetailCustomer extends StatelessWidget { @@ -63,7 +64,7 @@ class BookingDetailCustomer extends StatelessWidget { if ( (customer.first_name + customer.last_name).isEmpty ) Text( - 'not set', + AppLocalizations.of(context).notSetLabelText, style: TextStyle(fontStyle: FontStyle.italic), ), //endif @@ -106,10 +107,10 @@ class BookingDetailCustomer extends StatelessWidget { final snackBar = SnackBar( content: Text( - '${customer.email} copied' + '${customer.email} ' + AppLocalizations.of(context).copiedLabelText ) ); - + ScaffoldMessenger.of(context). clearSnackBars(); ScaffoldMessenger.of(context). @@ -161,7 +162,7 @@ class BookingDetailCustomer extends StatelessWidget { IconButton( icon: const Icon(Icons.content_copy), iconSize: 14, - tooltip: 'Copy', + tooltip: AppLocalizations.of(context).copyTooltipText, onPressed: () { Clipboard.setData( ClipboardData(text: customer.phone)) @@ -169,7 +170,7 @@ class BookingDetailCustomer extends StatelessWidget { final snackBar = SnackBar( content: Text( - '${customer.phone} copied' + '${customer.phone} ' + AppLocalizations.of(context).copiedLabelText ) ); diff --git a/lib/screens/booking_detail/booking_detail_price.dart b/lib/screens/booking_detail/booking_detail_price.dart index 8a4a9c1..d2af432 100644 --- a/lib/screens/booking_detail/booking_detail_price.dart +++ b/lib/screens/booking_detail/booking_detail_price.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:mphb_app/models/booking.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class BookingDetailPrice extends StatelessWidget { @@ -47,7 +48,7 @@ class BookingDetailPrice extends StatelessWidget { Padding ( padding: EdgeInsets.only(top: 5.0), child: Text( - 'Total', + AppLocalizations.of(context).totalLabelText, style: TextStyle(fontSize: 12), ), ), @@ -69,7 +70,7 @@ class BookingDetailPrice extends StatelessWidget { Padding ( padding: EdgeInsets.only(top: 5.0), child: Text( - 'Paid', + AppLocalizations.of(context).paidLabelText, style: TextStyle(fontSize: 12), ), ), @@ -91,7 +92,7 @@ class BookingDetailPrice extends StatelessWidget { Padding ( padding: EdgeInsets.only(top: 5.0), child: Text( - 'To Pay', + AppLocalizations.of(context).toPayLabelText, style: TextStyle(fontSize: 12), ), ), @@ -104,7 +105,7 @@ class BookingDetailPrice extends StatelessWidget { Padding( padding: EdgeInsets.only(top: 20.0), child: Text( - 'Coupon code used: ${booking.coupon_code}', + AppLocalizations.of(context).couponCodeUsedLabelText + ': ${booking.coupon_code}', style: TextStyle(fontSize: 12), ), ), diff --git a/lib/screens/booking_detail/booking_detail_services.dart b/lib/screens/booking_detail/booking_detail_services.dart index dd6cf56..47d9f91 100644 --- a/lib/screens/booking_detail/booking_detail_services.dart +++ b/lib/screens/booking_detail/booking_detail_services.dart @@ -3,6 +3,7 @@ import 'package:mphb_app/models/reserved_accommodation.dart'; import 'package:mphb_app/models/reserved_service.dart'; import 'package:mphb_app/models/service.dart'; import 'package:mphb_app/models/booking.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class BookingDetailServices extends StatelessWidget { @@ -35,14 +36,14 @@ class BookingDetailServices extends StatelessWidget { }, defaultVerticalAlignment: TableCellVerticalAlignment.middle, children: reserved_accommodation.services.map( - (item) => buildTableRow(item, booking) + (item) => buildTableRow(context, item, booking) ).toList(), ), ); } - TableRow buildTableRow(Reserved_Service reserved_service, Booking booking) { + TableRow buildTableRow(BuildContext context, Reserved_Service reserved_service, Booking booking) { return TableRow( key: ValueKey(reserved_service.id), @@ -62,7 +63,7 @@ class BookingDetailServices extends StatelessWidget { padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 15.0), child: Text( reserved_service.adults != null ? - 'x ' + reserved_service.adults.toString() + ' guest(s)' : '', + 'x ' + reserved_service.adults.toString() + ' ' + AppLocalizations.of(context).guestsText : '', style: TextStyle(fontStyle: FontStyle.italic), ), ), @@ -72,11 +73,11 @@ class BookingDetailServices extends StatelessWidget { padding: const EdgeInsets.only(left: 10.0, top: 10.0, bottom: 10.0), child: Text( reserved_service.quantity != null ? - 'x ' + reserved_service.quantity.toString() + ' time(s)' : + 'x ' + reserved_service.quantity.toString() + ' '+ AppLocalizations.of(context).timesText : ( booking.getServiceByID( reserved_service.id)?.periodicity['typeof'] == 'once' ? - 'Once' : 'Daily' + AppLocalizations.of(context).onceText : AppLocalizations.of(context).dailyText ), style: TextStyle(fontStyle: FontStyle.italic), ), diff --git a/lib/screens/booking_detail/booking_detail_status.dart b/lib/screens/booking_detail/booking_detail_status.dart index 39507fb..1e14070 100644 --- a/lib/screens/booking_detail/booking_detail_status.dart +++ b/lib/screens/booking_detail/booking_detail_status.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:mphb_app/models/booking.dart'; import 'package:mphb_app/models/enum/booking_status.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class BookingDetailStatus extends StatelessWidget { @@ -21,7 +22,7 @@ class BookingDetailStatus extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - 'Booking #' + booking.id.toString(), + AppLocalizations.of(context).bookingLabelText + ' #' + booking.id.toString(), style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ), Padding ( diff --git a/lib/screens/bookings.dart b/lib/screens/bookings.dart index ba86f88..0542df5 100644 --- a/lib/screens/bookings.dart +++ b/lib/screens/bookings.dart @@ -7,6 +7,7 @@ import 'package:mphb_app/models/bookings_filters.dart'; import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; import 'package:mphb_app/screens/bookings/create/create_booking.dart'; import 'package:mphb_app/screens/bookings/character_search_input_sliver.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class BookingsPage extends StatefulWidget { @override @@ -79,7 +80,7 @@ class _BookingsListViewState extends State { return Scaffold( appBar: AppBar( - title: Text('Bookings'), + title: Text(AppLocalizations.of(context).bookingsLabelText), shape: Border( bottom: BorderSide( color: const Color(0xFFF4F5F8), @@ -89,7 +90,7 @@ class _BookingsListViewState extends State { actions: [ IconButton( icon: const Icon(Icons.add_circle_outline), - tooltip: 'New Booking', + tooltip: AppLocalizations.of(context).newBookingTooltipText, onPressed: () async { await Navigator.push(context, MaterialPageRoute ( builder: (BuildContext context) { @@ -103,7 +104,7 @@ class _BookingsListViewState extends State { ), IconButton( icon: const Icon(Icons.sync), - tooltip: 'Refresh', + tooltip: AppLocalizations.of(context).refreshTootlipText, onPressed: () { _pagingController.refresh(); @@ -114,7 +115,7 @@ class _BookingsListViewState extends State { children: [ IconButton( icon: const Icon(Icons.filter_list), - tooltip: 'Filter', + tooltip: AppLocalizations.of(context).filterTootlipText, onPressed: () async { await Navigator.push(context, MaterialPageRoute ( builder: (BuildContext context) { @@ -182,7 +183,7 @@ class _BookingsListViewState extends State { deleteBookingCallback: deleteBookingCallback, ), noItemsFoundIndicatorBuilder: (context) => - Center( child: Text('Nothing Found') ), + Center( child: Text(AppLocalizations.of(context).nothingFoundText) ), firstPageErrorIndicatorBuilder: (context) => Center( child: Text(_pagingController.error.toString()) ), diff --git a/lib/screens/bookings/booking_list_item.dart b/lib/screens/bookings/booking_list_item.dart index eff3510..c9fc2d7 100644 --- a/lib/screens/bookings/booking_list_item.dart +++ b/lib/screens/bookings/booking_list_item.dart @@ -5,6 +5,7 @@ import 'package:mphb_app/screens/common/booking_date.dart'; import 'package:mphb_app/models/booking.dart'; import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; import 'package:mphb_app/models/enum/booking_status.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class BookingListItem extends StatefulWidget { @@ -195,7 +196,7 @@ class _BookingListItemState extends State { ) ), Text( - 'External', + AppLocalizations.of(context).externalText, style: TextStyle( fontSize: 12, ), diff --git a/lib/screens/bookings/bookings_filter.dart b/lib/screens/bookings/bookings_filter.dart index 2bae4b7..282deae 100644 --- a/lib/screens/bookings/bookings_filter.dart +++ b/lib/screens/bookings/bookings_filter.dart @@ -2,173 +2,160 @@ import 'package:flutter/material.dart'; import 'package:mphb_app/models/bookings_filters.dart'; import 'package:mphb_app/models/enum/date_range.dart'; import 'package:mphb_app/models/enum/booking_status.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class BookingsFilter extends StatefulWidget { + final Bookings_Filters bookings_filters; - final Bookings_Filters bookings_filters; - - const BookingsFilter({ - required this.bookings_filters, - Key? key - }) : super(key: key); - - @override - _BookingsFilterState createState() => - _BookingsFilterState( bookings_filters: this.bookings_filters ); + const BookingsFilter({required this.bookings_filters, Key? key}) + : super(key: key); + @override + _BookingsFilterState createState() => + _BookingsFilterState(bookings_filters: this.bookings_filters); } class _BookingsFilterState extends State { - - _BookingsFilterState({ - required this.bookings_filters - }); - - Bookings_Filters bookings_filters; - - final List _bookingStatusesOptions = [ - const {'label': 'Confirmed', 'value': BookingStatusEnum.CONFIRMED}, - const {'label': 'Cancelled', 'value': BookingStatusEnum.CANCELLED}, - const {'label': 'Abandoned', 'value': BookingStatusEnum.ABANDONED}, - const {'label': 'Pending Admin', 'value': BookingStatusEnum.PENDING}, - const {'label': 'Pending User', 'value': BookingStatusEnum.PENDING_USER}, - const {'label': 'Pending Payment', 'value': BookingStatusEnum.PENDING_PAYMENT}, - ]; - - final List _bookingDateRangeOptions = [ - const {'label': 'Today', 'value': DateRangeEnum.TODAY}, - const {'label': 'This Week', 'value': DateRangeEnum.THIS_WEEK}, - const {'label': 'This Month', 'value': DateRangeEnum.THIS_MONTH}, - ]; - - Iterable get bookingStatusesFilter sync* { - - for (final status in _bookingStatusesOptions) { - yield Padding( - padding: const EdgeInsets.all(4.0), - child: FilterChip( - label: Text(status['label']), - selected: bookings_filters.post_status.contains(status['value']), - onSelected: (bool value) { - setState(() { - if (value) { - - bookings_filters.post_status.add(status['value']); - - } else { - - bookings_filters.post_status.removeWhere((String value) { - return value == status['value']; - }); - } - }); - }, - ), - ); - } - } - - Iterable get bookingDateRangeFilter sync* { - - for (final range in _bookingDateRangeOptions) { - yield Padding( - padding: const EdgeInsets.all(4.0), - child: ChoiceChip( - label: Text(range['label']), - selected: bookings_filters.date_range == range['value'], - onSelected: (bool value) { - setState(() { - if (value) { - - bookings_filters.date_range = range['value']; - } else { - - bookings_filters.date_range = ''; - } - }); - }, - ), - ); - } - } - - void reset() { - setState(() { - bookings_filters = new Bookings_Filters(); - }); - } - - @override - Widget build(BuildContext context) { - - return WillPopScope( - child: Scaffold( - backgroundColor: const Color(0xFFF4F5F8), - appBar: AppBar( - title: const Text('Filters'), - actions: [ - Padding( - padding: EdgeInsets.all(10.0), - child: TextButton( - onPressed: reset, - child: const Text('Reset'), - style: TextButton.styleFrom( - primary: Colors.black, - ), - ), - ), - ], - ), - body: SingleChildScrollView( - child: Container( - padding: const EdgeInsets.all(20.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - - Container( - margin: const EdgeInsets.only(top: 0.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.only(bottom: 10.0), - child: Text('Booking Status:'), - ), - Wrap( - children: bookingStatusesFilter.toList(), - ), - SizedBox(height: 10), - ], - ), - ), - Container( - margin: const EdgeInsets.only(top: 20.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.only(bottom: 10.0), - child: Text('Date Created:'), - ), - Wrap( - children: bookingDateRangeFilter.toList(), - ), - SizedBox(height: 10), - ], - ), - ), - ], - ), - ), - ), - ), - onWillPop: () async { - Navigator.pop(context, bookings_filters); - return false; - } - ); - } - + _BookingsFilterState({required this.bookings_filters}); + + Bookings_Filters bookings_filters; + + static List _bookingStatusesOptions(BuildContext context) { + return [ + {'label': AppLocalizations.of(context).bookingConfirmedOptionText, 'value': BookingStatusEnum.CONFIRMED}, + {'label': AppLocalizations.of(context).bookingCanceledOptionText, 'value': BookingStatusEnum.CANCELLED}, + {'label': AppLocalizations.of(context).bookingAbandonedOptionText, 'value': BookingStatusEnum.ABANDONED}, + {'label': AppLocalizations.of(context).bookingPendingAdminOptionText, 'value': BookingStatusEnum.PENDING}, + {'label': AppLocalizations.of(context).bookingPendingUserOptionText, 'value': BookingStatusEnum.PENDING_USER}, + {'label': AppLocalizations.of(context).bookingPendingPaymentOptionText, 'value': BookingStatusEnum.PENDING_PAYMENT}, + ]; + } + + static List _bookingDateRangeOptions(BuildContext context) { + return [ + {'label': AppLocalizations.of(context).todayOptionText, 'value': DateRangeEnum.TODAY}, + {'label': AppLocalizations.of(context).thisWeekOptionText, 'value': DateRangeEnum.THIS_WEEK}, + {'label': AppLocalizations.of(context).thisMonthOptionText, 'value': DateRangeEnum.THIS_MONTH}, + ]; + } + + Iterable get bookingStatusesFilter sync* { + for (final status in _bookingStatusesOptions(context)) { + yield Padding( + padding: const EdgeInsets.all(4.0), + child: FilterChip( + label: Text(status['label']), + selected: bookings_filters.post_status.contains(status['value']), + onSelected: (bool value) { + setState(() { + if (value) { + bookings_filters.post_status.add(status['value']); + } else { + bookings_filters.post_status.removeWhere((String value) { + return value == status['value']; + }); + } + }); + }, + ), + ); + } + } + + Iterable get bookingDateRangeFilter sync* { + for (final range in _bookingDateRangeOptions(context)) { + yield Padding( + padding: const EdgeInsets.all(4.0), + child: ChoiceChip( + label: Text(range['label']), + selected: bookings_filters.date_range == range['value'], + onSelected: (bool value) { + setState(() { + if (value) { + bookings_filters.date_range = range['value']; + } else { + bookings_filters.date_range = ''; + } + }); + }, + ), + ); + } + } + + void reset() { + setState(() { + bookings_filters = new Bookings_Filters(); + }); + } + + @override + Widget build(BuildContext context) { + return WillPopScope( + child: Scaffold( + backgroundColor: const Color(0xFFF4F5F8), + appBar: AppBar( + title: Text(AppLocalizations.of(context).filtersTitleText), + actions: [ + Padding( + padding: EdgeInsets.all(10.0), + child: TextButton( + onPressed: reset, + child: Text(AppLocalizations.of(context).resetButtonText), + style: TextButton.styleFrom( + primary: Colors.black, + ), + ), + ), + ], + ), + body: SingleChildScrollView( + child: Container( + padding: const EdgeInsets.all(20.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + margin: const EdgeInsets.only(top: 0.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(bottom: 10.0), + child: Text(AppLocalizations.of(context).bookingStatusLabelText + ':'), + ), + Wrap( + children: bookingStatusesFilter.toList(), + ), + SizedBox(height: 10), + ], + ), + ), + Container( + margin: const EdgeInsets.only(top: 20.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(bottom: 10.0), + child: Text(AppLocalizations.of(context).dateCreatedLabelText + ':'), + ), + Wrap( + children: bookingDateRangeFilter.toList(), + ), + SizedBox(height: 10), + ], + ), + ), + ], + ), + ), + ), + ), + onWillPop: () async { + Navigator.pop(context, bookings_filters); + return false; + }); + } } diff --git a/lib/screens/bookings/character_search_input_sliver.dart b/lib/screens/bookings/character_search_input_sliver.dart index 43ef2ce..f2d2c66 100644 --- a/lib/screens/bookings/character_search_input_sliver.dart +++ b/lib/screens/bookings/character_search_input_sliver.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:rxdart/rxdart.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class CharacterSearchInputSliver extends StatefulWidget { const CharacterSearchInputSliver({ @@ -65,14 +66,14 @@ class _CharacterSearchInputSliverState ), border: OutlineInputBorder( borderRadius: const BorderRadius.all( - const Radius.circular(25.0), + const Radius.circular(25.0), ), borderSide: BorderSide( - width: 0, + width: 0, style: BorderStyle.none, ), ), - hintText: 'search...', + hintText: AppLocalizations.of(context).searchHintText, hintStyle: TextStyle(fontSize: 14, ), fillColor: const Color(0xFFE8E9EA), filled: true, diff --git a/lib/screens/bookings/create/create_booking.dart b/lib/screens/bookings/create/create_booking.dart index d73dc3a..23e7085 100644 --- a/lib/screens/bookings/create/create_booking.dart +++ b/lib/screens/bookings/create/create_booking.dart @@ -4,6 +4,7 @@ import 'package:mphb_app/screens/bookings/create/create_booking_checkout.dart'; import 'package:mphb_app/screens/bookings/create/create_booking_complete.dart'; import 'package:mphb_app/models/create_booking.dart'; import 'package:mphb_app/models/booking.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class CreateBookingPage extends StatefulWidget { @@ -40,7 +41,7 @@ class _CreateBookingPageState extends State { }); } else { - + Navigator.maybePop(context); } } @@ -53,7 +54,7 @@ class _CreateBookingPageState extends State { child: Scaffold( appBar: AppBar( - title: const Text('Add Booking'), + title: Text(AppLocalizations.of(context).addBookingTitleText), leading: BackButton(onPressed: _onBackPressed), ), body: Navigator( @@ -88,7 +89,7 @@ class _CreateBookingPageState extends State { break; default: - throw Exception('Invalid route: ${settings.name}'); + throw Exception(AppLocalizations.of(context).invalidRouteText + ': ${settings.name}'); } return MaterialPageRoute(builder: builder, settings: settings); @@ -99,7 +100,7 @@ class _CreateBookingPageState extends State { if ( _booking.state == Create_Booking.INITIAL ) ElevatedButton( - child: const Text('Continue'), + child: Text(AppLocalizations.of(context).continueButtonText), onPressed: _booking.accommodations.isEmpty ? null : () { _navigatorKey.currentState!.pushNamed( @@ -115,7 +116,7 @@ class _CreateBookingPageState extends State { if ( _booking.state == Create_Booking.CHECKOUT ) ElevatedButton( - child: const Text('Book Now'), + child: Text(AppLocalizations.of(context).bookNowButtonText), onPressed: _booking.reserved_accommodations.isEmpty ? null : () { _navigatorKey.currentState!.pushNamed( 'create_booking/complete', @@ -129,7 +130,7 @@ class _CreateBookingPageState extends State { if ( _booking.state == Create_Booking.COMPLETE ) OutlinedButton( - child: const Text('Quit'), + child: Text(AppLocalizations.of(context).quitButtonText), onPressed: _onBackPressed, ), ], diff --git a/lib/screens/bookings/create/create_booking_checkout.dart b/lib/screens/bookings/create/create_booking_checkout.dart index d638037..56fee8f 100644 --- a/lib/screens/bookings/create/create_booking_checkout.dart +++ b/lib/screens/bookings/create/create_booking_checkout.dart @@ -3,6 +3,7 @@ import 'package:mphb_app/models/create_booking.dart'; import 'package:mphb_app/models/accommodation.dart'; import 'package:mphb_app/models/reserved_accommodation.dart'; import 'package:mphb_app/screens/bookings/create/single_accommodation.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class CreateBookingCheckoutPage extends StatefulWidget { @@ -31,7 +32,7 @@ class _CreateBookingCheckoutPageState extends State { void initState() { super.initState(); - + //reset booking.reset(); } @@ -65,10 +66,10 @@ class _CreateBookingCheckoutPageState extends State { mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text('Customer Information'), + Text(AppLocalizations.of(context).customerInformationText), TextField( - decoration: const InputDecoration( - labelText: 'First Name', + decoration: InputDecoration( + labelText: AppLocalizations.of(context).firstnameLabelText, ), keyboardType: TextInputType.name, textCapitalization: TextCapitalization.sentences, @@ -77,8 +78,8 @@ class _CreateBookingCheckoutPageState extends State { }, ), TextField( - decoration: const InputDecoration( - labelText: 'Last Name', + decoration: InputDecoration( + labelText: AppLocalizations.of(context).lastnameLabelText, ), keyboardType: TextInputType.name, textCapitalization: TextCapitalization.words, @@ -87,8 +88,8 @@ class _CreateBookingCheckoutPageState extends State { }, ), TextField( - decoration: const InputDecoration( - labelText: 'Email', + decoration: InputDecoration( + labelText: AppLocalizations.of(context).emailLabelText, ), keyboardType: TextInputType.emailAddress, onChanged: (text) { @@ -96,8 +97,8 @@ class _CreateBookingCheckoutPageState extends State { }, ), TextField( - decoration: const InputDecoration( - labelText: 'Phone', + decoration: InputDecoration( + labelText: AppLocalizations.of(context).phoneLabelText, ), keyboardType: TextInputType.numberWithOptions(signed: true), onChanged: (text) { diff --git a/lib/screens/bookings/create/create_booking_complete.dart b/lib/screens/bookings/create/create_booking_complete.dart index 56f9fcf..f0ee3c8 100644 --- a/lib/screens/bookings/create/create_booking_complete.dart +++ b/lib/screens/bookings/create/create_booking_complete.dart @@ -5,6 +5,8 @@ import 'package:mphb_app/models/accommodation.dart'; import 'package:mphb_app/models/reserved_accommodation.dart'; import 'package:mphb_app/models/booking.dart'; import 'package:mphb_app/screens/bookings/create/single_accommodation.dart'; +import 'package:sprintf/sprintf.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class CreateBookingCompletePage extends StatefulWidget { @@ -84,9 +86,9 @@ class _CreateBookingCompletePageState extends State { final bookingObj = await _bookingsController.wpCreateBooking( params ); setState(() {_state = 'complete';}); - + ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Booking ${bookingObj.id} created.')) + SnackBar(content: Text(sprintf(AppLocalizations.of(context).bookingCreatedMessage, [bookingObj.id]))) ); widget.createBookingCallback( bookingObj ); diff --git a/lib/screens/bookings/create/create_booking_search.dart b/lib/screens/bookings/create/create_booking_search.dart index b74575c..c4f1855 100644 --- a/lib/screens/bookings/create/create_booking_search.dart +++ b/lib/screens/bookings/create/create_booking_search.dart @@ -4,6 +4,7 @@ import 'package:mphb_app/controller/bookings_controller.dart'; import 'package:mphb_app/models/accommodation_availability.dart'; import 'package:mphb_app/models/accommodation.dart'; import 'package:mphb_app/models/create_booking.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class CreateBookingSearchPage extends StatefulWidget { @@ -81,10 +82,10 @@ class _CreateBookingSearchPageState extends State { if ( _accommodations.length > 0 ) { return buildAccommodations.toList(); } else { - return [Center(child:Text('Nothing found'))]; + return [Center(child:Text(AppLocalizations.of(context).nothingFoundText))]; } break; - + case 'waiting': return [CircularProgressIndicator()]; break; @@ -105,7 +106,7 @@ class _CreateBookingSearchPageState extends State { title: Text(accommodation_availability.title + ' (' + accommodation_availability.accommodations.length.toString() + ')'), subtitle: Text( - 'Base price: ' + accommodation_availability.base_price.toStringAsFixed(2), + AppLocalizations.of(context).basePriceText + ': ' + accommodation_availability.base_price.toStringAsFixed(2), style: const TextStyle(fontSize: 11), ), children: [ diff --git a/lib/screens/bookings/create/search_availability_form.dart b/lib/screens/bookings/create/search_availability_form.dart index 36119d7..832130d 100644 --- a/lib/screens/bookings/create/search_availability_form.dart +++ b/lib/screens/bookings/create/search_availability_form.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class SearchAvailabilityForm extends StatefulWidget { @@ -94,15 +95,15 @@ class _SearchAvailabilityFormState extends State { child: TextFormField( controller: checkInController, keyboardType: TextInputType.numberWithOptions(signed: true), - decoration: const InputDecoration( + decoration: InputDecoration( isDense: true, hintText: '1970-12-31', - labelText: 'Check-in', + labelText: AppLocalizations.of(context).checkInLabelText, floatingLabelBehavior: FloatingLabelBehavior.always, ), validator: (value) { if (value == null || value.isEmpty) { - return 'Please enter date'; + return AppLocalizations.of(context).dateValidatorMessage; } return null; }, @@ -118,15 +119,15 @@ class _SearchAvailabilityFormState extends State { child: TextFormField( controller: checkOutController, keyboardType: TextInputType.numberWithOptions(signed: true), - decoration: const InputDecoration( + decoration: InputDecoration( isDense: true, hintText: '1970-12-31', - labelText: 'Check-out', + labelText: AppLocalizations.of(context).checkOutLabelText, floatingLabelBehavior: FloatingLabelBehavior.always, ), validator: (value) { if (value == null || value.isEmpty) { - return 'Please enter date'; + return AppLocalizations.of(context).dateValidatorMessage; } return null; }, @@ -156,9 +157,9 @@ class _SearchAvailabilityFormState extends State { children: [ Expanded( child: DropdownButtonFormField( - decoration: const InputDecoration( + decoration: InputDecoration( isDense: true, - labelText: 'Adults', + labelText: AppLocalizations.of(context).adultsLabelText, ), value: _adults, @@ -181,9 +182,9 @@ class _SearchAvailabilityFormState extends State { SizedBox(width: 10), Expanded( child: DropdownButtonFormField( - decoration: const InputDecoration( + decoration: InputDecoration( isDense: true, - labelText: 'Children', + labelText: AppLocalizations.of(context).childrenLabelText, ), value: _children, items: List.generate( @@ -228,7 +229,7 @@ class _SearchAvailabilityFormState extends State { widget.callback( params ); } }, - child: const Text('Search',), + child: Text(AppLocalizations.of(context).searchButtonText), ), ), ] diff --git a/lib/screens/bookings/create/single_accommodation.dart b/lib/screens/bookings/create/single_accommodation.dart index f70b198..0cfe608 100644 --- a/lib/screens/bookings/create/single_accommodation.dart +++ b/lib/screens/bookings/create/single_accommodation.dart @@ -4,6 +4,7 @@ import 'package:mphb_app/models/create_booking.dart'; import 'package:mphb_app/models/accommodation.dart'; import 'package:mphb_app/models/reserved_accommodation.dart'; import 'package:mphb_app/models/accommodation_type.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class SingleAccommodation extends StatefulWidget { @@ -87,7 +88,7 @@ class _SingleAccommodationState extends State { booking.dispatch(context); } catch (error) { - + setState(() {_state = 'complete';}); ScaffoldMessenger.of(context).clearSnackBars(); @@ -113,7 +114,7 @@ class _SingleAccommodationState extends State { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( 'Adults' ), + Text(AppLocalizations.of(context).adultsLabelText), DropdownButton( value: _reserved_accommodation.adults.toString(), @@ -143,7 +144,7 @@ class _SingleAccommodationState extends State { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( 'Children' ), + Text(AppLocalizations.of(context).childrenLabelText), DropdownButton( value: _reserved_accommodation.children.toString(), items: List.generate( @@ -168,7 +169,7 @@ class _SingleAccommodationState extends State { ), ]; break; - + case 'waiting': children += [ Center( diff --git a/lib/screens/calendar.dart b/lib/screens/calendar.dart index 01c9742..a77b178 100644 --- a/lib/screens/calendar.dart +++ b/lib/screens/calendar.dart @@ -8,6 +8,7 @@ import 'package:mphb_app/screens/calendar/booking_list_item.dart'; import 'package:mphb_app/screens/calendar/calendar_filter.dart'; import 'package:mphb_app/models/calendar_filters.dart'; import 'package:mphb_app/screens/bookings/create/create_booking.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class CalendarPage extends StatefulWidget { @override @@ -99,7 +100,7 @@ class _TableEventsState extends State { try { await Future.doWhile( () async { - + _bookings = await _bookingsController.wpGetAllBookings( offset, limit, filters); bookings.addAll( _bookings ); @@ -229,7 +230,7 @@ class _TableEventsState extends State { return Scaffold( appBar: AppBar( - title: Text('Calendar'), + title: Text(AppLocalizations.of(context).calendarLabelText), shape: Border( bottom: BorderSide( color: const Color(0xFFF4F5F8), @@ -237,7 +238,7 @@ class _TableEventsState extends State { ) ), actions: [ - + if ( _loading == true ) Center( child: Padding( @@ -255,7 +256,7 @@ class _TableEventsState extends State { // endif IconButton( icon: const Icon(Icons.add_circle_outline), - tooltip: 'New Booking', + tooltip: AppLocalizations.of(context).newBookingTooltipText, onPressed: () async { await Navigator.push(context, MaterialPageRoute ( builder: (BuildContext context) { @@ -269,7 +270,7 @@ class _TableEventsState extends State { ), IconButton( icon: const Icon(Icons.sync), - tooltip: 'Refresh', + tooltip: AppLocalizations.of(context).refreshTootlipText, onPressed: () { setState(() { _selectedDay = null; @@ -283,7 +284,7 @@ class _TableEventsState extends State { children: [ IconButton( icon: const Icon(Icons.filter_list), - tooltip: 'Filter', + tooltip: AppLocalizations.of(context).filterTootlipText, onPressed: () async { await Navigator.push(context, MaterialPageRoute ( builder: (BuildContext context) { @@ -299,7 +300,7 @@ class _TableEventsState extends State { _selectedDay = null; _selectedEvents.value = []; }); - + _dataProvider.clear(); _getData(); } @@ -530,13 +531,13 @@ class _TableEventsState extends State { } } - + Widget _buildEventsMarker(DateTime date, DateTime focusedDay, List events) { return Container( decoration: BoxDecoration( shape: BoxShape.rectangle, borderRadius: BorderRadius.circular(10), - color: + color: focusedDay.month != date.month ? Colors.grey.shade600 : DateUtils.dateOnly( DateTime.now() ).isBefore( date ) ? Colors.indigo : Colors.black, ), diff --git a/lib/screens/calendar/booking_list_item.dart b/lib/screens/calendar/booking_list_item.dart index ac33e2c..6c1b568 100644 --- a/lib/screens/calendar/booking_list_item.dart +++ b/lib/screens/calendar/booking_list_item.dart @@ -5,6 +5,7 @@ import 'package:mphb_app/screens/common/booking_date.dart'; import 'package:mphb_app/models/booking.dart'; import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; import 'package:mphb_app/models/enum/booking_status.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class BookingListItem extends StatefulWidget { @@ -180,7 +181,7 @@ class _BookingListItemState extends State { ) ), Text( - 'External', + AppLocalizations.of(context).externalText, style: TextStyle( fontSize: 12, ), @@ -211,7 +212,7 @@ class _BookingListItemState extends State { if ( booking.reserved_accommodations.length > 0 && booking.getAccommodationByID( booking.reserved_accommodations[0].accommodation ) != null ) ...[ - + Padding( padding: EdgeInsets.only(right: 3.0, left: 8.0), child: Icon( diff --git a/lib/screens/calendar/calendar_filter.dart b/lib/screens/calendar/calendar_filter.dart index 135995b..e779e2d 100644 --- a/lib/screens/calendar/calendar_filter.dart +++ b/lib/screens/calendar/calendar_filter.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:mphb_app/models/calendar_filters.dart'; import 'package:mphb_app/models/enum/booking_status.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class CalendarFilter extends StatefulWidget { @@ -25,18 +26,20 @@ class _CalendarFilterState extends State { Calendar_Filters calendar_filters; - final List _bookingStatusesOptions = [ - const {'label': 'Confirmed', 'value': BookingStatusEnum.CONFIRMED}, - const {'label': 'Cancelled', 'value': BookingStatusEnum.CANCELLED}, - const {'label': 'Abandoned', 'value': BookingStatusEnum.ABANDONED}, - const {'label': 'Pending Admin', 'value': BookingStatusEnum.PENDING}, - const {'label': 'Pending User', 'value': BookingStatusEnum.PENDING_USER}, - const {'label': 'Pending Payment', 'value': BookingStatusEnum.PENDING_PAYMENT}, - ]; + static List _bookingStatusesOptions(BuildContext context) { + return [ + {'label': AppLocalizations.of(context).bookingConfirmedOptionText, 'value': BookingStatusEnum.CONFIRMED}, + {'label': AppLocalizations.of(context).bookingCanceledOptionText, 'value': BookingStatusEnum.CANCELLED}, + {'label': AppLocalizations.of(context).bookingAbandonedOptionText, 'value': BookingStatusEnum.ABANDONED}, + {'label': AppLocalizations.of(context).bookingPendingAdminOptionText, 'value': BookingStatusEnum.PENDING}, + {'label': AppLocalizations.of(context).bookingPendingUserOptionText, 'value': BookingStatusEnum.PENDING_USER}, + {'label': AppLocalizations.of(context).bookingPendingPaymentOptionText, 'value': BookingStatusEnum.PENDING_PAYMENT}, + ]; + } Iterable get bookingStatusesFilter sync* { - for (final status in _bookingStatusesOptions) { + for (final status in _bookingStatusesOptions(context)) { yield Padding( padding: const EdgeInsets.all(4.0), child: FilterChip( @@ -74,13 +77,13 @@ class _CalendarFilterState extends State { child: Scaffold( backgroundColor: const Color(0xFFF4F5F8), appBar: AppBar( - title: const Text('Filters'), + title: Text(AppLocalizations.of(context).filtersTitleText), actions: [ Padding( padding: EdgeInsets.all(10.0), child: TextButton( onPressed: reset, - child: const Text('Reset'), + child: Text(AppLocalizations.of(context).resetButtonText), style: TextButton.styleFrom( primary: Colors.black, ), @@ -103,7 +106,7 @@ class _CalendarFilterState extends State { children: [ Padding( padding: const EdgeInsets.only(bottom: 10.0), - child: Text('Booking Status:'), + child: Text(AppLocalizations.of(context).bookingStatusLabelText + ':'), ), Wrap( children: bookingStatusesFilter.toList(), @@ -115,7 +118,7 @@ class _CalendarFilterState extends State { Container( margin: const EdgeInsets.only(top: 20.0), child: SwitchListTile( - title: const Text('Display external bookings'), + title: Text(AppLocalizations.of(context).displayExternalBookingsLabelText), value: calendar_filters.show_imported, onChanged: (bool value) { setState(() { diff --git a/lib/screens/form.dart b/lib/screens/form.dart index 82e49a4..0ae180c 100644 --- a/lib/screens/form.dart +++ b/lib/screens/form.dart @@ -6,9 +6,9 @@ import 'package:package_info_plus/package_info_plus.dart'; import 'package:mphb_app/models/form_model.dart'; import 'package:mphb_app/screens/scanner.dart'; import 'package:mphb_app/local_storage.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class LoginForm extends StatefulWidget { - const LoginForm({Key? key}) : super(key: key); @override @@ -16,9 +16,8 @@ class LoginForm extends StatefulWidget { } class _LoginFormState extends State { - final _formKey = GlobalKey(); - + final model = FormModel(); final domainController = TextEditingController(); @@ -33,10 +32,6 @@ class _LoginFormState extends State { buildSignature: 'Unknown', ); - String _textInstructions = - 'Navigate to Accommodation \u{2192} Settings \u{2192} Advanced to generate API keys and scan QR code. ' - 'Or enter your data in the form below.'; - @override void initState() { super.initState(); @@ -51,49 +46,42 @@ class _LoginFormState extends State { } void qr_code_scanner() async { - /* * Web issue * https://github.com/juliuscanute/qr_code_scanner/issues/441 - */ + */ await Navigator.push( context, MaterialPageRoute(builder: (context) => Scanner()), ).then((formModel) { - - if ( formModel.isEmpty ) { - + if (formModel.isEmpty) { ScaffoldMessenger.of(context).clearSnackBars(); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - backgroundColor: Colors.red, - content: Text( 'QR code is not valid.' ), - ) - ); + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + backgroundColor: Colors.red, + content: Text(AppLocalizations.of(context).invalidQRCodeMessage), + )); } domainController.text = formModel.domain; keyController.text = formModel.consumer_key; secretController.text = formModel.consumer_secret; }); - } - void login () { + void login() { // Validate returns true if the form is valid, or false otherwise. if (_formKey.currentState!.validate()) { - _formKey.currentState!.save(); // trim slash - if ( model.domain.endsWith('/') ) { + if (model.domain.endsWith('/')) { model.domain = model.domain.substring(0, model.domain.length - 1); } /* * https://developer.wordpress.org/rest-api/extending-the-rest-api/routes-and-endpoints/ - * + * * 1. All routes should be built onto this route, the wp-json portion can be changed, * but in general, it is advised to keep it the same. * 2. On sites without pretty permalinks, the route is instead added to the URL as the @@ -101,29 +89,23 @@ class _LoginFormState extends State { * http://example.com/?rest_route=/wp/v2/posts/123 */ - //TODO: make it better - if ( model.domain.endsWith( '/wp-json/mphb/v1' ) ) { - + //TODO: make it better + if (model.domain.endsWith('/wp-json/mphb/v1')) { LocalStorage().domain = model.domain; - } else { - LocalStorage().domain = model.domain + '/wp-json/mphb/v1'; } - //TODO: use secure storage LocalStorage().consumer_key = model.consumer_key; LocalStorage().consumer_secret = model.consumer_secret; - + Navigator.pushReplacementNamed(context, '/home'); } } @override Widget build(BuildContext context) { - - final ColorScheme colorScheme = Theme.of(context).colorScheme; final TextTheme textTheme = Theme.of(context).textTheme; final bodyTextStyle = textTheme.bodyText2!.apply( @@ -134,42 +116,33 @@ class _LoginFormState extends State { body: Center( child: SingleChildScrollView( child: Container( - padding: const EdgeInsets.only( - left: 20.0, right: 20.0, top: 30.0, bottom: 30.0), + left: 20.0, right: 20.0, top: 30.0, bottom: 30.0), child: Column( - - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - - children: [ - Container( - padding: EdgeInsets.only( - left: 20.0, right: 20.0, top: 30.0, bottom: 30.0), - - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all( - Radius.circular(6) + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + padding: EdgeInsets.only( + left: 20.0, right: 20.0, top: 30.0, bottom: 30.0), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(6)), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.15), + spreadRadius: 4, + blurRadius: 16, + offset: Offset(0, 10), + ), + ], ), - boxShadow: [ - BoxShadow( - color: Colors.grey.withOpacity(0.15), - spreadRadius: 4, - blurRadius: 16, - offset: Offset(0, 10), - ), - ], - ), - - child: Column( - children: [ - + child: Column(children: [ ElevatedButton.icon( onPressed: () => qr_code_scanner(), icon: Icon(Icons.qr_code_scanner), label: Text( - "Scan QR Code", + AppLocalizations.of(context).scanQRCodeButtonText, style: const TextStyle(fontSize: 16), ), style: ElevatedButton.styleFrom( @@ -178,30 +151,28 @@ class _LoginFormState extends State { minimumSize: Size(double.infinity, 0), ), ), - SizedBox(height: 20.0), - Text( - _textInstructions, + // _textInstructions, + AppLocalizations.of(context).textInstructions, style: const TextStyle(fontSize: 12), textAlign: TextAlign.center, ), SizedBox(height: 15.0), - Form( key: _formKey, child: Column( children: [ TextFormField( controller: domainController, - decoration: const InputDecoration( + decoration: InputDecoration( hintText: 'https://mywebsite.com', - labelText: 'Domain', + labelText: AppLocalizations.of(context).domainLabelText, border: OutlineInputBorder(), ), validator: (value) { if (value == null || value.isEmpty) { - return 'Please enter Domain'; + return AppLocalizations.of(context).domainValidatorMessage; } return null; }, @@ -212,14 +183,14 @@ class _LoginFormState extends State { SizedBox(height: 10), TextFormField( controller: keyController, - decoration: const InputDecoration( + decoration: InputDecoration( hintText: 'ck_xxxxxxxxxx', - labelText: 'Key', + labelText: AppLocalizations.of(context).keyLabelText, border: OutlineInputBorder(), ), validator: (value) { if (value == null || value.isEmpty) { - return 'Please enter Key'; + return AppLocalizations.of(context).keyValidatorMessage; } return null; }, @@ -230,15 +201,15 @@ class _LoginFormState extends State { SizedBox(height: 10), TextFormField( controller: secretController, - decoration: const InputDecoration( + decoration: InputDecoration( hintText: 'cs_xxxxxxxxxx', - labelText: 'Secret', + labelText: AppLocalizations.of(context).secretLabelText, border: OutlineInputBorder(), ), obscureText: true, validator: (value) { if (value == null || value.isEmpty) { - return 'Please enter Secret'; + return AppLocalizations.of(context).secretValidatorMessage; } return null; }, @@ -253,55 +224,55 @@ class _LoginFormState extends State { padding: EdgeInsets.all(15), ), onPressed: login, - child: const Text( - 'Submit', + child: Text( + AppLocalizations.of(context).submitButtonText, ), ), ], ), ), - ] + ]), ), - ), - + SizedBox(height: 25.0), SizedBox(height: 25.0), - SelectableText.rich( - TextSpan( - children: [ - TextSpan( - style: bodyTextStyle, - text: '${_packageInfo.appName} application by ', - ), - TextSpan( - text: 'MotoPress', - style: bodyTextStyle.copyWith( - color: colorScheme.primary, + SizedBox(height: 25.0), + + + SelectableText.rich( + TextSpan( + children: [ + TextSpan( + style: bodyTextStyle, + text: '${_packageInfo.appName} application by ', ), - recognizer: TapGestureRecognizer() - ..onTap = () async { - final url = 'https://motopress.com'; - if (await canLaunch(url)) { - await launch( - url, - forceSafariVC: false, - ); - } - }, - ), - ], + TextSpan( + text: 'MotoPress', + style: bodyTextStyle.copyWith( + color: colorScheme.primary, + ), + recognizer: TapGestureRecognizer() + ..onTap = () async { + final url = 'https://motopress.com'; + if (await canLaunch(url)) { + await launch( + url, + forceSafariVC: false, + ); + } + }, + ), + ], + ), ), - ), - - SizedBox(height: 5.0), - Text( - 'Version: ${_packageInfo.version} build ${_packageInfo.buildNumber}', - style: const TextStyle(fontSize: 11), - textAlign: TextAlign.center, - ), - ] - ), + SizedBox(height: 5.0), + Text( + 'Version: ${_packageInfo.version} build ${_packageInfo.buildNumber}', + style: const TextStyle(fontSize: 11), + textAlign: TextAlign.center, + ), + ]), ), ), ), diff --git a/lib/screens/home.dart b/lib/screens/home.dart index be9dc00..7c23850 100644 --- a/lib/screens/home.dart +++ b/lib/screens/home.dart @@ -4,9 +4,10 @@ import 'package:mphb_app/screens/calendar.dart'; import 'package:mphb_app/screens/bookings.dart'; import 'package:mphb_app/screens/payments.dart'; import 'package:mphb_app/screens/settings.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class HomePage extends StatefulWidget { - + const HomePage({Key? key}) : super(key: key); @override @@ -46,26 +47,26 @@ class _HomePageState extends State { showUnselectedLabels: false, unselectedFontSize: 0.0, //fix for Failed assertion error. selectedFontSize: 0.0, - items: const [ + items: [ BottomNavigationBarItem( icon: Icon(Icons.event_outlined), activeIcon: Icon(Icons.event), - label: 'Calendar', + label: AppLocalizations.of(context).calendarLabelText, ), BottomNavigationBarItem( icon: Icon(Icons.source_outlined), activeIcon: Icon(Icons.source), - label: 'Bookings', + label: AppLocalizations.of(context).bookingsLabelText, ), BottomNavigationBarItem( icon: Icon(Icons.payments_outlined), activeIcon: Icon(Icons.payments), - label: 'Payments', + label: AppLocalizations.of(context).paymentsLabelText, ), BottomNavigationBarItem( icon: Icon(Icons.manage_accounts_outlined), activeIcon: Icon(Icons.manage_accounts), - label: 'Settings', + label: AppLocalizations.of(context).settingsLabelText, ), ], currentIndex: _selectedIndex, diff --git a/lib/screens/payment_detail/payment_detail.dart b/lib/screens/payment_detail/payment_detail.dart index 69dd458..fe5f3c0 100644 --- a/lib/screens/payment_detail/payment_detail.dart +++ b/lib/screens/payment_detail/payment_detail.dart @@ -7,6 +7,7 @@ import 'package:mphb_app/screens/payment_detail/payment_detail_booking.dart'; import 'package:mphb_app/screens/payment_detail/payment_detail_gateway.dart'; import 'package:mphb_app/screens/booking_detail/booking_detail_customer.dart'; import 'package:mphb_app/screens/payment_detail/payment_detail_actions.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class PaymentDetailScreen extends StatefulWidget { @@ -109,11 +110,11 @@ class _PaymentDetailScreenState extends State { return WillPopScope( child: Scaffold( appBar: AppBar( - title: Text( 'Payment #$paymentID' ), + title: Text(AppLocalizations.of(context).paymentText + ' #$paymentID'), actions: [ IconButton( icon: const Icon(Icons.sync), - tooltip: 'Refresh', + tooltip: AppLocalizations.of(context).refreshTootlipText, onPressed: () { setState(() { _paymentFuture = _getPayment( paymentID ); @@ -145,7 +146,7 @@ class _PaymentDetailScreenState extends State { return IconButton( icon: const Icon(Icons.more_vert), - tooltip: 'Actions', + tooltip: AppLocalizations.of(context).actionsTooltipText, onPressed: () => _showModalBottomSheet( context, payment ), ); } @@ -160,7 +161,7 @@ class _PaymentDetailScreenState extends State { if (snapshot.hasError) { - return new Text('Error: ${snapshot.error}'); + return new Text(AppLocalizations.of(context).errorText + ': ${snapshot.error}'); } else { Payment payment = snapshot.data; diff --git a/lib/screens/payment_detail/payment_detail_actions.dart b/lib/screens/payment_detail/payment_detail_actions.dart index 464108a..027cb8f 100644 --- a/lib/screens/payment_detail/payment_detail_actions.dart +++ b/lib/screens/payment_detail/payment_detail_actions.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:mphb_app/models/payment.dart'; import 'package:mphb_app/models/enum/payment_status.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class PaymentDetailActions extends StatelessWidget { @@ -15,42 +16,42 @@ class PaymentDetailActions extends StatelessWidget { children: [ ListTile( leading: Icon(Icons.done), - title: Text('Set to Completed'), + title: Text(AppLocalizations.of(context).paymentSetToCompletedButtonText), onTap: () { Navigator.pop(context, PaymentStatusEnum.COMPLETED); }, ), ListTile( leading: Icon(Icons.block), - title: Text('Set to Cancelled'), + title: Text(AppLocalizations.of(context).paymentSetToCanceledButtonText), onTap: () { Navigator.pop(context, PaymentStatusEnum.CANCELLED); }, ), ListTile( leading: Icon(Icons.hourglass_empty), - title: Text('Set to On Hold'), + title: Text(AppLocalizations.of(context).paymentSetToOnHoldButtonText), onTap: () { Navigator.pop(context, PaymentStatusEnum.ON_HOLD); }, ), ListTile( leading: Icon(Icons.hourglass_empty), - title: Text('Set to Pending'), + title: Text(AppLocalizations.of(context).paymentSetToPendingButtonText), onTap: () { Navigator.pop(context, PaymentStatusEnum.PENDING); }, ), ListTile( leading: Icon(Icons.block), - title: Text('Set to Failed'), + title: Text(AppLocalizations.of(context).paymentSetToFailedButtonText), onTap: () { Navigator.pop(context, PaymentStatusEnum.FAILED); }, ), ListTile( leading: Icon(Icons.block), - title: Text('Set to Refunded'), + title: Text(AppLocalizations.of(context).paymentSetToRefundedButtonText), onTap: () { Navigator.pop(context, PaymentStatusEnum.REFUNDED); }, diff --git a/lib/screens/payment_detail/payment_detail_booking.dart b/lib/screens/payment_detail/payment_detail_booking.dart index d143766..c54f2e4 100644 --- a/lib/screens/payment_detail/payment_detail_booking.dart +++ b/lib/screens/payment_detail/payment_detail_booking.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:mphb_app/models/payment.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class PaymentDetailBooking extends StatelessWidget { @@ -41,7 +42,7 @@ class PaymentDetailBooking extends StatelessWidget { Padding ( padding: EdgeInsets.only(top: 5.0), child: Text( - 'Booking', + AppLocalizations.of(context).bookingLabelText, style: TextStyle(fontSize: 12), ), ), diff --git a/lib/screens/payment_detail/payment_detail_gateway.dart b/lib/screens/payment_detail/payment_detail_gateway.dart index bb6e4f4..5ad8ffc 100644 --- a/lib/screens/payment_detail/payment_detail_gateway.dart +++ b/lib/screens/payment_detail/payment_detail_gateway.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:mphb_app/models/payment.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class PaymentDetailGateway extends StatelessWidget { @@ -61,14 +62,14 @@ class PaymentDetailGateway extends StatelessWidget { IconButton( icon: const Icon(Icons.content_copy), iconSize: 14, - tooltip: 'Copy', + tooltip: AppLocalizations.of(context).copyTooltipText, onPressed: () { Clipboard.setData( ClipboardData(text: payment.transaction_id)) .then((_) { final snackBar = SnackBar( content: Text( - '${payment.transaction_id} copied' + '${payment.transaction_id} ' + AppLocalizations.of(context).copiedLabelText ) ); diff --git a/lib/screens/payment_detail/payment_detail_status.dart b/lib/screens/payment_detail/payment_detail_status.dart index ec2f7ad..6be5b1b 100644 --- a/lib/screens/payment_detail/payment_detail_status.dart +++ b/lib/screens/payment_detail/payment_detail_status.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:mphb_app/models/payment.dart'; import 'package:mphb_app/models/enum/payment_status.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class PaymentDetailStatus extends StatelessWidget { @@ -21,7 +22,7 @@ class PaymentDetailStatus extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - 'Payment #' + payment.id.toString(), + AppLocalizations.of(context).paymentText + ' #' + payment.id.toString(), style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ), Padding ( diff --git a/lib/screens/payments.dart b/lib/screens/payments.dart index 0fc2746..477b013 100644 --- a/lib/screens/payments.dart +++ b/lib/screens/payments.dart @@ -6,6 +6,7 @@ import 'package:mphb_app/models/payment.dart'; import 'package:mphb_app/models/payments_filters.dart'; import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; import 'package:mphb_app/screens/bookings/character_search_input_sliver.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class PaymentsPage extends StatefulWidget { @override @@ -68,7 +69,7 @@ class _PaymentsListViewState extends State { return Scaffold( appBar: AppBar( - title: Text('Payments'), + title: Text(AppLocalizations.of(context).paymentsLabelText), shape: Border( bottom: BorderSide( color: const Color(0xFFF4F5F8), @@ -78,7 +79,7 @@ class _PaymentsListViewState extends State { actions: [ IconButton( icon: const Icon(Icons.sync), - tooltip: 'Refresh', + tooltip: AppLocalizations.of(context).refreshTootlipText, onPressed: () { _pagingController.refresh(); }, @@ -88,7 +89,7 @@ class _PaymentsListViewState extends State { children: [ IconButton( icon: const Icon(Icons.filter_list), - tooltip: 'Filter', + tooltip: AppLocalizations.of(context).filterTootlipText, onPressed: () async { await Navigator.push(context, MaterialPageRoute ( builder: (BuildContext context) { @@ -155,7 +156,7 @@ class _PaymentsListViewState extends State { key: ObjectKey(item), ), noItemsFoundIndicatorBuilder: (context) => - Center( child: Text('Nothing Found') ), + Center( child: Text(AppLocalizations.of(context).nothingFoundText) ), firstPageErrorIndicatorBuilder: (context) => Center( child: Text(_pagingController.error.toString()) ), diff --git a/lib/screens/payments/payments_filter.dart b/lib/screens/payments/payments_filter.dart index 89bacb5..b6ded0a 100644 --- a/lib/screens/payments/payments_filter.dart +++ b/lib/screens/payments/payments_filter.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:mphb_app/models/payments_filters.dart'; import 'package:mphb_app/models/enum/date_range.dart'; import 'package:mphb_app/models/enum/payment_status.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class PaymentsFilter extends StatefulWidget { @@ -26,24 +27,28 @@ class _PaymentsFilterState extends State { Payments_Filters payments_filters; - final List _paymentStatusesOptions = [ - const {'label': 'Completed', 'value': PaymentStatusEnum.COMPLETED}, - const {'label': 'Cancelled', 'value': PaymentStatusEnum.CANCELLED}, - const {'label': 'Abandoned', 'value': PaymentStatusEnum.ABANDONED}, - const {'label': 'Pending', 'value': PaymentStatusEnum.PENDING}, - const {'label': 'Failed', 'value': PaymentStatusEnum.FAILED}, - const {'label': 'Refunded', 'value': PaymentStatusEnum.REFUNDED}, - const {'label': 'On Hold', 'value': PaymentStatusEnum.ON_HOLD}, - ]; - - final List _paymentDateRangeOptions = [ - const {'label': 'Today', 'value': DateRangeEnum.TODAY}, - const {'label': 'This Week', 'value': DateRangeEnum.THIS_WEEK}, - const {'label': 'This Month', 'value': DateRangeEnum.THIS_MONTH}, - ]; + static List _paymentStatusesOptions(BuildContext context) { + return [ + {'label': AppLocalizations.of(context).paymentCompletedOptionText, 'value': PaymentStatusEnum.COMPLETED}, + {'label': AppLocalizations.of(context).paymentCanceledOptionText, 'value': PaymentStatusEnum.CANCELLED}, + {'label': AppLocalizations.of(context).paymentAbandonedOptionText, 'value': PaymentStatusEnum.ABANDONED}, + {'label': AppLocalizations.of(context).paymentPendingOptionText, 'value': PaymentStatusEnum.PENDING}, + {'label': AppLocalizations.of(context).paymentFailedOptionText, 'value': PaymentStatusEnum.FAILED}, + {'label': AppLocalizations.of(context).paymentRefundedOptionText, 'value': PaymentStatusEnum.REFUNDED}, + {'label': AppLocalizations.of(context).paymentOnHoldOptionText, 'value': PaymentStatusEnum.ON_HOLD}, + ]; + } + + static List _paymentDateRangeOptions(BuildContext context) { + return [ + {'label': AppLocalizations.of(context).todayOptionText, 'value': DateRangeEnum.TODAY}, + {'label': AppLocalizations.of(context).thisWeekOptionText, 'value': DateRangeEnum.THIS_WEEK}, + {'label': AppLocalizations.of(context).thisMonthOptionText, 'value': DateRangeEnum.THIS_MONTH}, + ]; + } Iterable get paymentStatusesFilter sync* { - for (final status in _paymentStatusesOptions) { + for (final status in _paymentStatusesOptions(context)) { yield Padding( padding: const EdgeInsets.all(4.0), child: FilterChip( @@ -68,7 +73,7 @@ class _PaymentsFilterState extends State { } Iterable get paymentDateRangeFilter sync* { - for (final range in _paymentDateRangeOptions) { + for (final range in _paymentDateRangeOptions(context)) { yield Padding( padding: const EdgeInsets.all(4.0), child: ChoiceChip( @@ -101,13 +106,13 @@ class _PaymentsFilterState extends State { child: Scaffold( backgroundColor: const Color(0xFFF4F5F8), appBar: AppBar( - title: const Text('Filters'), + title: Text(AppLocalizations.of(context).filtersTitleText), actions: [ Padding( padding: EdgeInsets.all(10.0), child: TextButton( onPressed: reset, - child: const Text('Reset'), + child: Text(AppLocalizations.of(context).resetButtonText), style: TextButton.styleFrom( primary: Colors.black, ), @@ -130,7 +135,7 @@ class _PaymentsFilterState extends State { children: [ Padding( padding: const EdgeInsets.only(bottom: 10.0), - child: Text('Payment Status:'), + child: Text(AppLocalizations.of(context).paymentStatusLabelText + ':'), ), Wrap( children: paymentStatusesFilter.toList(), @@ -146,7 +151,7 @@ class _PaymentsFilterState extends State { children: [ Padding( padding: const EdgeInsets.only(bottom: 10.0), - child: Text('Date Created:'), + child: Text(AppLocalizations.of(context).dateCreatedLabelText + ':') ), Wrap( children: paymentDateRangeFilter.toList(), diff --git a/lib/screens/scanner.dart b/lib/screens/scanner.dart index a784e5f..8aae9d6 100644 --- a/lib/screens/scanner.dart +++ b/lib/screens/scanner.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'dart:io'; import 'package:qr_code_scanner/qr_code_scanner.dart'; import 'package:mphb_app/models/form_model.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class Scanner extends StatefulWidget { @override @@ -44,7 +45,7 @@ class _ScannerState extends State { return Scaffold( appBar: AppBar( - title: Text("Scan a code"), + title: Text(AppLocalizations.of(context).scanQRCodeButtonText), ), body: QRView( key: qrKey, @@ -80,7 +81,7 @@ class _ScannerState extends State { try { - formModel = FormModel.fromRawData(rawData ?? ''); + formModel = FormModel.fromRawData(rawData ?? ''); } on Exception catch (e) {} diff --git a/lib/screens/settings.dart b/lib/screens/settings.dart index a0d0c1d..98f52db 100644 --- a/lib/screens/settings.dart +++ b/lib/screens/settings.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:mphb_app/local_storage.dart'; import 'package:package_info_plus/package_info_plus.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class SettingsPage extends StatefulWidget { @@ -38,13 +39,13 @@ class _SettingsPageState extends State { // set up the buttons Widget cancelButton = TextButton( - child: Text("Cancel"), + child: Text(AppLocalizations.of(context).cancelButttonText), onPressed: () { Navigator.of(context).pop(); // dismiss dialog }, ); Widget continueButton = TextButton( - child: Text("Log out"), + child: Text(AppLocalizations.of(context).logoutButtonText), onPressed: () { LocalStorage().clear(); Navigator.pushNamedAndRemoveUntil(context, '/login', (_) => false); @@ -53,7 +54,7 @@ class _SettingsPageState extends State { // set up the AlertDialog AlertDialog alert = AlertDialog( - title: Text("Are you sure you want to log out?"), + title: Text(AppLocalizations.of(context).confirmLogoutMessage), actions: [ cancelButton, continueButton, @@ -74,7 +75,7 @@ class _SettingsPageState extends State { return Scaffold( appBar: AppBar( - title: const Text('Settings'), + title: Text(AppLocalizations.of(context).settingsLabelText), shape: Border( bottom: BorderSide( color: const Color(0xFFF4F5F8), @@ -95,7 +96,7 @@ class _SettingsPageState extends State { ), SizedBox(height: 10.0), Text( - 'Consumer key ending in: ' + + AppLocalizations.of(context).consumerKeyEndingInLabelText + ': ' + LocalStorage().consumer_key.substring( LocalStorage().consumer_key.length - 7), ), @@ -110,7 +111,7 @@ class _SettingsPageState extends State { onPressed: () { _showAlertDialog(context); }, - child: Text("Log out"), + child: Text(AppLocalizations.of(context).logoutButtonText), ), ] ), diff --git a/pubspec.lock b/pubspec.lock index bee1acf..d408215 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -376,6 +376,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.1" + sprintf: + dependency: "direct main" + description: + name: sprintf + url: "https://pub.dartlang.org" + source: hosted + version: "7.0.0" stack_trace: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 55b518e..337b87e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -47,6 +47,7 @@ dependencies: rxdart: ^0.27.3 table_calendar: ^3.0.7 lazy_load_indexed_stack: ^0.1.4 + sprintf: ^7.0.0 dev_dependencies: flutter_test: @@ -101,6 +102,8 @@ flutter: # For details regarding fonts from package dependencies, # see https://flutter.dev/custom-fonts/#from-packages + generate: true + flutter_icons: image_path_android: "assets/icons/icon.png" image_path_ios: "assets/icons/icon.png" From 46fe8c66d0d25154d5548f50819585967bb278f3 Mon Sep 17 00:00:00 2001 From: mototeam Date: Fri, 14 Jul 2023 00:25:24 +0300 Subject: [PATCH 2/5] l10n --- lib/l10n/app_de.arb | 103 ++++++++++++++++++ lib/l10n/app_en.arb | 5 +- lib/l10n/app_es.arb | 103 ++++++++++++++++++ lib/l10n/app_fr.arb | 7 +- lib/l10n/app_it.arb | 103 ++++++++++++++++++ lib/l10n/app_uk.arb | 103 ++++++++++++++++++ lib/main.dart | 4 + .../create/search_availability_form.dart | 2 +- lib/screens/calendar.dart | 6 + 9 files changed, 432 insertions(+), 4 deletions(-) create mode 100644 lib/l10n/app_de.arb create mode 100644 lib/l10n/app_es.arb create mode 100644 lib/l10n/app_it.arb create mode 100644 lib/l10n/app_uk.arb diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb new file mode 100644 index 0000000..00b062d --- /dev/null +++ b/lib/l10n/app_de.arb @@ -0,0 +1,103 @@ +{ + "@@locale": "de", + "textInstructions": "Navigieren Sie zu Unterkunft → Einstellungen → Erweitert um API-Schlüssel zu generieren und QR-Code zu scannen oder geben Sie Ihre Daten in das untenstehende Formular ein.", + "scanQRCodeButtonText": "Scan QR code", + "invalidQRCodeMessage": "QR-Code ist nicht gültig.", + "domainLabelText": "Domäne", + "domainValidatorMessage": "Bitte Domain eingeben", + "keyLabelText": "Schlüssel", + "keyValidatorMessage": "Bitte geben Sie den Schlüssel ein", + "secretLabelText": "Geheimnis", + "secretValidatorMessage": "Bitte Geheimnis eingeben", + "submitButtonText": "Übermitteln", + "calendarLabelText": "Kalender", + "bookingsLabelText": "Buchungen", + "paymentsLabelText": "Zahlungen", + "settingsLabelText": "Einstellungen", + "refreshTootlipText": "Aktualisieren", + "filterTootlipText": "Filtern", + "nothingFoundText": "Nichts gefunden", + "newBookingTooltipText": "Neue Buchung", + "cancelButttonText": "Stornieren", + "logoutButtonText": "Abmelden", + "confirmLogoutMessage": "Sind Sie sicher, dass Sie sich abmelden möchten?", + "consumerKeyEndingInLabelText": "Verbraucherschlüssel läuft ab in", + "adultsLabelText": "Erwachsene", + "childrenLabelText": "Kinder", + "rateLabelText": "Tarif", + "servicesLabelText": "Dienstleistungen", + "bookingSetToConfirmedButtonText": "Bestätigt", + "bookingSetToCanceledButtonText": "Auf Abbruch setzen", + "bookingSetToPendingAdminButtonText": "Auf ausstehender Admin setzen", + "bookingSetToPendingUserConfirmationButtonText": "Auf Ausstehende Benutzerbestätigung setzen", + "bookingSetToPendingPaymentButtonText": "Auf Ausstehende Zahlung setzen", + "deleteButtonText": "Löschen", + "notSetLabelText": "nicht gesetzt", + "copiedLabelText": "kopiert", + "copyTooltipText": "Kopieren", + "totalLabelText": "Gesamt", + "paidLabelText": "Bezahlt", + "toPayLabelText": "Bezahlen", + "couponCodeUsedLabelText": "Gutscheincode verwendet", + "guestsText": "gast(e)", + "timesText": "Mal", + "onceText": "Einmal", + "dailyText": "Täglich", + "bookingDeletedMessage": "Buchung %d gelöscht", + "bookingLabelText": "Buchung", + "actionsTooltipText": "Aktionen", + "errorText": "Fehler", + "reservationText": "Reservierung", + "customerNoteText": "Notizen des Kunden", + "internalNotesText": "Interne Notizen", + "customerInformationText": "Kundeninformationen", + "firstnameLabelText": "Vorname", + "lastnameLabelText": "Nachname", + "emailLabelText": "E-Mail", + "phoneLabelText": "Telefon", + "bookingCreatedMessage": "Buchung %d erstellt", + "basePriceText": "Basispreis", + "addBookingTitleText": "Buchung hinzufügen", + "invalidRouteText": "Ungültige Route", + "continueButtonText": "Weiter", + "bookNowButtonText": "Jetzt buchen", + "quitButtonText": "Beenden", + "checkInLabelText": "Anreise", + "checkOutLabelText": "Abreise", + "dateValidatorMessage": "Bitte Datum eingeben", + "searchButtonText": "Suche", + "externalText": "Extern", + "bookingConfirmedOptionText": "Bestätigt", + "bookingCanceledOptionText": "Abgebrochen", + "bookingAbandonedOptionText": "Aufgegeben", + "bookingPendingAdminOptionText": "Ausstehender Administrator", + "bookingPendingUserOptionText": "Ausstehender Benutzer", + "bookingPendingPaymentOptionText": "Ausstehende Zahlung", + "todayOptionText": "Heute", + "thisWeekOptionText": "Diese Woche", + "thisMonthOptionText": "Diesen Monat", + "filtersTitleText": "Filter", + "resetButtonText": "Zurücksetzen", + "bookingStatusLabelText": "Buchungsstatus", + "dateCreatedLabelText": "Erstellungsdatum", + "searchHintText": "suchen...", + "displayExternalBookingsLabelText": "Zeige externe Buchungen", + "paymentCompletedOptionText": "Abgeschlossen", + "paymentCanceledOptionText": "Abgebrochen", + "paymentAbandonedOptionText": "Aufgegeben", + "paymentPendingOptionText": "Ausstehend", + "paymentFailedOptionText": "Fehlgeschlagen", + "paymentRefundedOptionText": "Zurückerstattet", + "paymentOnHoldOptionText": "In der Warteschleife", + "paymentStatusLabelText": "Zahlungsstatus", + "paymentSetToCompletedButtonText": "Erledigte", + "paymentSetToCanceledButtonText": "Auf Abbruch setzen", + "paymentSetToOnHoldButtonText": "Halten auf", + "paymentSetToPendingButtonText": "Auf Ausstehend setzen", + "paymentSetToFailedButtonText": "Fehlgeschlagen", + "paymentSetToRefundedButtonText": "Auf Erstattung setzen", + "paymentText": "Zahlung", + "calendarFormatMonth": "Monat", + "calendarFormatTwoWeeks": "2 Wochen", + "calendarFormatWeek": "Woche" +} \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index f7a2748..b612d35 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -96,5 +96,8 @@ "paymentSetToPendingButtonText": "Set to Pending", "paymentSetToFailedButtonText": "Set to Failed", "paymentSetToRefundedButtonText": "Set to Refunded", - "paymentText": "Payment" + "paymentText": "Payment", + "calendarFormatMonth": "Month", + "calendarFormatTwoWeeks": "2 weeks", + "calendarFormatWeek": "Week" } diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb new file mode 100644 index 0000000..0e018c5 --- /dev/null +++ b/lib/l10n/app_es.arb @@ -0,0 +1,103 @@ +{ + "@@locale": "es", + "textInstructions": "Vaya a Alojamiento → Configuración → Avanzado para generar claves API y escanear código QR. O introduzca sus datos en el formulario de abajo.", + "scanQRCodeButtonText": "Escanear código QR", + "invalidQRCodeMessage": "El código QR no es válido.", + "domainLabelText": "Dominio", + "domainValidatorMessage": "Por favor introduce un dominio", + "keyLabelText": "Clave", + "keyValidatorMessage": "Por favor, introduzca la clave", + "secretLabelText": "Secreto", + "secretValidatorMessage": "Por favor ingrese secreto", + "submitButtonText": "Enviar", + "calendarLabelText": "Calendario", + "bookingsLabelText": "Reservas", + "paymentsLabelText": "Pagos", + "settingsLabelText": "Configuración", + "refreshTootlipText": "Refrescar", + "filterTootlipText": "Filtro", + "nothingFoundText": "Nada encontrado", + "newBookingTooltipText": "Nueva reserva", + "cancelButttonText": "Cancelar", + "logoutButtonText": "Cerrar sesión", + "confirmLogoutMessage": "¿Estás seguro de que quieres cerrar sesión?", + "consumerKeyEndingInLabelText": "Clave de consumidor que termina en", + "adultsLabelText": "Adultos", + "childrenLabelText": "Niños", + "rateLabelText": "Tarifa", + "servicesLabelText": "Servicios", + "bookingSetToConfirmedButtonText": "Establecer como confirmado", + "bookingSetToCanceledButtonText": "Establecer a Cancelar", + "bookingSetToPendingAdminButtonText": "Establecer a Administrador Pendiente", + "bookingSetToPendingUserConfirmationButtonText": "Establecer a confirmación de usuario pendiente", + "bookingSetToPendingPaymentButtonText": "Establecer a Pago Pendiente", + "deleteButtonText": "Eliminar", + "notSetLabelText": "no establecido", + "copiedLabelText": "copiado", + "copyTooltipText": "Copiar", + "totalLabelText": "Total", + "paidLabelText": "Pagada", + "toPayLabelText": "A pagar", + "couponCodeUsedLabelText": "Código de cupón usado", + "guestsText": "invitado(s)", + "timesText": "vez/veces", + "onceText": "Una sola vez", + "dailyText": "Diario", + "bookingDeletedMessage": "Reserva %d eliminada", + "bookingLabelText": "Reserva", + "actionsTooltipText": "Acciones", + "errorText": "Error", + "reservationText": "Reserva", + "customerNoteText": "Nota de cliente", + "internalNotesText": "Notas internas", + "customerInformationText": "Información sobre cliente", + "firstnameLabelText": "Nombre", + "lastnameLabelText": "Apellido", + "emailLabelText": "Email", + "phoneLabelText": "Teléfono", + "bookingCreatedMessage": "Reservando %d creado", + "basePriceText": "Precio base", + "addBookingTitleText": "Añadir reserva", + "invalidRouteText": "Ruta no válida", + "continueButtonText": "Continuar", + "bookNowButtonText": "Reservar ahora", + "quitButtonText": "Salir", + "checkInLabelText": "Día de llegada", + "checkOutLabelText": "Día de salida", + "dateValidatorMessage": "Introduce la fecha", + "searchButtonText": "Búsqueda", + "externalText": "Externo", + "bookingConfirmedOptionText": "Confirmada", + "bookingCanceledOptionText": "Cancelado", + "bookingAbandonedOptionText": "Abandonada", + "bookingPendingAdminOptionText": "Requiere acción de admin", + "bookingPendingUserOptionText": "Usuario pendiente", + "bookingPendingPaymentOptionText": "Requiere pago", + "todayOptionText": "Hoy", + "thisWeekOptionText": "Esta semana", + "thisMonthOptionText": "Este mes", + "filtersTitleText": "Filtros", + "resetButtonText": "Reset", + "bookingStatusLabelText": "Estado de la reserva", + "dateCreatedLabelText": "Fecha de creación", + "searchHintText": "buscar...", + "displayExternalBookingsLabelText": "Mostrar reservas externas", + "paymentCompletedOptionText": "Completado", + "paymentCanceledOptionText": "Cancelado", + "paymentAbandonedOptionText": "Abandonada", + "paymentPendingOptionText": "Pendiente", + "paymentFailedOptionText": "Erróneo", + "paymentRefundedOptionText": "Reembolsado", + "paymentOnHoldOptionText": "En espera", + "paymentStatusLabelText": "Estado del pago", + "paymentSetToCompletedButtonText": "Establecer a Completado", + "paymentSetToCanceledButtonText": "Establecer a Cancelar", + "paymentSetToOnHoldButtonText": "Poner en espera", + "paymentSetToPendingButtonText": "Establecer a Pendiente", + "paymentSetToFailedButtonText": "Error al establecer", + "paymentSetToRefundedButtonText": "Establecer a reembolsado", + "paymentText": "Pago", + "calendarFormatMonth": "Mes", + "calendarFormatTwoWeeks": "2 semanas", + "calendarFormatWeek": "Semana" +} \ No newline at end of file diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index 5b601be..7190095 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -96,5 +96,8 @@ "paymentSetToPendingButtonText": "Définir en tant que: en attente", "paymentSetToFailedButtonText": "Définir en tant que: échoué", "paymentSetToRefundedButtonText": "Définir en tant que: remboursé", - "paymentText": "Paiement" -} + "paymentText": "Paiement", + "calendarFormatMonth": "Mois", + "calendarFormatTwoWeeks": "2 semaines", + "calendarFormatWeek": "Semaine" +} \ No newline at end of file diff --git a/lib/l10n/app_it.arb b/lib/l10n/app_it.arb new file mode 100644 index 0000000..272e5a5 --- /dev/null +++ b/lib/l10n/app_it.arb @@ -0,0 +1,103 @@ +{ + "@@locale": "it", + "textInstructions": "Vai a Sistemazione → Impostazioni → Avanzate per generare chiavi API e scansionare il codice QR. O inserisci i tuoi dati nel modulo sottostante.", + "scanQRCodeButtonText": "Scan QR code", + "invalidQRCodeMessage": "Il codice QR non è valido.", + "domainLabelText": "Dominio", + "domainValidatorMessage": "Inserisci il dominio", + "keyLabelText": "Chiave", + "keyValidatorMessage": "Inserisci la chiave", + "secretLabelText": "Segreto", + "secretValidatorMessage": "Inserisci il Segreto", + "submitButtonText": "Invia", + "calendarLabelText": "Calendario", + "bookingsLabelText": "Prenotazioni", + "paymentsLabelText": "Pagamenti", + "settingsLabelText": "Impostazioni", + "refreshTootlipText": "Aggiorna", + "filterTootlipText": "Filtro", + "nothingFoundText": "Niente Trovato", + "newBookingTooltipText": "Nuova Prenotazione", + "cancelButttonText": "Annulla", + "logoutButtonText": "Log out", + "confirmLogoutMessage": "Sei sicuro di voler uscire?", + "consumerKeyEndingInLabelText": "La chiave Consumatore termina in", + "adultsLabelText": "Adulti", + "childrenLabelText": "Bambini", + "rateLabelText": "Tariffa", + "servicesLabelText": "Servizi", + "bookingSetToConfirmedButtonText": "Imposta a Confermato", + "bookingSetToCanceledButtonText": "Imposta a Annullato", + "bookingSetToPendingAdminButtonText": "Imposta a amministratore in attesa", + "bookingSetToPendingUserConfirmationButtonText": "Imposta a conferma utente in sospeso", + "bookingSetToPendingPaymentButtonText": "Imposta a pagamento in sospeso", + "deleteButtonText": "Elimina", + "notSetLabelText": "non impostato", + "copiedLabelText": "copiata", + "copyTooltipText": "Copia", + "totalLabelText": "Totale", + "paidLabelText": "Pagato", + "toPayLabelText": "Da pagare", + "couponCodeUsedLabelText": "Codice coupon utilizzato", + "guestsText": "ospite/i", + "timesText": "volta/e", + "onceText": "Una volta", + "dailyText": "Giornaliero", + "bookingDeletedMessage": "Prenotazione %d cancellato", + "bookingLabelText": "Prenotazione", + "actionsTooltipText": "Azioni", + "errorText": "Errore", + "reservationText": "Prenotazione", + "customerNoteText": "Note del cliente", + "internalNotesText": "Note Interne", + "customerInformationText": "Informazioni cliente", + "firstnameLabelText": "Nome", + "lastnameLabelText": "Cognome", + "emailLabelText": "Email", + "phoneLabelText": "Numero di telefono", + "bookingCreatedMessage": "Prenotazione %d creata", + "basePriceText": "Prezzo base", + "addBookingTitleText": "Aggiungi Prenotazione", + "invalidRouteText": "Percorso non valido", + "continueButtonText": "Continua", + "bookNowButtonText": "Prenota ora", + "quitButtonText": "Esci", + "checkInLabelText": "Check-In", + "checkOutLabelText": "Check-Out", + "dateValidatorMessage": "Inserisci la data", + "searchButtonText": "Cerca", + "externalText": "Esterno", + "bookingConfirmedOptionText": "Confermato", + "bookingCanceledOptionText": "Annullato", + "bookingAbandonedOptionText": "Abbandonato", + "bookingPendingAdminOptionText": "In attesa di approvazione da parte dell'amministratore", + "bookingPendingUserOptionText": "Utente In Attesa", + "bookingPendingPaymentOptionText": "In attesa di pagamento", + "todayOptionText": "Oggi", + "thisWeekOptionText": "Questa Settimana", + "thisMonthOptionText": "Questo Mese", + "filtersTitleText": "Filtri", + "resetButtonText": "Azzera", + "bookingStatusLabelText": "Stato Prenotazione", + "dateCreatedLabelText": "Data di creazione", + "searchHintText": "cerca...", + "displayExternalBookingsLabelText": "Visualizza prenotazioni esterne", + "paymentCompletedOptionText": "Completato", + "paymentCanceledOptionText": "Annullato", + "paymentAbandonedOptionText": "Abbandonato", + "paymentPendingOptionText": "In attesa", + "paymentFailedOptionText": "Fallito", + "paymentRefundedOptionText": "Rimborsato", + "paymentOnHoldOptionText": "In attesa", + "paymentStatusLabelText": "Stato Del Pagamento", + "paymentSetToCompletedButtonText": "Imposta a Completato", + "paymentSetToCanceledButtonText": "Imposta a Annullato", + "paymentSetToOnHoldButtonText": "Imposta su Attesa", + "paymentSetToPendingButtonText": "Imposta in sospeso", + "paymentSetToFailedButtonText": "Impostazione fallita", + "paymentSetToRefundedButtonText": "Imposta su Rimborsato", + "paymentText": "Pagamento", + "calendarFormatMonth": "Mese", + "calendarFormatTwoWeeks": "2 settimane", + "calendarFormatWeek": "Settimana" +} \ No newline at end of file diff --git a/lib/l10n/app_uk.arb b/lib/l10n/app_uk.arb new file mode 100644 index 0000000..183781e --- /dev/null +++ b/lib/l10n/app_uk.arb @@ -0,0 +1,103 @@ +{ + "@@locale": "uk", + "textInstructions": "Перейдіть до розміщення → Установки → Розширені, щоб згенерувати ключі API і сканувати QR-код. Або введіть ваші дані у формі нижче.", + "scanQRCodeButtonText": "Scan QR code", + "invalidQRCodeMessage": "QR-код не дійсний.", + "domainLabelText": "Домен", + "domainValidatorMessage": "Будь ласка, введіть домен", + "keyLabelText": "Ключ", + "keyValidatorMessage": "Будь ласка, введіть ключ", + "secretLabelText": "Секретний ключ", + "secretValidatorMessage": "Будь ласка, введіть секретний ключ", + "submitButtonText": "Ввести", + "calendarLabelText": "Календар", + "bookingsLabelText": "Бронювання", + "paymentsLabelText": "Платежі", + "settingsLabelText": "Налаштування", + "refreshTootlipText": "Оновити", + "filterTootlipText": "Фільтр", + "nothingFoundText": "Нічого не знайдено", + "newBookingTooltipText": "Нове бронювання", + "cancelButttonText": "Скасувати", + "logoutButtonText": "Вийти з системи", + "confirmLogoutMessage": "Ви впевнені, що хочете вийти?", + "consumerKeyEndingInLabelText": "Ключ користувача закінчується на", + "adultsLabelText": "Дорослі", + "childrenLabelText": "Діти", + "rateLabelText": "Тариф", + "servicesLabelText": "Послуги", + "bookingSetToConfirmedButtonText": "Позначити як підтверджене", + "bookingSetToCanceledButtonText": "Позначити як відмінене", + "bookingSetToPendingAdminButtonText": "Позначити як в очікуванні адміністратора", + "bookingSetToPendingUserConfirmationButtonText": "Позначити як в очікуванні підтвердження гостем", + "bookingSetToPendingPaymentButtonText": "Позначити як в очікуванні оплати", + "deleteButtonText": "Видалити", + "notSetLabelText": "не встановлено", + "copiedLabelText": "скопійовано", + "copyTooltipText": "Копіювати", + "totalLabelText": "Загалом", + "paidLabelText": "Оплачено", + "toPayLabelText": "До оплати", + "couponCodeUsedLabelText": "Використано код купона", + "guestsText": "гість(ей)", + "timesText": "раз(и)", + "onceText": "Один раз", + "dailyText": "Щоденно", + "bookingDeletedMessage": "Бронювання %d видалено", + "bookingLabelText": "Бронювання", + "actionsTooltipText": "Дії", + "errorText": "Помилка", + "reservationText": "Бронювання", + "customerNoteText": "Примітка клієнта", + "internalNotesText": "Внутрішні нотатки", + "customerInformationText": "Інформація про клієнта", + "firstnameLabelText": "Ім’я", + "lastnameLabelText": "Прізвище", + "emailLabelText": "Ел. пошта", + "phoneLabelText": "Телефон", + "bookingCreatedMessage": "Бронювання %d створено", + "basePriceText": "Початкова ціна", + "addBookingTitleText": "Додати бронювання", + "invalidRouteText": "Неприпустимий маршрут", + "continueButtonText": "Продовжити", + "bookNowButtonText": "Забронювати зараз", + "quitButtonText": "Вийти", + "checkInLabelText": "Прибуття", + "checkOutLabelText": "Виїзд", + "dateValidatorMessage": "Будь ласка, введіть дату", + "searchButtonText": "Пошук", + "externalText": "Зовнішнє", + "bookingConfirmedOptionText": "Підтверджено", + "bookingCanceledOptionText": "Скасовано", + "bookingAbandonedOptionText": "Незавершено", + "bookingPendingAdminOptionText": "Очікує адміністратора", + "bookingPendingUserOptionText": "Очікує гостя", + "bookingPendingPaymentOptionText": "Очікує оплати", + "todayOptionText": "Сьогодні", + "thisWeekOptionText": "На цьому тижні", + "thisMonthOptionText": "Цього місяця", + "filtersTitleText": "Фільтри", + "resetButtonText": "Скинути", + "bookingStatusLabelText": "Статус бронювання", + "dateCreatedLabelText": "Дата створення", + "searchHintText": "пошук...", + "displayExternalBookingsLabelText": "Відображати зовнішні бронювання", + "paymentCompletedOptionText": "Виконано", + "paymentCanceledOptionText": "Скасовано", + "paymentAbandonedOptionText": "Незавершено", + "paymentPendingOptionText": "В очікуванні", + "paymentFailedOptionText": "Невдало", + "paymentRefundedOptionText": "Повернено", + "paymentOnHoldOptionText": "На утриманні", + "paymentStatusLabelText": "Статус платежу", + "paymentSetToCompletedButtonText": "Позначити як завершений", + "paymentSetToCanceledButtonText": "Позначити як відмінений", + "paymentSetToOnHoldButtonText": "Позначити як на утриманні", + "paymentSetToPendingButtonText": "Позначити як в очікуванні", + "paymentSetToFailedButtonText": "Позначити як невдалий", + "paymentSetToRefundedButtonText": "Позначити як повернений", + "paymentText": "Платіж", + "calendarFormatMonth": "Місяць", + "calendarFormatTwoWeeks": "2 тижні", + "calendarFormatWeek": "Тиждень" +} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 835a2e2..4b9104b 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -33,6 +33,10 @@ class MyApp extends StatelessWidget { supportedLocales: [ Locale('en'), // English Locale('fr'), // French + Locale('de'), // German + Locale('es'), // Spanish + Locale('it'), // Italian + Locale('uk'), // Ukrainian ], theme: ThemeData( primarySwatch: Colors.indigo, diff --git a/lib/screens/bookings/create/search_availability_form.dart b/lib/screens/bookings/create/search_availability_form.dart index 832130d..6d0b01f 100644 --- a/lib/screens/bookings/create/search_availability_form.dart +++ b/lib/screens/bookings/create/search_availability_form.dart @@ -34,7 +34,7 @@ class _SearchAvailabilityFormState extends State { final DateTimeRange? dateRange = await showDateRangePicker( context: context, - locale: const Locale('en', 'GB'), + //locale: const Locale('en', 'GB'), initialEntryMode: DatePickerEntryMode.calendarOnly, firstDate: DateTime.now(), lastDate: DateTime( DateTime.now().year + 10, 12, 31 ), diff --git a/lib/screens/calendar.dart b/lib/screens/calendar.dart index a77b178..e63453e 100644 --- a/lib/screens/calendar.dart +++ b/lib/screens/calendar.dart @@ -348,6 +348,7 @@ class _TableEventsState extends State { //https://github.com/aleksanderwozniak/table_calendar child: TableCalendar( + locale: Localizations.localeOf(context).toString(), firstDay: _firstDay, lastDay: _lastDay, focusedDay: _focusedDay, @@ -407,6 +408,11 @@ class _TableEventsState extends State { } }, ), + availableCalendarFormats: { + CalendarFormat.month: AppLocalizations.of(context).calendarFormatMonth, + CalendarFormat.twoWeeks: AppLocalizations.of(context).calendarFormatTwoWeeks, + CalendarFormat.week: AppLocalizations.of(context).calendarFormatWeek, + }, ), ), const SizedBox(height: 16.0), From 14f8017bc63ccbc72b69330f3229d99fefaab4c6 Mon Sep 17 00:00:00 2001 From: mototeam Date: Fri, 14 Jul 2023 00:41:23 +0300 Subject: [PATCH 3/5] version bump --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 337b87e..7203354 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,7 +15,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.1.0+8 +version: 1.2.0+9 environment: sdk: ">=2.12.0 <3.0.0" From de094951dca3747dd9040b95d0f504f06b03f940 Mon Sep 17 00:00:00 2001 From: mototeam Date: Fri, 14 Jul 2023 01:33:54 +0300 Subject: [PATCH 4/5] targetSdkVersion --- README.md | 1 + android/app/build.gradle | 4 ++-- android/app/src/main/AndroidManifest.xml | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 67b086b..c967c44 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,7 @@ _Note: You will need a WordPress website and the Hotel Booking plugin from MotoP ### Prepare 1. Update version name and build number in `pubspec.yaml`. +1. Update l10n `flutter gen-l10n`. ### Build and Release for iOS diff --git a/android/app/build.gradle b/android/app/build.gradle index 69b7ae1..e839d72 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -32,7 +32,7 @@ if (keystorePropertiesFile.exists()) { } android { - compileSdkVersion 30 + compileSdkVersion 31 compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 @@ -51,7 +51,7 @@ android { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.motopress.mphb_app" minSdkVersion 20 - targetSdkVersion 30 + targetSdkVersion 31 versionCode flutterVersionCode.toInteger() versionName flutterVersionName } diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 1dafee3..9201980 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -6,6 +6,7 @@ android:icon="@mipmap/ic_launcher"> Date: Fri, 14 Jul 2023 03:03:59 +0300 Subject: [PATCH 5/5] IPHONEOS_DEPLOYMENT_TARGET --- ios/Runner.xcodeproj/project.pbxproj | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index bb8b912..8a30309 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 51; objects = { /* Begin PBXBuildFile section */ @@ -76,7 +76,6 @@ E66942F8A137BA1B63A2B2FA /* Pods-Runner.release.xcconfig */, 73D896FD74FEC34E6FDA785F /* Pods-Runner.profile.xcconfig */, ); - name = Pods; path = Pods; sourceTree = ""; }; @@ -359,6 +358,7 @@ DEVELOPMENT_TEAM = KPZYD43D2A; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -488,6 +488,7 @@ DEVELOPMENT_TEAM = KPZYD43D2A; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -511,6 +512,7 @@ DEVELOPMENT_TEAM = KPZYD43D2A; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks",