From afefe19fb0f3687f5c3a3a667dbbfd0bba37d795 Mon Sep 17 00:00:00 2001 From: Alex Rintt <51419598+alexrintt@users.noreply.github.com> Date: Mon, 12 Jun 2023 01:10:49 -0300 Subject: [PATCH] Remove hardcoded strings and replace with translation keys --- README.md | 12 +- i18n/{app_de.arb => de.arb} | 1 + i18n/{app_en.arb => en.arb} | 106 +++- i18n/{app_es.arb => es.arb} | 1 + i18n/{app_it.arb => it.arb} | 1 + i18n/{app_ja.arb => ja.arb} | 1 + i18n/{app_pt.arb => pt.arb} | 1 + l10n.yaml | 2 +- lib/pages/settings_page.dart | 32 +- lib/screens/app_list_screen.dart | 23 +- lib/screens/background_task_list_screen.dart | 11 +- lib/screens/file_list_screen.dart | 5 +- lib/stores/settings_store.dart | 32 +- lib/stores/theme_store.dart | 38 +- lib/utils/app_localization_strings.dart | 10 - lib/utils/context_confirm.dart | 14 +- .../context_show_apk_result_message.dart | 4 +- lib/utils/context_try_install_apk.dart | 5 +- lib/utils/copy_to_clipboard.dart | 3 +- lib/widgets/apk_file_menu_bottom_sheet.dart | 40 +- lib/widgets/apk_file_tile.dart | 3 +- lib/widgets/apk_list_progress_stepper.dart | 19 +- .../background_task_list_contextual_menu.dart | 12 +- lib/widgets/bottom_navigation.dart | 7 +- lib/widgets/file_list_contextual_menu.dart | 2 +- lib/widgets/package_menu_bottom_sheet.dart | 29 +- missing-translations.txt | 502 +++++++++++++++++- pubspec.lock | 2 +- website/docs/build-yourself.md | 4 + 29 files changed, 765 insertions(+), 157 deletions(-) rename i18n/{app_de.arb => de.arb} (98%) rename i18n/{app_en.arb => en.arb} (53%) rename i18n/{app_es.arb => es.arb} (98%) rename i18n/{app_it.arb => it.arb} (98%) rename i18n/{app_ja.arb => ja.arb} (99%) rename i18n/{app_pt.arb => pt.arb} (98%) diff --git a/README.md b/README.md index c155ec2..2c5e85b 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,11 @@ PlayStore link, add again when the new version is available. There are several ways to contribute: -- To improve the translation: 1. open the `/i18n` folder, 2. create a file `app_.arb` and 3. translate the keys 4. then open a PR, that's it. +- To improve the translation: + 1. Open the `/i18n` folder. + 2. Create/edit a file `.arb` (e.g `en.arb`). + 3. Translate the keys. + 4. Open a PR, that's it. - To report a bug, create a new issue with an screenshot or a small description of the bug. - To request a feature please add an issue to further discuss. @@ -103,9 +107,11 @@ If you wanna contribute in private, you can also ping me on my email [kanade@ale ## Contributors -- Glad to have your work here [@WSTxda](https://linktr.ee/wstxda)! Thanks for your efforts on the [app icon](https://t.me/WSTprojects/1401), banner and the download badges. +- [Fantazzj](https://github.com/Fantazzj) added Italian language support. +- [@WSTxda](https://linktr.ee/wstxda) made the v0.4.0 app icon and provided support in the v0.5.0 icon. +- [IzzySoft](https://gitlab.com/IzzySoft) reported a issue with android version code [#13](https://github.com/alexrintt/kanade/issues/13) and added fastlane docs [#15](https://github.com/alexrintt/kanade/pull/15). -- I wanna thanks [IzzySoft](https://gitlab.com/IzzySoft) for taking time to point the [version code issue #13](https://github.com/alexrintt/kanade/issues/13), indexing this app to the [IzzyOnDroid app repository](https://gitlab.com/IzzyOnDroid/repo) and [helping with fastlane docs #15](https://github.com/alexrintt/kanade/pull/15), thanks man! +Thanks to all contributors! ## Credits diff --git a/i18n/app_de.arb b/i18n/de.arb similarity index 98% rename from i18n/app_de.arb rename to i18n/de.arb index a755389..356c437 100644 --- a/i18n/app_de.arb +++ b/i18n/de.arb @@ -1,4 +1,5 @@ { + "@@locale": "de", "settings": "Einstellungen", "selectOutputFolder": "Ausgabeordner auswählen", "notDefined": "Nicht definiert", diff --git a/i18n/app_en.arb b/i18n/en.arb similarity index 53% rename from i18n/app_en.arb rename to i18n/en.arb index 424d225..ede4cd5 100644 --- a/i18n/app_en.arb +++ b/i18n/en.arb @@ -1,5 +1,101 @@ { + "@@locale": "en", + "behaviorPreferences": "Behavior preferences", + "appearancePreferences": "Appearance preferences", + "donate": "Donate", + "links": "Links", + "openSourceLicenses": "Open source licenses", + "reportIssue": "Report issue", + "followMeOnGitHub": "Follow me on GitHub", + "githubRepository": "GitHub repository", + "packageAndVersion": "Package and version", + "overscrollIndicator": "Overscroll indicator", + "donateOnGitHub": "Donate on GitHub (Card)", + "donateOnKofi": "Ko-fi (Card or PayPal)", + "donateUsingPix": "Pix donation (Brazil only)", + "donateUsingBtc": "BTC donation", + "otherDonationMethods": "Other donation methods", + "unnamedPackage": "Unnamed package", + "version": "Version", + "unavailable": "Unavailable", + "user": "User", + "builtIn": "Built-in", + "system": "System", + "noResults": "No results!", + "cancelTask": "Cancel task", + "darkSimple": "Dark light", + "extractionIsNotFinishedCanNotInstallYet": "Not fully extracted yet, can not install right now", + "tasksAreAlreadyBeingDeleted": "These tasks were deleted and will be removed soon", + "loadingInfoEllipsis": "Loading info...", + "notAvailable": "Not available", + "openingFolderIsNotSupportedYet": "Opening a folder is not supported yet", + "confirmIrreversibleActionsExplanation": "Ask for confirmation whenever the user tries to do any irreversible action like deleting a file.", + "filterWillRemoveSomeSelectedItems": "This filter will erase some of your selected items, and you will need to re-select them again", + "hideAppBarOnScroll": "Hide app bar on scroll", + "extractWithSingleClick": "Extract with single click", + "confirmIrreversibleActions": "Ask for confirmation", + "displayUserInstalledApps": "Show user installed apps", + "displaySystemApps": "Show system apps", + "displayBuiltInApps": "Show built-in apps", + "transparentNavigationBar": "Translucent glass effect", + "hideAppBarOnScrollExplanation": "If enabled, the app bar will automatically hide when scroll down.", + "displaySystemAppsExplanation": "If enabled the home list will include system apps, they may not be launchable.", + "noActivityFoundThatCanHandleThisFileType": "There's no activity that can handle this file", + "displayBuiltInAppsExplanation": "If enabled the home list will include built-in apps, they are like system apps but openable.", + "displayUserInstalledAppsExplanation": "If enabled the home list will include apps installed by you.", + "transparentNavigationBarExplanation": "Apply a blur transparent effect to the home navigation bar.", + "trySelectingAtLeastOneFilter": "Try selecting at least one filter!", + "extractWithSingleClickExplanation": "If enabled, the app list will extract apk with a single click instead of opening the details page.", + "paymentMethodCard": "Card", "settings": "Settings", + "goToAppList": "Go to app list", + "invalidApkItWasProbablyDeleted": "Invalid apk, is was probably deleted.", + "openFileLocation": "Open file location", + "resetAllPreferencesQuestion": "Reset all preferences?", + "exportApkExplanationMessage": "The apk list will appear here, to get start try to click over a tile on the app list screen! It will create a new export job that will copy the app apk to the folder you chose.", + "storagePermissionExplanationMessage": "To extract the apks this app needs access permission to a folder. It is recommended to select an empty folder or create a new one. It is also important to not select folders that are reserved by the system, such as the Android or Downloads folder.", + "notSet": "Not set", + "resetFolder": "Reset folder", + "launchApp": "Launch app", + "allFiles": "All files", + "exportApk": "Export apk", + "extracted": "Extracted", + "openOnPlayStore": "Open on Play Store", + "openOnFDroid": "Open on F-Droid", + "searchOnline": "Search online", + "remove": "Remove", + "deleteAllSelected": "Delete all selected", + "doYouWantToForceBulkDeleteAllTheseTasks": "Do you want force a bulk delete on all these tasks?", + "doYouWantToForceBulkCancelAllTheseTasks": "Do you want force a bulk cancel on all these tasks?", + "apps": "Apps", + "couldNotFindTargetFile": "We could not find the target file", + "couldNotFindFileLocationWithExplanation": "Could not find the file location this either was deleted or we have no permission over the folder.", + "soonEllipsis": "Soon...", + "soon": "Soon", + "loadingInfo": "Loading info", + "copiedToClipboard": "Copied to clipboard", + "invalidPackageUri": "Invalid package Uri", + "share": "Share", + "bouncing": "Bouncing", + "glow": "Glow", + "none": "None", + "areYouSure": "Are you sure?", + "delete": "Delete", + "shareApk": "Share apk", + "cancel": "Cancel", + "confirm": "Confirm", + "install": "Install", + "thisIsIrreversible": "This is a irreversible action, be sure you want to do it.", + "couldNotExtractWithExplanation": "Could not extract, this apk was probably uninstalled because we did not found it is apk file", + "installApk": "Install apk", + "extract": "Extract", + "successQueued": "Success! check \"Extracted\" tab", + "extractApk": "Extract apk", + "packageNameIsNotAvailable": "Package name is not available", + "copyPackageName": "Copy package name", + "packageIdIsNotAvailable": "Package ID is not available", + "copyPackageId": "Copy package ID", + "uninstall": "Uninstall", "@settings": { "description": "Label for the settings page." }, @@ -21,7 +117,7 @@ }, "ofN": "of", "@ofN": { - "description": "String to be used as preposition." + "description": "String to be used as preposition, e.g: Showing 10 results of 1000." }, "extractAllSelected": "Extract all selected", "@extractAllSelected": { @@ -103,12 +199,12 @@ "@followTheSystem": { "description": "One of the available themes representing a theme that follows the device/system theme." }, - "darkHacker": "Dark hacker", - "@darkHacker": { + "greenDark": "Dark hacker", + "@greenDark": { "description": "One of the available themes representing a dark lights out with green as primary color." }, - "darkBlood": "Dark blood", - "@darkBlood": { + "redDark": "Red dark", + "@redDark": { "description": "One of the available themes representing a dark lights out with red as primary color." }, "someApkWereNotExtracted": "Some apks are located in {apkLocation} but some could not be extracted", diff --git a/i18n/app_es.arb b/i18n/es.arb similarity index 98% rename from i18n/app_es.arb rename to i18n/es.arb index 2272111..735787d 100644 --- a/i18n/app_es.arb +++ b/i18n/es.arb @@ -1,4 +1,5 @@ { + "@@locale": "es", "settings": "Configuraciones", "selectOutputFolder": "Seleccionar carpeta de salida", "notDefined": "No definido", diff --git a/i18n/app_it.arb b/i18n/it.arb similarity index 98% rename from i18n/app_it.arb rename to i18n/it.arb index 4d0c1bc..dd0c679 100644 --- a/i18n/app_it.arb +++ b/i18n/it.arb @@ -1,4 +1,5 @@ { + "@@locale": "it", "settings": "Impostazioni", "selectOutputFolder": "Seleziona cartella di output", "notDefined": "Non definita", diff --git a/i18n/app_ja.arb b/i18n/ja.arb similarity index 99% rename from i18n/app_ja.arb rename to i18n/ja.arb index c4af695..fadf7ea 100644 --- a/i18n/app_ja.arb +++ b/i18n/ja.arb @@ -1,4 +1,5 @@ { + "@@locale": "ja", "settings": "設定", "selectOutputFolder": "出力フォルダを選択", "notDefined": "定義されていません", diff --git a/i18n/app_pt.arb b/i18n/pt.arb similarity index 98% rename from i18n/app_pt.arb rename to i18n/pt.arb index d0b38db..a319992 100644 --- a/i18n/app_pt.arb +++ b/i18n/pt.arb @@ -1,4 +1,5 @@ { + "@@locale": "pt", "settings": "Configurações", "selectOutputFolder": "Selecionar a pasta de saída", "notDefined": "Não definido", diff --git a/l10n.yaml b/l10n.yaml index d47c1d1..f920656 100644 --- a/l10n.yaml +++ b/l10n.yaml @@ -1,4 +1,4 @@ arb-dir: ./i18n -template-arb-file: app_en.arb +template-arb-file: en.arb output-localization-file: app_localizations.dart untranslated-messages-file: missing-translations.txt diff --git a/lib/pages/settings_page.dart b/lib/pages/settings_page.dart index e1936b4..736487a 100644 --- a/lib/pages/settings_page.dart +++ b/lib/pages/settings_page.dart @@ -71,7 +71,7 @@ class _SettingsPageState extends State onTap: () async { final bool confirmed = await showConfirmationModal( context: context, - message: 'Reset all preferences?', + message: context.strings.resetAllPreferencesQuestion, ); if (confirmed) { @@ -96,14 +96,14 @@ class _SettingsPageState extends State const AppFontFamilySettingsTile(), const AppLocalizationSettingsTile(), const HorizontalRule(), - const SettingsTileTitle('Behavior preferences'), + SettingsTileTitle(context.strings.behaviorPreferences), AppBooleanPreferencesSettingsTile( values: SettingsBoolPreference.filterBy( category: SettingsBoolPreferenceCategory.behavior, ), ), const HorizontalRule(), - const SettingsTileTitle('Appearance preferences'), + SettingsTileTitle(context.strings.appearancePreferences), const AppOverscrollPhysicsTile(), AppBooleanPreferencesSettingsTile( values: SettingsBoolPreference.filterBy( @@ -111,10 +111,10 @@ class _SettingsPageState extends State ), ), const HorizontalRule(), - const SettingsTileTitle('Donate'), + SettingsTileTitle(context.strings.donate), const DonationSettingsTile(), const HorizontalRule(), - const SettingsTileTitle('Links'), + SettingsTileTitle(context.strings.links), const RelatedLinks(), const HorizontalRule(), const Padding( @@ -170,25 +170,25 @@ class _RelatedLinksState extends State mainAxisSize: MainAxisSize.min, children: [ buildTile( - title: 'Open source licenses', + title: context.strings.openSourceLicenses, onTap: () => showLicensePage(context: context), ), buildTile( - title: 'Report a issue', + title: context.strings.reportIssue, onTap: openThisLink('https://github.com/alexrintt/kanade/issues'), ), buildTile( - title: 'Follow me on GitHub', + title: context.strings.followMeOnGitHub, onTap: openThisLink('https://github.com/alexrintt'), description: '@alexrintt', ), buildTile( - title: 'GitHub repository', + title: context.strings.githubRepository, onTap: openThisLink('https://github.com/alexrintt/kanade'), description: 'github.com/alexrintt/kanade', ), buildTile( - title: 'Package and version', + title: context.strings.packageAndVersion, onTap: copyThisText(_packageVersion), description: _packageVersion, ), @@ -333,7 +333,7 @@ class _AppOverscrollPhysicsTileState extends State horizontal: k10dp, ), enableFeedback: true, - title: const Text('Overscroll indicator'), + title: Text(context.strings.overscrollIndicator), subtitle: AnimatedBuilder( animation: themeStore, builder: (BuildContext context, Widget? child) { @@ -514,28 +514,28 @@ class _DonationSettingsTileState extends State mainAxisSize: MainAxisSize.min, children: [ buildTile( - title: 'Donate on GitHub (Card)', + title: context.strings.donateOnGitHub, onTap: openThisLink(_githubSponsor.toString()), description: _githubSponsor.host + _githubSponsor.path, ), buildTile( - title: 'Ko-fi (Card or PayPal)', + title: context.strings.donateOnKofi, onTap: openThisLink(_kofi.toString()), description: _kofi.host + _kofi.path, ), buildTile( - title: 'Pix donation (Brazil only)', + title: context.strings.donateUsingPix, onTap: openThisLink(_livePix.toString()), description: _livePix.host + _livePix.path, ), buildTile( - title: 'BTC donation', + title: context.strings.donateUsingBtc, onLongPress: copyThisText(_btcAddress), onTap: copyThisText(_btcAddress), description: _btcAddress, ), buildTile( - title: 'Other donation methods', + title: context.strings.otherDonationMethods, onTap: openThisLink('https://donate.alexrintt.io'), description: 'donate.alexrintt.io', ), diff --git a/lib/screens/app_list_screen.dart b/lib/screens/app_list_screen.dart index 761bccf..bdbf889 100644 --- a/lib/screens/app_list_screen.dart +++ b/lib/screens/app_list_screen.dart @@ -13,6 +13,7 @@ import '../stores/contextual_menu_store.dart'; import '../stores/device_apps_store.dart'; import '../stores/settings_store.dart'; import '../stores/theme_store.dart'; +import '../utils/app_localization_strings.dart'; import '../utils/context_confirm.dart'; import '../utils/context_of.dart'; import '../utils/context_show_apk_result_message.dart'; @@ -210,7 +211,7 @@ class _MainAppListState extends State builder: (_) => InstalledAppMenuOptions( iconBytes: package.icon, packageId: package.id, - title: package.name ?? package.id ?? 'Unnamed package', + title: package.name ?? package.id ?? context.strings.unnamedPackage, subtitle: _generatePackageSubtitle(package), packageInstallerFile: package.installerPath != null ? File(package.installerPath!) : null, @@ -266,8 +267,7 @@ class _MainAppListState extends State final bool confirmed = await showConfirmationModal( context: context, force: true, - message: - 'This filter will erase some of your selected items, and you will need to re-select them again', + message: context.strings.filterWillRemoveSomeSelectedItems, ); if (!confirmed) return; @@ -290,7 +290,9 @@ class _MainAppListState extends State if (package.versionName != null) { final String before = subtitle.isNotEmpty ? ' (' : ''; final String after = subtitle.isNotEmpty ? ')' : ''; - subtitle.write('${before}Version: ${package.versionName}$after'); + subtitle.write( + '$before${context.strings.version}: ${package.versionName}$after', + ); } if (subtitle.isEmpty && package.name != null) { @@ -301,7 +303,7 @@ class _MainAppListState extends State return subtitle.toString(); } - return 'Unavailable'; + return context.strings.unavailable; } Widget _buildFilterChips() { @@ -330,15 +332,15 @@ class _MainAppListState extends State ), ), _buildInstalledAppsFilterChip( - 'User', + context.strings.user, SettingsBoolPreference.displayUserInstalledApps, ), _buildInstalledAppsFilterChip( - 'Built-in', + context.strings.builtIn, SettingsBoolPreference.displayBuiltInApps, ), _buildInstalledAppsFilterChip( - 'System', + context.strings.system, SettingsBoolPreference.displaySystemApps, ), ], @@ -419,8 +421,9 @@ class _MainAppListState extends State padding: const EdgeInsets.all(k8dp), child: LooksEmptyHere( message: store.isSearchMode - ? 'No results!' - : 'Try selecting at least one filter!', + ? context.strings.noResults + : context + .strings.trySelectingAtLeastOneFilter, ), ), Padding( diff --git a/lib/screens/background_task_list_screen.dart b/lib/screens/background_task_list_screen.dart index 483213e..e9dbdf7 100644 --- a/lib/screens/background_task_list_screen.dart +++ b/lib/screens/background_task_list_screen.dart @@ -10,6 +10,7 @@ import '../stores/contextual_menu_store.dart'; import '../stores/localization_store.dart'; import '../stores/settings_store.dart'; import '../utils/app_icons.dart'; +import '../utils/app_localization_strings.dart'; import '../utils/context_of.dart'; import '../utils/context_try_install_apk.dart'; import '../utils/package_bytes.dart'; @@ -221,7 +222,7 @@ class _BackgroundTaskTileState extends State return AppIconButton( onTap: () => backgroundTaskStore.cancelBackgroundTask(widget.task), icon: Icon(AppIcons.x.data, size: AppIcons.x.size), - tooltip: 'Cancel task', + tooltip: context.strings.cancelTask, ); } @@ -257,14 +258,14 @@ class _BackgroundTaskTileState extends State case TaskStatus.initial: showToast( context, - 'Not fully extracted yet, can not install right now', + context.strings.extractionIsNotFinishedCanNotInstallYet, ); break; case TaskStatus.deleted: case TaskStatus.deleteRequested: showToast( context, - 'These tasks were deleted and will be removed soon', + context.strings.tasksAreAlreadyBeingDeleted, ); break; case TaskStatus.finished: @@ -283,7 +284,7 @@ class _BackgroundTaskTileState extends State Widget build(BuildContext context) { return AppListTile( onTap: _onBackgroundTaskTileTapped, - title: Text(widget.task.title ?? 'Loading info...'), + title: Text(widget.task.title ?? context.strings.loadingInfoEllipsis), subtitle: Text(_taskSubtitle), trailing: _buildTrailing(), onPopupMenuTapped: () async { @@ -304,7 +305,7 @@ class _BackgroundTaskTileState extends State packageInstallerUri: widget.task.targetUri, iconUri: widget.task.apkIconUri, subtitle: _taskSubtitle, - title: widget.task.title ?? 'Not available', + title: widget.task.title ?? context.strings.notAvailable, ), ); }, diff --git a/lib/screens/file_list_screen.dart b/lib/screens/file_list_screen.dart index c24e622..db8b7e3 100644 --- a/lib/screens/file_list_screen.dart +++ b/lib/screens/file_list_screen.dart @@ -11,6 +11,7 @@ import '../stores/file_list_store.dart'; import '../stores/localization_store.dart'; import '../stores/settings_store.dart'; import '../utils/app_icons.dart'; +import '../utils/app_localization_strings.dart'; import '../utils/context_of.dart'; import '../utils/mime_types.dart'; import '../utils/package_bytes.dart'; @@ -261,14 +262,14 @@ class _DocumentFileTileState extends State _toggleSelect(); } else { if (widget.file.isDirectory ?? false) { - showToast(context, 'Opening a folder is not supported yet'); + showToast(context, context.strings.openingFolderIsNotSupportedYet); } else { try { await widget.file.open(); } on PlatformException { showToast( context, - "There's no activity that can handle this file", + context.strings.noActivityFoundThatCanHandleThisFileType, ); } } diff --git a/lib/stores/settings_store.dart b/lib/stores/settings_store.dart index 006162b..2f1f9f4 100644 --- a/lib/stores/settings_store.dart +++ b/lib/stores/settings_store.dart @@ -203,41 +203,41 @@ enum SettingsBoolPreference { final SettingsBoolPreferenceCategory category; - String getNameString(AppLocalizations localizations) { + String getNameString(AppLocalizations strings) { switch (this) { case SettingsBoolPreference.hideAppBarOnScroll: - return 'Hide app bar on scroll'; + return strings.hideAppBarOnScroll; case SettingsBoolPreference.extractWithSingleClick: - return 'Extract with single click'; + return strings.extractWithSingleClick; case SettingsBoolPreference.confirmIrreversibleActions: - return 'Ask for confirmation'; + return strings.confirmIrreversibleActions; case SettingsBoolPreference.displaySystemApps: - return 'Show system apps'; + return strings.displaySystemApps; case SettingsBoolPreference.displayBuiltInApps: - return 'Show built-in apps'; + return strings.displayBuiltInApps; case SettingsBoolPreference.displayUserInstalledApps: - return 'Show user installed apps'; + return strings.displayUserInstalledApps; case SettingsBoolPreference.transparentNavigationBar: - return 'Translucent glass effect'; + return strings.transparentNavigationBar; } } - String getDescriptionString(AppLocalizations localizations) { + String getDescriptionString(AppLocalizations strings) { switch (this) { case SettingsBoolPreference.confirmIrreversibleActions: - return 'Ask for confirmation whenever the user tries to do any irreversible action like deleting a file.'; + return strings.confirmIrreversibleActionsExplanation; case SettingsBoolPreference.hideAppBarOnScroll: - return 'If enabled, the app bar will automatically hide when scroll down.'; + return strings.hideAppBarOnScrollExplanation; case SettingsBoolPreference.displaySystemApps: - return 'If enabled the home list will include system apps, they may not be launchable.'; + return strings.displaySystemAppsExplanation; case SettingsBoolPreference.displayBuiltInApps: - return 'If enabled the home list will include built-in apps, they are like system apps but openable.'; + return strings.displayBuiltInAppsExplanation; case SettingsBoolPreference.displayUserInstalledApps: - return 'If enabled the home list will include apps installed by you.'; + return strings.displayUserInstalledAppsExplanation; case SettingsBoolPreference.transparentNavigationBar: - return 'Apply a blur transparent effect to the home navigation bar.'; + return strings.transparentNavigationBarExplanation; case SettingsBoolPreference.extractWithSingleClick: - return 'If enabled, the app list will extract apk with a single click instead of opening the details page.'; + return strings.extractWithSingleClickExplanation; } } diff --git a/lib/stores/theme_store.dart b/lib/stores/theme_store.dart index 6bd1483..337c184 100644 --- a/lib/stores/theme_store.dart +++ b/lib/stores/theme_store.dart @@ -13,28 +13,28 @@ import 'key_value_storage.dart'; enum AppTheme { darkLightsOut, darkDimmed, - darkLight, + darkSimple, lightDefault, - darkHacker, - darkBlood, + greenDark, + redDark, followSystem; String getNameString(AppLocalizations strings) { switch (this) { case AppTheme.darkDimmed: return strings.darkDimmed; - case AppTheme.darkLight: - return 'Dark light'; + case AppTheme.darkSimple: + return strings.darkSimple; case AppTheme.lightDefault: return strings.light; case AppTheme.followSystem: return strings.followTheSystem; case AppTheme.darkLightsOut: return strings.darkLightsOut; - case AppTheme.darkHacker: - return strings.darkHacker; - case AppTheme.darkBlood: - return strings.darkBlood; + case AppTheme.greenDark: + return strings.greenDark; + case AppTheme.redDark: + return strings.redDark; } } @@ -311,15 +311,15 @@ class ThemeStore extends ChangeNotifier { return _lightDefaultThemeData(); case AppTheme.darkLightsOut: return _darkLightsOutThemeData(); - case AppTheme.darkHacker: + case AppTheme.greenDark: return _darkHackerThemeData(); - case AppTheme.darkBlood: + case AppTheme.redDark: return _darkBloodThemeData(); case AppTheme.followSystem: return currentThemeBrightness == Brightness.dark ? _darkLightThemeData() : _lightDefaultThemeData(); - case AppTheme.darkLight: + case AppTheme.darkSimple: return _darkLightThemeData(); } } @@ -332,13 +332,13 @@ class ThemeStore extends ChangeNotifier { return Brightness.light; case AppTheme.darkLightsOut: return Brightness.dark; - case AppTheme.darkHacker: + case AppTheme.greenDark: return Brightness.dark; - case AppTheme.darkBlood: + case AppTheme.redDark: return Brightness.dark; case AppTheme.followSystem: return SchedulerBinding.instance.platformDispatcher.platformBrightness; - case AppTheme.darkLight: + case AppTheme.darkSimple: return Brightness.dark; } } @@ -420,14 +420,14 @@ enum OverscrollPhysics { OverscrollPhysics.none; /// Font family name decribed in the pubspec.yaml - String getNameString(AppLocalizations localizations) { + String getNameString(AppLocalizations strings) { switch (this) { case OverscrollPhysics.bouncing: - return 'Bouncing'; + return strings.bouncing; case OverscrollPhysics.glow: - return 'Glow'; + return strings.glow; case OverscrollPhysics.none: - return 'None'; + return strings.none; } } diff --git a/lib/utils/app_localization_strings.dart b/lib/utils/app_localization_strings.dart index e327b11..c4f896f 100644 --- a/lib/utils/app_localization_strings.dart +++ b/lib/utils/app_localization_strings.dart @@ -2,16 +2,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'lang_code_full_names.dart'; -extension StringWithParams on String { - String withArgs(List args) { - final RegExp paramRegExp = RegExp('{{.*}}'); - - int index = 0; - - return replaceAllMapped(paramRegExp, (Match match) => args[index++]); - } -} - extension ContextStrings on BuildContext { AppLocalizations get strings => AppLocalizations.of(this)!; } diff --git a/lib/utils/context_confirm.dart b/lib/utils/context_confirm.dart index d2d5a8c..813da53 100644 --- a/lib/utils/context_confirm.dart +++ b/lib/utils/context_confirm.dart @@ -3,6 +3,7 @@ import 'package:flutter_shared_tools/flutter_shared_tools.dart'; import '../setup.dart'; import '../stores/settings_store.dart'; +import 'app_localization_strings.dart'; Future showConfirmationModal({ required BuildContext context, @@ -19,10 +20,9 @@ Future showConfirmationModal({ context: context, builder: (BuildContext context) { return AlertDialog( - title: const Text('Are you sure?'), + title: Text(context.strings.areYouSure), content: Text( - message ?? - 'This is a irreversible action, be sure you want to do it.', + message ?? context.strings.thisIsIrreversible, style: const TextStyle( fontSize: 12, ), @@ -32,15 +32,15 @@ Future showConfirmationModal({ onPressed: () { context.pop(false); }, - child: const Text('Cancel'), + child: Text(context.strings.cancel), ), TextButton( onPressed: () { context.pop(true); }, - child: const Text( - 'Confirm', - style: TextStyle(color: Colors.red), + child: Text( + context.strings.confirm, + style: const TextStyle(color: Colors.red), ), ), ], diff --git a/lib/utils/context_show_apk_result_message.dart b/lib/utils/context_show_apk_result_message.dart index 358d954..d3144ce 100644 --- a/lib/utils/context_show_apk_result_message.dart +++ b/lib/utils/context_show_apk_result_message.dart @@ -22,13 +22,13 @@ extension ContextShowApkResultMessage on BuildContext { case SingleExtractionResult.notFound: showToast( this, - 'Could not extract, this apk was probably uninstalled because we did not found it is apk file', + strings.couldNotExtractWithExplanation, ); break; case SingleExtractionResult.queued: // The bottom navigation bar actually changes its badge indicator, // so we don't need to do anything here to indicate the apk is being extracted. - showToast(this, 'Success! check "Extracted" tab'); + showToast(this, strings.successQueued); break; } } diff --git a/lib/utils/context_try_install_apk.dart b/lib/utils/context_try_install_apk.dart index 4d325fd..6e2543d 100644 --- a/lib/utils/context_try_install_apk.dart +++ b/lib/utils/context_try_install_apk.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import '../stores/background_task_store.dart'; import '../stores/indexed_collection_store.dart'; import '../widgets/toast.dart'; +import 'app_localization_strings.dart'; extension ContextTryInstallApk on BuildContext { Future tryInstallPackage({ @@ -11,7 +12,7 @@ extension ContextTryInstallApk on BuildContext { Uri? packageUri, }) async { if (packageUri == null) { - return showToast(this, 'Invalid package Uri, got null'); + return showToast(this, strings.invalidPackageUri); } final PackageInstallationIntentResult result = @@ -24,7 +25,7 @@ extension ContextTryInstallApk on BuildContext { if (mounted) { showToast( this, - 'Invalid apk, it is was probably deleted.', + strings.invalidApkItWasProbablyDeleted, ); } } diff --git a/lib/utils/copy_to_clipboard.dart b/lib/utils/copy_to_clipboard.dart index ccd5c58..cacc8bb 100644 --- a/lib/utils/copy_to_clipboard.dart +++ b/lib/utils/copy_to_clipboard.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import '../widgets/toast.dart'; +import 'app_localization_strings.dart'; Future copyTextToClipboard(String text) => Clipboard.setData(ClipboardData(text: text)); @@ -9,6 +10,6 @@ Future copyTextToClipboard(String text) => extension CopyTextToClipboardAndShowToast on BuildContext { Future copyTextToClipboardAndShowToast(String text) async { await copyTextToClipboard(text); - if (mounted) showToast(this, 'Copied to clipboard'); + if (mounted) showToast(this, strings.copiedToClipboard); } } diff --git a/lib/widgets/apk_file_menu_bottom_sheet.dart b/lib/widgets/apk_file_menu_bottom_sheet.dart index 154b31b..e7fb4f2 100644 --- a/lib/widgets/apk_file_menu_bottom_sheet.dart +++ b/lib/widgets/apk_file_menu_bottom_sheet.dart @@ -8,6 +8,7 @@ import 'package:shared_storage/shared_storage.dart'; import '../stores/device_apps_store.dart'; import '../utils/app_icons.dart'; +import '../utils/app_localization_strings.dart'; import '../utils/copy_to_clipboard.dart'; import '../utils/generate_play_store_uri.dart'; import '../utils/install_package.dart'; @@ -82,12 +83,12 @@ class _ApkFileMenuOptionsState extends State ); break; case ApkFileTileAction.analyze: - showToast(context, 'Soon...'); + showToast(context, context.strings.soonEllipsis); break; case ApkFileTileAction.openFileLocation: if (widget.packageInstallerUri == null) { if (mounted) { - showToast(context, 'We could not find the target file'); + showToast(context, context.strings.couldNotFindTargetFile); } return; } @@ -108,7 +109,7 @@ class _ApkFileMenuOptionsState extends State if (mounted) { showToast( context, - 'Could not find the file location this either was deleted or we have no permission over the folder.', + context.strings.couldNotFindFileLocationWithExplanation, ); } } @@ -143,7 +144,7 @@ class _ApkFileMenuOptionsState extends State const Divider(height: 1), AppListTile( dense: true, - title: const Text('Search online'), + title: Text(context.strings.searchOnline), leading: Icon( AppIcons.browser.data, size: AppIcons.browser.size, @@ -157,7 +158,7 @@ class _ApkFileMenuOptionsState extends State ), AppListTile( dense: true, - title: const Text('Open on F-Droid'), + title: Text(context.strings.openOnFDroid), onLongPress: () {}, leading: Icon( AppIcons.android.data, @@ -171,7 +172,7 @@ class _ApkFileMenuOptionsState extends State ), AppListTile( dense: true, - title: const Text('Open on Play Store'), + title: Text(context.strings.openOnPlayStore), onLongPress: () {}, leading: Icon(AppIcons.playStore.data, size: AppIcons.playStore.size), @@ -185,36 +186,37 @@ class _ApkFileMenuOptionsState extends State ), AppListTile( dense: true, - title: const Text('Copy package ID'), + title: Text(context.strings.copyPackageId), enabled: widget.packageId != null, - subtitle: Text(widget.packageId ?? 'Not available'), + subtitle: Text(widget.packageId ?? context.strings.notAvailable), leading: Icon(AppIcons.clipboard.data, size: AppIcons.clipboard.size), onTap: () { if (widget.packageId != null) { context.copyTextToClipboardAndShowToast(widget.packageId!); } else { - showToast(context, 'Package ID is not available'); + showToast(context, context.strings.packageIdIsNotAvailable); } }, ), AppListTile( dense: true, - title: const Text('Copy package name'), + title: Text(context.strings.copyPackageName), enabled: widget.packageName != null, - subtitle: Text(widget.packageName ?? 'Not available'), + subtitle: + Text(widget.packageName ?? context.strings.notAvailable), leading: Icon(AppIcons.name.data, size: AppIcons.name.size), onTap: () { if (widget.packageName != null) { context.copyTextToClipboardAndShowToast(widget.packageName!); } else { - showToast(context, 'Package name is not available'); + showToast(context, context.strings.packageNameIsNotAvailable); } }, ), AppListTile( dense: true, - title: const Text('Delete'), + title: Text(context.strings.delete), leading: Icon( AppIcons.delete.data, size: kDefaultIconSize, @@ -270,8 +272,8 @@ class _ApkFileMenuOptionsState extends State onTap: () { perform(ApkFileTileAction.install); }, - text: 'Install', - tooltip: 'Install apk', + text: context.strings.install, + tooltip: context.strings.installApk, ), ActionButton( icon: AppIcons.share.data, @@ -279,8 +281,8 @@ class _ApkFileMenuOptionsState extends State onTap: () { perform(ApkFileTileAction.share); }, - text: 'Share', - tooltip: 'Share apk', + text: context.strings.share, + tooltip: context.strings.shareApk, ), ActionButton( icon: AppIcons.folder.data, @@ -288,8 +290,8 @@ class _ApkFileMenuOptionsState extends State onTap: () { perform(ApkFileTileAction.openFileLocation); }, - text: 'Open file location', - tooltip: 'Open file location', + text: context.strings.openFileLocation, + tooltip: context.strings.openFileLocation, ), ], ), diff --git a/lib/widgets/apk_file_tile.dart b/lib/widgets/apk_file_tile.dart index 96ee06b..92d0ecd 100644 --- a/lib/widgets/apk_file_tile.dart +++ b/lib/widgets/apk_file_tile.dart @@ -4,6 +4,7 @@ import 'package:intl/intl.dart'; import 'package:shared_storage/shared_storage.dart'; import '../stores/localization_store.dart'; +import '../utils/app_localization_strings.dart'; import '../utils/package_bytes.dart'; import 'app_list_tile.dart'; import 'image_uri.dart'; @@ -41,7 +42,7 @@ class _ApkFileTileState extends State with LocalizationStoreMixin { try { await DevicePackages.installPackage(installerUri: widget.file.uri); } on InvalidInstallerException { - showToast(context, 'Invalid apk, is was probably deleted.'); + showToast(context, context.strings.invalidApkItWasProbablyDeleted); } }, ); diff --git a/lib/widgets/apk_list_progress_stepper.dart b/lib/widgets/apk_list_progress_stepper.dart index b6782ea..ecae0e8 100644 --- a/lib/widgets/apk_list_progress_stepper.dart +++ b/lib/widgets/apk_list_progress_stepper.dart @@ -79,8 +79,7 @@ class _StorageRequirementsProgressStepperState child = Row( children: [ _buildFilledButton( - // TODO: Add translation. - 'Go to app list', + context.strings.goToAppList, AppIcons.apps.data, onPressed: bottomNavigationStore.navigateToAppList, ), @@ -92,8 +91,7 @@ class _StorageRequirementsProgressStepperState borderRadius: BorderRadius.circular(k20dp), ), ), - // TODO: Add translation. - child: const Text('Reset folder'), + child: Text(context.strings.resetFolder), ) ], ); @@ -123,15 +121,12 @@ class _StorageRequirementsProgressStepperState return Text.rich( TextSpan( children: [ - // TODO: Add translation. - const TextSpan( - text: - 'The apk list will appear here, to get start try to click over a tile on the app list screen! It will create a new export job that will copy the app apk to the folder you chose.\n\n', + TextSpan( + text: '${context.strings.exportApkExplanationMessage}\n\n', ), TextSpan( - // TODO: Add translation. text: - '${stringifyTreeUri(settingsStore.exportLocation) ?? 'Not set.'}.', + '${stringifyTreeUri(settingsStore.exportLocation) ?? context.strings.notSet}.', recognizer: TapGestureRecognizer() ..onTap = settingsStore.requestExportLocation, style: context.textTheme.labelLarge!.copyWith( @@ -150,7 +145,7 @@ class _StorageRequirementsProgressStepperState Widget _buildPermissionExplanationMessage() { return Text( - 'To extract the apks this app needs access permission to a folder. It is recommended to select an empty folder or create a new one. It is also important to not select folders that are reserved by the system, such as the Android or Downloads folder.', + context.strings.storagePermissionExplanationMessage, style: context.isDark ? TextStyle(color: context.theme.disabledColor) : TextStyle( @@ -191,7 +186,7 @@ class _StorageRequirementsProgressStepperState child: _buildPermissionExplanationMessage(), ), _createStep( - title: 'Export apk', + title: context.strings.exportApk, index: 1, child: _buildExportApkExplanationMessage(), ), diff --git a/lib/widgets/background_task_list_contextual_menu.dart b/lib/widgets/background_task_list_contextual_menu.dart index 482d38f..ea77d18 100644 --- a/lib/widgets/background_task_list_contextual_menu.dart +++ b/lib/widgets/background_task_list_contextual_menu.dart @@ -57,7 +57,7 @@ class _BackgroundTaskListContextualMenuState ), actions: [ AppIconButton( - tooltip: 'Delete all selected', + tooltip: context.strings.deleteAllSelected, onTap: () async { final bool confirm = await showConfirmationModal(context: context); @@ -140,13 +140,13 @@ class _BackgroundTaskListContextualMenuState size: kDefaultIconSize, color: Colors.red, ), - tooltip: 'Remove', + tooltip: context.strings.remove, onTap: () async { if (backgroundTaskStore.idle) { final bool confirmed = await showConfirmationModal( context: context, - message: - 'Do you want force a bulk delete on all these tasks?', + message: context + .strings.doYouWantToForceBulkDeleteAllTheseTasks, ); if (confirmed) { @@ -155,8 +155,8 @@ class _BackgroundTaskListContextualMenuState } else { final bool confirmed = await showConfirmationModal( context: context, - message: - 'Do you want force a bulk cancel on all these tasks?', + message: context + .strings.doYouWantToForceBulkCancelAllTheseTasks, ); if (confirmed) { diff --git a/lib/widgets/bottom_navigation.dart b/lib/widgets/bottom_navigation.dart index af4ee88..76d3c82 100644 --- a/lib/widgets/bottom_navigation.dart +++ b/lib/widgets/bottom_navigation.dart @@ -6,6 +6,7 @@ import 'package:flutter_shared_tools/flutter_shared_tools.dart'; import '../stores/background_task_store.dart'; import '../stores/settings_store.dart'; import '../utils/app_icons.dart'; +import '../utils/app_localization_strings.dart'; import 'multi_animated_builder.dart'; class BottomNavigation extends StatefulWidget { @@ -53,7 +54,7 @@ class _BottomNavigationState extends State AppIcons.apps.data, size: kDefaultIconSize, ), - label: 'Apps', + label: context.strings.apps, ), NavigationDestination( icon: Badge( @@ -64,14 +65,14 @@ class _BottomNavigationState extends State size: kDefaultIconSize, ), ), - label: 'Extracted', + label: context.strings.extracted, ), NavigationDestination( icon: Icon( AppIcons.folder.data, size: kDefaultIconSize, ), - label: 'All files', + label: context.strings.allFiles, ), ], ); diff --git a/lib/widgets/file_list_contextual_menu.dart b/lib/widgets/file_list_contextual_menu.dart index cc7f4fd..974070b 100644 --- a/lib/widgets/file_list_contextual_menu.dart +++ b/lib/widgets/file_list_contextual_menu.dart @@ -54,7 +54,7 @@ class _FileListContextualMenuState extends State ), actions: [ AppIconButton( - tooltip: 'Delete all selected', + tooltip: context.strings.deleteAllSelected, onTap: () async { final bool confirm = await showConfirmationModal(context: context); diff --git a/lib/widgets/package_menu_bottom_sheet.dart b/lib/widgets/package_menu_bottom_sheet.dart index 3a376e6..4045e59 100644 --- a/lib/widgets/package_menu_bottom_sheet.dart +++ b/lib/widgets/package_menu_bottom_sheet.dart @@ -8,6 +8,7 @@ import 'package:flutter_shared_tools/flutter_shared_tools.dart'; import '../stores/device_apps_store.dart'; import '../utils/app_icons.dart'; +import '../utils/app_localization_strings.dart'; import '../utils/context_show_apk_result_message.dart'; import '../utils/copy_to_clipboard.dart'; import '../utils/generate_play_store_uri.dart'; @@ -179,22 +180,22 @@ class _InstalledAppMenuOptionsState extends State ), AppListTile( dense: true, - title: const Text('Copy package ID'), + title: Text(context.strings.copyPackageId), enabled: widget.packageId != null, - subtitle: Text(widget.packageId ?? 'Not available'), + subtitle: Text(widget.packageId ?? context.strings.notAvailable), leading: Icon(AppIcons.clipboard.data, size: AppIcons.clipboard.size), onTap: () { if (widget.packageId != null) { context.copyTextToClipboardAndShowToast(widget.packageId!); } else { - showToast(context, 'Package ID is not available'); + showToast(context, context.strings.packageIdIsNotAvailable); } }, ), AppListTile( dense: true, - title: const Text('Copy package name'), + title: Text(context.strings.copyPackageName), enabled: widget.packageName != null, subtitle: Text(widget.packageName ?? 'Not available'), leading: Icon(AppIcons.name.data, size: AppIcons.name.size), @@ -202,13 +203,13 @@ class _InstalledAppMenuOptionsState extends State if (widget.packageName != null) { context.copyTextToClipboardAndShowToast(widget.packageName!); } else { - showToast(context, 'Package name is not available'); + showToast(context, context.strings.packageNameIsNotAvailable); } }, ), AppListTile( dense: true, - title: const Text('Uninstall'), + title: Text(context.strings.uninstall), leading: Icon( AppIcons.delete.data, size: kDefaultIconSize, @@ -272,8 +273,8 @@ class _InstalledAppMenuOptionsState extends State onTap: () { perform(InstalledAppTileAction.extract); }, - text: 'Extract', - tooltip: 'Extract apk', + text: context.strings.extract, + tooltip: context.strings.extractApk, ), ActionButton( icon: AppIcons.share.data, @@ -281,8 +282,8 @@ class _InstalledAppMenuOptionsState extends State onTap: () { perform(InstalledAppTileAction.share); }, - text: 'Share', - tooltip: 'Share apk', + text: context.strings.share, + tooltip: context.strings.shareApk, ), ActionButton( icon: AppIcons.externalLink.data, @@ -290,8 +291,8 @@ class _InstalledAppMenuOptionsState extends State onTap: () { perform(InstalledAppTileAction.open); }, - text: 'Open app', - tooltip: 'Open app', + text: context.strings.launchApp, + tooltip: context.strings.launchApp, ), ActionButton( icon: AppIcons.settings.data, @@ -299,8 +300,8 @@ class _InstalledAppMenuOptionsState extends State onTap: () { perform(InstalledAppTileAction.openSettings); }, - text: 'Settings', - tooltip: 'Open app settings', + text: context.strings.settings, + tooltip: context.strings.openSettingsPage, ), ], ), diff --git a/missing-translations.txt b/missing-translations.txt index 9e26dfe..26e8c62 100644 --- a/missing-translations.txt +++ b/missing-translations.txt @@ -1 +1,501 @@ -{} \ No newline at end of file +{ + "de": [ + "behaviorPreferences", + "appearancePreferences", + "donate", + "links", + "openSourceLicenses", + "reportIssue", + "followMeOnGitHub", + "githubRepository", + "packageAndVersion", + "overscrollIndicator", + "donateOnGitHub", + "donateOnKofi", + "donateUsingPix", + "donateUsingBtc", + "otherDonationMethods", + "unnamedPackage", + "version", + "unavailable", + "user", + "builtIn", + "system", + "noResults", + "cancelTask", + "darkSimple", + "extractionIsNotFinishedCanNotInstallYet", + "tasksAreAlreadyBeingDeleted", + "loadingInfoEllipsis", + "notAvailable", + "openingFolderIsNotSupportedYet", + "confirmIrreversibleActionsExplanation", + "filterWillRemoveSomeSelectedItems", + "hideAppBarOnScroll", + "extractWithSingleClick", + "confirmIrreversibleActions", + "displayUserInstalledApps", + "displaySystemApps", + "displayBuiltInApps", + "transparentNavigationBar", + "hideAppBarOnScrollExplanation", + "displaySystemAppsExplanation", + "noActivityFoundThatCanHandleThisFileType", + "displayBuiltInAppsExplanation", + "displayUserInstalledAppsExplanation", + "transparentNavigationBarExplanation", + "trySelectingAtLeastOneFilter", + "extractWithSingleClickExplanation", + "paymentMethodCard", + "goToAppList", + "invalidApkItWasProbablyDeleted", + "openFileLocation", + "resetAllPreferencesQuestion", + "exportApkExplanationMessage", + "storagePermissionExplanationMessage", + "notSet", + "resetFolder", + "launchApp", + "allFiles", + "exportApk", + "extracted", + "openOnPlayStore", + "openOnFDroid", + "searchOnline", + "remove", + "deleteAllSelected", + "doYouWantToForceBulkDeleteAllTheseTasks", + "doYouWantToForceBulkCancelAllTheseTasks", + "apps", + "couldNotFindTargetFile", + "couldNotFindFileLocationWithExplanation", + "soonEllipsis", + "soon", + "loadingInfo", + "copiedToClipboard", + "invalidPackageUri", + "share", + "bouncing", + "glow", + "none", + "areYouSure", + "delete", + "shareApk", + "cancel", + "confirm", + "install", + "thisIsIrreversible", + "couldNotExtractWithExplanation", + "installApk", + "extract", + "successQueued", + "extractApk", + "packageNameIsNotAvailable", + "copyPackageName", + "packageIdIsNotAvailable", + "copyPackageId", + "uninstall", + "greenDark", + "redDark" + ], + + "es": [ + "behaviorPreferences", + "appearancePreferences", + "donate", + "links", + "openSourceLicenses", + "reportIssue", + "followMeOnGitHub", + "githubRepository", + "packageAndVersion", + "overscrollIndicator", + "donateOnGitHub", + "donateOnKofi", + "donateUsingPix", + "donateUsingBtc", + "otherDonationMethods", + "unnamedPackage", + "version", + "unavailable", + "user", + "builtIn", + "system", + "noResults", + "cancelTask", + "darkSimple", + "extractionIsNotFinishedCanNotInstallYet", + "tasksAreAlreadyBeingDeleted", + "loadingInfoEllipsis", + "notAvailable", + "openingFolderIsNotSupportedYet", + "confirmIrreversibleActionsExplanation", + "filterWillRemoveSomeSelectedItems", + "hideAppBarOnScroll", + "extractWithSingleClick", + "confirmIrreversibleActions", + "displayUserInstalledApps", + "displaySystemApps", + "displayBuiltInApps", + "transparentNavigationBar", + "hideAppBarOnScrollExplanation", + "displaySystemAppsExplanation", + "noActivityFoundThatCanHandleThisFileType", + "displayBuiltInAppsExplanation", + "displayUserInstalledAppsExplanation", + "transparentNavigationBarExplanation", + "trySelectingAtLeastOneFilter", + "extractWithSingleClickExplanation", + "paymentMethodCard", + "goToAppList", + "invalidApkItWasProbablyDeleted", + "openFileLocation", + "resetAllPreferencesQuestion", + "exportApkExplanationMessage", + "storagePermissionExplanationMessage", + "notSet", + "resetFolder", + "launchApp", + "allFiles", + "exportApk", + "extracted", + "openOnPlayStore", + "openOnFDroid", + "searchOnline", + "remove", + "deleteAllSelected", + "doYouWantToForceBulkDeleteAllTheseTasks", + "doYouWantToForceBulkCancelAllTheseTasks", + "apps", + "couldNotFindTargetFile", + "couldNotFindFileLocationWithExplanation", + "soonEllipsis", + "soon", + "loadingInfo", + "copiedToClipboard", + "invalidPackageUri", + "share", + "bouncing", + "glow", + "none", + "areYouSure", + "delete", + "shareApk", + "cancel", + "confirm", + "install", + "thisIsIrreversible", + "couldNotExtractWithExplanation", + "installApk", + "extract", + "successQueued", + "extractApk", + "packageNameIsNotAvailable", + "copyPackageName", + "packageIdIsNotAvailable", + "copyPackageId", + "uninstall", + "greenDark", + "redDark" + ], + + "it": [ + "behaviorPreferences", + "appearancePreferences", + "donate", + "links", + "openSourceLicenses", + "reportIssue", + "followMeOnGitHub", + "githubRepository", + "packageAndVersion", + "overscrollIndicator", + "donateOnGitHub", + "donateOnKofi", + "donateUsingPix", + "donateUsingBtc", + "otherDonationMethods", + "unnamedPackage", + "version", + "unavailable", + "user", + "builtIn", + "system", + "noResults", + "cancelTask", + "darkSimple", + "extractionIsNotFinishedCanNotInstallYet", + "tasksAreAlreadyBeingDeleted", + "loadingInfoEllipsis", + "notAvailable", + "openingFolderIsNotSupportedYet", + "confirmIrreversibleActionsExplanation", + "filterWillRemoveSomeSelectedItems", + "hideAppBarOnScroll", + "extractWithSingleClick", + "confirmIrreversibleActions", + "displayUserInstalledApps", + "displaySystemApps", + "displayBuiltInApps", + "transparentNavigationBar", + "hideAppBarOnScrollExplanation", + "displaySystemAppsExplanation", + "noActivityFoundThatCanHandleThisFileType", + "displayBuiltInAppsExplanation", + "displayUserInstalledAppsExplanation", + "transparentNavigationBarExplanation", + "trySelectingAtLeastOneFilter", + "extractWithSingleClickExplanation", + "paymentMethodCard", + "goToAppList", + "invalidApkItWasProbablyDeleted", + "openFileLocation", + "resetAllPreferencesQuestion", + "exportApkExplanationMessage", + "storagePermissionExplanationMessage", + "notSet", + "resetFolder", + "launchApp", + "allFiles", + "exportApk", + "extracted", + "openOnPlayStore", + "openOnFDroid", + "searchOnline", + "remove", + "deleteAllSelected", + "doYouWantToForceBulkDeleteAllTheseTasks", + "doYouWantToForceBulkCancelAllTheseTasks", + "apps", + "couldNotFindTargetFile", + "couldNotFindFileLocationWithExplanation", + "soonEllipsis", + "soon", + "loadingInfo", + "copiedToClipboard", + "invalidPackageUri", + "share", + "bouncing", + "glow", + "none", + "areYouSure", + "delete", + "shareApk", + "cancel", + "confirm", + "install", + "thisIsIrreversible", + "couldNotExtractWithExplanation", + "installApk", + "extract", + "successQueued", + "extractApk", + "packageNameIsNotAvailable", + "copyPackageName", + "packageIdIsNotAvailable", + "copyPackageId", + "uninstall", + "greenDark", + "redDark" + ], + + "ja": [ + "behaviorPreferences", + "appearancePreferences", + "donate", + "links", + "openSourceLicenses", + "reportIssue", + "followMeOnGitHub", + "githubRepository", + "packageAndVersion", + "overscrollIndicator", + "donateOnGitHub", + "donateOnKofi", + "donateUsingPix", + "donateUsingBtc", + "otherDonationMethods", + "unnamedPackage", + "version", + "unavailable", + "user", + "builtIn", + "system", + "noResults", + "cancelTask", + "darkSimple", + "extractionIsNotFinishedCanNotInstallYet", + "tasksAreAlreadyBeingDeleted", + "loadingInfoEllipsis", + "notAvailable", + "openingFolderIsNotSupportedYet", + "confirmIrreversibleActionsExplanation", + "filterWillRemoveSomeSelectedItems", + "hideAppBarOnScroll", + "extractWithSingleClick", + "confirmIrreversibleActions", + "displayUserInstalledApps", + "displaySystemApps", + "displayBuiltInApps", + "transparentNavigationBar", + "hideAppBarOnScrollExplanation", + "displaySystemAppsExplanation", + "noActivityFoundThatCanHandleThisFileType", + "displayBuiltInAppsExplanation", + "displayUserInstalledAppsExplanation", + "transparentNavigationBarExplanation", + "trySelectingAtLeastOneFilter", + "extractWithSingleClickExplanation", + "paymentMethodCard", + "goToAppList", + "invalidApkItWasProbablyDeleted", + "openFileLocation", + "resetAllPreferencesQuestion", + "exportApkExplanationMessage", + "storagePermissionExplanationMessage", + "notSet", + "resetFolder", + "launchApp", + "allFiles", + "exportApk", + "extracted", + "openOnPlayStore", + "openOnFDroid", + "searchOnline", + "remove", + "deleteAllSelected", + "doYouWantToForceBulkDeleteAllTheseTasks", + "doYouWantToForceBulkCancelAllTheseTasks", + "apps", + "couldNotFindTargetFile", + "couldNotFindFileLocationWithExplanation", + "soonEllipsis", + "soon", + "loadingInfo", + "copiedToClipboard", + "invalidPackageUri", + "share", + "bouncing", + "glow", + "none", + "areYouSure", + "delete", + "shareApk", + "cancel", + "confirm", + "install", + "thisIsIrreversible", + "couldNotExtractWithExplanation", + "installApk", + "extract", + "successQueued", + "extractApk", + "packageNameIsNotAvailable", + "copyPackageName", + "packageIdIsNotAvailable", + "copyPackageId", + "uninstall", + "greenDark", + "redDark" + ], + + "pt": [ + "behaviorPreferences", + "appearancePreferences", + "donate", + "links", + "openSourceLicenses", + "reportIssue", + "followMeOnGitHub", + "githubRepository", + "packageAndVersion", + "overscrollIndicator", + "donateOnGitHub", + "donateOnKofi", + "donateUsingPix", + "donateUsingBtc", + "otherDonationMethods", + "unnamedPackage", + "version", + "unavailable", + "user", + "builtIn", + "system", + "noResults", + "cancelTask", + "darkSimple", + "extractionIsNotFinishedCanNotInstallYet", + "tasksAreAlreadyBeingDeleted", + "loadingInfoEllipsis", + "notAvailable", + "openingFolderIsNotSupportedYet", + "confirmIrreversibleActionsExplanation", + "filterWillRemoveSomeSelectedItems", + "hideAppBarOnScroll", + "extractWithSingleClick", + "confirmIrreversibleActions", + "displayUserInstalledApps", + "displaySystemApps", + "displayBuiltInApps", + "transparentNavigationBar", + "hideAppBarOnScrollExplanation", + "displaySystemAppsExplanation", + "noActivityFoundThatCanHandleThisFileType", + "displayBuiltInAppsExplanation", + "displayUserInstalledAppsExplanation", + "transparentNavigationBarExplanation", + "trySelectingAtLeastOneFilter", + "extractWithSingleClickExplanation", + "paymentMethodCard", + "goToAppList", + "invalidApkItWasProbablyDeleted", + "openFileLocation", + "resetAllPreferencesQuestion", + "exportApkExplanationMessage", + "storagePermissionExplanationMessage", + "notSet", + "resetFolder", + "launchApp", + "allFiles", + "exportApk", + "extracted", + "openOnPlayStore", + "openOnFDroid", + "searchOnline", + "remove", + "deleteAllSelected", + "doYouWantToForceBulkDeleteAllTheseTasks", + "doYouWantToForceBulkCancelAllTheseTasks", + "apps", + "couldNotFindTargetFile", + "couldNotFindFileLocationWithExplanation", + "soonEllipsis", + "soon", + "loadingInfo", + "copiedToClipboard", + "invalidPackageUri", + "share", + "bouncing", + "glow", + "none", + "areYouSure", + "delete", + "shareApk", + "cancel", + "confirm", + "install", + "thisIsIrreversible", + "couldNotExtractWithExplanation", + "installApk", + "extract", + "successQueued", + "extractApk", + "packageNameIsNotAvailable", + "copyPackageName", + "packageIdIsNotAvailable", + "copyPackageId", + "uninstall", + "greenDark", + "redDark" + ] +} diff --git a/pubspec.lock b/pubspec.lock index d488f7d..0092f0b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -682,7 +682,7 @@ packages: path: "../shared-storage" relative: true source: path - version: "0.8.0" + version: "0.9.0" shelf: dependency: transitive description: diff --git a/website/docs/build-yourself.md b/website/docs/build-yourself.md index 7b9b380..f65ddc6 100644 --- a/website/docs/build-yourself.md +++ b/website/docs/build-yourself.md @@ -13,6 +13,10 @@ To run the code generation (that generates the `flutter_gen` library used for i1 ```shell flutter gen-l10n + +# Use nodemon if you are developing (watch for changes). +# https://www.npmjs.com/package/nodemon +nodemon --watch i18n --ext arb --exec "flutter gen-l10n" ``` ### 2. Generate binaries