diff --git a/README.md b/README.md index fe7baa8..f880fe9 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ chromedriver --port=4444 ``` And then run the script: ```shell -./integration_test/run_tests.sh +./integration_test/run_web_tests.sh ``` If the HEADER environment variable is set, the tests run with a header. diff --git a/l10n.yaml b/l10n.yaml new file mode 100644 index 0000000..c114495 --- /dev/null +++ b/l10n.yaml @@ -0,0 +1,4 @@ +arb-dir: lib/l10n +template-arb-file: app_en.arb +output-localization-file: app_localizations.dart +nullable-getter: false \ 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..619eeee --- /dev/null +++ b/lib/l10n/app_en.arb @@ -0,0 +1,8 @@ +{ + "cont": "Continue", + "before_you_begin": "Before you begin", + "intro_text": "Before you start using the Concordium Mobile Wallet, you have to set up a passcode and optionally biometrics.\n\nIt is very important that you keep your passcode safe, because it is the only way to access your accounts. Concordium is not able to change your passcode or help you unlock your wallet if you lose your passcode.", + "read_and_agree": "I have read and agree to the ", + "terms_and_conditions": "Terms and Conditions v{v}", + "previously_accepted": " (you previously accepted v{v})." +} diff --git a/lib/main.dart b/lib/main.dart index 239c8d3..80b8c59 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -11,6 +11,7 @@ import 'package:concordium_wallet/theme.dart'; import 'package:concordium_wallet/types/future_value.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; void main() { runApp(const App()); @@ -55,10 +56,13 @@ class App extends StatelessWidget { child: _WithSelectedNetwork( initialNetwork: initialNetwork, child: _WithTermsAndConditionAcceptance( - child: MaterialApp( - routes: appRoutes, - theme: concordiumTheme(), - )), + child: MaterialApp( + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, + routes: appRoutes, + theme: concordiumTheme(), + ), + ), ), ); } @@ -202,8 +206,8 @@ class _Initializing extends StatelessWidget { children: [ CircularProgressIndicator(), SizedBox(height: 16), - // Setting text direction is required because we're outside 'MaterialApp' widget. - Text('Initializing...', textDirection: TextDirection.ltr), + // Setting hardcoded text and text direction is required because we're outside 'MaterialApp' widget. + Text("Initializing...", textDirection: TextDirection.ltr), ], ); } diff --git a/lib/screens/terms_and_conditions/screen.dart b/lib/screens/terms_and_conditions/screen.dart index 302b342..65fe6b5 100644 --- a/lib/screens/terms_and_conditions/screen.dart +++ b/lib/screens/terms_and_conditions/screen.dart @@ -5,6 +5,7 @@ import 'package:concordium_wallet/state/terms_and_conditions.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class TermsAndConditionsScreen extends StatefulWidget { final TermsAndConditions validTermsAndConditions; @@ -53,18 +54,15 @@ class _TermsAndConditionsScreenState extends State { const SizedBox(height: 24), Center( child: Text( - 'Before you begin', + AppLocalizations.of(context).before_you_begin, style: Theme.of(context).textTheme.displaySmall, ), ), Container( padding: const EdgeInsets.all(16), - child: const Column( + child: Column( children: [ - Text('Before you start using the Concordium Mobile Wallet, you have to set up a passcode and optionally biometrics.'), - SizedBox(height: 9), - Text( - 'It is very important that you keep your passcode safe, because it is the only way to access your accounts. Concordium is not able to change your passcode or help you unlock your wallet if you lose your passcode.'), + Text(AppLocalizations.of(context).intro_text), ], ), ), @@ -84,9 +82,9 @@ class _TermsAndConditionsScreenState extends State { text: TextSpan( style: Theme.of(context).textTheme.bodySmall, children: [ - const TextSpan(text: 'I have read and agree to the '), + TextSpan(text: AppLocalizations.of(context).read_and_agree), TextSpan( - text: 'Terms and Conditions v${widget.validTermsAndConditions.version}', + text: AppLocalizations.of(context).terms_and_conditions(widget.validTermsAndConditions.version), style: const TextStyle( color: Colors.indigo, fontWeight: FontWeight.bold, @@ -95,7 +93,7 @@ class _TermsAndConditionsScreenState extends State { switch (widget.acceptedTermsAndConditionsVersion) { null => const TextSpan(text: '.'), String v => TextSpan( - text: ' (you previously accepted v$v).', + text: AppLocalizations.of(context).previously_accepted(v), style: Theme.of(context).textTheme.bodySmall, ), }, @@ -113,7 +111,7 @@ class _TermsAndConditionsScreenState extends State { const SizedBox(height: 9), ElevatedButton( onPressed: _onAcceptButtonPressed(context), - child: const Text('Continue'), + child: Text(AppLocalizations.of(context).cont), ), ], ), diff --git a/pubspec.lock b/pubspec.lock index baf93b4..f5a9469 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -173,10 +173,10 @@ packages: dependency: transitive description: name: collection - sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.2" + version: "1.18.0" colorize: dependency: transitive description: @@ -299,6 +299,11 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.3" + flutter_localizations: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" flutter_svg: dependency: "direct main" description: @@ -407,6 +412,14 @@ packages: description: flutter source: sdk version: "0.0.0" + intl: + dependency: "direct main" + description: + name: intl + sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" + url: "https://pub.dev" + source: hosted + version: "0.18.1" io: dependency: transitive description: @@ -491,10 +504,10 @@ packages: dependency: transitive description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" mime: dependency: transitive description: @@ -635,10 +648,10 @@ packages: dependency: transitive description: name: platform - sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + sha256: ae68c7bfcd7383af3629daafb32fb4e8681c7154428da4febcff06200585f102 url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.2" plugin_platform_interface: dependency: transitive description: @@ -784,18 +797,18 @@ packages: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" stream_transform: dependency: transitive description: @@ -848,26 +861,26 @@ packages: dependency: transitive description: name: test - sha256: "13b41f318e2a5751c3169137103b60c584297353d4b1761b66029bae6411fe46" + sha256: a1f7595805820fcc05e5c52e3a231aedd0b72972cb333e8c738a8b1239448b6f url: "https://pub.dev" source: hosted - version: "1.24.3" + version: "1.24.9" test_api: dependency: transitive description: name: test_api - sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" url: "https://pub.dev" source: hosted - version: "0.6.0" + version: "0.6.1" test_core: dependency: transitive description: name: test_core - sha256: "99806e9e6d95c7b059b7a0fc08f07fc53fabe54a829497f0d9676299f1e8637e" + sha256: a757b14fc47507060a162cc2530d9a4a2f92f5100a952c7443b5cad5ef5b106a url: "https://pub.dev" source: hosted - version: "0.5.3" + version: "0.5.9" timing: dependency: transitive description: @@ -984,10 +997,10 @@ packages: dependency: transitive description: name: vm_service - sha256: c620a6f783fa22436da68e42db7ebbf18b8c44b9a46ab911f666ff09ffd9153f + sha256: c538be99af830f478718b51630ec1b6bee5e74e52c8a802d328d9e71d35d2583 url: "https://pub.dev" source: hosted - version: "11.7.1" + version: "11.10.0" watcher: dependency: transitive description: @@ -1000,10 +1013,10 @@ packages: dependency: transitive description: name: web - sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 url: "https://pub.dev" source: hosted - version: "0.1.4-beta" + version: "0.3.0" web_socket_channel: dependency: transitive description: @@ -1061,5 +1074,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.1.3 <4.0.0" + dart: ">=3.2.0-194.0.dev <4.0.0" flutter: ">=3.13.0" diff --git a/pubspec.yaml b/pubspec.yaml index 6191ea5..bc56ff0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -44,6 +44,9 @@ dependencies: package_info_plus: ^4.2.0 hive: ^2.2.3 hive_flutter: ^1.1.0 + flutter_localizations: + sdk: flutter + intl: ^0.18.1 dev_dependencies: flutter_test: @@ -68,6 +71,7 @@ dev_dependencies: # The following section is specific to Flutter packages. flutter: + generate: true # The following line ensures that the Material Icons font is # included with your application, so that you can use the icons in diff --git a/scripts/license.yaml b/scripts/license.yaml index 0328a80..158ec62 100644 --- a/scripts/license.yaml +++ b/scripts/license.yaml @@ -23,6 +23,7 @@ packageLicenseOverride: flutter_web_plugins: BSD-3-Clause flutter_driver: BSD-3-Clause integration_test: BSD-3-Clause + flutter_localizations: BSD-3-Clause fuchsia_remote_debug_protocol: BSD-3-Clause omitDisclaimer: diff --git a/test/helpers.dart b/test/helpers.dart index e52789f..e0a64c7 100644 --- a/test/helpers.dart +++ b/test/helpers.dart @@ -1,4 +1,8 @@ import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; /// Wrap MaterialApp and Scaffold around the given widget. -Widget wrapMaterial({required Widget? child}) => MaterialApp(home: Scaffold(body: child)); +Widget wrapMaterial({required Widget? child}) => MaterialApp( + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, + home: Scaffold(body: child)); diff --git a/test/terms_and_conditions_test.dart b/test/terms_and_conditions_test.dart index ff63b48..fd743ce 100644 --- a/test/terms_and_conditions_test.dart +++ b/test/terms_and_conditions_test.dart @@ -8,6 +8,7 @@ import 'package:concordium_wallet/screens/terms_and_conditions/screen.dart'; import 'package:concordium_wallet/services/wallet_proxy/model.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations_en.dart'; import 'helpers.dart'; @@ -52,8 +53,7 @@ void main() { await tester.pumpWidget(wrapMaterial(child: tacScreen)); // Act - // TODO use internationalized version here. - await tester.tap(find.text("Continue", findRichText: true)); + await tester.tap(find.text(AppLocalizationsEn().cont, findRichText: true)); // Assert expect(checked, false); @@ -68,8 +68,7 @@ void main() { await tester.pump(); - // TODO use internationalized version here. - await tester.tap(find.text("Continue", findRichText: true)); + await tester.tap(find.text(AppLocalizationsEn().cont, findRichText: true)); await tester.pump(); @@ -95,8 +94,7 @@ void main() { when(() => launcher.launch(uri)).thenAnswer((_) => Future.value(true)); // Act - // TODO use internationalized version here. - await tester.tap(find.textContaining("I have read and agree to the", findRichText: true)); + await tester.tap(find.textContaining(AppLocalizationsEn().read_and_agree, findRichText: true)); // Assert verify(() => launcher.launch(uri)).called(1);