From 51b311f933f7d1f35ff90c2b357cbd806b53f936 Mon Sep 17 00:00:00 2001 From: Serdar1112 <56867621+Serdar1112@users.noreply.github.com> Date: Wed, 14 Jun 2023 02:46:11 +0200 Subject: [PATCH] Localization --- android/app/build.gradle | 2 +- lib/assets/translations/de-DE.json | 24 +++++++++ lib/assets/translations/en-US.json | 24 +++++++++ lib/main.dart | 78 ++++++++++++++++++------------ lib/preferences.dart | 29 +++++++++-- pubspec.lock | 33 ++++++++++++- pubspec.yaml | 4 ++ 7 files changed, 154 insertions(+), 40 deletions(-) create mode 100644 lib/assets/translations/de-DE.json create mode 100644 lib/assets/translations/en-US.json diff --git a/android/app/build.gradle b/android/app/build.gradle index cf6e265..e1506c5 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -27,7 +27,7 @@ apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { compileSdkVersion flutter.compileSdkVersion - ndkVersion flutter.ndkVersion + ndkVersion "25.1.8937393" compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 diff --git a/lib/assets/translations/de-DE.json b/lib/assets/translations/de-DE.json new file mode 100644 index 0000000..57e05ce --- /dev/null +++ b/lib/assets/translations/de-DE.json @@ -0,0 +1,24 @@ +{ + "title" : "Finanzplaner", + "delete" : "Löschen", + "deleteaccount" : "Account Löschen", + "sure" : "Sind Sie sicher, dass Sie dieses Konto löschen möchten?", + "balance" : "Bilanz", + "addaccount" : "Konto hinzufügen", + "entername" : "Bitte geben Sie einen Namen ein", + "enterbalance" : "Bitte geben Sie einen Saldo ein", + "entervalidnumber" : "Bitte geben Sie eine gültige Nummer ein", + "cancel" : "Abbrechen", + "add" : "Hinzufügen", + "income": "Einnahmen", + "expenditures": "Ausgaben", + "addtrans": "Transaktion hinzufügen", + "entertitle": "Bitte geben Sie einen Titel ein", + "amount": "Betrag", + "enteramount": "Bitte geben Sie einen Betrag ein", + "expense": "Ausgabe", + "settings": "Einstellungen", + "darkmode": "Dunkel Modus", + "language": "Sprache", + "currency": "Währung" +} \ No newline at end of file diff --git a/lib/assets/translations/en-US.json b/lib/assets/translations/en-US.json new file mode 100644 index 0000000..3453905 --- /dev/null +++ b/lib/assets/translations/en-US.json @@ -0,0 +1,24 @@ +{ + "title" : "Financial Planner", + "delete" : "Delete", + "deleteaccount" : "Delete Account", + "sure" : "Are you sure you want to delete this account?", + "balance" : "Balance", + "addaccount" : "Add Account", + "entername" : "Please enter a name", + "enterbalance" : "Please enter a balance", + "entervalidnumber" : "Please enter a valid number", + "cancel" : "Cancel", + "add" : "Add", + "income": "Income", + "expenditures": "Expenditures", + "addtrans": "Add Transaction", + "entertitle": "Please enter a title", + "amount": "Amount", + "enteramount": "Please enter an amount", + "expense": "Expense", + "settings": "Settings", + "darkmode": "Dark Mode", + "language": "Language", + "currency": "Currency" +} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index b242f1a..c16ea0b 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -8,10 +8,17 @@ import 'package:syncfusion_flutter_charts/charts.dart'; import 'package:tests/preferences.dart'; import 'package:tests/theme/theme_constants.dart'; import 'package:tests/theme/theme_manager.dart'; +import "package:easy_localization/easy_localization.dart"; -void main() { - - runApp(const FinancialPlannerApp()); +Future main() async { + WidgetsFlutterBinding.ensureInitialized(); + await EasyLocalization.ensureInitialized(); + runApp(EasyLocalization( + supportedLocales: [Locale('en', 'US'), Locale('de', 'DE')], + path: 'lib/assets/translations', // <-- change the path of the translation files + fallbackLocale: Locale('en', 'US'), + child: const FinancialPlannerApp() + ),); } ThemeManager _themeManager = ThemeManager(); @@ -21,8 +28,11 @@ class FinancialPlannerApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( + localizationsDelegates: context.localizationDelegates, + supportedLocales: context.supportedLocales, + locale: context.locale, debugShowCheckedModeBanner: false, - title: 'Financial Planner', + title: 'title'.tr(), theme: lightTheme, darkTheme: darkTheme, themeMode: _themeManager.themeMode, @@ -102,9 +112,9 @@ class HomePageState extends State { centerTitle: true, backgroundColor: Colors.transparent, elevation: 0, - title: const Text( - 'Financial Planner', - style: TextStyle( + title: Text( + 'title'.tr(), + style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: Colors.black54, @@ -114,11 +124,15 @@ class HomePageState extends State { Padding( padding: const EdgeInsets.only(right: 16.0, top: 3, bottom: 7), child: NeumorphicButton( - onPressed: () { - Navigator.push( + onPressed: () async { + + String value = await Navigator.push( context, MaterialPageRoute(builder: (context) => Settings()), ); + setState(() { + + }); }, style: NeumorphicStyle( shape: NeumorphicShape.convex, @@ -139,15 +153,15 @@ class HomePageState extends State { return GestureDetector( onLongPress: () { AwesomeDialog( - btnOkText: "Delete", + btnOkText: "Delete".tr(), btnOkColor: Colors.lightGreen, btnCancelColor: Colors.grey, context: context, animType: AnimType.bottomSlide, dialogType: DialogType.info, - title: 'Delete Account', + title: 'deleteaccount'.tr(), headerAnimationLoop: false, - desc: 'Are you sure you want to delete this account?', + desc: 'sure'.tr(), btnCancelOnPress: () {}, btnOkOnPress: () { deleteAccount(accounts[index]); @@ -166,7 +180,7 @@ class HomePageState extends State { ), child: ListTile( title: Text(accounts[index].name), - subtitle: Text('Balance: \$${accounts[index].balance.toStringAsFixed(2)}'), + subtitle: Text('${'balance'.tr()}: \$${accounts[index].balance.toStringAsFixed(2)}'), onTap: () { Navigator.push( context, @@ -274,8 +288,8 @@ class AddAccountDialogState extends State { shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(15), ), - title: const Text( - 'Add Account', + title: Text( + 'addaccount'.tr(), ), titleTextStyle: TextStyle( color: Colors.black54, @@ -304,7 +318,7 @@ class AddAccountDialogState extends State { ), validator: (value) { if (value!.isEmpty) { - return 'Please enter a name'; + return 'entername'.tr(); } return null; }, @@ -323,17 +337,17 @@ class AddAccountDialogState extends State { child: TextFormField( controller: _balanceController, decoration: InputDecoration( - labelText: 'Balance', + labelText: 'balance'.tr(), border: InputBorder.none, contentPadding: EdgeInsets.fromLTRB(12, 16, 12, 16), ), keyboardType: TextInputType.number, validator: (value) { if (value!.isEmpty) { - return 'Please enter a balance'; + return 'enterbalance'.tr(); } if (double.tryParse(value) == null) { - return 'Please enter a valid number'; + return 'entervalidnumber'.tr(); } return null; }, @@ -358,7 +372,7 @@ class AddAccountDialogState extends State { ), padding: EdgeInsets.symmetric(vertical: 12, horizontal: 16), child: Text( - 'Cancel', + 'cancel'.tr(), style: TextStyle( fontSize: 12, fontWeight: FontWeight.bold, @@ -378,7 +392,7 @@ class AddAccountDialogState extends State { ), padding: EdgeInsets.symmetric(vertical: 12, horizontal: 16), child: Text( - 'Add', + 'add'.tr(), style: TextStyle( fontSize: 12, fontWeight: FontWeight.bold, @@ -533,9 +547,9 @@ class AccountDetailPageState extends State with SingleTickerP TabBar( controller: _tabController, labelColor: Colors.black, - tabs: const [ - Tab(text: 'Einnahmen'), - Tab(text: 'Ausgaben'), + tabs: [ + Tab(text: 'income'.tr()), + Tab(text: 'expenditures'.tr()), ], ), Expanded( @@ -702,7 +716,7 @@ class AddTransactionDialogState extends State { borderRadius: BorderRadius.circular(15), ), title: Text( - 'Add Transaction', + 'addtrans'.tr(), style: TextStyle( fontSize: 20, color: Colors.black54, @@ -732,7 +746,7 @@ class AddTransactionDialogState extends State { ), validator: (value) { if (value!.isEmpty) { - return 'Please enter a title'; + return 'entertitle'.tr(); } return null; }, @@ -751,7 +765,7 @@ class AddTransactionDialogState extends State { child: TextFormField( controller: _amountController, decoration: InputDecoration( - labelText: 'Amount', + labelText: 'amount'.tr(), border: InputBorder.none, contentPadding: EdgeInsets.symmetric( vertical: 12, @@ -761,10 +775,10 @@ class AddTransactionDialogState extends State { keyboardType: TextInputType.number, validator: (value) { if (value!.isEmpty) { - return 'Please enter an amount'; + return 'enteramount'.tr(); } if (double.tryParse(value) == null) { - return 'Please enter a valid number'; + return 'entervalidnumber'.tr(); } return null; }, @@ -783,7 +797,7 @@ class AddTransactionDialogState extends State { }, ), SizedBox(width: 8), - Text('Expense', style: TextStyle(color: Colors.black87),), + Text('expense'.tr(), style: TextStyle(color: Colors.black87),), ], ), ], @@ -804,7 +818,7 @@ class AddTransactionDialogState extends State { ), padding: EdgeInsets.symmetric(vertical: 12, horizontal: 16), child: Text( - 'Cancel', + 'cancel'.tr(), style: TextStyle( fontSize: 12, fontWeight: FontWeight.bold, @@ -824,7 +838,7 @@ class AddTransactionDialogState extends State { ), padding: EdgeInsets.symmetric(vertical: 12, horizontal: 16), child: Text( - 'Add', + 'add'.tr(), style: TextStyle( fontSize: 12, fontWeight: FontWeight.bold, diff --git a/lib/preferences.dart b/lib/preferences.dart index d49a967..71497b4 100644 --- a/lib/preferences.dart +++ b/lib/preferences.dart @@ -1,3 +1,4 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter_neumorphic/flutter_neumorphic.dart'; import 'package:tests/theme/theme_manager.dart'; @@ -18,6 +19,15 @@ class SettingsState extends State { final List _languages = ['English', 'Deutsch']; final List _currencies = ['Euro', 'Dollar', 'CHF']; + void checkForLanguage(BuildContext context){ + String language = context.locale.toString(); + print(language); + switch(language){ + case "en_US": _selectedLanguage = "English"; break; + case "de_DE": _selectedLanguage = "Deutsch"; break; + } + } + @override void dispose() { _themeManager.removeListener(themeListener); @@ -34,18 +44,21 @@ class SettingsState extends State { @override void initState() { super.initState(); + _themeManager.addListener(themeListener); } @override Widget build(BuildContext context) { + checkForLanguage(context); + return Scaffold( appBar: AppBar( backgroundColor: Colors.transparent, elevation: 0, toolbarHeight: 80, title: Text( - 'Settings', + 'settings'.tr(), style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, @@ -64,7 +77,8 @@ class SettingsState extends State { padding: const EdgeInsets.only(left: 16.0), child: NeumorphicButton( onPressed: () { - Navigator.pop(context); + Navigator.pop(context, "Change"); + }, style: NeumorphicStyle( shape: NeumorphicShape.flat, @@ -90,7 +104,7 @@ class SettingsState extends State { boxShape: NeumorphicBoxShape.roundRect(BorderRadius.circular(15)), ), child: ListTile( - title: const Text('Dark Mode'), + title: Text('darkmode'.tr()), trailing: NeumorphicSwitch( value: _themeManager.themeMode == ThemeMode.dark, onChanged: (bool value) { @@ -122,12 +136,17 @@ class SettingsState extends State { boxShape: NeumorphicBoxShape.roundRect(BorderRadius.circular(15)), ), child: ListTile( - title: const Text('Language'), + title: Text('language'.tr()), trailing: DropdownButton( value: _selectedLanguage, onChanged: (String? newValue) { setState(() { _selectedLanguage = newValue!; + switch(_selectedLanguage){ + case "English": context.setLocale(Locale('en', 'US')); break; + case "Deutsch": context.setLocale(Locale('de', 'DE')); break; + } + // Hier kannst du die Spracheinstellung entsprechend anpassen // z.B. mit einer Funktion, die die App-Sprache ändert. }); @@ -151,7 +170,7 @@ class SettingsState extends State { boxShape: NeumorphicBoxShape.roundRect(BorderRadius.circular(15)), ), child: ListTile( - title: const Text('Currency'), + title: Text('currency'.tr()), trailing: DropdownButton( value: _selectedCurrency, onChanged: (String? newValue) { diff --git a/pubspec.lock b/pubspec.lock index b59f42d..8766b72 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,14 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + args: + dependency: transitive + description: + name: args + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 + url: "https://pub.dev" + source: hosted + version: "2.4.2" async: dependency: transitive description: @@ -73,6 +81,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.5" + easy_localization: + dependency: "direct main" + description: + name: easy_localization + sha256: "30ebf25448ffe169e0bd9bc4b5da94faa8398967a2ad2ca09f438be8b6953645" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + easy_logger: + dependency: transitive + description: + name: easy_logger + sha256: c764a6e024846f33405a2342caf91c62e357c24b02c04dbc712ef232bf30ffb7 + url: "https://pub.dev" + source: hosted + version: "0.0.2" fake_async: dependency: transitive description: @@ -110,6 +134,11 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.1" + flutter_localizations: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" flutter_neumorphic: dependency: "direct main" description: @@ -385,10 +414,10 @@ packages: dependency: transitive description: name: syncfusion_flutter_core - sha256: "4aa69e3541d38810533b1455aa38997a89755f9928e16ef813b62b2e8bcc398c" + sha256: "8db8f55c77f56968681447d3837c10f27a9e861e238a898fda116c7531def979" url: "https://pub.dev" source: hosted - version: "21.2.9" + version: "21.2.10" term_glyph: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 8093ac7..123fc11 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -39,6 +39,7 @@ dependencies: syncfusion_flutter_charts: ^21.2.4 flutter_neumorphic: ^3.2.0 awesome_dialog: ^3.1.0 + easy_localization: ^3.0.2 dev_dependencies: flutter_test: @@ -62,6 +63,9 @@ flutter: # the material Icons class. uses-material-design: true + assets: + - lib/assets/translations/ + fonts: - family: Montserrat fonts: