diff --git a/.github/workflows/pr-build.yml b/.github/workflows/pr-build.yml index 08cb344c..bc961798 100644 --- a/.github/workflows/pr-build.yml +++ b/.github/workflows/pr-build.yml @@ -73,7 +73,8 @@ jobs: - name: Install Flutter dependencies run: flutter pub get - + - name: Generate translation with Slang + run: dart run slang - name: Generate files with Builder run: dart run build_runner build --delete-conflicting-outputs diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index 80ca25c6..68e3ac00 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -42,7 +42,8 @@ jobs: - name: Set up Flutter run: flutter pub get - + - name: Generate translation with Slang + run: dart run slang - name: Generate files with Builder run: dart run build_runner build --delete-conflicting-outputs diff --git a/.github/workflows/sync-crowdin.yml b/.github/workflows/sync-crowdin.yml new file mode 100644 index 00000000..7ae331ab --- /dev/null +++ b/.github/workflows/sync-crowdin.yml @@ -0,0 +1,53 @@ +name: Crowdin Action + +on: + workflow_dispatch: + push: + branches: [dev] + +jobs: + synchronize-with-crowdin: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Dart + uses: dart-lang/setup-dart@v1 + + - name: Sync translation from Crowdin + uses: crowdin/github-action@v1 + with: + config: crowdin.yml + upload_sources: true + upload_translations: false + download_translations: true + localization_branch_name: feat/translations + create_pull_request: true + pull_request_title: "chore(i18n): Sync translations" + pull_request_body: "Sync translations from [Crowdin/ReVanced](https://crowdin.com/project/revanced)" + pull_request_base_branch_name: "dev" + commit_message: "chore(i18n): Sync translations" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} + CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} + + - name: Remove empty values from JSON + run: | + cd assets/i18n + sudo chmod 777 * + dart nuke.dart >> $GITHUB_STEP_SUMMARY + + - name: Push out changes to i10n + run: | + git config user.name revanced-bot + git config user.email github@revanced.app + sudo chown -R $USER:$USER .git + git add assets/i18n/*.json + git commit -m "chore(Translation): Remove empty values from JSON" assets/i18n/*.json + git push origin HEAD:feat/translations + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/assets/i18n/README.md b/assets/i18n/README.md new file mode 100644 index 00000000..5ad11681 --- /dev/null +++ b/assets/i18n/README.md @@ -0,0 +1,14 @@ +# Nuke:tm: + +> ![CAUTION] +> Some of the code are licensed under BSD 3-Clause License, please check inside the code file for more information. + +## Usage + +Move to your desire directory and run + +```bash +dart nuke.dart +``` + +and it will remove all the empty keys from the JSON files in the current folder. diff --git a/assets/i18n/en_US.json b/assets/i18n/en_US.json deleted file mode 100644 index 56e7c6f5..00000000 --- a/assets/i18n/en_US.json +++ /dev/null @@ -1,373 +0,0 @@ -{ - "okButton": "OK", - "cancelButton": "Cancel", - "dismissButton": "Dismiss", - "quitButton": "Quit", - "updateButton": "Update", - "enabledLabel": "Enabled", - "disabledLabel": "Disabled", - "installed":"Installed: {version}", - "suggested":"Suggested: {version}", - "yesButton": "Yes", - "noButton": "No", - "warning": "Warning", - "options": "Options", - "notice": "Notice", - "noShowAgain": "Don't show this again", - "add": "Add", - "remove": "Remove", - "showChangelogButton": "Show changelog", - "showUpdateButton": "Show update", - "navigationView": { - "dashboardTab": "Dashboard", - "patcherTab": "Patcher", - "settingsTab": "Settings" - }, - "homeView": { - "refreshSuccess": "Refreshed successfully", - "widgetTitle": "Dashboard", - - "updatesSubtitle": "Updates", - "patchedSubtitle": "Patched apps", - "changeLaterSubtitle": "You can change this in the settings at a later time.", - - "noUpdates": "No updates available", - - "WIP": "Work in progress...", - - "noInstallations": "No patched apps installed", - "installUpdate": "Continue to install the update?", - - "updateSheetTitle": "Update ReVanced Manager", - "updateDialogTitle": "New update available", - "updatePatchesSheetTitle": "Update ReVanced Patches", - "updateChangelogTitle": "Changelog", - - "updateDialogText": "A new update is available for {file}.\n\nThe currently installed version is {version}.", - - "downloadConsentDialogTitle": "Download necessary files?", - "downloadConsentDialogText": "ReVanced Manager needs to download necessary files to work properly.", - "downloadConsentDialogText2": "This will connect you to {url}.", - - "checkUpdateDialogTitle": "Check for updates?", - "checkUpdateDialogText": "Do you want ReVanced Manager to check for updates automatically?", - - "notificationTitle": "Update downloaded", - "notificationText": "Tap to install the update", - - "downloadingMessage": "Downloading update...", - "downloadedMessage": "Update downloaded", - - "installingMessage": "Installing update...", - - "errorDownloadMessage": "Unable to download update", - "errorInstallMessage": "Unable to install update", - - "noConnection": "No internet connection", - "updatesDisabled": "Updating a patched app is currently disabled. Repatch the app again." - }, - "applicationItem": { - "infoButton": "Info" - }, - "latestCommitCard": { - "loadingLabel": "Loading...", - "timeagoLabel": "{time} ago", - "patcherLabel": "Patcher: ", - "managerLabel": "Manager: ", - "updateButton": "Update Manager" - }, - "patcherView": { - "widgetTitle": "Patcher", - "patchButton": "Patch", - - "armv7WarningDialogText": "Patching on ARMv7 devices is not yet supported and might fail. Continue anyways?", - - "removedPatchesWarningDialogText": "The following patches have been removed since the last time you used them.\n\n{patches}\n\nContinue anyways?", - "requiredOptionDialogText" : "Some patch options have to be set." - }, - "appSelectorCard": { - "widgetTitle": "Select an app", - "widgetTitleSelected": "Selected app", - "widgetSubtitle": "No app selected", - - "noAppsLabel": "No applications found", - - "currentVersion": "Current", - "suggestedVersion": "Suggested", - "anyVersion": "Any version" - }, - "patchSelectorCard": { - "widgetTitle": "Select patches", - "widgetTitleSelected": "Selected patches", - - "widgetSubtitle": "Select an application first", - "widgetEmptySubtitle": "No patches selected" - }, - "socialMediaCard": { - "widgetTitle": "Socials", - "widgetSubtitle": "We are online!" - }, - "appSelectorView": { - "viewTitle": "Select an app", - "searchBarHint": "Search app", - - "storageButton": "Storage", - "selectFromStorageButton": "Select from storage", - - "errorMessage": "Unable to use selected application", - - "downloadToast": "Download function is not available yet", - - "requireSuggestedAppVersionDialogText": "The version of the app you have selected does not match the suggested version which can lead to unexpected issues. Please use the suggested version.\n\nSelected version: {selected}\nSuggested version: {suggested}\n\nTo continue anyway, disable \"Require suggested app version\" in the settings.", - - "featureNotAvailable": "Feature not implemented", - "featureNotAvailableText": "This app is a split APK and can only be patched and installed reliably by mounting with root permissions. However, you can patch and install a full APK by selecting it from storage." - }, - "patchesSelectorView": { - "viewTitle": "Select patches", - "searchBarHint": "Search patches", - "universalPatches": "Universal patches", - "newPatches": "New patches", - "patches": "Patches", - - "doneButton": "Done", - - "default": "Default", - "defaultTooltip": "Select all default patches", - - "none": "None", - "noneTooltip": "Deselect all patches", - - "loadPatchesSelection": "Load patch selection", - "noSavedPatches": "No saved patch selection for the selected app.\nPress Done to save the current selection.", - "noPatchesFound": "No patches found for the selected app", - "setRequiredOption": "Some patches require options to be set:\n\n{patches}\n\nPlease set them before continuing." - }, - "patchOptionsView": { - "customValue": "Custom value", - "resetOptionsTooltip": "Reset patch options", - "viewTitle": "Patch options", - "saveOptions": "Save", - - "addOptions": "Add options", - "deselectPatch": "Deselect patch", - "tooltip": "More input options", - "selectFilePath": "Select file path", - "selectFolder": "Select folder", - "selectOption": "Select option", - - "requiredOption": "This option is required", - "unsupportedOption": "This option is not supported", - "requiredOptionNull": "The following options have to be set:\n\n{options}" - }, - "patchItem": { - "unsupportedDialogText": "Selecting this patch may result in patching errors.\n\nApp version: {packageVersion}\nSupported versions:\n{supportedVersions}", - "unsupportedPatchVersion": "Patch is not supported for this app version.", - "unsupportedRequiredOption": "This patch contains a required option that is not supported by this app", - - "patchesChangeWarningDialogText": "It is recommended to use the default patch selection and options. Changing them may result in unexpected issues.\n\nYou'll need to turn on \"Allow changing patch selection\" in the settings before changing any patch selection.", - "patchesChangeWarningDialogButton": "Use default selection" - }, - "installerView": { - "widgetTitle": "Installer", - "installType": "Select install type", - "installTypeDescription": "Select the installation type to continue with.", - - "installButton": "Install", - "installRootType": "Mount", - "installNonRootType": "Regular", - - "warning": "Disable auto updates for the patched app to avoid unexpected issues.", - - "pressBackAgain": "Press back again to cancel", - "openButton": "Open", - "shareButton": "Share file", - - "notificationTitle": "ReVanced Manager is patching", - "notificationText": "Tap to return to the installer", - - "exportApkButtonTooltip": "Export patched APK", - "exportLogButtonTooltip": "Export log", - - "screenshotDetected": "A screenshot has been detected. If you are trying to share the log, please share a text copy instead.\n\nCopy log to clipboard?", - "copiedToClipboard": "Copied log to clipboard", - - "noExit": "Installer is still running, cannot exit..." - }, - "settingsView": { - "widgetTitle": "Settings", - - "appearanceSectionTitle": "Appearance", - "teamSectionTitle": "Team", - "debugSectionTitle": "Debugging", - "advancedSectionTitle": "Advanced", - "exportSectionTitle": "Import & export", - - "themeModeLabel": "App theme", - "systemThemeLabel": "System", - "lightThemeLabel": "Light", - "darkThemeLabel": "Dark", - - "dynamicThemeLabel": "Material You", - "dynamicThemeHint": "Enjoy an experience closer to your device", - - "languageLabel": "Language", - "englishOption": "English", - - "sourcesLabel": "Sources", - "sourcesLabelHint": "Configure the source of patches and integrations", - "sourcesIntegrationsLabel": "Integrations source", - "sourcesResetDialogTitle": "Reset", - "sourcesResetDialogText": "Are you sure you want to reset your sources to their default values?", - "apiURLResetDialogText": "Are you sure you want to reset your API URL to its default value?", - "sourcesUpdateNote": "Note: Patches will be updated to the latest version automatically.\n\nThis will reveal your IP address to the server.", - - "apiURLLabel": "API URL", - "apiURLHint": "Configure the URL of the API to use", - "selectApiURL": "API URL", - "hostRepositoryLabel": "Repository API", - "orgPatchesLabel": "Patches organization", - "sourcesPatchesLabel": "Patches source", - "orgIntegrationsLabel": "Integrations organization", - - "contributorsLabel": "Contributors", - "contributorsHint": "A list of contributors of ReVanced", - - "logsLabel": "Share logs", - "logsHint": "Share ReVanced Manager logs", - - "enablePatchesSelectionLabel": "Allow changing patch selection", - "enablePatchesSelectionHint": "Do not prevent selecting or deselecting patches", - "enablePatchesSelectionWarningText": "Changing the selection of patches may cause unexpected issues.\n\nEnable anyways?", - "disablePatchesSelectionWarningText": "You are about to disable changing the selection of patches.\nThe default selection of patches will be restored.\n\nDisable anyways?", - - "autoUpdatePatchesLabel": "Auto update patches", - "autoUpdatePatchesHint": "Automatically update patches to the latest version", - "showUpdateDialogLabel": "Show update dialog", - "showUpdateDialogHint": "Show a dialog when a new update is available", - "universalPatchesLabel": "Show universal patches", - "universalPatchesHint": "Display all apps and universal patches (may slow down the app list)", - - "versionCompatibilityCheckLabel": "Version compatibility check", - "versionCompatibilityCheckHint": "Prevent selecting patches that are not compatible with the selected app version", - - "requireSuggestedAppVersionLabel": "Require suggested app version", - "requireSuggestedAppVersionHint": "Prevent selecting an app with a version that is not the suggested", - "requireSuggestedAppVersionDialogText": "Selecting an app that is not the suggested version may cause unexpected issues.\n\nDo you want to proceed anyways?", - - "aboutLabel": "About", - "snackbarMessage": "Copied to clipboard", - "restartAppForChanges": "Restart the app to apply changes", - - "deleteTempDirLabel": "Delete temporary files", - "deleteTempDirHint": "Delete unused temporary files", - "deletedTempDir": "Temporary files deleted", - - "exportPatchesLabel": "Export patch selection", - "exportPatchesHint": "Export patch selection to a JSON file", - "exportedPatches": "Patch selection exported", - "noExportFileFound": "No patch selection to export", - - "importPatchesLabel": "Import patch selection", - "importPatchesHint": "Import patch selection from a JSON file", - "importedPatches": "Patch selection imported", - - "resetStoredPatchesLabel": "Reset patch selection", - "resetStoredPatchesHint": "Reset the stored patch selection", - "resetStoredPatchesDialogTitle": "Reset patch selection?", - "resetStoredPatchesDialogText": "The default selection of patches will be restored.", - "resetStoredPatches": "Patch selection has been reset", - - "resetStoredOptionsLabel": "Reset patch options", - "resetStoredOptionsHint": "Reset all patch options", - "resetStoredOptionsDialogTitle": "Reset patch options?", - "resetStoredOptionsDialogText": "Resetting patch options will remove all saved options.", - "resetStoredOptions": "Options have been reset", - - "deleteLogsLabel": "Clear logs", - "deleteLogsHint": "Delete collected ReVanced Manager logs", - "deletedLogs": "Logs deleted", - - "regenerateKeystoreLabel": "Regenerate keystore", - "regenerateKeystoreHint": "Regenerate the keystore used to sign apps", - - "regenerateKeystoreDialogTitle": "Regenerate keystore?", - "regenerateKeystoreDialogText": "Patched apps signed with the old keystore will no longer be able to be updated.", - "regeneratedKeystore": "Keystore regenerated", - - "exportKeystoreLabel": "Export keystore", - "exportKeystoreHint": "Export the keystore used to sign apps", - "exportedKeystore": "Keystore exported", - "noKeystoreExportFileFound": "No keystore to export", - - "importKeystoreLabel": "Import keystore", - "importKeystoreHint": "Import a keystore used to sign apps", - "importedKeystore": "Keystore imported", - - "selectKeystorePassword": "Keystore password", - "selectKeystorePasswordHint": "Select keystore password used to sign apps", - - "jsonSelectorErrorMessage": "Unable to use selected JSON file", - "keystoreSelectorErrorMessage": "Unable to use selected keystore file" - }, - "appInfoView": { - "widgetTitle": "App info", - "openButton": "Open", - "uninstallButton": "Uninstall", - "unmountButton": "Unmount", - "rootDialogTitle": "Error", - - "unmountDialogText": "Are you sure you want to unmount this app?", - "uninstallDialogText": "Are you sure you want to uninstall this app?", - "rootDialogText": "App was installed with superuser permissions, but currently ReVanced Manager has no permissions.\nPlease grant superuser permissions first.", - - "packageNameLabel": "Package name", - "installTypeLabel": "Installation type", - "mountTypeLabel": "Mount", - "regularTypeLabel": "Regular", - "patchedDateLabel": "Patched date", - "appliedPatchesLabel": "Applied patches", - - "patchedDateHint": "{date} at {time}", - "appliedPatchesHint": "{quantity} applied patches", - - "updateNotImplemented": "This feature has not been implemented yet" - }, - "contributorsView": { - "widgetTitle": "Contributors", - "patcherContributors": "Patcher contributors", - "patchesContributors": "Patches contributors", - "integrationsContributors": "Integrations contributors", - "cliContributors": "CLI contributors", - "managerContributors": "Manager contributors" - }, - "installErrorDialog": { - "mount_version_mismatch": "Version mismatch", - "mount_no_root": "No root access", - "mount_missing_installation": "Installation not found", - - "status_failure_blocked": "Installation blocked", - "install_failed_verification_failure": "Verification failed", - "status_failure_invalid": "Installation invalid", - "install_failed_version_downgrade": "Can't downgrade", - "status_failure_conflict": "Installation conflict", - "status_failure_storage": "Installation storage issue", - "status_failure_incompatible": "Installation incompatible", - "status_failure_timeout": "Installation timeout", - "status_unknown": "Installation failed", - - "mount_version_mismatch_description": "The installation failed due to the installed app being a different version than the patched app.\n\nInstall the version of the app you are mounting and try again.", - "mount_no_root_description": "The installation failed due to root access not being granted.\n\nGrant root access to ReVanced Manager and try again.", - "mount_missing_installation_description": "The installation failed due to the unpatched app not being installed on this device in order to mount over it.\n\nInstall the unpatched app before mounting and try again.", - - "status_failure_timeout_description": "The installation took too long to finish.\n\nWould you like to try again?", - "status_failure_storage_description": "The installation failed due to insufficient storage.\n\nFree up some space and try again.", - "status_failure_invalid_description": "The installation failed due to the patched app being invalid.\n\nUninstall the app and try again?", - "status_failure_incompatible_description": "The app is incompatible with this device.\n\nContact the developer of the app and ask for support.", - "status_failure_conflict_description": "The installation was prevented by an existing installation of the app.\n\nUninstall the installed app and try again?", - "status_failure_blocked_description": "The installation was blocked by {packageName}.\n\nAdjust your security settings and try again.", - "install_failed_verification_failure_description": "The installation failed due to a verification issue.\n\nAdjust your security settings and try again.", - "install_failed_version_downgrade_description": "The installation failed due to the patched app being a lower version than the installed app.\n\nUninstall the app and try again?", - "status_unknown_description": "The installation failed due to an unknown reason. Please try again." - } -} diff --git a/assets/i18n/nuke.dart b/assets/i18n/nuke.dart new file mode 100644 index 00000000..7b8c3a1a --- /dev/null +++ b/assets/i18n/nuke.dart @@ -0,0 +1,79 @@ +// ignore_for_file: avoid_print + +import 'dart:convert'; +import 'dart:io'; + +T? removeBlankEntries(T? json) { + // This function is protected by BSD 3-Clause License + // Changes made to this section are allow removing of '' values from JSON + + /* + https://pub.dev/documentation/swiss_knife/latest/swiss_knife/removeEmptyEntries.html + + Copyright 2014, the Dart project authors. All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + if (json == null) { + return null; + } + if (json is List) { + json.removeWhere((e) => e == null); + json.forEach(removeBlankEntries); + } else if (json is Map) { + json.removeWhere( + (key, value) => key == null || value == null || value == '', + ); + json.values.forEach(removeBlankEntries); + } + return json; +} + +Future processJsonFiles() async { + final Directory directory = Directory.current; + final List files = directory.listSync(); + + for (final file in files) { + try { + if (file is File && file.path.endsWith('.json')) { + final String contents = await file.readAsString(); + final dynamic json = jsonDecode(contents); + final dynamic processedJson = removeBlankEntries(json); + + file.writeAsString( + const JsonEncoder.withIndent(' ').convert(processedJson), + ); + print('šŸ„ž Task successful on: ${file.path}'); + } + } catch (e) { + print('šŸ’„ Task failed on: ${file.path}: $e'); + } + } +} + +void main() async { + processJsonFiles(); +} diff --git a/assets/i18n/strings.i18n.json b/assets/i18n/strings.i18n.json new file mode 100644 index 00000000..0167e1ca --- /dev/null +++ b/assets/i18n/strings.i18n.json @@ -0,0 +1,305 @@ +{ + "okButton": "OK", + "cancelButton": "Cancel", + "dismissButton": "Dismiss", + "quitButton": "Quit", + "updateButton": "Update", + "enabledLabel": "Enabled", + "disabledLabel": "Disabled", + "installed": "Installed: ${version}", + "suggested": "Suggested: ${version}", + "yesButton": "Yes", + "noButton": "No", + "warning": "Warning", + "options": "Options", + "notice": "Notice", + "noShowAgain": "Don't show this again", + "add": "Add", + "remove": "Remove", + "showChangelogButton": "Show changelog", + "showUpdateButton": "Show update", + "navigationView": { + "dashboardTab": "Dashboard", + "patcherTab": "Patcher", + "settingsTab": "Settings" + }, + "homeView": { + "refreshSuccess": "Refreshed successfully", + "widgetTitle": "Dashboard", + "updatesSubtitle": "Updates", + "patchedSubtitle": "Patched apps", + "changeLaterSubtitle": "You can change this in the settings at a later time.", + "noUpdates": "No updates available", + "WIP": "Work in progress...", + "noInstallations": "No patched apps installed", + "installUpdate": "Continue to install the update?", + "updateSheetTitle": "Update ReVanced Manager", + "updateDialogTitle": "New update available", + "updatePatchesSheetTitle": "Update ReVanced Patches", + "updateChangelogTitle": "Changelog", + "updateDialogText": "A new update is available for ${file}.\n\nThe currently installed version is ${version}.", + "downloadConsentDialogTitle": "Download necessary files?", + "downloadConsentDialogText": "ReVanced Manager needs to download necessary files to work properly.", + "downloadConsentDialogText2": "This will connect you to ${url}.", + "checkUpdateDialogTitle": "Check for updates?", + "checkUpdateDialogText": "Do you want ReVanced Manager to check for updates automatically?", + "notificationTitle": "Update downloaded", + "notificationText": "Tap to install the update", + "downloadingMessage": "Downloading update...", + "downloadedMessage": "Update downloaded", + "installingMessage": "Installing update...", + "errorDownloadMessage": "Unable to download update", + "errorInstallMessage": "Unable to install update", + "noConnection": "No internet connection", + "updatesDisabled": "Updating a patched app is currently disabled. Repatch the app again." + }, + "applicationItem": { + "infoButton": "Info" + }, + "latestCommitCard": { + "loadingLabel": "Loading...", + "timeagoLabel": "${time} ago", + "patcherLabel": "Patcher: ", + "managerLabel": "Manager: ", + "updateButton": "Update Manager" + }, + "patcherView": { + "widgetTitle": "Patcher", + "patchButton": "Patch", + "armv7WarningDialogText": "Patching on ARMv7 devices is not yet supported and might fail. Continue anyways?", + "removedPatchesWarningDialogText": "The following patches have been removed since the last time you used them.\n\n${patches}\n\nContinue anyways?", + "requiredOptionDialogText": "Some patch options have to be set." + }, + "appSelectorCard": { + "widgetTitle": "Select an app", + "widgetTitleSelected": "Selected app", + "widgetSubtitle": "No app selected", + "noAppsLabel": "No applications found", + "currentVersion": "Current", + "suggestedVersion": "Suggested", + "anyVersion": "Any version" + }, + "patchSelectorCard": { + "widgetTitle": "Select patches", + "widgetTitleSelected": "Selected patches", + "widgetSubtitle": "Select an application first", + "widgetEmptySubtitle": "No patches selected" + }, + "socialMediaCard": { + "widgetTitle": "Socials", + "widgetSubtitle": "We are online!" + }, + "appSelectorView": { + "viewTitle": "Select an app", + "searchBarHint": "Search app", + "storageButton": "Storage", + "selectFromStorageButton": "Select from storage", + "errorMessage": "Unable to use selected application", + "downloadToast": "Download function is not available yet", + "requireSuggestedAppVersionDialogText": "The version of the app you have selected does not match the suggested version which can lead to unexpected issues. Please use the suggested version.\n\nSelected version: ${selected}\nSuggested version: ${suggested}\n\nTo continue anyway, disable \"Require suggested app version\" in the settings.", + "featureNotAvailable": "Feature not implemented", + "featureNotAvailableText": "This app is a split APK and can only be patched and installed reliably by mounting with root permissions. However, you can patch and install a full APK by selecting it from storage." + }, + "patchesSelectorView": { + "viewTitle": "Select patches", + "searchBarHint": "Search patches", + "universalPatches": "Universal patches", + "newPatches": "New patches", + "patches": "Patches", + "doneButton": "Done", + "defaultChip": "Default", + "defaultTooltip": "Select all default patches", + "noneChip": "None", + "noneTooltip": "Deselect all patches", + "loadPatchesSelection": "Load patch selection", + "noSavedPatches": "No saved patch selection for the selected app.\nPress Done to save the current selection.", + "noPatchesFound": "No patches found for the selected app", + "setRequiredOption": "Some patches require options to be set:\n\n${patches}\n\nPlease set them before continuing." + }, + "patchOptionsView": { + "customValue": "Custom value", + "resetOptionsTooltip": "Reset patch options", + "viewTitle": "Patch options", + "saveOptions": "Save", + "addOptions": "Add options", + "deselectPatch": "Deselect patch", + "tooltip": "More input options", + "selectFilePath": "Select file path", + "selectFolder": "Select folder", + "selectOption": "Select option", + "requiredOption": "This option is required", + "unsupportedOption": "This option is not supported", + "requiredOptionNull": "The following options have to be set:\n\n${options}" + }, + "patchItem": { + "unsupportedDialogText": "Selecting this patch may result in patching errors.\n\nApp version: ${packageVersion}\nSupported versions:\n${supportedVersions}", + "unsupportedPatchVersion": "Patch is not supported for this app version.", + "unsupportedRequiredOption": "This patch contains a required option that is not supported by this app", + "patchesChangeWarningDialogText": "It is recommended to use the default patch selection and options. Changing them may result in unexpected issues.\n\nYou'll need to turn on \"Allow changing patch selection\" in the settings before changing any patch selection.", + "patchesChangeWarningDialogButton": "Use default selection" + }, + "installerView": { + "widgetTitle": "Installer", + "installType": "Select install type", + "installTypeDescription": "Select the installation type to continue with.", + "installButton": "Install", + "installRootType": "Mount", + "installNonRootType": "Regular", + "warning": "Disable auto updates for the patched app to avoid unexpected issues.", + "pressBackAgain": "Press back again to cancel", + "openButton": "Open", + "shareButton": "Share file", + "notificationTitle": "ReVanced Manager is patching", + "notificationText": "Tap to return to the installer", + "exportApkButtonTooltip": "Export patched APK", + "exportLogButtonTooltip": "Export log", + "screenshotDetected": "A screenshot has been detected. If you are trying to share the log, please share a text copy instead.\n\nCopy log to clipboard?", + "copiedToClipboard": "Copied log to clipboard", + "noExit": "Installer is still running, cannot exit..." + }, + "settingsView": { + "widgetTitle": "Settings", + "appearanceSectionTitle": "Appearance", + "teamSectionTitle": "Team", + "debugSectionTitle": "Debugging", + "advancedSectionTitle": "Advanced", + "exportSectionTitle": "Import & export", + "themeModeLabel": "App theme", + "systemThemeLabel": "System", + "lightThemeLabel": "Light", + "darkThemeLabel": "Dark", + "dynamicThemeLabel": "Material You", + "dynamicThemeHint": "Enjoy an experience closer to your device", + "languageLabel": "Language", + "languageUpdated": "Language updated", + "englishOption": "English", + "sourcesLabel": "Sources", + "sourcesLabelHint": "Configure the source of patches and integrations", + "sourcesIntegrationsLabel": "Integrations source", + "sourcesResetDialogTitle": "Reset", + "sourcesResetDialogText": "Are you sure you want to reset your sources to their default values?", + "apiURLResetDialogText": "Are you sure you want to reset your API URL to its default value?", + "sourcesUpdateNote": "Note: Patches will be updated to the latest version automatically.\n\nThis will reveal your IP address to the server.", + "apiURLLabel": "API URL", + "apiURLHint": "Configure the URL of the API to use", + "selectApiURL": "API URL", + "hostRepositoryLabel": "Repository API", + "orgPatchesLabel": "Patches organization", + "sourcesPatchesLabel": "Patches source", + "orgIntegrationsLabel": "Integrations organization", + "contributorsLabel": "Contributors", + "contributorsHint": "A list of contributors of ReVanced", + "logsLabel": "Share logs", + "logsHint": "Share ReVanced Manager logs", + "enablePatchesSelectionLabel": "Allow changing patch selection", + "enablePatchesSelectionHint": "Do not prevent selecting or deselecting patches", + "enablePatchesSelectionWarningText": "Changing the selection of patches may cause unexpected issues.\n\nEnable anyways?", + "disablePatchesSelectionWarningText": "You are about to disable changing the selection of patches.\nThe default selection of patches will be restored.\n\nDisable anyways?", + "autoUpdatePatchesLabel": "Auto update patches", + "autoUpdatePatchesHint": "Automatically update patches to the latest version", + "showUpdateDialogLabel": "Show update dialog", + "showUpdateDialogHint": "Show a dialog when a new update is available", + "universalPatchesLabel": "Show universal patches", + "universalPatchesHint": "Display all apps and universal patches (may slow down the app list)", + "versionCompatibilityCheckLabel": "Version compatibility check", + "versionCompatibilityCheckHint": "Prevent selecting patches that are not compatible with the selected app version", + "requireSuggestedAppVersionLabel": "Require suggested app version", + "requireSuggestedAppVersionHint": "Prevent selecting an app with a version that is not the suggested", + "requireSuggestedAppVersionDialogText": "Selecting an app that is not the suggested version may cause unexpected issues.\n\nDo you want to proceed anyways?", + "aboutLabel": "About", + "snackbarMessage": "Copied to clipboard", + "restartAppForChanges": "Restart the app to apply changes", + "deleteTempDirLabel": "Delete temporary files", + "deleteTempDirHint": "Delete unused temporary files", + "deletedTempDir": "Temporary files deleted", + "exportPatchesLabel": "Export patch selection", + "exportPatchesHint": "Export patch selection to a JSON file", + "exportedPatches": "Patch selection exported", + "noExportFileFound": "No patch selection to export", + "importPatchesLabel": "Import patch selection", + "importPatchesHint": "Import patch selection from a JSON file", + "importedPatches": "Patch selection imported", + "resetStoredPatchesLabel": "Reset patch selection", + "resetStoredPatchesHint": "Reset the stored patch selection", + "resetStoredPatchesDialogTitle": "Reset patch selection?", + "resetStoredPatchesDialogText": "The default selection of patches will be restored.", + "resetStoredPatches": "Patch selection has been reset", + "resetStoredOptionsLabel": "Reset patch options", + "resetStoredOptionsHint": "Reset all patch options", + "resetStoredOptionsDialogTitle": "Reset patch options?", + "resetStoredOptionsDialogText": "Resetting patch options will remove all saved options.", + "resetStoredOptions": "Options have been reset", + "deleteLogsLabel": "Clear logs", + "deleteLogsHint": "Delete collected ReVanced Manager logs", + "deletedLogs": "Logs deleted", + "regenerateKeystoreLabel": "Regenerate keystore", + "regenerateKeystoreHint": "Regenerate the keystore used to sign apps", + "regenerateKeystoreDialogTitle": "Regenerate keystore?", + "regenerateKeystoreDialogText": "Patched apps signed with the old keystore will no longer be able to be updated.", + "regeneratedKeystore": "Keystore regenerated", + "exportKeystoreLabel": "Export keystore", + "exportKeystoreHint": "Export the keystore used to sign apps", + "exportedKeystore": "Keystore exported", + "noKeystoreExportFileFound": "No keystore to export", + "importKeystoreLabel": "Import keystore", + "importKeystoreHint": "Import a keystore used to sign apps", + "importedKeystore": "Keystore imported", + "selectKeystorePassword": "Keystore password", + "selectKeystorePasswordHint": "Select keystore password used to sign apps", + "jsonSelectorErrorMessage": "Unable to use selected JSON file", + "keystoreSelectorErrorMessage": "Unable to use selected keystore file" + }, + "appInfoView": { + "widgetTitle": "App info", + "openButton": "Open", + "uninstallButton": "Uninstall", + "unmountButton": "Unmount", + "rootDialogTitle": "Error", + "unmountDialogText": "Are you sure you want to unmount this app?", + "uninstallDialogText": "Are you sure you want to uninstall this app?", + "rootDialogText": "App was installed with superuser permissions, but currently ReVanced Manager has no permissions.\nPlease grant superuser permissions first.", + "packageNameLabel": "Package name", + "installTypeLabel": "Installation type", + "mountTypeLabel": "Mount", + "regularTypeLabel": "Regular", + "patchedDateLabel": "Patched date", + "appliedPatchesLabel": "Applied patches", + "patchedDateHint": "${date} at ${time}", + "appliedPatchesHint": "${quantity} applied patches", + "updateNotImplemented": "This feature has not been implemented yet" + }, + "contributorsView": { + "widgetTitle": "Contributors", + "patcherContributors": "Patcher contributors", + "patchesContributors": "Patches contributors", + "integrationsContributors": "Integrations contributors", + "cliContributors": "CLI contributors", + "managerContributors": "Manager contributors" + }, + "installErrorDialog": { + "mount_version_mismatch": "Version mismatch", + "mount_no_root": "No root access", + "mount_missing_installation": "Installation not found", + "status_failure_blocked": "Installation blocked", + "install_failed_verification_failure": "Verification failed", + "status_failure_invalid": "Installation invalid", + "install_failed_version_downgrade": "Can't downgrade", + "status_failure_conflict": "Installation conflict", + "status_failure_storage": "Installation storage issue", + "status_failure_incompatible": "Installation incompatible", + "status_failure_timeout": "Installation timeout", + "status_unknown": "Installation failed", + "mount_version_mismatch_description": "The installation failed due to the installed app being a different version than the patched app.\n\nInstall the version of the app you are mounting and try again.", + "mount_no_root_description": "The installation failed due to root access not being granted.\n\nGrant root access to ReVanced Manager and try again.", + "mount_missing_installation_description": "The installation failed due to the unpatched app not being installed on this device in order to mount over it.\n\nInstall the unpatched app before mounting and try again.", + "status_failure_timeout_description": "The installation took too long to finish.\n\nWould you like to try again?", + "status_failure_storage_description": "The installation failed due to insufficient storage.\n\nFree up some space and try again.", + "status_failure_invalid_description": "The installation failed due to the patched app being invalid.\n\nUninstall the app and try again?", + "status_failure_incompatible_description": "The app is incompatible with this device.\n\nContact the developer of the app and ask for support.", + "status_failure_conflict_description": "The installation was prevented by an existing installation of the app.\n\nUninstall the installed app and try again?", + "status_failure_blocked_description": "The installation was blocked by ${packageName}.\n\nAdjust your security settings and try again.", + "install_failed_verification_failure_description": "The installation failed due to a verification issue.\n\nAdjust your security settings and try again.", + "install_failed_version_downgrade_description": "The installation failed due to the patched app being a lower version than the installed app.\n\nUninstall the app and try again?", + "status_unknown_description": "The installation failed due to an unknown reason. Please try again." + } +} \ No newline at end of file diff --git a/crowdin.yml b/crowdin.yml index fdbf11ba..7dabb6a9 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -1,4 +1,8 @@ -preserve_hierarchy: 1 +project_id_env: "CROWDIN_PROJECT_ID" +api_token_env: "CROWDIN_PERSONAL_TOKEN" + +preserve_hierarchy: true files: - - source: /assets/i18n/en_US.json - translation: /assets/i18n/%locale_with_underscore%.json + - source: /assets/i18n/strings.i18n.json + translation: /assets/i18n/strings_%locale_with_underscore%.i18n.json + skip_untranslated_strings: true diff --git a/docs/4_building.md b/docs/4_building.md index 29168acc..03987f16 100644 --- a/docs/4_building.md +++ b/docs/4_building.md @@ -15,7 +15,13 @@ This page will guide you through building ReVanced Manager from source. flutter pub get ``` -4\. Delete conflicting outputs +4\. Generate translation file + + ```sh + dart run slang + ``` + +5\. Delete conflicting outputs > [!TIP] > Must be run every time you sync your local repository with the remote repository. @@ -24,9 +30,7 @@ This page will guide you through building ReVanced Manager from source. dart run build_runner build --delete-conflicting-outputs ``` - - -5\. Build the APK +6\. Build the APK ```sh flutter build apk diff --git a/lib/main.dart b/lib/main.dart index 5b8df919..6b0317c8 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,9 +1,6 @@ -import 'dart:developer'; - import 'package:flutter/material.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; -import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:revanced_manager/app/app.locator.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/services/download_manager.dart'; import 'package:revanced_manager/services/github_api.dart'; import 'package:revanced_manager/services/manager_api.dart'; @@ -19,6 +16,7 @@ Future main() async { await setupLocator(); WidgetsFlutterBinding.ensureInitialized(); await locator().initialize(); + await locator().initialize(); final String apiUrl = locator().getApiUrl(); await locator().initialize(apiUrl); @@ -34,7 +32,11 @@ Future main() async { prefs = await SharedPreferences.getInstance(); - runApp(const MyApp()); + final managerAPI = locator(); + final locale = managerAPI.getLocale(); + LocaleSettings.setLocaleRaw(locale); + + runApp(TranslationProvider(child: const MyApp())); } class MyApp extends StatelessWidget { @@ -42,32 +44,9 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { - // String rawLocale = prefs.getString('language') ?? 'en_US'; - // String replaceLocale = rawLocale.replaceAll('_', '-'); - // List localeList = replaceLocale.split('-'); - // Locale locale = Locale(localeList[0], localeList[1]); - const Locale locale = Locale('en', 'US'); - - return DynamicThemeBuilder( + return const DynamicThemeBuilder( title: 'ReVanced Manager', - home: const NavigationView(), - localizationsDelegates: [ - FlutterI18nDelegate( - translationLoader: FileTranslationLoader( - fallbackFile: 'en_US', - forcedLocale: locale, - basePath: 'assets/i18n', - useCountryCode: true, - ), - missingTranslationHandler: (key, locale) { - log( - '--> Missing translation: key: $key, languageCode: ${locale?.languageCode}', - ); - }, - ), - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - ], + home: NavigationView(), ); } } diff --git a/lib/services/manager_api.dart b/lib/services/manager_api.dart index 1044cbaa..091ddf22 100644 --- a/lib/services/manager_api.dart +++ b/lib/services/manager_api.dart @@ -4,11 +4,11 @@ import 'package:device_apps/device_apps.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_i18n/widgets/I18nText.dart'; import 'package:injectable/injectable.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:path_provider/path_provider.dart'; import 'package:revanced_manager/app/app.locator.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/models/patch.dart'; import 'package:revanced_manager/models/patched_application.dart'; import 'package:revanced_manager/services/github_api.dart'; @@ -58,8 +58,7 @@ class ManagerAPI { } bool isDefaultIntegrationsRepo() { - return getIntegrationsRepo().toLowerCase() == - defaultIntegrationsRepo; + return getIntegrationsRepo().toLowerCase() == defaultIntegrationsRepo; } Future initialize() async { @@ -99,7 +98,7 @@ class ManagerAPI { } await _revancedAPI.clearAllCache(); await _prefs.setString('apiUrl', url); - _toast.showBottom('settingsView.restartAppForChanges'); + _toast.showBottom(t.settingsView.restartAppForChanges); } String getRepoUrl() { @@ -302,6 +301,14 @@ class ManagerAPI { return _prefs.getString('keystorePassword') ?? defaultKeystorePassword; } + String getLocale() { + return _prefs.getString('locale') ?? 'en'; + } + + Future setLocale(String value) async { + await _prefs.setString('locale', value); + } + Future deleteTempFolder() async { final Directory dir = Directory('/data/local/tmp/revanced-manager'); if (await dir.exists()) { @@ -615,7 +622,7 @@ class ManagerAPI { builder: (context) => PopScope( canPop: false, child: AlertDialog( - title: I18nText('warning'), + title: Text(t.warning), content: ValueListenableBuilder( valueListenable: noShow, builder: (context, value, child) { @@ -623,22 +630,19 @@ class ManagerAPI { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - I18nText( - 'patchItem.patchesChangeWarningDialogText', - child: const Text( - '', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - ), + Text( + t.patchItem.patchesChangeWarningDialogText, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, ), ), const SizedBox(height: 8), HapticCheckboxListTile( value: value, contentPadding: EdgeInsets.zero, - title: I18nText( - 'noShowAgain', + title: Text( + t.noShowAgain, ), onChanged: (selected) { noShow.value = selected!; @@ -654,7 +658,7 @@ class ManagerAPI { setPatchesChangeWarning(noShow.value); Navigator.of(context).pop(); }, - child: I18nText('okButton'), + child: Text(t.okButton), ), ], ), diff --git a/lib/services/patcher_api.dart b/lib/services/patcher_api.dart index da6db552..edd4bb5b 100644 --- a/lib/services/patcher_api.dart +++ b/lib/services/patcher_api.dart @@ -6,10 +6,10 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_file_dialog/flutter_file_dialog.dart'; -import 'package:flutter_i18n/widgets/I18nText.dart'; import 'package:injectable/injectable.dart'; import 'package:path_provider/path_provider.dart'; import 'package:revanced_manager/app/app.locator.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/models/patch.dart'; import 'package:revanced_manager/models/patched_application.dart'; import 'package:revanced_manager/services/manager_api.dart'; @@ -304,18 +304,19 @@ class PatcherAPI { context: _managerAPI.ctx!, builder: (context) => AlertDialog( backgroundColor: Theme.of(context).colorScheme.secondaryContainer, - title: I18nText('installErrorDialog.$statusValue'), + title: Text(t['installErrorDialog.$statusValue']), content: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ - I18nText( - 'installErrorDialog.${statusValue}_description', - translationParams: statusCode == 2 - ? { - 'packageName': status['otherPackageName'], - } - : null, + Text( + t['installErrorDialog.${statusValue}_description']( + packageName: statusCode == 2 + ? { + 'packageName': status['otherPackageName'], + } + : null, + ), ), ], ), @@ -325,7 +326,7 @@ class PatcherAPI { onPressed: () async { Navigator.pop(context); }, - child: I18nText('okButton'), + child: Text(t.okButton), ), ] : [ @@ -334,14 +335,14 @@ class PatcherAPI { onPressed: () { Navigator.pop(context); }, - child: I18nText('cancelButton'), + child: Text(t.cancelButton), ) else TextButton( onPressed: () { Navigator.pop(context); }, - child: I18nText('cancelButton'), + child: Text(t.cancelButton), ), if (isFixable) FilledButton( @@ -355,7 +356,7 @@ class PatcherAPI { Navigator.pop(context); } }, - child: I18nText('okButton'), + child: Text(t.okButton), ), ], ), diff --git a/lib/services/toast.dart b/lib/services/toast.dart index cb9a62b7..e49d5176 100644 --- a/lib/services/toast.dart +++ b/lib/services/toast.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:fluttertoast/fluttertoast.dart' as t; class Toast { @@ -12,10 +11,7 @@ class Toast { void show(String text) { t.Fluttertoast.showToast( - msg: FlutterI18n.translate( - _fToast.context!, - text, - ), + msg: text, toastLength: t.Toast.LENGTH_LONG, gravity: t.ToastGravity.CENTER, ); @@ -23,10 +19,7 @@ class Toast { void showBottom(String text) { t.Fluttertoast.showToast( - msg: FlutterI18n.translate( - _fToast.context!, - text, - ), + msg: text, toastLength: t.Toast.LENGTH_LONG, gravity: t.ToastGravity.BOTTOM, ); diff --git a/lib/ui/theme/dynamic_theme_builder.dart b/lib/ui/theme/dynamic_theme_builder.dart index 9ec2d1bd..94a93b97 100644 --- a/lib/ui/theme/dynamic_theme_builder.dart +++ b/lib/ui/theme/dynamic_theme_builder.dart @@ -3,9 +3,11 @@ import 'package:dynamic_color/dynamic_color.dart'; import 'package:dynamic_themes/dynamic_themes.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:revanced_manager/app/app.locator.dart'; import 'package:revanced_manager/app/app.router.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/services/manager_api.dart'; import 'package:revanced_manager/theme.dart'; import 'package:stacked_services/stacked_services.dart'; @@ -15,11 +17,9 @@ class DynamicThemeBuilder extends StatefulWidget { super.key, required this.title, required this.home, - required this.localizationsDelegates, }); final String title; final Widget home; - final Iterable localizationsDelegates; @override State createState() => _DynamicThemeBuilderState(); @@ -108,7 +108,9 @@ class _DynamicThemeBuilderState extends State onGenerateRoute: StackedRouter().onGenerateRoute, theme: theme, home: widget.home, - localizationsDelegates: widget.localizationsDelegates, + localizationsDelegates: GlobalMaterialLocalizations.delegates, + locale: TranslationProvider.of(context).flutterLocale, + supportedLocales: AppLocaleUtils.supportedLocales, ), ); }, diff --git a/lib/ui/views/app_selector/app_selector_view.dart b/lib/ui/views/app_selector/app_selector_view.dart index ef679b0c..6c3540dd 100644 --- a/lib/ui/views/app_selector/app_selector_view.dart +++ b/lib/ui/views/app_selector/app_selector_view.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart' hide SearchBar; -import 'package:flutter_i18n/flutter_i18n.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/ui/views/app_selector/app_selector_viewmodel.dart'; import 'package:revanced_manager/ui/widgets/appSelectorView/app_skeleton_loader.dart'; import 'package:revanced_manager/ui/widgets/appSelectorView/installed_app_item.dart'; @@ -25,7 +25,7 @@ class _AppSelectorViewState extends State { viewModelBuilder: () => AppSelectorViewModel(), builder: (context, model, child) => Scaffold( floatingActionButton: HapticFloatingActionButtonExtended( - label: I18nText('appSelectorView.storageButton'), + label: Text(t.appSelectorView.storageButton), icon: const Icon(Icons.sd_storage), onPressed: () { model.selectAppFromStorage(context); @@ -36,8 +36,8 @@ class _AppSelectorViewState extends State { SliverAppBar( pinned: true, floating: true, - title: I18nText( - 'appSelectorView.viewTitle', + title: Text( + t.appSelectorView.viewTitle, ), titleTextStyle: TextStyle( fontSize: 22.0, @@ -58,10 +58,7 @@ class _AppSelectorViewState extends State { horizontal: 12.0, ), child: SearchBar( - hintText: FlutterI18n.translate( - context, - 'appSelectorView.searchBarHint', - ), + hintText: t.appSelectorView.searchBarHint, onQueryChanged: (searchQuery) { setState(() { _query = searchQuery; @@ -74,14 +71,10 @@ class _AppSelectorViewState extends State { SliverToBoxAdapter( child: model.noApps ? Center( - child: I18nText( - 'appSelectorCard.noAppsLabel', - child: Text( - '', - style: TextStyle( - color: - Theme.of(context).textTheme.titleLarge!.color, - ), + child: Text( + t.appSelectorCard.noAppsLabel, + style: TextStyle( + color: Theme.of(context).textTheme.titleLarge!.color, ), ), ) diff --git a/lib/ui/views/app_selector/app_selector_viewmodel.dart b/lib/ui/views/app_selector/app_selector_viewmodel.dart index dc3d03de..55d9ce85 100644 --- a/lib/ui/views/app_selector/app_selector_viewmodel.dart +++ b/lib/ui/views/app_selector/app_selector_viewmodel.dart @@ -5,8 +5,8 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_file_dialog/flutter_file_dialog.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:revanced_manager/app/app.locator.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/models/patch.dart'; import 'package:revanced_manager/models/patched_application.dart'; import 'package:revanced_manager/services/manager_api.dart'; @@ -168,25 +168,22 @@ class AppSelectorViewModel extends BaseViewModel { return showDialog( context: context, builder: (context) => AlertDialog( - title: I18nText('warning'), - content: I18nText( - 'appSelectorView.requireSuggestedAppVersionDialogText', - translationParams: { - 'suggested': suggestedVersion, - 'selected': selectedVersion, - }, - child: const Text( - '', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - ), + title: Text(t.warning), + content: Text( + t.appSelectorView.requireSuggestedAppVersionDialogText( + suggested: suggestedVersion, + selected: selectedVersion, ), + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + ), + ), actions: [ FilledButton( onPressed: () => Navigator.of(context).pop(), - child: I18nText('okButton'), + child: Text(t.okButton), ), ], ), @@ -208,26 +205,20 @@ class AppSelectorViewModel extends BaseViewModel { color: Theme.of(innerContext).colorScheme.primary, ), const SizedBox(height: 20), - I18nText( - 'appSelectorView.featureNotAvailable', - child: const Text( - '', - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w600, - wordSpacing: 1.5, - ), + Text( + t.appSelectorView.featureNotAvailable, + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w600, + wordSpacing: 1.5, ), ), const SizedBox(height: 20), - I18nText( - 'appSelectorView.featureNotAvailableText', - child: const Text( - '', - style: TextStyle( - fontSize: 14, - ), + Text( + t.appSelectorView.featureNotAvailableText, + style: const TextStyle( + fontSize: 14, ), ), const SizedBox(height: 30), @@ -241,7 +232,7 @@ class AppSelectorViewModel extends BaseViewModel { children: [ const Icon(Icons.sd_card), const SizedBox(width: 10), - I18nText('appSelectorView.selectFromStorageButton'), + Text(t.appSelectorView.selectFromStorageButton), ], ), ), @@ -254,7 +245,7 @@ class AppSelectorViewModel extends BaseViewModel { mainAxisAlignment: MainAxisAlignment.center, children: [ const SizedBox(width: 10), - I18nText('cancelButton'), + Text(t.cancelButton), ], ), ), @@ -295,7 +286,7 @@ class AppSelectorViewModel extends BaseViewModel { if (kDebugMode) { print(e); } - _toast.showBottom('appSelectorView.errorMessage'); + _toast.showBottom(t.appSelectorView.errorMessage); } } @@ -323,5 +314,5 @@ class AppSelectorViewModel extends BaseViewModel { } void showDownloadToast() => - _toast.showBottom('appSelectorView.downloadToast'); + _toast.showBottom(t.appSelectorView.downloadToast); } diff --git a/lib/ui/views/contributors/contributors_view.dart b/lib/ui/views/contributors/contributors_view.dart index 2d9c8b74..33740a7b 100644 --- a/lib/ui/views/contributors/contributors_view.dart +++ b/lib/ui/views/contributors/contributors_view.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/ui/views/contributors/contributors_viewmodel.dart'; import 'package:revanced_manager/ui/widgets/contributorsView/contributors_card.dart'; import 'package:revanced_manager/ui/widgets/shared/custom_sliver_app_bar.dart'; @@ -18,13 +18,10 @@ class ContributorsView extends StatelessWidget { body: CustomScrollView( slivers: [ CustomSliverAppBar( - title: I18nText( - 'contributorsView.widgetTitle', - child: Text( - '', - style: GoogleFonts.inter( - color: Theme.of(context).textTheme.titleLarge!.color, - ), + title: Text( + t.contributorsView.widgetTitle, + style: GoogleFonts.inter( + color: Theme.of(context).textTheme.titleLarge!.color, ), ), ), @@ -34,27 +31,27 @@ class ContributorsView extends StatelessWidget { delegate: SliverChildListDelegate.fixed( [ ContributorsCard( - title: 'contributorsView.patcherContributors', + title: t.contributorsView.patcherContributors, contributors: model.patcherContributors, ), const SizedBox(height: 20), ContributorsCard( - title: 'contributorsView.patchesContributors', + title: t.contributorsView.patchesContributors, contributors: model.patchesContributors, ), const SizedBox(height: 20), ContributorsCard( - title: 'contributorsView.integrationsContributors', + title: t.contributorsView.integrationsContributors, contributors: model.integrationsContributors, ), const SizedBox(height: 20), ContributorsCard( - title: 'contributorsView.cliContributors', + title: t.contributorsView.cliContributors, contributors: model.cliContributors, ), const SizedBox(height: 20), ContributorsCard( - title: 'contributorsView.managerContributors', + title: t.contributorsView.managerContributors, contributors: model.managerContributors, ), SizedBox(height: MediaQuery.viewPaddingOf(context).bottom), diff --git a/lib/ui/views/home/home_view.dart b/lib/ui/views/home/home_view.dart index b2fdcd86..c5deea5e 100644 --- a/lib/ui/views/home/home_view.dart +++ b/lib/ui/views/home/home_view.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:revanced_manager/app/app.locator.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/ui/views/home/home_viewmodel.dart'; import 'package:revanced_manager/ui/widgets/homeView/installed_apps_card.dart'; import 'package:revanced_manager/ui/widgets/homeView/latest_commit_card.dart'; @@ -25,13 +25,10 @@ class HomeView extends StatelessWidget { slivers: [ CustomSliverAppBar( isMainView: true, - title: I18nText( - 'homeView.widgetTitle', - child: Text( - '', - style: GoogleFonts.inter( - color: Theme.of(context).textTheme.titleLarge!.color, - ), + title: Text( + t.homeView.widgetTitle, + style: GoogleFonts.inter( + color: Theme.of(context).textTheme.titleLarge!.color, ), ), ), @@ -40,22 +37,16 @@ class HomeView extends StatelessWidget { sliver: SliverList( delegate: SliverChildListDelegate.fixed( [ - I18nText( - 'homeView.updatesSubtitle', - child: Text( - '', - style: Theme.of(context).textTheme.titleLarge, - ), + Text( + t.homeView.updatesSubtitle, + style: Theme.of(context).textTheme.titleLarge, ), const SizedBox(height: 10), LatestCommitCard(model: model, parentContext: context), const SizedBox(height: 23), - I18nText( - 'homeView.patchedSubtitle', - child: Text( - '', - style: Theme.of(context).textTheme.titleLarge, - ), + Text( + t.homeView.patchedSubtitle, + style: Theme.of(context).textTheme.titleLarge, ), const SizedBox(height: 10), InstalledAppsCard(), diff --git a/lib/ui/views/home/home_viewmodel.dart b/lib/ui/views/home/home_viewmodel.dart index a50a1c38..0debb464 100644 --- a/lib/ui/views/home/home_viewmodel.dart +++ b/lib/ui/views/home/home_viewmodel.dart @@ -1,16 +1,17 @@ // ignore_for_file: use_build_context_synchronously import 'dart:async'; import 'dart:io'; + import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:injectable/injectable.dart'; import 'package:path_provider/path_provider.dart'; import 'package:revanced_manager/app/app.locator.dart'; import 'package:revanced_manager/app/app.router.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/models/patched_application.dart'; import 'package:revanced_manager/services/github_api.dart'; import 'package:revanced_manager/services/manager_api.dart'; @@ -68,12 +69,12 @@ class HomeViewModel extends BaseViewModel { ), onDidReceiveNotificationResponse: (response) async { if (response.id == 0) { - _toast.showBottom('homeView.installingMessage'); + _toast.showBottom(t.homeView.installingMessage); final File? managerApk = await _managerAPI.downloadManager(); if (managerApk != null) { await _patcherAPI.installApk(context, managerApk.path); } else { - _toast.showBottom('homeView.errorDownloadMessage'); + _toast.showBottom(t.homeView.errorDownloadMessage); } } }, @@ -82,22 +83,21 @@ class HomeViewModel extends BaseViewModel { .resolvePlatformSpecificImplementation< AndroidFlutterLocalNotificationsPlugin>() ?.requestNotificationsPermission(); - final bool isConnected = await Connectivity().checkConnectivity() != ConnectivityResult.none; if (!isConnected) { - _toast.showBottom('homeView.noConnection'); + _toast.showBottom(t.homeView.noConnection); } final NotificationAppLaunchDetails? notificationAppLaunchDetails = await flutterLocalNotificationsPlugin.getNotificationAppLaunchDetails(); if (notificationAppLaunchDetails?.didNotificationLaunchApp ?? false) { - _toast.showBottom('homeView.installingMessage'); + _toast.showBottom(t.homeView.installingMessage); final File? managerApk = await _managerAPI.downloadManager(); if (managerApk != null) { await _patcherAPI.installApk(context, managerApk.path); } else { - _toast.showBottom('homeView.errorDownloadMessage'); + _toast.showBottom(t.homeView.errorDownloadMessage); } } } @@ -183,7 +183,7 @@ class HomeViewModel extends BaseViewModel { builder: (context) => PopScope( canPop: false, child: AlertDialog( - title: I18nText('homeView.downloadConsentDialogTitle'), + title: Text(t.homeView.downloadConsentDialogTitle), content: ValueListenableBuilder( valueListenable: autoUpdate, builder: (context, value, child) { @@ -191,31 +191,24 @@ class HomeViewModel extends BaseViewModel { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - I18nText( - 'homeView.downloadConsentDialogText', - child: Text( - '', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.secondary, - ), + Text( + t.homeView.downloadConsentDialogText, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.secondary, ), ), Padding( padding: const EdgeInsets.symmetric(vertical: 10), - child: I18nText( - 'homeView.downloadConsentDialogText2', - translationParams: { - 'url': _managerAPI.defaultApiUrl.split('/')[2], - }, - child: Text( - '', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.error, - ), + child: Text( + t.homeView.downloadConsentDialogText2( + url: _managerAPI.defaultApiUrl.split('/')[2], + ), + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.error, ), ), ), @@ -229,7 +222,7 @@ class HomeViewModel extends BaseViewModel { _managerAPI.setDownloadConsent(false); SystemNavigator.pop(); }, - child: I18nText('quitButton'), + child: Text(t.quitButton), ), FilledButton( onPressed: () async { @@ -237,7 +230,7 @@ class HomeViewModel extends BaseViewModel { _managerAPI.setPatchesAutoUpdate(autoUpdate.value); Navigator.of(context).pop(); }, - child: I18nText('okButton'), + child: Text(t.okButton), ), ], ), @@ -251,7 +244,7 @@ class HomeViewModel extends BaseViewModel { showDialog( context: context, builder: (innerContext) => AlertDialog( - title: I18nText('homeView.updateDialogTitle'), + title: Text(t.homeView.updateDialogTitle), content: ValueListenableBuilder( valueListenable: noShow, builder: (context, value, child) { @@ -259,33 +252,25 @@ class HomeViewModel extends BaseViewModel { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - I18nText( - 'homeView.updateDialogText', - translationParams: { - 'file': isPatches ? 'ReVanced Patches' : 'ReVanced Manager', - 'version': isPatches + Text( + t.homeView.updateDialogText( + file: isPatches ? 'ReVanced Patches' : 'ReVanced Manager', + version: isPatches ? _currentPatchesVersion : _currentManagerVersion, - }, - child: Text( - '', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.secondary, - ), + ), + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.secondary, ), ), const SizedBox(height: 10), HapticCheckboxListTile( value: value, contentPadding: EdgeInsets.zero, - title: I18nText( - 'noShowAgain', - ), - subtitle: I18nText( - 'homeView.changeLaterSubtitle', - ), + title: Text(t.noShowAgain), + subtitle: Text(t.homeView.changeLaterSubtitle), onChanged: (selected) { noShow.value = selected!; }, @@ -300,7 +285,7 @@ class HomeViewModel extends BaseViewModel { _managerAPI.setShowUpdateDialog(!noShow.value); Navigator.pop(innerContext); }, - child: I18nText('dismissButton'), // Decide later + child: Text(t.dismissButton), // Decide later ), FilledButton( onPressed: () async { @@ -308,7 +293,7 @@ class HomeViewModel extends BaseViewModel { Navigator.pop(innerContext); await showUpdateConfirmationDialog(context, isPatches); }, - child: I18nText('showUpdateButton'), + child: Text(t.showUpdateButton), ), ], ), @@ -316,7 +301,7 @@ class HomeViewModel extends BaseViewModel { } Future updatePatches(BuildContext context) async { - _toast.showBottom('homeView.downloadingMessage'); + _toast.showBottom(t.homeView.downloadingMessage); final String patchesVersion = await _managerAPI.getLatestPatchesVersion() ?? '0.0.0'; final String integrationsVersion = @@ -324,27 +309,27 @@ class HomeViewModel extends BaseViewModel { if (patchesVersion != '0.0.0' && integrationsVersion != '0.0.0') { await _managerAPI.setCurrentPatchesVersion(patchesVersion); await _managerAPI.setCurrentIntegrationsVersion(integrationsVersion); - _toast.showBottom('homeView.downloadedMessage'); + _toast.showBottom(t.homeView.downloadedMessage); forceRefresh(context); } else { - _toast.showBottom('homeView.errorDownloadMessage'); + _toast.showBottom(t.homeView.errorDownloadMessage); } } Future updateManager(BuildContext context) async { final ValueNotifier downloaded = ValueNotifier(false); try { - _toast.showBottom('homeView.downloadingMessage'); + _toast.showBottom(t.homeView.downloadingMessage); showDialog( context: context, builder: (context) => ValueListenableBuilder( valueListenable: downloaded, builder: (context, value, child) { return AlertDialog( - title: I18nText( + title: Text( !value - ? 'homeView.downloadingMessage' - : 'homeView.downloadedMessage', + ? t.homeView.downloadingMessage + : t.homeView.downloadedMessage, ), content: Column( mainAxisSize: MainAxisSize.min, @@ -373,7 +358,7 @@ class HomeViewModel extends BaseViewModel { _revancedAPI.disposeManagerUpdateProgress(); Navigator.of(context).pop(); }, - child: I18nText('cancelButton'), + child: Text(t.cancelButton), ), ), ], @@ -382,15 +367,12 @@ class HomeViewModel extends BaseViewModel { Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - I18nText( - 'homeView.installUpdate', - child: Text( - '', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.secondary, - ), + Text( + t.homeView.installUpdate, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.secondary, ), ), const SizedBox(height: 16.0), @@ -403,7 +385,7 @@ class HomeViewModel extends BaseViewModel { onPressed: () { Navigator.of(context).pop(); }, - child: I18nText('cancelButton'), + child: Text(t.cancelButton), ), ), const SizedBox(width: 8.0), @@ -416,7 +398,7 @@ class HomeViewModel extends BaseViewModel { downloadedApk!.path, ); }, - child: I18nText('updateButton'), + child: Text(t.updateButton), ), ), ], @@ -457,21 +439,21 @@ class HomeViewModel extends BaseViewModel { // uiLocalNotificationDateInterpretation: // UILocalNotificationDateInterpretation.absoluteTime, // ); - _toast.showBottom('homeView.installingMessage'); + _toast.showBottom(t.homeView.installingMessage); await _patcherAPI.installApk(context, managerApk.path); } else { - _toast.showBottom('homeView.errorDownloadMessage'); + _toast.showBottom(t.homeView.errorDownloadMessage); } } on Exception catch (e) { if (kDebugMode) { print(e); } - _toast.showBottom('homeView.errorInstallMessage'); + _toast.showBottom(t.homeView.errorInstallMessage); } } void updatesAreDisabled() { - _toast.showBottom('homeView.updatesDisabled'); + _toast.showBottom(t.homeView.updatesDisabled); } Future showUpdateConfirmationDialog( @@ -510,7 +492,7 @@ class HomeViewModel extends BaseViewModel { Future forceRefresh(BuildContext context) async { _managerAPI.clearAllData(); - _toast.showBottom('homeView.refreshSuccess'); + _toast.showBottom(t.homeView.refreshSuccess); initialize(context); } } diff --git a/lib/ui/views/installer/installer_view.dart b/lib/ui/views/installer/installer_view.dart index fb654233..49fe9b9d 100644 --- a/lib/ui/views/installer/installer_view.dart +++ b/lib/ui/views/installer/installer_view.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/ui/views/installer/installer_viewmodel.dart'; import 'package:revanced_manager/ui/widgets/installerView/gradient_progress_indicator.dart'; import 'package:revanced_manager/ui/widgets/shared/custom_card.dart'; @@ -26,10 +26,10 @@ class InstallerView extends StatelessWidget { floatingActionButton: Visibility( visible: !model.isPatching && !model.hasErrors, child: HapticFloatingActionButtonExtended( - label: I18nText( + label: Text( model.isInstalled - ? 'installerView.openButton' - : 'installerView.installButton', + ? t.installerView.openButton + : t.installerView.installButton, ), icon: model.isInstalled ? const Icon(Icons.open_in_new) @@ -54,19 +54,13 @@ class InstallerView extends StatelessWidget { Visibility( visible: !model.hasErrors, child: IconButton.filledTonal( - tooltip: FlutterI18n.translate( - context, - 'installerView.exportApkButtonTooltip', - ), + tooltip: t.installerView.exportApkButtonTooltip, icon: const Icon(Icons.save), onPressed: () => model.onButtonPressed(0), ), ), IconButton.filledTonal( - tooltip: FlutterI18n.translate( - context, - 'installerView.exportLogButtonTooltip', - ), + tooltip: t.installerView.exportLogButtonTooltip, icon: const Icon(Icons.post_add), onPressed: () => model.onButtonPressed(1), ), diff --git a/lib/ui/views/installer/installer_viewmodel.dart b/lib/ui/views/installer/installer_viewmodel.dart index d345f2c6..1e4c9615 100644 --- a/lib/ui/views/installer/installer_viewmodel.dart +++ b/lib/ui/views/installer/installer_viewmodel.dart @@ -4,9 +4,9 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_background/flutter_background.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:revanced_manager/app/app.locator.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/models/patch.dart'; import 'package:revanced_manager/models/patched_application.dart'; import 'package:revanced_manager/services/manager_api.dart'; @@ -49,14 +49,8 @@ class InstallerViewModel extends BaseViewModel { try { FlutterBackground.initialize( androidConfig: FlutterBackgroundAndroidConfig( - notificationTitle: FlutterI18n.translate( - context, - 'installerView.notificationTitle', - ), - notificationText: FlutterI18n.translate( - context, - 'installerView.notificationText', - ), + notificationTitle: t.installerView.notificationTitle, + notificationText: t.installerView.notificationText, notificationIcon: const AndroidResource( name: 'ic_notification', ), @@ -280,26 +274,26 @@ class InstallerViewModel extends BaseViewModel { ]; Clipboard.setData(ClipboardData(text: formattedLogs.join('\n'))); - _toast.showBottom('installerView.copiedToClipboard'); + _toast.showBottom(t.installerView.copiedToClipboard); } Future screenshotDetected(BuildContext context) async { await showDialog( context: context, builder: (context) => AlertDialog( - title: I18nText( - 'warning', + title: Text( + t.warning, ), icon: const Icon(Icons.warning), content: SingleChildScrollView( - child: I18nText('installerView.screenshotDetected'), + child: Text(t.installerView.screenshotDetected), ), actions: [ TextButton( onPressed: () { Navigator.of(context).pop(); }, - child: I18nText('noButton'), + child: Text(t.noButton), ), FilledButton( onPressed: () { @@ -307,7 +301,7 @@ class InstallerViewModel extends BaseViewModel { showPopupScreenshotWarning = true; Navigator.of(context).pop(); }, - child: I18nText('yesButton'), + child: Text(t.yesButton), ), ], ), @@ -321,8 +315,8 @@ class InstallerViewModel extends BaseViewModel { context: context, barrierDismissible: false, builder: (innerContext) => AlertDialog( - title: I18nText( - 'installerView.installType', + title: Text( + t.installerView.installType, ), icon: const Icon(Icons.file_download_outlined), contentPadding: const EdgeInsets.symmetric(vertical: 16), @@ -339,20 +333,17 @@ class InstallerViewModel extends BaseViewModel { horizontal: 20, vertical: 10, ), - child: I18nText( - 'installerView.installTypeDescription', - child: Text( - '', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.secondary, - ), + child: Text( + t.installerView.installTypeDescription, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.secondary, ), ), ), RadioListTile( - title: I18nText('installerView.installNonRootType'), + title: Text(t.installerView.installNonRootType), contentPadding: const EdgeInsets.symmetric(horizontal: 16), value: 0, @@ -362,7 +353,7 @@ class InstallerViewModel extends BaseViewModel { }, ), RadioListTile( - title: I18nText('installerView.installRootType'), + title: Text(t.installerView.installRootType), contentPadding: const EdgeInsets.symmetric(horizontal: 16), value: 1, @@ -373,14 +364,11 @@ class InstallerViewModel extends BaseViewModel { ), Padding( padding: const EdgeInsets.symmetric(horizontal: 16), - child: I18nText( - 'installerView.warning', - child: Text( - '', - style: TextStyle( - fontWeight: FontWeight.w500, - color: Theme.of(context).colorScheme.error, - ), + child: Text( + t.installerView.warning, + style: TextStyle( + fontWeight: FontWeight.w500, + color: Theme.of(context).colorScheme.error, ), ), ), @@ -394,14 +382,14 @@ class InstallerViewModel extends BaseViewModel { onPressed: () { Navigator.of(innerContext).pop(); }, - child: I18nText('cancelButton'), + child: Text(t.cancelButton), ), FilledButton( onPressed: () { Navigator.of(innerContext).pop(); installResult(context, installType.value == 1); }, - child: I18nText('installerView.installButton'), + child: Text(t.installerView.installButton), ), ], ), @@ -411,24 +399,22 @@ class InstallerViewModel extends BaseViewModel { context: context, barrierDismissible: false, builder: (innerContext) => AlertDialog( - title: I18nText( - 'warning', - ), + title: Text(t.warning), contentPadding: const EdgeInsets.all(16), - content: I18nText('installerView.warning'), + content: Text(t.installerView.warning), actions: [ TextButton( onPressed: () { Navigator.of(innerContext).pop(); }, - child: I18nText('cancelButton'), + child: Text(t.cancelButton), ), FilledButton( onPressed: () { Navigator.of(innerContext).pop(); installResult(context, false); }, - child: I18nText('installerView.installButton'), + child: Text(t.installerView.installButton), ), ], ), @@ -544,11 +530,11 @@ class InstallerViewModel extends BaseViewModel { if (isPatching) { if (!cancel) { cancel = true; - _toast.showBottom('installerView.pressBackAgain'); + _toast.showBottom(t.installerView.pressBackAgain); } else if (!isCanceled) { await stopPatcher(); } else { - _toast.showBottom('installerView.noExit'); + _toast.showBottom(t.installerView.noExit); } return false; } diff --git a/lib/ui/views/navigation/navigation_view.dart b/lib/ui/views/navigation/navigation_view.dart index 5eb6926a..285331fc 100644 --- a/lib/ui/views/navigation/navigation_view.dart +++ b/lib/ui/views/navigation/navigation_view.dart @@ -1,7 +1,7 @@ import 'package:animations/animations.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:revanced_manager/app/app.locator.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/ui/views/navigation/navigation_viewmodel.dart'; import 'package:stacked/stacked.dart'; @@ -43,30 +43,21 @@ class NavigationView extends StatelessWidget { icon: model.isIndexSelected(0) ? const Icon(Icons.dashboard) : const Icon(Icons.dashboard_outlined), - label: FlutterI18n.translate( - context, - 'navigationView.dashboardTab', - ), + label: t.navigationView.dashboardTab, tooltip: '', ), NavigationDestination( icon: model.isIndexSelected(1) ? const Icon(Icons.build) : const Icon(Icons.build_outlined), - label: FlutterI18n.translate( - context, - 'navigationView.patcherTab', - ), + label: t.navigationView.patcherTab, tooltip: '', ), NavigationDestination( icon: model.isIndexSelected(2) ? const Icon(Icons.settings) : const Icon(Icons.settings_outlined), - label: FlutterI18n.translate( - context, - 'navigationView.settingsTab', - ), + label: t.navigationView.settingsTab, tooltip: '', ), ], diff --git a/lib/ui/views/patch_options/patch_options_view.dart b/lib/ui/views/patch_options/patch_options_view.dart index 74f56657..b221b8a5 100644 --- a/lib/ui/views/patch_options/patch_options_view.dart +++ b/lib/ui/views/patch_options/patch_options_view.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/models/patch.dart'; import 'package:revanced_manager/ui/views/patch_options/patch_options_viewmodel.dart'; import 'package:revanced_manager/ui/widgets/patchesSelectorView/patch_options_fields.dart'; @@ -25,19 +25,16 @@ class PatchOptionsView extends StatelessWidget { Navigator.pop(context); } }, - label: I18nText('patchOptionsView.saveOptions'), + label: Text(t.patchOptionsView.saveOptions), icon: const Icon(Icons.save), ), body: CustomScrollView( slivers: [ SliverAppBar( - title: I18nText( - 'patchOptionsView.viewTitle', - child: Text( - '', - style: GoogleFonts.inter( - color: Theme.of(context).textTheme.titleLarge!.color, - ), + title: Text( + t.patchOptionsView.viewTitle, + style: GoogleFonts.inter( + color: Theme.of(context).textTheme.titleLarge!.color, ), ), actions: [ @@ -48,10 +45,7 @@ class PatchOptionsView extends StatelessWidget { icon: const Icon( Icons.history, ), - tooltip: FlutterI18n.translate( - context, - 'patchOptionsView.resetOptionsTooltip', - ), + tooltip: t.patchOptionsView.resetOptionsTooltip, ), ], ), @@ -111,7 +105,7 @@ class PatchOptionsView extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.add), - I18nText('patchOptionsView.addOptions'), + Text(t.patchOptionsView.addOptions), ], ), ), diff --git a/lib/ui/views/patch_options/patch_options_viewmodel.dart b/lib/ui/views/patch_options/patch_options_viewmodel.dart index b835a993..a982f32e 100644 --- a/lib/ui/views/patch_options/patch_options_viewmodel.dart +++ b/lib/ui/views/patch_options/patch_options_viewmodel.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:flutter_i18n/widgets/I18nText.dart'; import 'package:revanced_manager/app/app.locator.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/models/patch.dart'; import 'package:revanced_manager/services/manager_api.dart'; import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart'; @@ -137,8 +137,8 @@ class PatchOptionsViewModel extends BaseViewModel { crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ - I18nText( - 'patchOptionsView.addOptions', + Text( + t.patchOptionsView.addOptions, ), Text( '', @@ -154,7 +154,7 @@ class PatchOptionsViewModel extends BaseViewModel { onPressed: () { Navigator.of(context).pop(); }, - child: I18nText('cancelButton'), + child: Text(t.cancelButton), ), ], contentPadding: const EdgeInsets.all(8), @@ -224,7 +224,7 @@ Future showRequiredOptionNullDialog( await showDialog( context: context, builder: (context) => AlertDialog( - title: I18nText('notice'), + title: Text(t.notice), actions: [ TextButton( onPressed: () async { @@ -248,20 +248,19 @@ Future showRequiredOptionNullDialog( PatchesSelectorViewModel().showPatchesChangeDialog(context); } }, - child: I18nText('patchOptionsView.deselectPatch'), + child: Text(t.patchOptionsView.deselectPatch), ), FilledButton( onPressed: () { Navigator.of(context).pop(); }, - child: I18nText('okButton'), + child: Text(t.okButton), ), ], - content: I18nText( - 'patchOptionsView.requiredOptionNull', - translationParams: { - 'options': optionsTitles.join('\n'), - }, + content: Text( + t.patchOptionsView.requiredOptionNull( + options: optionsTitles.join('\n'), + ), ), ), ); diff --git a/lib/ui/views/patcher/patcher_view.dart b/lib/ui/views/patcher/patcher_view.dart index fb0592c0..f3dc39c0 100644 --- a/lib/ui/views/patcher/patcher_view.dart +++ b/lib/ui/views/patcher/patcher_view.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:revanced_manager/app/app.locator.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart'; import 'package:revanced_manager/ui/widgets/patcherView/app_selector_card.dart'; import 'package:revanced_manager/ui/widgets/patcherView/patch_selector_card.dart'; @@ -21,7 +21,7 @@ class PatcherView extends StatelessWidget { floatingActionButton: Visibility( visible: model.showPatchButton(), child: HapticFloatingActionButtonExtended( - label: I18nText('patcherView.patchButton'), + label: Text(t.patcherView.patchButton), icon: const Icon(Icons.build), onPressed: () async { if (model.checkRequiredPatchOption(context)) { @@ -37,13 +37,10 @@ class PatcherView extends StatelessWidget { slivers: [ CustomSliverAppBar( isMainView: true, - title: I18nText( - 'patcherView.widgetTitle', - child: Text( - '', - style: GoogleFonts.inter( - color: Theme.of(context).textTheme.titleLarge!.color, - ), + title: Text( + t.patcherView.widgetTitle, + style: GoogleFonts.inter( + color: Theme.of(context).textTheme.titleLarge!.color, ), ), ), diff --git a/lib/ui/views/patcher/patcher_viewmodel.dart b/lib/ui/views/patcher/patcher_viewmodel.dart index f20ccc65..5f8f5324 100644 --- a/lib/ui/views/patcher/patcher_viewmodel.dart +++ b/lib/ui/views/patcher/patcher_viewmodel.dart @@ -5,10 +5,10 @@ import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:injectable/injectable.dart'; import 'package:revanced_manager/app/app.locator.dart'; import 'package:revanced_manager/app/app.router.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/models/patch.dart'; import 'package:revanced_manager/models/patched_application.dart'; import 'package:revanced_manager/services/manager_api.dart'; @@ -54,24 +54,25 @@ class PatcherViewModel extends BaseViewModel { showDialog( context: context, builder: (context) => AlertDialog( - title: I18nText('notice'), - content: I18nText( - 'patcherView.removedPatchesWarningDialogText', - translationParams: {'patches': removedPatches.join('\n')}, + title: Text(t.notice), + content: Text( + t.patcherView.removedPatchesWarningDialogText( + patches: removedPatches.join('\n'), + ), ), actions: [ TextButton( onPressed: () { Navigator.of(context).pop(); }, - child: I18nText('noButton'), + child: Text(t.noButton), ), FilledButton( onPressed: () { Navigator.of(context).pop(); showArmv7WarningDialog(context); }, - child: I18nText('yesButton'), + child: Text(t.yesButton), ), ], ), @@ -94,21 +95,21 @@ class PatcherViewModel extends BaseViewModel { showDialog( context: context ?? ctx, builder: (context) => AlertDialog( - title: I18nText('notice'), - content: I18nText('patcherView.requiredOptionDialogText'), + title: Text(t.notice), + content: Text(t.patcherView.requiredOptionDialogText), actions: [ TextButton( onPressed: () => { Navigator.of(context).pop(), }, - child: I18nText('cancelButton'), + child: Text(t.cancelButton), ), FilledButton( onPressed: () => { Navigator.pop(context), navigateToPatchesSelector(), }, - child: I18nText('okButton'), + child: Text(t.okButton), ), ], ), @@ -125,19 +126,19 @@ class PatcherViewModel extends BaseViewModel { return showDialog( context: context, builder: (context) => AlertDialog( - title: I18nText('warning'), - content: I18nText('patcherView.armv7WarningDialogText'), + title: Text(t.warning), + content: Text(t.patcherView.armv7WarningDialogText), actions: [ FilledButton( onPressed: () => Navigator.of(context).pop(), - child: I18nText('noButton'), + child: Text(t.noButton), ), TextButton( onPressed: () { Navigator.of(context).pop(); navigateToInstaller(); }, - child: I18nText('yesButton'), + child: Text(t.yesButton), ), ], ), diff --git a/lib/ui/views/patches_selector/patches_selector_view.dart b/lib/ui/views/patches_selector/patches_selector_view.dart index 3aa1da24..6ae2eedf 100644 --- a/lib/ui/views/patches_selector/patches_selector_view.dart +++ b/lib/ui/views/patches_selector/patches_selector_view.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart' hide SearchBar; -import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:revanced_manager/app/app.locator.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/services/manager_api.dart'; import 'package:revanced_manager/ui/views/patches_selector/patches_selector_viewmodel.dart'; import 'package:revanced_manager/ui/widgets/shared/haptics/haptic_floating_action_button_extended.dart'; @@ -40,7 +40,7 @@ class _PatchesSelectorViewState extends State { child: HapticFloatingActionButtonExtended( label: Row( children: [ - I18nText('patchesSelectorView.doneButton'), + Text(t.patchesSelectorView.doneButton), Text(' (${model.selectedPatches.length})'), ], ), @@ -58,8 +58,8 @@ class _PatchesSelectorViewState extends State { SliverAppBar( pinned: true, floating: true, - title: I18nText( - 'patchesSelectorView.viewTitle', + title: Text( + t.patchesSelectorView.viewTitle, ), titleTextStyle: TextStyle( fontSize: 22.0, @@ -99,8 +99,8 @@ class _PatchesSelectorViewState extends State { itemBuilder: (BuildContext context) => [ PopupMenuItem( value: 0, - child: I18nText( - 'patchesSelectorView.loadPatchesSelection', + child: Text( + t.patchesSelectorView.loadPatchesSelection, ), ), ], @@ -114,10 +114,7 @@ class _PatchesSelectorViewState extends State { horizontal: 12.0, ), child: SearchBar( - hintText: FlutterI18n.translate( - context, - 'patchesSelectorView.searchBarHint', - ), + hintText: t.patchesSelectorView.searchBarHint, onQueryChanged: (searchQuery) { setState(() { _query = searchQuery; @@ -132,12 +129,9 @@ class _PatchesSelectorViewState extends State { ? Padding( padding: const EdgeInsets.all(8.0), child: Center( - child: I18nText( - 'patchesSelectorView.noPatchesFound', - child: Text( - '', - style: Theme.of(context).textTheme.bodyMedium, - ), + child: Text( + t.patchesSelectorView.noPatchesFound, + style: Theme.of(context).textTheme.bodyMedium, ), ), ) @@ -151,11 +145,8 @@ class _PatchesSelectorViewState extends State { Row( children: [ ActionChip( - label: I18nText('patchesSelectorView.default'), - tooltip: FlutterI18n.translate( - context, - 'patchesSelectorView.defaultTooltip', - ), + label: Text(t.patchesSelectorView.defaultChip), + tooltip: t.patchesSelectorView.defaultTooltip, onPressed: () { if (_managerAPI.isPatchesChangeEnabled()) { model.selectDefaultPatches(); @@ -166,11 +157,8 @@ class _PatchesSelectorViewState extends State { ), const SizedBox(width: 8), ActionChip( - label: I18nText('patchesSelectorView.none'), - tooltip: FlutterI18n.translate( - context, - 'patchesSelectorView.noneTooltip', - ), + label: Text(t.patchesSelectorView.noneChip), + tooltip: t.patchesSelectorView.noneTooltip, onPressed: () { if (_managerAPI.isPatchesChangeEnabled()) { model.clearPatches(); @@ -189,7 +177,7 @@ class _PatchesSelectorViewState extends State { children: [ model.getPatchCategory( context, - 'patchesSelectorView.newPatches', + t.patchesSelectorView.newPatches, ), ...model.getQueriedPatches(_query).map((patch) { if (model.isPatchNew(patch)) { @@ -205,7 +193,7 @@ class _PatchesSelectorViewState extends State { )) model.getPatchCategory( context, - 'patchesSelectorView.patches', + t.patchesSelectorView.patches, ), ], ), @@ -227,7 +215,7 @@ class _PatchesSelectorViewState extends State { children: [ model.getPatchCategory( context, - 'patchesSelectorView.universalPatches', + t.patchesSelectorView.universalPatches, ), ...model.getQueriedPatches(_query).map((patch) { if (patch.compatiblePackages.isEmpty && diff --git a/lib/ui/views/patches_selector/patches_selector_viewmodel.dart b/lib/ui/views/patches_selector/patches_selector_viewmodel.dart index 82f330b5..80f3fba9 100644 --- a/lib/ui/views/patches_selector/patches_selector_viewmodel.dart +++ b/lib/ui/views/patches_selector/patches_selector_viewmodel.dart @@ -1,8 +1,8 @@ import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_i18n/widgets/I18nText.dart'; import 'package:revanced_manager/app/app.locator.dart'; import 'package:revanced_manager/app/app.router.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/models/patch.dart'; import 'package:revanced_manager/models/patched_application.dart'; import 'package:revanced_manager/services/manager_api.dart'; @@ -92,19 +92,18 @@ class PatchesSelectorViewModel extends BaseViewModel { barrierDismissible: false, context: context, builder: (context) => AlertDialog( - title: I18nText('notice'), - content: I18nText( - 'patchesSelectorView.setRequiredOption', - translationParams: { - 'patches': patches.map((patch) => 'ā€¢ $patch').join('\n'), - }, + title: Text(t.notice), + content: Text( + t.patchesSelectorView.setRequiredOption( + patches: patches.map((patch) => 'ā€¢ $patch').join('\n'), + ), ), actions: [ FilledButton( onPressed: () => { Navigator.of(context).pop(), }, - child: I18nText('okButton'), + child: Text(t.okButton), ), ], ), @@ -128,21 +127,18 @@ class PatchesSelectorViewModel extends BaseViewModel { return showDialog( context: context, builder: (context) => AlertDialog( - title: I18nText('warning'), - content: I18nText( - 'patchItem.patchesChangeWarningDialogText', - child: const Text( - '', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - ), + title: Text(t.warning), + content: Text( + t.patchItem.patchesChangeWarningDialogText, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, ), ), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), - child: I18nText('okButton'), + child: Text(t.okButton), ), FilledButton( onPressed: () { @@ -150,7 +146,7 @@ class PatchesSelectorViewModel extends BaseViewModel { ..pop() ..pop(); }, - child: I18nText('patchItem.patchesChangeWarningDialogButton'), + child: Text(t.patchItem.patchesChangeWarningDialogButton), ), ], ), @@ -257,13 +253,10 @@ class PatchesSelectorViewModel extends BaseViewModel { bottom: 10.0, left: 5.0, ), - child: I18nText( + child: Text( category, - child: Text( - '', - style: TextStyle( - color: Theme.of(context).colorScheme.primary, - ), + style: TextStyle( + color: Theme.of(context).colorScheme.primary, ), ), ), @@ -321,7 +314,7 @@ class PatchesSelectorViewModel extends BaseViewModel { this.selectedPatches.removeWhere((patch) => !isPatchSupported(patch)); } } else { - locator().showBottom('patchesSelectorView.noSavedPatches'); + locator().showBottom(t.patchesSelectorView.noSavedPatches); } notifyListeners(); } else { diff --git a/lib/ui/views/settings/settingsFragment/settings_manage_api_url.dart b/lib/ui/views/settings/settingsFragment/settings_manage_api_url.dart index d0c44c42..7de77b87 100644 --- a/lib/ui/views/settings/settingsFragment/settings_manage_api_url.dart +++ b/lib/ui/views/settings/settingsFragment/settings_manage_api_url.dart @@ -1,8 +1,8 @@ // ignore_for_file: use_build_context_synchronously import 'package:flutter/material.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:revanced_manager/app/app.locator.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/services/manager_api.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_tile_dialog.dart'; import 'package:stacked/stacked.dart'; @@ -20,7 +20,7 @@ class SManageApiUrl extends BaseViewModel { builder: (context) => AlertDialog( title: Row( children: [ - I18nText('settingsView.apiURLLabel'), + Text(t.settingsView.apiURLLabel), const Spacer(), IconButton( icon: const Icon(Icons.manage_history_outlined), @@ -42,10 +42,7 @@ class SManageApiUrl extends BaseViewModel { color: Theme.of(context).colorScheme.onSurfaceVariant, ), border: const OutlineInputBorder(), - labelText: FlutterI18n.translate( - context, - 'settingsView.selectApiURL', - ), + labelText: t.settingsView.selectApiURL, hintText: apiUrl, ), ), @@ -58,7 +55,7 @@ class SManageApiUrl extends BaseViewModel { _apiUrlController.clear(); Navigator.of(context).pop(); }, - child: I18nText('cancelButton'), + child: Text(t.cancelButton), ), FilledButton( onPressed: () { @@ -69,7 +66,7 @@ class SManageApiUrl extends BaseViewModel { _managerAPI.setApiUrl(apiUrl); Navigator.of(context).pop(); }, - child: I18nText('okButton'), + child: Text(t.okButton), ), ], ), @@ -80,12 +77,12 @@ class SManageApiUrl extends BaseViewModel { return showDialog( context: context, builder: (context) => AlertDialog( - title: I18nText('settingsView.sourcesResetDialogTitle'), - content: I18nText('settingsView.apiURLResetDialogText'), + title: Text(t.settingsView.sourcesResetDialogTitle), + content: Text(t.settingsView.apiURLResetDialogText), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), - child: I18nText('noButton'), + child: Text(t.noButton), ), FilledButton( onPressed: () { @@ -94,7 +91,7 @@ class SManageApiUrl extends BaseViewModel { ..pop() ..pop(); }, - child: I18nText('yesButton'), + child: Text(t.yesButton), ), ], ), @@ -111,8 +108,8 @@ class SManageApiUrlUI extends StatelessWidget { Widget build(BuildContext context) { return SettingsTileDialog( padding: const EdgeInsets.symmetric(horizontal: 20.0), - title: 'settingsView.apiURLLabel', - subtitle: 'settingsView.apiURLHint', + title: t.settingsView.apiURLLabel, + subtitle: t.settingsView.apiURLHint, onTap: () => sManageApiUrl.showApiUrlDialog(context), ); } diff --git a/lib/ui/views/settings/settingsFragment/settings_manage_keystore_password.dart b/lib/ui/views/settings/settingsFragment/settings_manage_keystore_password.dart index 874130b4..015f2aee 100644 --- a/lib/ui/views/settings/settingsFragment/settings_manage_keystore_password.dart +++ b/lib/ui/views/settings/settingsFragment/settings_manage_keystore_password.dart @@ -1,8 +1,8 @@ // ignore_for_file: use_build_context_synchronously import 'package:flutter/material.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:revanced_manager/app/app.locator.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/services/manager_api.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_tile_dialog.dart'; import 'package:stacked/stacked.dart'; @@ -21,7 +21,7 @@ class SManageKeystorePassword extends BaseViewModel { builder: (context) => AlertDialog( title: Row( children: [ - I18nText('settingsView.selectKeystorePassword'), + Text(t.settingsView.selectKeystorePassword), const Spacer(), IconButton( icon: const Icon(Icons.manage_history_outlined), @@ -41,10 +41,7 @@ class SManageKeystorePassword extends BaseViewModel { onChanged: (value) => notifyListeners(), decoration: InputDecoration( border: const OutlineInputBorder(), - labelText: FlutterI18n.translate( - context, - 'settingsView.selectKeystorePassword', - ), + labelText: t.settingsView.selectKeystorePassword, ), ), ], @@ -56,7 +53,7 @@ class SManageKeystorePassword extends BaseViewModel { _keystorePasswordController.clear(); Navigator.of(context).pop(); }, - child: I18nText('cancelButton'), + child: Text(t.cancelButton), ), FilledButton( onPressed: () { @@ -64,7 +61,7 @@ class SManageKeystorePassword extends BaseViewModel { _managerAPI.setKeystorePassword(passwd); Navigator.of(context).pop(); }, - child: I18nText('okButton'), + child: Text(t.okButton), ), ], ), @@ -81,8 +78,8 @@ class SManageKeystorePasswordUI extends StatelessWidget { Widget build(BuildContext context) { return SettingsTileDialog( padding: const EdgeInsets.symmetric(horizontal: 20.0), - title: 'settingsView.selectKeystorePassword', - subtitle: 'settingsView.selectKeystorePasswordHint', + title: t.settingsView.selectKeystorePassword, + subtitle: t.settingsView.selectKeystorePasswordHint, onTap: () => sManageKeystorePassword.showKeystoreDialog(context), ); } diff --git a/lib/ui/views/settings/settingsFragment/settings_manage_sources.dart b/lib/ui/views/settings/settingsFragment/settings_manage_sources.dart index 363dab8a..1e7daabc 100644 --- a/lib/ui/views/settings/settingsFragment/settings_manage_sources.dart +++ b/lib/ui/views/settings/settingsFragment/settings_manage_sources.dart @@ -1,8 +1,8 @@ // ignore_for_file: use_build_context_synchronously import 'package:flutter/material.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:revanced_manager/app/app.locator.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/services/manager_api.dart'; import 'package:revanced_manager/services/toast.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_tile_dialog.dart'; @@ -32,7 +32,7 @@ class SManageSources extends BaseViewModel { builder: (context) => AlertDialog( title: Row( children: [ - I18nText('settingsView.sourcesLabel'), + Text(t.settingsView.sourcesLabel), const Spacer(), IconButton( icon: const Icon(Icons.manage_history_outlined), @@ -58,10 +58,7 @@ class SManageSources extends BaseViewModel { color: Theme.of(context).colorScheme.onSurfaceVariant, ), border: const OutlineInputBorder(), - labelText: FlutterI18n.translate( - context, - 'settingsView.hostRepositoryLabel', - ), + labelText: t.settingsView.hostRepositoryLabel, hintText: hostRepository, ), ), @@ -77,10 +74,7 @@ class SManageSources extends BaseViewModel { color: Theme.of(context).colorScheme.onSurfaceVariant, ), border: const OutlineInputBorder(), - labelText: FlutterI18n.translate( - context, - 'settingsView.orgPatchesLabel', - ), + labelText: t.settingsView.orgPatchesLabel, hintText: patchesRepo.split('/')[0], ), ), @@ -96,10 +90,7 @@ class SManageSources extends BaseViewModel { color: Colors.transparent, ), border: const OutlineInputBorder(), - labelText: FlutterI18n.translate( - context, - 'settingsView.sourcesPatchesLabel', - ), + labelText: t.settingsView.sourcesPatchesLabel, hintText: patchesRepo.split('/')[1], ), ), @@ -115,10 +106,7 @@ class SManageSources extends BaseViewModel { color: Theme.of(context).colorScheme.onSurfaceVariant, ), border: const OutlineInputBorder(), - labelText: FlutterI18n.translate( - context, - 'settingsView.orgIntegrationsLabel', - ), + labelText: t.settingsView.orgIntegrationsLabel, hintText: integrationsRepo.split('/')[0], ), ), @@ -134,15 +122,12 @@ class SManageSources extends BaseViewModel { color: Colors.transparent, ), border: const OutlineInputBorder(), - labelText: FlutterI18n.translate( - context, - 'settingsView.sourcesIntegrationsLabel', - ), + labelText: t.settingsView.sourcesIntegrationsLabel, hintText: integrationsRepo.split('/')[1], ), ), const SizedBox(height: 20), - I18nText('settingsView.sourcesUpdateNote'), + Text(t.settingsView.sourcesUpdateNote), ], ), ), @@ -155,7 +140,7 @@ class SManageSources extends BaseViewModel { _intSourceController.clear(); Navigator.of(context).pop(); }, - child: I18nText('cancelButton'), + child: Text(t.cancelButton), ), FilledButton( onPressed: () { @@ -168,10 +153,10 @@ class SManageSources extends BaseViewModel { ); _managerAPI.setCurrentPatchesVersion('0.0.0'); _managerAPI.setCurrentIntegrationsVersion('0.0.0'); - _toast.showBottom('settingsView.restartAppForChanges'); + _toast.showBottom(t.settingsView.restartAppForChanges); Navigator.of(context).pop(); }, - child: I18nText('okButton'), + child: Text(t.okButton), ), ], ), @@ -182,12 +167,12 @@ class SManageSources extends BaseViewModel { return showDialog( context: context, builder: (context) => AlertDialog( - title: I18nText('settingsView.sourcesResetDialogTitle'), - content: I18nText('settingsView.sourcesResetDialogText'), + title: Text(t.settingsView.sourcesResetDialogTitle), + content: Text(t.settingsView.sourcesResetDialogText), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), - child: I18nText('noButton'), + child: Text(t.noButton), ), FilledButton( onPressed: () { @@ -196,12 +181,12 @@ class SManageSources extends BaseViewModel { _managerAPI.setIntegrationsRepo(''); _managerAPI.setCurrentPatchesVersion('0.0.0'); _managerAPI.setCurrentIntegrationsVersion('0.0.0'); - _toast.showBottom('settingsView.restartAppForChanges'); + _toast.showBottom(t.settingsView.restartAppForChanges); Navigator.of(context) ..pop() ..pop(); }, - child: I18nText('yesButton'), + child: Text(t.yesButton), ), ], ), @@ -218,8 +203,8 @@ class SManageSourcesUI extends StatelessWidget { Widget build(BuildContext context) { return SettingsTileDialog( padding: const EdgeInsets.symmetric(horizontal: 20.0), - title: 'settingsView.sourcesLabel', - subtitle: 'settingsView.sourcesLabelHint', + title: t.settingsView.sourcesLabel, + subtitle: t.settingsView.sourcesLabelHint, onTap: () => sManageSources.showSourcesDialog(context), ); } diff --git a/lib/ui/views/settings/settingsFragment/settings_update_language.dart b/lib/ui/views/settings/settingsFragment/settings_update_language.dart index 1e7b4a72..d40f9933 100644 --- a/lib/ui/views/settings/settingsFragment/settings_update_language.dart +++ b/lib/ui/views/settings/settingsFragment/settings_update_language.dart @@ -1,76 +1,101 @@ // ignore_for_file: use_build_context_synchronously import 'package:flutter/material.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; +import 'package:language_code/language_code.dart'; import 'package:revanced_manager/app/app.locator.dart'; -import 'package:revanced_manager/main.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; +import 'package:revanced_manager/services/manager_api.dart'; import 'package:revanced_manager/services/toast.dart'; -import 'package:revanced_manager/ui/views/navigation/navigation_viewmodel.dart'; import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_tile_dialog.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:stacked/stacked.dart'; -import 'package:timeago/timeago.dart' as timeago; final _settingViewModel = SettingsViewModel(); class SUpdateLanguage extends BaseViewModel { final Toast _toast = locator(); late SharedPreferences _prefs; - String selectedLanguage = 'English'; - String selectedLanguageLocale = prefs.getString('language') ?? 'en_US'; - List languages = []; + final ManagerAPI _managerAPI = locator(); Future initialize() async { _prefs = await SharedPreferences.getInstance(); - selectedLanguageLocale = - _prefs.getString('language') ?? selectedLanguageLocale; + _prefs.getString('language'); notifyListeners(); } - Future updateLanguage(BuildContext context, String? value) async { - if (value != null) { - selectedLanguageLocale = value; - _prefs = await SharedPreferences.getInstance(); - await _prefs.setString('language', value); - await FlutterI18n.refresh(context, Locale(value)); - timeago.setLocaleMessages(value, timeago.EnMessages()); - locator().notifyListeners(); - notifyListeners(); - } - } - - Future initLang() async { - languages.sort((a, b) => a['name'].compareTo(b['name'])); - notifyListeners(); + Future updateLocale(String locale) async { + LocaleSettings.setLocaleRaw(locale); + _managerAPI.setLocale(locale); + Future.delayed( + const Duration(milliseconds: 120), + () => _toast.showBottom(t.settingsView.languageUpdated), + ); } Future showLanguagesDialog(BuildContext parentContext) { - initLang(); + final ValueNotifier selectedLanguageCode = + ValueNotifier(LocaleSettings.currentLocale.languageCode); + // initLang(); + + // Return a dialog with list for each language supported by the application. + // the dialog will display the english and native name of each languages, + // the current language will be highlighted by selected radio button. return showDialog( context: parentContext, - builder: (context) => SimpleDialog( - title: I18nText('settingsView.languageLabel'), - children: [ - SizedBox( - height: 500, - child: ListView.builder( - itemCount: languages.length, - itemBuilder: (context, index) { - return RadioListTile( - title: Text(languages[index]['name']), - subtitle: Text(languages[index]['locale']), - value: languages[index]['locale'], - groupValue: selectedLanguageLocale, - onChanged: (value) { - selectedLanguage = languages[index]['name']; - _toast.showBottom('settingsView.restartAppForChanges'); - updateLanguage(context, value); - Navigator.pop(context); + builder: (context) => AlertDialog( + title: Text(t.settingsView.languageLabel), + icon: const Icon(Icons.language), + backgroundColor: Theme.of(context).colorScheme.secondaryContainer, + contentPadding: EdgeInsets.zero, + content: ValueListenableBuilder( + valueListenable: selectedLanguageCode, + builder: (context, value, child) { + return SingleChildScrollView( + child: ListBody( + children: AppLocale.values.map( + (locale) { + LanguageCodes? languageCode; + Text? languageNativeName; + + try { + languageCode = + LanguageCodes.fromCode(locale.languageCode); + } catch (e) {} + if (languageCode != null) { + languageNativeName = Text(languageCode.nativeName); + } + + return RadioListTile( + title: Text( + languageCode?.englishName ?? locale.languageCode, + ), + subtitle: languageNativeName, + value: locale.languageCode == selectedLanguageCode.value, + groupValue: true, + onChanged: (value) { + selectedLanguageCode.value = locale.languageCode; + }, + ); }, - ); - }, - ), + ).toList(), + ), + ); + }, + ), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text(t.cancelButton), + ), + TextButton( + onPressed: () { + updateLocale(selectedLanguageCode.value); + Navigator.of(context).pop(); + }, + child: Text(t.okButton), ), ], ), @@ -85,8 +110,10 @@ class SUpdateLanguageUI extends StatelessWidget { Widget build(BuildContext context) { return SettingsTileDialog( padding: const EdgeInsets.symmetric(horizontal: 20.0), - title: 'settingsView.languageLabel', - subtitle: _settingViewModel.sUpdateLanguage.selectedLanguage, + title: t.settingsView.languageLabel, + subtitle: + LanguageCodes.fromCode(LocaleSettings.currentLocale.languageCode) + .nativeName, onTap: () => _settingViewModel.sUpdateLanguage.showLanguagesDialog(context), ); diff --git a/lib/ui/views/settings/settingsFragment/settings_update_theme.dart b/lib/ui/views/settings/settingsFragment/settings_update_theme.dart index cdd6c540..37d768f2 100644 --- a/lib/ui/views/settings/settingsFragment/settings_update_theme.dart +++ b/lib/ui/views/settings/settingsFragment/settings_update_theme.dart @@ -3,8 +3,8 @@ import 'package:dynamic_themes/dynamic_themes.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:flutter_i18n/widgets/I18nText.dart'; import 'package:revanced_manager/app/app.locator.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/services/manager_api.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_section.dart'; import 'package:revanced_manager/ui/widgets/shared/haptics/haptic_radio_list_tile.dart'; @@ -23,18 +23,15 @@ class _SUpdateThemeUIState extends State { @override Widget build(BuildContext context) { return SettingsSection( - title: 'settingsView.appearanceSectionTitle', + title: t.settingsView.appearanceSectionTitle, children: [ ListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 20.0), - title: I18nText( - 'settingsView.themeModeLabel', - child: const Text( - '', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - ), + title: Text( + t.settingsView.themeModeLabel, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, ), ), trailing: FilledButton( @@ -46,17 +43,14 @@ class _SUpdateThemeUIState extends State { if (managerAPI.isDynamicThemeAvailable) HapticSwitchListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 20.0), - title: I18nText( - 'settingsView.dynamicThemeLabel', - child: const Text( - '', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - ), + title: Text( + t.settingsView.dynamicThemeLabel, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, ), ), - subtitle: I18nText('settingsView.dynamicThemeHint'), + subtitle: Text(t.settingsView.dynamicThemeHint), value: getDynamicThemeStatus(), onChanged: (value) => { setUseDynamicTheme( @@ -101,16 +95,16 @@ class _SUpdateThemeUIState extends State { setState(() {}); } - I18nText getThemeModeName() { + Text getThemeModeName() { switch (getThemeMode()) { case 0: - return I18nText('settingsView.systemThemeLabel'); + return Text(t.settingsView.systemThemeLabel); case 1: - return I18nText('settingsView.lightThemeLabel'); + return Text(t.settingsView.lightThemeLabel); case 2: - return I18nText('settingsView.darkThemeLabel'); + return Text(t.settingsView.darkThemeLabel); default: - return I18nText('settingsView.systemThemeLabel'); + return Text(t.settingsView.systemThemeLabel); } } @@ -120,7 +114,7 @@ class _SUpdateThemeUIState extends State { return showDialog( context: context, builder: (context) => AlertDialog( - title: I18nText('settingsView.themeModeLabel'), + title: Text(t.settingsView.themeModeLabel), icon: const Icon(Icons.palette), contentPadding: const EdgeInsets.symmetric(vertical: 16), content: SingleChildScrollView( @@ -132,7 +126,7 @@ class _SUpdateThemeUIState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ HapticRadioListTile( - title: I18nText('settingsView.systemThemeLabel'), + title: Text(t.settingsView.systemThemeLabel), contentPadding: const EdgeInsets.symmetric(horizontal: 16), value: 0, groupValue: value, @@ -141,7 +135,7 @@ class _SUpdateThemeUIState extends State { }, ), HapticRadioListTile( - title: I18nText('settingsView.lightThemeLabel'), + title: Text(t.settingsView.lightThemeLabel), contentPadding: const EdgeInsets.symmetric(horizontal: 16), value: 1, groupValue: value, @@ -150,7 +144,7 @@ class _SUpdateThemeUIState extends State { }, ), HapticRadioListTile( - title: I18nText('settingsView.darkThemeLabel'), + title: Text(t.settingsView.darkThemeLabel), contentPadding: const EdgeInsets.symmetric(horizontal: 16), value: 2, groupValue: value, @@ -168,14 +162,14 @@ class _SUpdateThemeUIState extends State { onPressed: () { Navigator.of(context).pop(); }, - child: I18nText('cancelButton'), + child: Text(t.cancelButton), ), FilledButton( onPressed: () { setThemeMode(context, newTheme.value); Navigator.of(context).pop(); }, - child: I18nText('okButton'), + child: Text(t.okButton), ), ], ), diff --git a/lib/ui/views/settings/settings_view.dart b/lib/ui/views/settings/settings_view.dart index 0d5b8e30..9ae5df62 100644 --- a/lib/ui/views/settings/settings_view.dart +++ b/lib/ui/views/settings/settings_view.dart @@ -1,8 +1,9 @@ // ignore_for_file: prefer_const_constructors import 'package:flutter/material.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; +import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_update_language.dart'; import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_update_theme.dart'; import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_advanced_section.dart'; @@ -27,13 +28,10 @@ class SettingsView extends StatelessWidget { slivers: [ CustomSliverAppBar( isMainView: true, - title: I18nText( - 'settingsView.widgetTitle', - child: Text( - '', - style: GoogleFonts.inter( - color: Theme.of(context).textTheme.titleLarge!.color, - ), + title: Text( + t.settingsView.widgetTitle, + style: GoogleFonts.inter( + color: Theme.of(context).textTheme.titleLarge!.color, ), ), ), @@ -47,7 +45,7 @@ class SettingsView extends StatelessWidget { children: const [ SUpdateThemeUI(), // _settingsDivider, - // SUpdateLanguageUI(), + SUpdateLanguageUI(), _settingsDivider, SAdvancedSection(), _settingsDivider, diff --git a/lib/ui/views/settings/settings_viewmodel.dart b/lib/ui/views/settings/settings_viewmodel.dart index 4bf3605b..09c0ce70 100644 --- a/lib/ui/views/settings/settings_viewmodel.dart +++ b/lib/ui/views/settings/settings_viewmodel.dart @@ -1,12 +1,13 @@ import 'dart:io'; + import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_file_dialog/flutter_file_dialog.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:logcat/logcat.dart'; import 'package:path_provider/path_provider.dart'; import 'package:revanced_manager/app/app.locator.dart'; import 'package:revanced_manager/app/app.router.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/services/manager_api.dart'; import 'package:revanced_manager/services/toast.dart'; import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart'; @@ -60,15 +61,12 @@ class SettingsViewModel extends BaseViewModel { return showDialog( context: context, builder: (context) => AlertDialog( - title: I18nText('warning'), - content: I18nText( - 'settingsView.enablePatchesSelectionWarningText', - child: const Text( - '', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - ), + title: Text(t.warning), + content: Text( + t.settingsView.enablePatchesSelectionWarningText, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, ), ), actions: [ @@ -78,13 +76,13 @@ class SettingsViewModel extends BaseViewModel { _managerAPI.setPatchesChangeEnabled(true); Navigator.of(context).pop(); }, - child: I18nText('yesButton'), + child: Text(t.yesButton), ), FilledButton( onPressed: () { Navigator.of(context).pop(); }, - child: I18nText('noButton'), + child: Text(t.noButton), ), ], ), @@ -93,15 +91,12 @@ class SettingsViewModel extends BaseViewModel { return showDialog( context: context, builder: (context) => AlertDialog( - title: I18nText('warning'), - content: I18nText( - 'settingsView.disablePatchesSelectionWarningText', - child: const Text( - '', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - ), + title: Text(t.warning), + content: Text( + t.settingsView.disablePatchesSelectionWarningText, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, ), ), actions: [ @@ -109,7 +104,7 @@ class SettingsViewModel extends BaseViewModel { onPressed: () { Navigator.of(context).pop(); }, - child: I18nText('noButton'), + child: Text(t.noButton), ), FilledButton( onPressed: () { @@ -118,7 +113,7 @@ class SettingsViewModel extends BaseViewModel { _managerAPI.setPatchesChangeEnabled(false); Navigator.of(context).pop(); }, - child: I18nText('yesButton'), + child: Text(t.yesButton), ), ], ), @@ -156,15 +151,12 @@ class SettingsViewModel extends BaseViewModel { return showDialog( context: context, builder: (context) => AlertDialog( - title: I18nText('warning'), - content: I18nText( - 'settingsView.requireSuggestedAppVersionDialogText', - child: const Text( - '', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - ), + title: Text(t.warning), + content: Text( + t.settingsView.requireSuggestedAppVersionDialogText, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, ), ), actions: [ @@ -173,13 +165,13 @@ class SettingsViewModel extends BaseViewModel { _managerAPI.enableRequireSuggestedAppVersionStatus(false); Navigator.of(context).pop(); }, - child: I18nText('yesButton'), + child: Text(t.yesButton), ), FilledButton( onPressed: () { Navigator.of(context).pop(); }, - child: I18nText('noButton'), + child: Text(t.noButton), ), ], ), @@ -197,13 +189,13 @@ class SettingsViewModel extends BaseViewModel { void deleteKeystore() { _managerAPI.deleteKeystore(); - _toast.showBottom('settingsView.regeneratedKeystore'); + _toast.showBottom(t.settingsView.regeneratedKeystore); notifyListeners(); } void deleteTempDir() { _managerAPI.deleteTempFolder(); - _toast.showBottom('settingsView.deletedTempDir'); + _toast.showBottom(t.settingsView.deletedTempDir); notifyListeners(); } @@ -219,9 +211,9 @@ class SettingsViewModel extends BaseViewModel { fileName: 'selected_patches_$dateTime.json', ), ); - _toast.showBottom('settingsView.exportedPatches'); + _toast.showBottom(t.settingsView.exportedPatches); } else { - _toast.showBottom('settingsView.noExportFileFound'); + _toast.showBottom(t.settingsView.noExportFileFound); } } on Exception catch (e) { if (kDebugMode) { @@ -245,13 +237,13 @@ class SettingsViewModel extends BaseViewModel { if (_patcherViewModel.selectedApp != null) { _patcherViewModel.loadLastSelectedPatches(); } - _toast.showBottom('settingsView.importedPatches'); + _toast.showBottom(t.settingsView.importedPatches); } } on Exception catch (e) { if (kDebugMode) { print(e); } - _toast.showBottom('settingsView.jsonSelectorErrorMessage'); + _toast.showBottom(t.settingsView.jsonSelectorErrorMessage); } } else { _managerAPI.showPatchesChangeWarningDialog(context); @@ -270,9 +262,9 @@ class SettingsViewModel extends BaseViewModel { fileName: 'keystore_$dateTime.keystore', ), ); - _toast.showBottom('settingsView.exportedKeystore'); + _toast.showBottom(t.settingsView.exportedKeystore); } else { - _toast.showBottom('settingsView.noKeystoreExportFileFound'); + _toast.showBottom(t.settingsView.noKeystoreExportFileFound); } } on Exception catch (e) { if (kDebugMode) { @@ -288,24 +280,24 @@ class SettingsViewModel extends BaseViewModel { final File inFile = File(result); inFile.copySync(_managerAPI.keystoreFile); - _toast.showBottom('settingsView.importedKeystore'); + _toast.showBottom(t.settingsView.importedKeystore); } } on Exception catch (e) { if (kDebugMode) { print(e); } - _toast.showBottom('settingsView.keystoreSelectorErrorMessage'); + _toast.showBottom(t.settingsView.keystoreSelectorErrorMessage); } } void resetAllOptions() { _managerAPI.resetAllOptions(); - _toast.showBottom('settingsView.resetStoredOptions'); + _toast.showBottom(t.settingsView.resetStoredOptions); } void resetSelectedPatches() { _managerAPI.resetLastSelectedPatches(); - _toast.showBottom('settingsView.resetStoredPatches'); + _toast.showBottom(t.settingsView.resetStoredPatches); } Future deleteLogs() async { @@ -314,7 +306,7 @@ class SettingsViewModel extends BaseViewModel { if (logsDir.existsSync()) { logsDir.deleteSync(recursive: true); } - _toast.showBottom('settingsView.deletedLogs'); + _toast.showBottom(t.settingsView.deletedLogs); } Future exportLogcatLogs() async { diff --git a/lib/ui/widgets/appInfoView/app_info_view.dart b/lib/ui/widgets/appInfoView/app_info_view.dart index da8cf7ba..4de2ed46 100644 --- a/lib/ui/widgets/appInfoView/app_info_view.dart +++ b/lib/ui/widgets/appInfoView/app_info_view.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/models/patched_application.dart'; import 'package:revanced_manager/ui/widgets/appInfoView/app_info_viewmodel.dart'; import 'package:revanced_manager/ui/widgets/shared/custom_card.dart'; @@ -22,13 +22,10 @@ class AppInfoView extends StatelessWidget { body: CustomScrollView( slivers: [ CustomSliverAppBar( - title: I18nText( - 'appInfoView.widgetTitle', - child: Text( - '', - style: GoogleFonts.inter( - color: Theme.of(context).textTheme.titleLarge!.color, - ), + title: Text( + t.appInfoView.widgetTitle, + style: GoogleFonts.inter( + color: Theme.of(context).textTheme.titleLarge!.color, ), ), ), @@ -86,16 +83,13 @@ class AppInfoView extends StatelessWidget { .primary, ), const SizedBox(height: 10), - I18nText( - 'appInfoView.openButton', - child: Text( - '', - style: TextStyle( - color: Theme.of(context) - .colorScheme - .primary, - fontWeight: FontWeight.bold, - ), + Text( + t.appInfoView.openButton, + style: TextStyle( + color: Theme.of(context) + .colorScheme + .primary, + fontWeight: FontWeight.bold, ), ), ], @@ -130,16 +124,13 @@ class AppInfoView extends StatelessWidget { .primary, ), const SizedBox(height: 10), - I18nText( - 'appInfoView.uninstallButton', - child: Text( - '', - style: TextStyle( - color: Theme.of(context) - .colorScheme - .primary, - fontWeight: FontWeight.bold, - ), + Text( + t.appInfoView.uninstallButton, + style: TextStyle( + color: Theme.of(context) + .colorScheme + .primary, + fontWeight: FontWeight.bold, ), ), ], @@ -183,16 +174,13 @@ class AppInfoView extends StatelessWidget { .primary, ), const SizedBox(height: 10), - I18nText( - 'appInfoView.unmountButton', - child: Text( - '', - style: TextStyle( - color: Theme.of(context) - .colorScheme - .primary, - fontWeight: FontWeight.bold, - ), + Text( + t.appInfoView.unmountButton, + style: TextStyle( + color: Theme.of(context) + .colorScheme + .primary, + fontWeight: FontWeight.bold, ), ), ], @@ -209,14 +197,11 @@ class AppInfoView extends StatelessWidget { ListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 20.0), - title: I18nText( - 'appInfoView.packageNameLabel', - child: const Text( - '', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - ), + title: Text( + t.appInfoView.packageNameLabel, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, ), ), subtitle: Text(app.packageName), @@ -225,61 +210,50 @@ class AppInfoView extends StatelessWidget { ListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 20.0), - title: I18nText( - 'appInfoView.installTypeLabel', - child: const Text( - '', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - ), + title: Text( + t.appInfoView.installTypeLabel, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, ), ), subtitle: app.isRooted - ? I18nText('appInfoView.mountTypeLabel') - : I18nText('appInfoView.regularTypeLabel'), + ? Text(t.appInfoView.mountTypeLabel) + : Text(t.appInfoView.regularTypeLabel), ), const SizedBox(height: 4), ListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 20.0), - title: I18nText( - 'appInfoView.patchedDateLabel', - child: const Text( - '', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - ), + title: Text( + t.appInfoView.patchedDateLabel, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, ), ), - subtitle: I18nText( - 'appInfoView.patchedDateHint', - translationParams: { - 'date': model.getPrettyDate(context, app.patchDate), - 'time': model.getPrettyTime(context, app.patchDate), - }, + subtitle: Text( + t.appInfoView.patchedDateHint( + date: model.getPrettyDate(context, app.patchDate), + time: model.getPrettyTime(context, app.patchDate), + ), ), ), const SizedBox(height: 4), ListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 20.0), - title: I18nText( - 'appInfoView.appliedPatchesLabel', - child: const Text( - '', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - ), + title: Text( + t.appInfoView.appliedPatchesLabel, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, ), ), - subtitle: I18nText( - 'appInfoView.appliedPatchesHint', - translationParams: { - 'quantity': app.appliedPatches.length.toString(), - }, + subtitle: Text( + t.appInfoView.appliedPatchesHint( + quantity: app.appliedPatches.length.toString(), + ), ), onTap: () => model.showAppliedPatchesDialog(context, app), ), diff --git a/lib/ui/widgets/appInfoView/app_info_viewmodel.dart b/lib/ui/widgets/appInfoView/app_info_viewmodel.dart index f3b70d31..1c9ec660 100644 --- a/lib/ui/widgets/appInfoView/app_info_viewmodel.dart +++ b/lib/ui/widgets/appInfoView/app_info_viewmodel.dart @@ -1,9 +1,9 @@ // ignore_for_file: use_build_context_synchronously import 'package:device_apps/device_apps.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:intl/intl.dart'; import 'package:revanced_manager/app/app.locator.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/models/patched_application.dart'; import 'package:revanced_manager/services/manager_api.dart'; import 'package:revanced_manager/services/patcher_api.dart'; @@ -32,7 +32,7 @@ class AppInfoViewModel extends BaseViewModel { isUninstalled = await DeviceApps.uninstallApp(app.packageName); } - if (isUninstalled && app.isRooted && await _rootAPI.hasRootPermissions()) { + if (isUninstalled && app.isRooted && await _rootAPI.hasRootPermissions()) { await _rootAPI.uninstall(app.packageName); } @@ -51,7 +51,7 @@ class AppInfoViewModel extends BaseViewModel { } void updateNotImplemented(BuildContext context) { - _toast.showBottom('appInfoView.updateNotImplemented'); + _toast.showBottom(t.appInfoView.updateNotImplemented); } Future showUninstallDialog( @@ -64,12 +64,12 @@ class AppInfoViewModel extends BaseViewModel { return showDialog( context: context, builder: (context) => AlertDialog( - title: I18nText('appInfoView.rootDialogTitle'), - content: I18nText('appInfoView.rootDialogText'), + title: Text(t.appInfoView.rootDialogTitle), + content: Text(t.appInfoView.rootDialogText), actions: [ FilledButton( onPressed: () => Navigator.of(context).pop(), - child: I18nText('okButton'), + child: Text(t.okButton), ), ], ), @@ -79,16 +79,12 @@ class AppInfoViewModel extends BaseViewModel { return showDialog( context: context, builder: (context) => AlertDialog( - title: I18nText( - 'appInfoView.unmountButton', - ), - content: I18nText( - 'appInfoView.unmountDialogText', - ), + title: Text(t.appInfoView.unmountButton), + content: Text(t.appInfoView.unmountDialogText), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), - child: I18nText('noButton'), + child: Text(t.noButton), ), FilledButton( onPressed: () { @@ -96,7 +92,7 @@ class AppInfoViewModel extends BaseViewModel { Navigator.of(context).pop(); Navigator.of(context).pop(); }, - child: I18nText('yesButton'), + child: Text(t.yesButton), ), ], ), @@ -105,16 +101,12 @@ class AppInfoViewModel extends BaseViewModel { return showDialog( context: context, builder: (context) => AlertDialog( - title: I18nText( - 'appInfoView.uninstallButton', - ), - content: I18nText( - 'appInfoView.uninstallDialogText', - ), + title: Text(t.appInfoView.uninstallButton), + content: Text(t.appInfoView.uninstallDialogText), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), - child: I18nText('noButton'), + child: Text(t.noButton), ), FilledButton( onPressed: () { @@ -122,7 +114,7 @@ class AppInfoViewModel extends BaseViewModel { Navigator.of(context).pop(); Navigator.of(context).pop(); }, - child: I18nText('yesButton'), + child: Text(t.yesButton), ), ], ), @@ -148,14 +140,14 @@ class AppInfoViewModel extends BaseViewModel { return showDialog( context: context, builder: (context) => AlertDialog( - title: I18nText('appInfoView.appliedPatchesLabel'), + title: Text(t.appInfoView.appliedPatchesLabel), content: SingleChildScrollView( child: Text(getAppliedPatchesString(app.appliedPatches)), ), actions: [ FilledButton( onPressed: () => Navigator.of(context).pop(), - child: I18nText('okButton'), + child: Text(t.okButton), ), ], ), diff --git a/lib/ui/widgets/appSelectorView/installed_app_item.dart b/lib/ui/widgets/appSelectorView/installed_app_item.dart index ab96d4f5..554be705 100644 --- a/lib/ui/widgets/appSelectorView/installed_app_item.dart +++ b/lib/ui/widgets/appSelectorView/installed_app_item.dart @@ -1,6 +1,6 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/ui/widgets/shared/custom_card.dart'; class InstalledAppItem extends StatefulWidget { @@ -107,16 +107,12 @@ class _InstalledAppItemState extends State { child: Row( mainAxisSize: MainAxisSize.min, children: [ - I18nText( - 'suggested', - translationParams: { - 'version': widget.suggestedVersion.isEmpty - ? FlutterI18n.translate( - context, - 'appSelectorCard.anyVersion', - ) - : widget.suggestedVersion, - }, + Text( + t.suggested( + version: widget.suggestedVersion.isEmpty + ? Text(t.appSelectorCard.anyVersion) + : 'v${widget.suggestedVersion}', + ), ), const SizedBox(width: 4), Icon( diff --git a/lib/ui/widgets/appSelectorView/not_installed_app_item.dart b/lib/ui/widgets/appSelectorView/not_installed_app_item.dart index 6e500b3d..4e1ac070 100644 --- a/lib/ui/widgets/appSelectorView/not_installed_app_item.dart +++ b/lib/ui/widgets/appSelectorView/not_installed_app_item.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/ui/widgets/shared/custom_card.dart'; class NotInstalledAppItem extends StatefulWidget { @@ -91,16 +91,12 @@ class _NotInstalledAppItem extends State { child: Row( mainAxisSize: MainAxisSize.min, children: [ - I18nText( - 'suggested', - translationParams: { - 'version': widget.suggestedVersion.isEmpty - ? FlutterI18n.translate( - context, - 'appSelectorCard.anyVersion', - ) - : widget.suggestedVersion, - }, + Text( + t.suggested( + version: widget.suggestedVersion.isEmpty + ? t.appSelectorCard.anyVersion + : 'v${widget.suggestedVersion}', + ), ), const SizedBox(width: 4), Icon( diff --git a/lib/ui/widgets/contributorsView/contributors_card.dart b/lib/ui/widgets/contributorsView/contributors_card.dart index d039e5b7..d5827ca0 100644 --- a/lib/ui/widgets/contributorsView/contributors_card.dart +++ b/lib/ui/widgets/contributorsView/contributors_card.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:flutter_cache_manager/file.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:revanced_manager/services/download_manager.dart'; import 'package:revanced_manager/ui/widgets/shared/custom_card.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -26,14 +25,11 @@ class _ContributorsCardState extends State { children: [ Padding( padding: const EdgeInsets.only(bottom: 8.0), - child: I18nText( + child: Text( widget.title, - child: const Text( - '', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - ), + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, ), ), ), diff --git a/lib/ui/widgets/homeView/installed_apps_card.dart b/lib/ui/widgets/homeView/installed_apps_card.dart index e6ac9a02..8de0fae9 100644 --- a/lib/ui/widgets/homeView/installed_apps_card.dart +++ b/lib/ui/widgets/homeView/installed_apps_card.dart @@ -1,7 +1,7 @@ import 'package:device_apps/device_apps.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:revanced_manager/app/app.locator.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/models/patched_application.dart'; import 'package:revanced_manager/services/manager_api.dart'; import 'package:revanced_manager/ui/views/home/home_viewmodel.dart'; @@ -51,19 +51,15 @@ class InstalledAppsCard extends StatelessWidget { color: Theme.of(context).colorScheme.secondary, ), const SizedBox(height: 16), - I18nText( - 'homeView.noInstallations', - child: Text( - '', - textAlign: TextAlign.center, - style: Theme.of(context) - .textTheme - .titleMedium! - .copyWith( - color: - Theme.of(context).colorScheme.secondary, - ), - ), + Text( + t.homeView.noInstallations, + textAlign: TextAlign.center, + style: Theme.of(context) + .textTheme + .titleMedium! + .copyWith( + color: Theme.of(context).colorScheme.secondary, + ), ), ], ), diff --git a/lib/ui/widgets/homeView/latest_commit_card.dart b/lib/ui/widgets/homeView/latest_commit_card.dart index e209d42c..8f5e4839 100644 --- a/lib/ui/widgets/homeView/latest_commit_card.dart +++ b/lib/ui/widgets/homeView/latest_commit_card.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:revanced_manager/app/app.locator.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/ui/views/home/home_viewmodel.dart'; import 'package:revanced_manager/ui/widgets/shared/custom_card.dart'; @@ -39,13 +39,13 @@ class _LatestCommitCardState extends State { children: [ FutureBuilder( future: model.getLatestManagerReleaseTime(), - builder: (context, snapshot) => snapshot.hasData && - snapshot.data!.isNotEmpty - ? I18nText( - 'latestCommitCard.timeagoLabel', - translationParams: {'time': snapshot.data!}, - ) - : I18nText('latestCommitCard.loadingLabel'), + builder: (context, snapshot) => + snapshot.hasData && snapshot.data!.isNotEmpty + ? Text( + t.latestCommitCard + .timeagoLabel(time: snapshot.data!), + ) + : Text(t.latestCommitCard.loadingLabel), ), ], ), @@ -62,8 +62,8 @@ class _LatestCommitCardState extends State { !snapshot.data!, ), child: (snapshot.hasData && !snapshot.data!) - ? I18nText('showChangelogButton') - : I18nText('showUpdateButton'), + ? Text(t.showChangelogButton) + : Text(t.showUpdateButton), ), ), ], @@ -89,15 +89,9 @@ class _LatestCommitCardState extends State { future: model.getLatestPatchesReleaseTime(), builder: (context, snapshot) => Text( snapshot.hasData && snapshot.data!.isNotEmpty - ? FlutterI18n.translate( - context, - 'latestCommitCard.timeagoLabel', - translationParams: {'time': snapshot.data!}, - ) - : FlutterI18n.translate( - context, - 'latestCommitCard.loadingLabel', - ), + ? t.latestCommitCard + .timeagoLabel(time: snapshot.data!) + : t.latestCommitCard.loadingLabel, ), ), ], @@ -115,8 +109,8 @@ class _LatestCommitCardState extends State { !snapshot.data!, ), child: (snapshot.hasData && !snapshot.data!) - ? I18nText('showChangelogButton') - : I18nText('showUpdateButton'), + ? Text(t.showChangelogButton) + : Text(t.showUpdateButton), ), ), ], diff --git a/lib/ui/widgets/homeView/update_confirmation_sheet.dart b/lib/ui/widgets/homeView/update_confirmation_sheet.dart index 7f1160d0..9f5a5b56 100644 --- a/lib/ui/widgets/homeView/update_confirmation_sheet.dart +++ b/lib/ui/widgets/homeView/update_confirmation_sheet.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:flutter_markdown/flutter_markdown.dart'; import 'package:revanced_manager/app/app.locator.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/ui/views/home/home_viewmodel.dart'; class UpdateConfirmationSheet extends StatelessWidget { @@ -51,16 +51,13 @@ class UpdateConfirmationSheet extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - I18nText( + Text( isPatches - ? 'homeView.updatePatchesSheetTitle' - : 'homeView.updateSheetTitle', - child: const Text( - '', - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - ), + ? t.homeView.updatePatchesSheetTitle + : t.homeView.updateSheetTitle, + style: const TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, ), ), const SizedBox(height: 4.0), @@ -94,40 +91,36 @@ class UpdateConfirmationSheet extends StatelessWidget { ? model.updatePatches(context) : model.updateManager(context); }, - child: I18nText('updateButton'), + child: Text(t.updateButton), ), ], ), ), Padding( padding: const EdgeInsets.only(top: 12.0, left: 24.0, bottom: 12.0), - child: I18nText( - 'homeView.updateChangelogTitle', - child: Text( - '', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - color: Theme.of(context) - .colorScheme - .onSecondaryContainer, + child: Text( + t.homeView.updateChangelogTitle, + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, + color: + Theme.of(context).colorScheme.onSecondaryContainer, ), ), ), - ), - Container( - margin: const EdgeInsets.symmetric(horizontal: 24.0), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.secondaryContainer, - borderRadius: BorderRadius.circular(12.0), + Container( + margin: const EdgeInsets.symmetric(horizontal: 24.0), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.secondaryContainer, + borderRadius: BorderRadius.circular(12.0), + ), + child: Markdown( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + padding: const EdgeInsets.all(20.0), + data: snapshot.data!['body'] ?? '', + ), ), - child: Markdown( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - padding: const EdgeInsets.all(20.0), - data: snapshot.data!['body'] ?? '', - ), - ), ], ); }, diff --git a/lib/ui/widgets/patcherView/app_selector_card.dart b/lib/ui/widgets/patcherView/app_selector_card.dart index a15359c0..744ef490 100644 --- a/lib/ui/widgets/patcherView/app_selector_card.dart +++ b/lib/ui/widgets/patcherView/app_selector_card.dart @@ -1,7 +1,8 @@ import 'dart:typed_data'; + import 'package:flutter/material.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:revanced_manager/app/app.locator.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart'; import 'package:revanced_manager/ui/widgets/shared/custom_card.dart'; @@ -28,21 +29,18 @@ class AppSelectorCard extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - I18nText( + Text( vm.selectedApp == null - ? 'appSelectorCard.widgetTitle' - : 'appSelectorCard.widgetTitleSelected', - child: const Text( - '', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w500, - ), + ? t.appSelectorCard.widgetTitle + : t.appSelectorCard.widgetTitleSelected, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, ), ), const SizedBox(height: 8), if (vm.selectedApp == null) - I18nText('appSelectorCard.widgetSubtitle') + Text(t.appSelectorCard.widgetSubtitle) else Row( children: [ @@ -96,11 +94,10 @@ class AppSelectorCard extends StatelessWidget { child: Row( mainAxisSize: MainAxisSize.min, children: [ - I18nText( - 'suggested', - translationParams: { - 'version': suggestedVersion, - }, + Text( + t.suggested( + version: suggestedVersion, + ), ), const SizedBox(width: 4), Icon( diff --git a/lib/ui/widgets/patcherView/patch_selector_card.dart b/lib/ui/widgets/patcherView/patch_selector_card.dart index 9dd48686..35162b7f 100644 --- a/lib/ui/widgets/patcherView/patch_selector_card.dart +++ b/lib/ui/widgets/patcherView/patch_selector_card.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:revanced_manager/app/app.locator.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/models/patch.dart'; import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart'; import 'package:revanced_manager/ui/widgets/shared/custom_card.dart'; @@ -21,16 +21,13 @@ class PatchSelectorCard extends StatelessWidget { children: [ Row( children: [ - I18nText( + Text( locator().selectedPatches.isEmpty - ? 'patchSelectorCard.widgetTitle' - : 'patchSelectorCard.widgetTitleSelected', - child: const Text( - '', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w500, - ), + ? t.patchSelectorCard.widgetTitle + : t.patchSelectorCard.widgetTitleSelected, + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w500, ), ), Text( @@ -46,10 +43,10 @@ class PatchSelectorCard extends StatelessWidget { ), const SizedBox(height: 4), if (locator().selectedApp == null) - I18nText('patchSelectorCard.widgetSubtitle') + Text(t.patchSelectorCard.widgetSubtitle) else locator().selectedPatches.isEmpty - ? I18nText('patchSelectorCard.widgetEmptySubtitle') + ? Text(t.patchSelectorCard.widgetEmptySubtitle) : Text(_getPatchesSelection()), ], ), diff --git a/lib/ui/widgets/patchesSelectorView/patch_item.dart b/lib/ui/widgets/patchesSelectorView/patch_item.dart index 17155c31..2a6a2c3b 100644 --- a/lib/ui/widgets/patchesSelectorView/patch_item.dart +++ b/lib/ui/widgets/patchesSelectorView/patch_item.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:revanced_manager/app/app.locator.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/models/patch.dart'; import 'package:revanced_manager/services/manager_api.dart'; import 'package:revanced_manager/services/toast.dart'; @@ -162,7 +162,7 @@ class _PatchItemState extends State { Padding( padding: const EdgeInsets.only(top: 8), child: TextButton.icon( - label: I18nText('warning'), + label: Text(t.warning), icon: const Icon( Icons.warning_amber_outlined, size: 20.0, @@ -215,19 +215,18 @@ class _PatchItemState extends State { return showDialog( context: context, builder: (context) => AlertDialog( - title: I18nText('warning'), - content: I18nText( - 'patchItem.unsupportedDialogText', - translationParams: { - 'packageVersion': widget.packageVersion, - 'supportedVersions': + title: Text(t.warning), + content: Text( + t.patchItem.unsupportedDialogText( + packageVersion: widget.packageVersion, + supportedVersions: 'ā€¢ ${widget.supportedPackageVersions.reversed.join('\nā€¢ ')}', - }, + ), ), actions: [ FilledButton( onPressed: () => Navigator.of(context).pop(), - child: I18nText('okButton'), + child: Text(t.okButton), ), ], ), @@ -238,14 +237,14 @@ class _PatchItemState extends State { return showDialog( context: context, builder: (context) => AlertDialog( - title: I18nText('notice'), - content: I18nText( - 'patchItem.unsupportedRequiredOption', + title: Text(t.notice), + content: Text( + t.patchItem.unsupportedRequiredOption, ), actions: [ FilledButton( onPressed: () => Navigator.of(context).pop(), - child: I18nText('okButton'), + child: Text(t.okButton), ), ], ), diff --git a/lib/ui/widgets/patchesSelectorView/patch_options_fields.dart b/lib/ui/widgets/patchesSelectorView/patch_options_fields.dart index 61247132..4dabc405 100644 --- a/lib/ui/widgets/patchesSelectorView/patch_options_fields.dart +++ b/lib/ui/widgets/patchesSelectorView/patch_options_fields.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_file_dialog/flutter_file_dialog.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/models/patch.dart'; import 'package:revanced_manager/ui/widgets/shared/custom_card.dart'; @@ -93,13 +93,10 @@ class IntAndStringPatchOption extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 8), - I18nText( - 'patchOptionsView.requiredOption', - child: Text( - '', - style: TextStyle( - color: Theme.of(context).colorScheme.error, - ), + Text( + t.patchOptionsView.requiredOption, + style: TextStyle( + color: Theme.of(context).colorScheme.error, ), ), ], @@ -240,14 +237,11 @@ class IntStringLongListPatchOption extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ const Icon(Icons.add, size: 20), - I18nText( - 'add', - child: const Text( - '', - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.w600, - ), + Text( + t.add, + style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w600, ), ), ], @@ -279,13 +273,10 @@ class UnsupportedPatchOption extends StatelessWidget { alignment: Alignment.centerLeft, child: Padding( padding: const EdgeInsets.symmetric(vertical: 8.0), - child: I18nText( - 'patchOptionsView.unsupportedOption', - child: const Text( - '', - style: TextStyle( - fontSize: 16, - ), + child: Text( + t.patchOptionsView.unsupportedOption, + style: const TextStyle( + fontSize: 16, ), ), ), @@ -452,13 +443,10 @@ class _TextFieldForPatchOptionState extends State { ..add( DropdownMenuItem( value: '', - child: I18nText( - 'patchOptionsView.customValue', - child: const Text( - '', - style: TextStyle( - fontSize: 16, - ), + child: Text( + t.patchOptionsView.customValue, + style: const TextStyle( + fontSize: 16, ), ), ), @@ -491,25 +479,22 @@ class _TextFieldForPatchOptionState extends State { isStringOption ? TextInputType.text : TextInputType.number, decoration: InputDecoration( suffixIcon: PopupMenuButton( - tooltip: FlutterI18n.translate( - context, - 'patchOptionsView.tooltip', - ), + tooltip: t.patchOptionsView.tooltip, itemBuilder: (BuildContext context) { return [ if (isArrayOption) PopupMenuItem( - value: 'remove', - child: I18nText('remove'), + value: t.remove, + child: Text(t.remove), ), if (isStringOption) ...[ PopupMenuItem( - value: 'patchOptionsView.selectFilePath', - child: I18nText('patchOptionsView.selectFilePath'), + value: t.patchOptionsView.selectFilePath, + child: Text(t.patchOptionsView.selectFilePath), ), PopupMenuItem( - value: 'patchOptionsView.selectFolder', - child: I18nText('patchOptionsView.selectFolder'), + value: t.patchOptionsView.selectFolder, + child: Text(t.patchOptionsView.selectFolder), ), ], ]; diff --git a/lib/ui/widgets/settingsView/about_widget.dart b/lib/ui/widgets/settingsView/about_widget.dart index 1884b5e3..1b087d5a 100644 --- a/lib/ui/widgets/settingsView/about_widget.dart +++ b/lib/ui/widgets/settingsView/about_widget.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/utils/about_info.dart'; class AboutWidget extends StatefulWidget { @@ -34,21 +34,18 @@ class _AboutWidgetState extends State { ); ScaffoldMessenger.of(context).showSnackBar( SnackBar( - content: I18nText('settingsView.snackbarMessage'), + content: Text(t.settingsView.snackbarMessage), backgroundColor: Theme.of(context).colorScheme.secondary, ), ); } : null, - title: I18nText( - 'settingsView.aboutLabel', - child: const Text( - '', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - ), + title: Text( + t.settingsView.aboutLabel, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, ), ), subtitle: snapshot.hasData diff --git a/lib/ui/widgets/settingsView/settings_advanced_section.dart b/lib/ui/widgets/settingsView/settings_advanced_section.dart index 5ab7b034..45fa8919 100644 --- a/lib/ui/widgets/settingsView/settings_advanced_section.dart +++ b/lib/ui/widgets/settingsView/settings_advanced_section.dart @@ -1,6 +1,7 @@ // ignore_for_file: prefer_const_constructors import 'package:flutter/material.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_manage_api_url.dart'; import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_manage_sources.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_auto_update_patches.dart'; @@ -17,7 +18,7 @@ class SAdvancedSection extends StatelessWidget { @override Widget build(BuildContext context) { return SettingsSection( - title: 'settingsView.advancedSectionTitle', + title: t.settingsView.advancedSectionTitle, children: const [ SAutoUpdatePatches(), SShowUpdateDialog(), diff --git a/lib/ui/widgets/settingsView/settings_auto_update_patches.dart b/lib/ui/widgets/settingsView/settings_auto_update_patches.dart index 14c5126c..1e0f50ad 100644 --- a/lib/ui/widgets/settingsView/settings_auto_update_patches.dart +++ b/lib/ui/widgets/settingsView/settings_auto_update_patches.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:flutter_i18n/widgets/I18nText.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart'; import 'package:revanced_manager/ui/widgets/shared/haptics/haptic_switch_list_tile.dart'; @@ -17,17 +17,14 @@ class _SAutoUpdatePatchesState extends State { Widget build(BuildContext context) { return HapticSwitchListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 20.0), - title: I18nText( - 'settingsView.autoUpdatePatchesLabel', - child: const Text( - '', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - ), + title: Text( + t.settingsView.autoUpdatePatchesLabel, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, ), ), - subtitle: I18nText('settingsView.autoUpdatePatchesHint'), + subtitle: Text(t.settingsView.autoUpdatePatchesHint), value: _settingsViewModel.isPatchesAutoUpdate(), onChanged: (value) { setState(() { diff --git a/lib/ui/widgets/settingsView/settings_debug_section.dart b/lib/ui/widgets/settingsView/settings_debug_section.dart index 7a155b4e..e4336b83 100644 --- a/lib/ui/widgets/settingsView/settings_debug_section.dart +++ b/lib/ui/widgets/settingsView/settings_debug_section.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:flutter_i18n/widgets/I18nText.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart'; import 'package:revanced_manager/ui/widgets/settingsView/about_widget.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_section.dart'; @@ -12,51 +12,42 @@ class SDebugSection extends StatelessWidget { @override Widget build(BuildContext context) { return SettingsSection( - title: 'settingsView.debugSectionTitle', + title: t.settingsView.debugSectionTitle, children: [ ListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 20.0), - title: I18nText( - 'settingsView.logsLabel', - child: const Text( - '', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - ), + title: Text( + t.settingsView.logsLabel, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, ), ), - subtitle: I18nText('settingsView.logsHint'), + subtitle: Text(t.settingsView.logsHint), onTap: () => _settingsViewModel.exportLogcatLogs(), ), ListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 20.0), - title: I18nText( - 'settingsView.deleteLogsLabel', - child: const Text( - '', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - ), + title: Text( + t.settingsView.deleteLogsLabel, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, ), ), - subtitle: I18nText('settingsView.deleteLogsHint'), + subtitle: Text(t.settingsView.deleteLogsHint), onTap: () => _settingsViewModel.deleteLogs(), ), ListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 20.0), - title: I18nText( - 'settingsView.deleteTempDirLabel', - child: const Text( - '', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - ), + title: Text( + t.settingsView.deleteTempDirLabel, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, ), ), - subtitle: I18nText('settingsView.deleteTempDirHint'), + subtitle: Text(t.settingsView.deleteTempDirHint), onTap: () => _settingsViewModel.deleteTempDir(), ), const AboutWidget( diff --git a/lib/ui/widgets/settingsView/settings_enable_patches_selection.dart b/lib/ui/widgets/settingsView/settings_enable_patches_selection.dart index c8384044..0d9d7ae6 100644 --- a/lib/ui/widgets/settingsView/settings_enable_patches_selection.dart +++ b/lib/ui/widgets/settingsView/settings_enable_patches_selection.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:flutter_i18n/widgets/I18nText.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart'; import 'package:revanced_manager/ui/widgets/shared/haptics/haptic_switch_list_tile.dart'; @@ -18,17 +18,14 @@ class _SEnablePatchesSelectionState extends State { Widget build(BuildContext context) { return HapticSwitchListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 20.0), - title: I18nText( - 'settingsView.enablePatchesSelectionLabel', - child: const Text( - '', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - ), + title: Text( + t.settingsView.enablePatchesSelectionLabel, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, ), ), - subtitle: I18nText('settingsView.enablePatchesSelectionHint'), + subtitle: Text(t.settingsView.enablePatchesSelectionHint), value: _settingsViewModel.isPatchesChangeEnabled(), onChanged: (value) async { await _settingsViewModel.showPatchesChangeEnableDialog(value, context); diff --git a/lib/ui/widgets/settingsView/settings_export_section.dart b/lib/ui/widgets/settingsView/settings_export_section.dart index 2f7e4aa7..3ac636bc 100644 --- a/lib/ui/widgets/settingsView/settings_export_section.dart +++ b/lib/ui/widgets/settingsView/settings_export_section.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:flutter_i18n/widgets/I18nText.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_manage_keystore_password.dart'; import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_section.dart'; @@ -12,106 +12,88 @@ class SExportSection extends StatelessWidget { @override Widget build(BuildContext context) { return SettingsSection( - title: 'settingsView.exportSectionTitle', + title: t.settingsView.exportSectionTitle, children: [ ListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 20.0), - title: I18nText( - 'settingsView.exportPatchesLabel', - child: const Text( - '', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - ), + title: Text( + t.settingsView.exportPatchesLabel, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, ), ), - subtitle: I18nText('settingsView.exportPatchesHint'), + subtitle: Text(t.settingsView.exportPatchesHint), onTap: () => _settingsViewModel.exportPatches(), ), ListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 20.0), - title: I18nText( - 'settingsView.importPatchesLabel', - child: const Text( - '', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - ), + title: Text( + t.settingsView.importPatchesLabel, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, ), ), - subtitle: I18nText('settingsView.importPatchesHint'), + subtitle: Text(t.settingsView.importPatchesHint), onTap: () => _settingsViewModel.importPatches(context), ), ListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 20.0), - title: I18nText( - 'settingsView.resetStoredPatchesLabel', - child: const Text( - '', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - ), + title: Text( + t.settingsView.resetStoredPatchesLabel, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, ), ), - subtitle: I18nText('settingsView.resetStoredPatchesHint'), + subtitle: Text(t.settingsView.resetStoredPatchesHint), onTap: () => _showResetDialog( context, - 'settingsView.resetStoredPatchesDialogTitle', - 'settingsView.resetStoredPatchesDialogText', + t.settingsView.resetStoredPatchesDialogTitle, + t.settingsView.resetStoredPatchesDialogText, _settingsViewModel.resetSelectedPatches, ), ), ListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 20.0), - title: I18nText( - 'settingsView.resetStoredOptionsLabel', - child: const Text( - '', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - ), + title: Text( + t.settingsView.resetStoredOptionsLabel, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, ), ), - subtitle: I18nText('settingsView.resetStoredOptionsHint'), + subtitle: Text(t.settingsView.resetStoredOptionsHint), onTap: () => _showResetDialog( context, - 'settingsView.resetStoredOptionsDialogTitle', - 'settingsView.resetStoredOptionsDialogText', + t.settingsView.resetStoredOptionsDialogTitle, + t.settingsView.resetStoredOptionsDialogText, _settingsViewModel.resetAllOptions, ), ), ListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 20.0), - title: I18nText( - 'settingsView.exportKeystoreLabel', - child: const Text( - '', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - ), + title: Text( + t.settingsView.exportKeystoreLabel, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, ), ), - subtitle: I18nText('settingsView.exportKeystoreHint'), + subtitle: Text(t.settingsView.exportKeystoreHint), onTap: () => _settingsViewModel.exportKeystore(), ), ListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 20.0), - title: I18nText( - 'settingsView.importKeystoreLabel', - child: const Text( - '', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - ), + title: Text( + t.settingsView.importKeystoreLabel, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, ), ), - subtitle: I18nText('settingsView.importKeystoreHint'), + subtitle: Text(t.settingsView.importKeystoreHint), onTap: () async { await _settingsViewModel.importKeystore(); final sManageKeystorePassword = SManageKeystorePassword(); @@ -122,17 +104,14 @@ class SExportSection extends StatelessWidget { ), ListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 20.0), - title: I18nText( - 'settingsView.regenerateKeystoreLabel', - child: const Text( - '', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - ), + title: Text( + t.settingsView.regenerateKeystoreLabel, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, ), ), - subtitle: I18nText('settingsView.regenerateKeystoreHint'), + subtitle: Text(t.settingsView.regenerateKeystoreHint), onTap: () => _showDeleteKeystoreDialog(context), ), // SManageKeystorePasswordUI(), @@ -149,19 +128,19 @@ class SExportSection extends StatelessWidget { return showDialog( context: context, builder: (context) => AlertDialog( - title: I18nText(dialogTitle), - content: I18nText(dialogText), + title: Text(dialogTitle), + content: Text(dialogText), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), - child: I18nText('noButton'), + child: Text(t.noButton), ), FilledButton( onPressed: () => { Navigator.of(context).pop(), dialogAction(), }, - child: I18nText('yesButton'), + child: Text(t.yesButton), ), ], ), @@ -172,19 +151,19 @@ class SExportSection extends StatelessWidget { return showDialog( context: context, builder: (context) => AlertDialog( - title: I18nText('settingsView.regenerateKeystoreDialogTitle'), - content: I18nText('settingsView.regenerateKeystoreDialogText'), + title: Text(t.settingsView.regenerateKeystoreDialogTitle), + content: Text(t.settingsView.regenerateKeystoreDialogText), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), - child: I18nText('noButton'), + child: Text(t.noButton), ), FilledButton( onPressed: () => { Navigator.of(context).pop(), _settingsViewModel.deleteKeystore(), }, - child: I18nText('yesButton'), + child: Text(t.yesButton), ), ], ), diff --git a/lib/ui/widgets/settingsView/settings_require_suggested_app_version.dart b/lib/ui/widgets/settingsView/settings_require_suggested_app_version.dart index 9e91b9cb..21c0922d 100644 --- a/lib/ui/widgets/settingsView/settings_require_suggested_app_version.dart +++ b/lib/ui/widgets/settingsView/settings_require_suggested_app_version.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:flutter_i18n/widgets/I18nText.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart'; import 'package:revanced_manager/ui/widgets/shared/haptics/haptic_switch_list_tile.dart'; @@ -19,17 +19,14 @@ class _SRequireSuggestedAppVersionState Widget build(BuildContext context) { return HapticSwitchListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 20.0), - title: I18nText( - 'settingsView.requireSuggestedAppVersionLabel', - child: const Text( - '', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - ), + title: Text( + t.settingsView.requireSuggestedAppVersionLabel, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, ), ), - subtitle: I18nText('settingsView.requireSuggestedAppVersionHint'), + subtitle: Text(t.settingsView.requireSuggestedAppVersionHint), value: _settingsViewModel.isRequireSuggestedAppVersionEnabled(), onChanged: (value) async { await _settingsViewModel.showRequireSuggestedAppVersionDialog( diff --git a/lib/ui/widgets/settingsView/settings_section.dart b/lib/ui/widgets/settingsView/settings_section.dart index 56e9247e..697dcbd4 100644 --- a/lib/ui/widgets/settingsView/settings_section.dart +++ b/lib/ui/widgets/settingsView/settings_section.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; class SettingsSection extends StatelessWidget { const SettingsSection({ @@ -17,13 +16,10 @@ class SettingsSection extends StatelessWidget { children: [ Container( padding: const EdgeInsets.only(top: 16.0, bottom: 10.0, left: 20.0), - child: I18nText( + child: Text( title, - child: Text( - '', - style: TextStyle( - color: Theme.of(context).colorScheme.primary, - ), + style: TextStyle( + color: Theme.of(context).colorScheme.primary, ), ), ), diff --git a/lib/ui/widgets/settingsView/settings_show_update_dialog.dart b/lib/ui/widgets/settingsView/settings_show_update_dialog.dart index 42b90dac..e48c8168 100644 --- a/lib/ui/widgets/settingsView/settings_show_update_dialog.dart +++ b/lib/ui/widgets/settingsView/settings_show_update_dialog.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:flutter_i18n/widgets/I18nText.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart'; import 'package:revanced_manager/ui/widgets/shared/haptics/haptic_switch_list_tile.dart'; @@ -17,17 +17,14 @@ class _SShowUpdateDialogState extends State { Widget build(BuildContext context) { return HapticSwitchListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 20.0), - title: I18nText( - 'settingsView.showUpdateDialogLabel', - child: const Text( - '', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - ), + title: Text( + t.settingsView.showUpdateDialogLabel, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, ), ), - subtitle: I18nText('settingsView.showUpdateDialogHint'), + subtitle: Text(t.settingsView.showUpdateDialogHint), value: _settingsViewModel.showUpdateDialog(), onChanged: (value) { setState(() { diff --git a/lib/ui/widgets/settingsView/settings_team_section.dart b/lib/ui/widgets/settingsView/settings_team_section.dart index aa2d81a6..bcf117e7 100644 --- a/lib/ui/widgets/settingsView/settings_team_section.dart +++ b/lib/ui/widgets/settingsView/settings_team_section.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:flutter_i18n/widgets/I18nText.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_section.dart'; import 'package:revanced_manager/ui/widgets/settingsView/social_media_widget.dart'; @@ -12,21 +12,18 @@ class STeamSection extends StatelessWidget { @override Widget build(BuildContext context) { return SettingsSection( - title: 'settingsView.teamSectionTitle', + title: t.settingsView.teamSectionTitle, children: [ ListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 20.0), - title: I18nText( - 'settingsView.contributorsLabel', - child: const Text( - '', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - ), + title: Text( + t.settingsView.contributorsLabel, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, ), ), - subtitle: I18nText('settingsView.contributorsHint'), + subtitle: Text(t.settingsView.contributorsHint), onTap: () => _settingsViewModel.navigateToContributors(), ), const SocialMediaWidget( diff --git a/lib/ui/widgets/settingsView/settings_tile_dialog.dart b/lib/ui/widgets/settingsView/settings_tile_dialog.dart index 822ffe6f..eed856cb 100644 --- a/lib/ui/widgets/settingsView/settings_tile_dialog.dart +++ b/lib/ui/widgets/settingsView/settings_tile_dialog.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; class SettingsTileDialog extends StatelessWidget { const SettingsTileDialog({ @@ -18,17 +17,14 @@ class SettingsTileDialog extends StatelessWidget { Widget build(BuildContext context) { return ListTile( contentPadding: padding ?? EdgeInsets.zero, - title: I18nText( + title: Text( title, - child: const Text( - '', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - ), + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, ), ), - subtitle: I18nText(subtitle), + subtitle: Text(subtitle), onTap: onTap, ); } diff --git a/lib/ui/widgets/settingsView/settings_universal_patches.dart b/lib/ui/widgets/settingsView/settings_universal_patches.dart index 98aefa93..e2d92e47 100644 --- a/lib/ui/widgets/settingsView/settings_universal_patches.dart +++ b/lib/ui/widgets/settingsView/settings_universal_patches.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:flutter_i18n/widgets/I18nText.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart'; import 'package:revanced_manager/ui/views/patches_selector/patches_selector_viewmodel.dart'; import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart'; @@ -21,17 +21,14 @@ class _SUniversalPatchesState extends State { Widget build(BuildContext context) { return HapticSwitchListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 20.0), - title: I18nText( - 'settingsView.universalPatchesLabel', - child: const Text( - '', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - ), + title: Text( + t.settingsView.universalPatchesLabel, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, ), ), - subtitle: I18nText('settingsView.universalPatchesHint'), + subtitle: Text(t.settingsView.universalPatchesHint), value: _settingsViewModel.areUniversalPatchesEnabled(), onChanged: (value) { setState(() { diff --git a/lib/ui/widgets/settingsView/settings_version_compatibility_check.dart b/lib/ui/widgets/settingsView/settings_version_compatibility_check.dart index 7f90bac2..93ff005a 100644 --- a/lib/ui/widgets/settingsView/settings_version_compatibility_check.dart +++ b/lib/ui/widgets/settingsView/settings_version_compatibility_check.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:flutter_i18n/widgets/I18nText.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart'; import 'package:revanced_manager/ui/views/patches_selector/patches_selector_viewmodel.dart'; import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart'; @@ -24,17 +24,14 @@ class _SVersionCompatibilityCheckState Widget build(BuildContext context) { return HapticSwitchListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 20.0), - title: I18nText( - 'settingsView.versionCompatibilityCheckLabel', - child: const Text( - '', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - ), + title: Text( + t.settingsView.versionCompatibilityCheckLabel, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, ), ), - subtitle: I18nText('settingsView.versionCompatibilityCheckHint'), + subtitle: Text(t.settingsView.versionCompatibilityCheckHint), value: _settingsViewModel.isVersionCompatibilityCheckEnabled(), onChanged: (value) { setState(() { diff --git a/lib/ui/widgets/settingsView/social_media_widget.dart b/lib/ui/widgets/settingsView/social_media_widget.dart index c42c526d..7bec8b1c 100644 --- a/lib/ui/widgets/settingsView/social_media_widget.dart +++ b/lib/ui/widgets/settingsView/social_media_widget.dart @@ -1,7 +1,7 @@ import 'package:expandable/expandable.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/ui/widgets/settingsView/social_media_item.dart'; import 'package:revanced_manager/ui/widgets/shared/custom_card.dart'; import 'package:revanced_manager/ui/widgets/shared/custom_icon.dart'; @@ -26,17 +26,14 @@ class SocialMediaWidget extends StatelessWidget { ), header: ListTile( contentPadding: padding ?? EdgeInsets.zero, - title: I18nText( - 'socialMediaCard.widgetTitle', - child: const Text( - '', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w500, - ), + title: Text( + t.socialMediaCard.widgetTitle, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, ), ), - subtitle: I18nText('socialMediaCard.widgetSubtitle'), + subtitle: Text(t.socialMediaCard.widgetSubtitle), ), expanded: Padding( padding: padding ?? EdgeInsets.zero, diff --git a/lib/ui/widgets/shared/application_item.dart b/lib/ui/widgets/shared/application_item.dart index ce432138..3980dff8 100644 --- a/lib/ui/widgets/shared/application_item.dart +++ b/lib/ui/widgets/shared/application_item.dart @@ -1,7 +1,7 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; -import 'package:flutter_i18n/flutter_i18n.dart'; +import 'package:revanced_manager/gen/strings.g.dart'; import 'package:revanced_manager/ui/widgets/shared/custom_card.dart'; import 'package:timeago/timeago.dart'; @@ -81,7 +81,7 @@ class _ApplicationItemState extends State { children: [ FilledButton( onPressed: widget.onPressed, - child: I18nText('applicationItem.infoButton'), + child: Text(t.applicationItem.infoButton), ), ], ), diff --git a/pubspec.yaml b/pubspec.yaml index d2135212..ffd513dc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -31,7 +31,6 @@ dependencies: ref: 560d21c4148b53933313573e7eafca0b0eb9aadf # Branch: specify-namespace flutter_cache_manager: ^3.3.0 flutter_file_dialog: ^3.0.2 - flutter_i18n: ^0.34.0 flutter_local_notifications: ^16.1.0 flutter_localizations: sdk: flutter @@ -68,12 +67,14 @@ dependencies: timezone: ^0.9.0 url_launcher: ^6.1.10 wakelock_plus: ^1.1.3 + slang: ^3.25.0 + slang_flutter: ^3.25.0 + language_code: ^0.3.1 dev_dependencies: build_runner: any flutter_lints: ^3.0.1 injectable_generator: ^2.1.5 - json_serializable: ^6.6.1 flutter: uses-material-design: true @@ -83,3 +84,6 @@ flutter: - asset: fonts/custom-icons.ttf assets: - assets/i18n/ + +flutter_localizations: + sdk: flutter diff --git a/slang.yaml b/slang.yaml new file mode 100644 index 00000000..42b2aed5 --- /dev/null +++ b/slang.yaml @@ -0,0 +1,5 @@ +base_locale: en +fallback_strategy: base_locale +input_file_pattern: .i18n.json +input_directory: assets/i18n +output_directory: lib/gen