diff --git a/l10n.yaml b/l10n.yaml new file mode 100644 index 0000000..aa74778 --- /dev/null +++ b/l10n.yaml @@ -0,0 +1,7 @@ +arb-dir: lib/src/core/l10n/translations +template-arb-file: intl_en.arb +output-localization-file: app_localizations.g.dart +output-dir: lib/src/core/l10n/generated +synthetic-package: false +nullable-getter: false +untranslated-messages-file: untranslated_messages.txt diff --git a/lib/src/app/presentation/page/root.dart b/lib/src/app/presentation/page/root.dart index 90b1495..1aa3981 100644 --- a/lib/src/app/presentation/page/root.dart +++ b/lib/src/app/presentation/page/root.dart @@ -1,8 +1,9 @@ import 'package:base_starter/src/app/router/router.dart'; import 'package:base_starter/src/common/utils/extensions/context_extension.dart'; -import 'package:base_starter/src/core/localization/generated/l10n.dart'; +import 'package:base_starter/src/core/l10n/localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:iconsax_plus/iconsax_plus.dart'; part '../widget/bottom_navigation_bar.dart'; diff --git a/lib/src/app/presentation/widget/bottom_navigation_bar.dart b/lib/src/app/presentation/widget/bottom_navigation_bar.dart index faa3560..b886eb9 100644 --- a/lib/src/app/presentation/widget/bottom_navigation_bar.dart +++ b/lib/src/app/presentation/widget/bottom_navigation_bar.dart @@ -31,13 +31,15 @@ class _BottomNavigationBar extends StatelessWidget { }, destinations: [ NavigationDestination( - icon: const Icon(Icons.home_outlined), - selectedIcon: const Icon(Icons.home, color: Colors.white), + icon: const Icon(IconsaxPlusLinear.home), + selectedIcon: + const Icon(IconsaxPlusBold.home, color: Colors.white), label: L10n.current.home, ), NavigationDestination( - icon: const Icon(Icons.person_outline), - selectedIcon: const Icon(Icons.person, color: Colors.white), + icon: const Icon(IconsaxPlusLinear.user_square), + selectedIcon: + const Icon(IconsaxPlusBold.user_square, color: Colors.white), label: L10n.current.profile, ), ], diff --git a/lib/src/app/presentation/widget/material_context.dart b/lib/src/app/presentation/widget/material_context.dart index 4341350..c02889d 100644 --- a/lib/src/app/presentation/widget/material_context.dart +++ b/lib/src/app/presentation/widget/material_context.dart @@ -1,6 +1,6 @@ import 'package:base_starter/flavors.dart'; import 'package:base_starter/src/app/router/router.dart'; -import 'package:base_starter/src/core/localization/generated/l10n.dart'; +import 'package:base_starter/src/core/l10n/localization.dart'; import 'package:base_starter/src/features/settings/presentation/settings.dart'; import 'package:flutter/material.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; @@ -43,7 +43,7 @@ class MaterialContext extends ConsumerWidget { localizationsDelegates: ISpectLocalizations.localizationDelegates([ L10n.delegate, ]), - supportedLocales: L10n.delegate.supportedLocales, + supportedLocales: L10n.supportedLocales, locale: locale, routerConfig: routerConfig, builder: (context, child) { diff --git a/lib/src/app/router/router.dart b/lib/src/app/router/router.dart index 63c03f1..0fc94a3 100644 --- a/lib/src/app/router/router.dart +++ b/lib/src/app/router/router.dart @@ -96,67 +96,4 @@ GoRouter createRouter = GoRouter( ); }, routes: $appRoutes, - // routes: [ - // $splashRoute, - // $authRoute, - // StatefulShellRoute.indexedStack( - // builder: ( - // _, - // __, - // navigationShell, - // ) { - // /// Return the widget that implements the custom shell (in this case - // /// using a BottomNavigationBar). The StatefulNavigationShell is passed - // /// to be able access the state of the shell and to navigate to other - // /// branches in a stateful way. - // return RootPage(navigationShell: navigationShell); - // }, - // branches: [ - // StatefulShellBranch( - // navigatorKey: _homeSectionNavigatorKey, - // observers: [ - // HeroController(), - // ISpectNavigatorObserver( - // isLogModals: false, - // ), - // ], - // routes: [ - // GoRoute( - // name: HomePage.name, - // path: HomePage.routePath, - // builder: (_, __) => const HomePage(), - // ), - // ], - // ), - // StatefulShellBranch( - // navigatorKey: _profileSectionNavigatorKey, - // routes: [ - // GoRoute( - // name: ProfilePage.name, - // path: ProfilePage.routePath, - // builder: (_, __) => const ProfilePage(), - // routes: [ - // GoRoute( - // name: SettingsPage.name, - // path: SettingsPage.routePath, - // builder: (_, state) { - // final queryParameters = state.uri.queryParameters; - // return SettingsPage( - // title: queryParameters[ExtraKeys.title] ?? 'Settings', - // ); - // }, - // ), - // ], - // ), - // ], - // observers: [ - // HeroController(), - // ISpectNavigatorObserver( - // isLogModals: false, - // ), - // ], - // ), - // ], - // ), - // ], ); diff --git a/lib/src/common/presentation/pages/error_router_page.dart b/lib/src/common/presentation/pages/error_router_page.dart index 0374afc..67b31f4 100644 --- a/lib/src/common/presentation/pages/error_router_page.dart +++ b/lib/src/common/presentation/pages/error_router_page.dart @@ -1,7 +1,7 @@ import 'package:auto_size_text/auto_size_text.dart'; import 'package:base_starter/src/app/router/router.dart'; import 'package:base_starter/src/common/utils/extensions/context_extension.dart'; -import 'package:base_starter/src/core/localization/generated/l10n.dart'; +import 'package:base_starter/src/core/l10n/localization.dart'; import 'package:flutter/material.dart'; import 'package:gap/gap.dart'; diff --git a/lib/src/common/presentation/widgets/bottom_sheet/body.dart b/lib/src/common/presentation/widgets/bottom_sheet/body.dart index 07fc312..d9bd8ce 100644 --- a/lib/src/common/presentation/widgets/bottom_sheet/body.dart +++ b/lib/src/common/presentation/widgets/bottom_sheet/body.dart @@ -2,6 +2,7 @@ import 'package:auto_size_text/auto_size_text.dart'; import 'package:base_starter/src/common/utils/extensions/context_extension.dart'; import 'package:flutter/material.dart'; +import 'package:iconsax_plus/iconsax_plus.dart'; class AppBottomSheet extends StatelessWidget { const AppBottomSheet({ @@ -72,7 +73,10 @@ class AppBottomSheet extends StatelessWidget { padding: const EdgeInsets.only(left: 16), child: IconButton( iconSize: 20, - icon: const Icon(Icons.cancel_outlined, size: 32), + icon: const Icon( + IconsaxPlusLinear.close_circle, + size: 32, + ), onPressed: () { Navigator.of(context).pop(); }, diff --git a/lib/src/common/presentation/widgets/dialogs/app_dialogs.dart b/lib/src/common/presentation/widgets/dialogs/app_dialogs.dart index 3f36ad5..9dad0d7 100644 --- a/lib/src/common/presentation/widgets/dialogs/app_dialogs.dart +++ b/lib/src/common/presentation/widgets/dialogs/app_dialogs.dart @@ -1,6 +1,6 @@ import 'package:base_starter/src/common/presentation/widgets/app_loading_indicator.dart'; import 'package:base_starter/src/common/utils/extensions/context_extension.dart'; -import 'package:base_starter/src/core/localization/generated/l10n.dart'; +import 'package:base_starter/src/core/l10n/localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; diff --git a/lib/src/common/presentation/widgets/dialogs/change_environment.dart b/lib/src/common/presentation/widgets/dialogs/change_environment.dart index 3c4e7e1..ccde16b 100644 --- a/lib/src/common/presentation/widgets/dialogs/change_environment.dart +++ b/lib/src/common/presentation/widgets/dialogs/change_environment.dart @@ -4,9 +4,10 @@ import 'package:base_starter/src/common/constants/preferences.dart'; import 'package:base_starter/src/common/presentation/pages/restart_wrapper.dart'; import 'package:base_starter/src/common/presentation/widgets/dialogs/toaster.dart'; import 'package:base_starter/src/common/utils/extensions/context_extension.dart'; -import 'package:base_starter/src/core/localization/generated/l10n.dart'; +import 'package:base_starter/src/core/l10n/localization.dart'; import 'package:flutter/material.dart'; import 'package:gap/gap.dart'; +import 'package:iconsax_plus/iconsax_plus.dart'; import 'package:ispect/ispect.dart'; final class ChangeEnvironmentDialog { @@ -37,7 +38,7 @@ final class ChangeEnvironmentDialog { children: [ if (F.appFlavor == env) ...[ Icon( - Icons.check_circle_outline_rounded, + IconsaxPlusLinear.tick_square, color: context.theme.colorScheme.primary, ), const Gap(8), diff --git a/lib/src/core/l10n/localization.dart b/lib/src/core/l10n/localization.dart new file mode 100644 index 0000000..f451208 --- /dev/null +++ b/lib/src/core/l10n/localization.dart @@ -0,0 +1,42 @@ +import 'package:base_starter/src/core/l10n/generated/app_localizations.g.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_localizations/flutter_localizations.dart'; + +/// Localization class which is used to localize app. +/// This class provides handy methods and tools. +/// Usage: +/// Before using L10n.localizations, ensure to call L10n.load(locale). +/// Example: +/// L10n.load(Locale('en')); +/// var myString = L10n.localizations.someTranslation; +final class L10n { + static late AppLocalizations _localizations; + + /// Initialize the L10n class with the correct localization + static void load(Locale locale) { + _localizations = lookupAppLocalizations(locale); + } + + /// Access localized strings directly + static AppLocalizations get current => _localizations; + + static LocalizationsDelegate get delegate => + AppLocalizations.delegate; + + static List get supportedLocales => AppLocalizations.supportedLocales; + + static Locale get computeDefaultLocale { + final locale = WidgetsBinding.instance.platformDispatcher.locale; + + if (AppLocalizations.delegate.isSupported(locale)) return locale; + + return const Locale('en'); + } + + static List> get delegates => [ + AppLocalizations.delegate, + GlobalMaterialLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + ]; +} diff --git a/lib/src/core/localization/translations/intl_en.arb b/lib/src/core/l10n/translations/intl_en.arb similarity index 100% rename from lib/src/core/localization/translations/intl_en.arb rename to lib/src/core/l10n/translations/intl_en.arb diff --git a/lib/src/core/localization/translations/intl_ru.arb b/lib/src/core/l10n/translations/intl_ru.arb similarity index 100% rename from lib/src/core/localization/translations/intl_ru.arb rename to lib/src/core/l10n/translations/intl_ru.arb diff --git a/lib/src/core/localization/localization.dart b/lib/src/core/localization/localization.dart deleted file mode 100644 index ba42f7c..0000000 --- a/lib/src/core/localization/localization.dart +++ /dev/null @@ -1,22 +0,0 @@ -import 'package:base_starter/src/core/localization/generated/l10n.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_localizations/flutter_localizations.dart'; - -/// Localization class which is used to localize app. -/// This class provides handy methods and tools. -final class Localization { - static Locale get computeDefaultLocale { - final locale = WidgetsBinding.instance.platformDispatcher.locale; - - if (L10n.delegate.isSupported(locale)) return locale; - - return const Locale('en'); - } - - static List> get delegates => [ - L10n.delegate, - GlobalMaterialLocalizations.delegate, - GlobalCupertinoLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - ]; -} diff --git a/lib/src/core/rest_client/dio_rest_client/src/interceptor/dio_interceptor.dart b/lib/src/core/rest_client/dio_rest_client/src/interceptor/dio_interceptor.dart index 5f90814..c655672 100644 --- a/lib/src/core/rest_client/dio_rest_client/src/interceptor/dio_interceptor.dart +++ b/lib/src/core/rest_client/dio_rest_client/src/interceptor/dio_interceptor.dart @@ -2,7 +2,7 @@ import 'package:base_starter/src/common/constants/exception_keys.dart'; import 'package:base_starter/src/common/utils/utils.dart'; -import 'package:base_starter/src/core/localization/generated/l10n.dart'; +import 'package:base_starter/src/core/l10n/localization.dart'; import 'package:dio/dio.dart'; /// `DioInterceptor` - This class is used to intercept `dio` errors. diff --git a/lib/src/features/auth/presentation/auth.dart b/lib/src/features/auth/presentation/auth.dart index 5575cbf..423eeb8 100644 --- a/lib/src/features/auth/presentation/auth.dart +++ b/lib/src/features/auth/presentation/auth.dart @@ -3,7 +3,7 @@ import 'package:base_starter/src/common/presentation/widgets/buttons/app_button. import 'package:base_starter/src/common/presentation/widgets/dialogs/app_dialogs.dart'; import 'package:base_starter/src/common/presentation/widgets/dialogs/toaster.dart'; import 'package:base_starter/src/common/utils/extensions/context_extension.dart'; -import 'package:base_starter/src/core/localization/generated/l10n.dart'; +import 'package:base_starter/src/core/l10n/localization.dart'; import 'package:base_starter/src/features/auth/bloc/auth/auth_bloc.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/lib/src/features/home/presentation/home.dart b/lib/src/features/home/presentation/home.dart index ea0b27c..ff1a520 100644 --- a/lib/src/features/home/presentation/home.dart +++ b/lib/src/features/home/presentation/home.dart @@ -1,10 +1,11 @@ import 'package:base_starter/src/common/utils/extensions/context_extension.dart'; import 'package:base_starter/src/common/utils/extensions/string_extension.dart'; -import 'package:base_starter/src/core/localization/generated/l10n.dart'; +import 'package:base_starter/src/core/l10n/localization.dart'; import 'package:base_starter/src/features/home/state/counter.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:gap/gap.dart'; +import 'package:iconsax_plus/iconsax_plus.dart'; class HomePage extends ConsumerWidget { const HomePage({super.key}); @@ -25,13 +26,13 @@ class HomePage extends ConsumerWidget { FloatingActionButton( heroTag: 'increment', onPressed: () => ref.read(counterProvider.notifier).increment(), - child: const Icon(Icons.add), + child: const Icon(IconsaxPlusLinear.add), ), const Gap(8), FloatingActionButton( heroTag: 'decrement', onPressed: () => ref.read(counterProvider.notifier).decrement(), - child: const Icon(Icons.remove), + child: const Icon(IconsaxPlusLinear.minus), ), ], ), diff --git a/lib/src/features/initialization/logic/initialization_steps.dart b/lib/src/features/initialization/logic/initialization_steps.dart index 2f42e38..35c0234 100644 --- a/lib/src/features/initialization/logic/initialization_steps.dart +++ b/lib/src/features/initialization/logic/initialization_steps.dart @@ -4,8 +4,7 @@ import 'package:base_starter/flavors.dart'; import 'package:base_starter/src/common/constants/app_constants.dart'; import 'package:base_starter/src/common/constants/preferences.dart'; import 'package:base_starter/src/core/database/src/preferences/app_config_manager.dart'; -import 'package:base_starter/src/core/localization/generated/l10n.dart'; -import 'package:base_starter/src/core/localization/localization.dart'; +import 'package:base_starter/src/core/l10n/localization.dart'; import 'package:base_starter/src/core/rest_client/dio_rest_client/src/rest_client_dio.dart'; import 'package:base_starter/src/features/auth/bloc/auth/auth_bloc.dart'; import 'package:base_starter/src/features/auth/bloc/user/user_cubit.dart'; @@ -79,9 +78,9 @@ mixin InitializationSteps { final localeFuture = localeRepository.getLocale(); final theme = await themeRepository.getTheme(); - final locale = await localeFuture ?? Localization.computeDefaultLocale; + final locale = await localeFuture ?? L10n.computeDefaultLocale; - await L10n.load(locale); + L10n.load(locale); final initialState = IdleSettingsState(appTheme: theme, locale: locale); diff --git a/lib/src/features/initialization/presentation/widget/initialization_failed_app.dart b/lib/src/features/initialization/presentation/widget/initialization_failed_app.dart index df9fc49..933911a 100644 --- a/lib/src/features/initialization/presentation/widget/initialization_failed_app.dart +++ b/lib/src/features/initialization/presentation/widget/initialization_failed_app.dart @@ -5,8 +5,7 @@ import 'package:base_starter/src/core/assets/generated/assets.gen.dart'; import 'package:base_starter/src/core/di/containers/dependencies.dart'; import 'package:base_starter/src/core/di/containers/repositories.dart'; import 'package:base_starter/src/core/di/dependencies_scope.dart'; -import 'package:base_starter/src/core/localization/generated/l10n.dart'; -import 'package:base_starter/src/core/localization/localization.dart'; +import 'package:base_starter/src/core/l10n/localization.dart'; import 'package:base_starter/src/features/settings/bloc/settings_bloc.dart'; import 'package:base_starter/src/features/settings/core/data/locale/locale_datasource.dart'; import 'package:base_starter/src/features/settings/core/data/locale/locale_repository.dart'; @@ -19,6 +18,7 @@ import 'package:base_starter/src/features/settings/presentation/settings.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:gap/gap.dart'; +import 'package:iconsax_plus/iconsax_plus.dart'; import 'package:ispect/ispect.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:talker/talker.dart'; @@ -121,8 +121,8 @@ class _InitializationFailedAppState extends State { darkTheme: _settingsState?.appTheme?.darkTheme, themeMode: _settingsState?.appTheme?.mode, locale: _settingsState?.locale, - localizationsDelegates: Localization.delegates, - supportedLocales: L10n.delegate.supportedLocales, + localizationsDelegates: L10n.delegates, + supportedLocales: L10n.supportedLocales, home: _View( error: widget.error, retryInitialization: widget.retryInitialization != null @@ -185,7 +185,7 @@ class _View extends StatelessWidget { Padding( padding: const EdgeInsets.only(right: 8), child: IconButton.filledTonal( - icon: const Icon(Icons.monitor_heart), + icon: const Icon(IconsaxPlusLinear.activity), onPressed: () { Navigator.push( context, @@ -237,7 +237,8 @@ class _View extends StatelessWidget { ), const Gap(8), const Icon( - Icons.refresh_rounded, + IconsaxPlusLinear.refresh_2, + size: 18, color: Colors.white, ), ], diff --git a/lib/src/features/profile/presentation/profile.dart b/lib/src/features/profile/presentation/profile.dart index 92068e9..fb50c62 100644 --- a/lib/src/features/profile/presentation/profile.dart +++ b/lib/src/features/profile/presentation/profile.dart @@ -1,7 +1,8 @@ import 'package:base_starter/src/app/router/router.dart'; import 'package:base_starter/src/common/utils/extensions/context_extension.dart'; -import 'package:base_starter/src/core/localization/generated/l10n.dart'; +import 'package:base_starter/src/core/l10n/localization.dart'; import 'package:flutter/material.dart'; +import 'package:iconsax_plus/iconsax_plus.dart'; class ProfilePage extends StatefulWidget { const ProfilePage({super.key}); @@ -11,6 +12,11 @@ class ProfilePage extends StatefulWidget { } class _ProfilePageState extends State { + @override + void initState() { + super.initState(); + } + @override Widget build(BuildContext context) => Scaffold( appBar: AppBar( @@ -24,7 +30,7 @@ class _ProfilePageState extends State { padding: const EdgeInsets.only(right: 16), child: IconButton.filledTonal( icon: const Icon( - Icons.settings_rounded, + IconsaxPlusLinear.setting_2, color: Colors.white, ), onPressed: () => SettingsRoute( diff --git a/lib/src/features/settings/bloc/settings_bloc.dart b/lib/src/features/settings/bloc/settings_bloc.dart index 9500074..94f9598 100644 --- a/lib/src/features/settings/bloc/settings_bloc.dart +++ b/lib/src/features/settings/bloc/settings_bloc.dart @@ -1,5 +1,5 @@ import 'package:base_starter/src/app/model/app_theme.dart'; -import 'package:base_starter/src/core/localization/generated/l10n.dart'; +import 'package:base_starter/src/core/l10n/localization.dart'; import 'package:base_starter/src/features/settings/core/domain/locale/locale_repository.dart'; import 'package:base_starter/src/features/settings/core/domain/theme/theme_repository.dart'; import 'package:equatable/equatable.dart'; @@ -65,7 +65,7 @@ class SettingsBloc extends Bloc { try { await _localeRepo.setLocale(event.locale); - await L10n.load(event.locale); + L10n.load(event.locale); emit( IdleSettingsState(appTheme: state.appTheme, locale: event.locale), diff --git a/lib/src/features/settings/presentation/controller/settings_scope.dart b/lib/src/features/settings/presentation/controller/settings_scope.dart index 957d805..7a8fb32 100644 --- a/lib/src/features/settings/presentation/controller/settings_scope.dart +++ b/lib/src/features/settings/presentation/controller/settings_scope.dart @@ -104,7 +104,7 @@ class _SettingsScopeState extends State @override Locale get locale => - widget.settingsBloc.state.locale ?? Localization.computeDefaultLocale; + widget.settingsBloc.state.locale ?? L10n.computeDefaultLocale; @override AppTheme get theme => diff --git a/lib/src/features/settings/presentation/settings.dart b/lib/src/features/settings/presentation/settings.dart index 41ba1b0..f5ec7b6 100644 --- a/lib/src/features/settings/presentation/settings.dart +++ b/lib/src/features/settings/presentation/settings.dart @@ -6,14 +6,14 @@ import 'package:base_starter/src/common/presentation/widgets/dialogs/change_envi import 'package:base_starter/src/common/presentation/widgets/dialogs/toaster.dart'; import 'package:base_starter/src/common/services/page_lifecycle_model.dart'; import 'package:base_starter/src/common/utils/extensions/context_extension.dart'; -import 'package:base_starter/src/core/localization/generated/l10n.dart'; -import 'package:base_starter/src/core/localization/localization.dart'; +import 'package:base_starter/src/core/l10n/localization.dart'; import 'package:base_starter/src/features/auth/bloc/auth/auth_bloc.dart'; import 'package:base_starter/src/features/settings/bloc/settings_bloc.dart'; import 'package:base_starter/src/features/settings/presentation/controller/settings_model.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:gap/gap.dart'; +import 'package:iconsax_plus/iconsax_plus.dart'; import 'package:ispect/ispect.dart'; part 'controller/settings_scope.dart'; @@ -60,7 +60,7 @@ class _SettingsPageState extends State { leading: IconButton( onPressed: () => context.pop(), icon: const Icon( - Icons.arrow_back, + IconsaxPlusLinear.arrow_square_left, ), ), title: Text( @@ -80,7 +80,7 @@ class _SettingsPageState extends State { ), ), _LanguagesSelector( - languages: L10n.delegate.supportedLocales, + languages: L10n.supportedLocales, onLocaleTapped: (locale) { SettingsScope.localeOf(context).setLocale(locale); }, diff --git a/pubspec.yaml b/pubspec.yaml index 42678ff..e2f5e21 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -58,6 +58,7 @@ dependencies: auto_size_text: ^3.0.0 fluttertoast: ^8.2.8 ispect: ^1.9.3-beta.8 + iconsax_plus: ^1.0.0 # Others provider: ^6.1.2 @@ -105,13 +106,6 @@ flutter_gen: output: lib/src/core/assets/generated line_length: 80 -flutter_intl: - enabled: true - class_name: L10n - main_locale: en - arb_dir: lib/src/core/localization/translations - output_dir: lib/src/core/localization/generated - flutter_launcher_icons: # dart pub run flutter_launcher_icons # image_path: "assets/images/icon-128x128.png" image_path_android: "assets/images/icon-1024x1024.png" diff --git a/untranslated_messages.txt b/untranslated_messages.txt new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/untranslated_messages.txt @@ -0,0 +1 @@ +{} \ No newline at end of file