From 5d2a08d8189c5a6c7c8f922ddef4d1cf88759e3a Mon Sep 17 00:00:00 2001 From: Fox2Code Date: Thu, 19 May 2022 18:12:56 +0200 Subject: [PATCH] Start fixes for last PR. --- LEGALS.md | 15 - app/build.gradle | 7 +- .../com/fox2code/mmm/MainApplication.java | 3 + .../fox2code/mmm/module/ActionButtonType.java | 14 +- .../mmm/settings/SettingsActivity.java | 11 +- rosetta/.gitignore | 33 -- rosetta/build.gradle | 66 ---- .../com/ahmedjazzar/rosetta/BuildConfig.java | 10 - rosetta/gradle.properties | 23 -- rosetta/proguard-rules.pro | 17 - rosetta/src/main/AndroidManifest.xml | 5 - .../ahmedjazzar/rosetta/LanguageSwitcher.java | 179 ----------- .../rosetta/LanguagesListDialogFragment.java | 180 ----------- .../ahmedjazzar/rosetta/LocalesDetector.java | 153 --------- .../rosetta/LocalesPreferenceManager.java | 161 ---------- .../com/ahmedjazzar/rosetta/LocalesUtils.java | 302 ------------------ .../java/com/ahmedjazzar/rosetta/Logger.java | 38 --- rosetta/src/main/res/values/strings.xml | 6 - settings.gradle | 1 - 19 files changed, 16 insertions(+), 1208 deletions(-) delete mode 100644 LEGALS.md delete mode 100644 rosetta/.gitignore delete mode 100644 rosetta/build.gradle delete mode 100644 rosetta/build/generated/source/buildConfig/debug/com/ahmedjazzar/rosetta/BuildConfig.java delete mode 100644 rosetta/gradle.properties delete mode 100644 rosetta/proguard-rules.pro delete mode 100644 rosetta/src/main/AndroidManifest.xml delete mode 100644 rosetta/src/main/java/com/ahmedjazzar/rosetta/LanguageSwitcher.java delete mode 100644 rosetta/src/main/java/com/ahmedjazzar/rosetta/LanguagesListDialogFragment.java delete mode 100644 rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesDetector.java delete mode 100644 rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesPreferenceManager.java delete mode 100644 rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesUtils.java delete mode 100644 rosetta/src/main/java/com/ahmedjazzar/rosetta/Logger.java delete mode 100644 rosetta/src/main/res/values/strings.xml diff --git a/LEGALS.md b/LEGALS.md deleted file mode 100644 index 1cb249f..0000000 --- a/LEGALS.md +++ /dev/null @@ -1,15 +0,0 @@ -# LEGALS - -## Fox's Magisk Module Manager -- Maintained: Yes - - Maintainers - - [Fox2Code](https://github.com/Fox2Code) - - [androidacybot](https://github.com/androidacybot) -- License: [ LGPL-3.0 license](https://github.com/Fox2Code/FoxMagiskModuleManager/blob/master/LICENCE) - -## Rosetta ([Fork](https://github.com/iamjazzar/rosetta)) -- Maintained: No - - Maintainers - - [iamjazzar](https://github.com/iamjazzar) - - Others unknown -- License: [ MIT license](https://github.com/iamjazzar/rosetta/blob/master/LICENSE) diff --git a/app/build.gradle b/app/build.gradle index 91cb9fa..7cd511d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -71,10 +71,7 @@ android { } aboutLibraries { - additionalLicenses = [ - "LGPL_3_0_only", - "rosetta" - ] + additionalLicenses = ["LGPL_3_0_only"] } configurations { @@ -101,7 +98,7 @@ dependencies { implementation 'com.squareup.okhttp3:okhttp-dnsoverhttps:4.9.3' implementation 'com.squareup.okhttp3:okhttp-brotli:4.9.3' implementation 'com.github.topjohnwu.libsu:io:5.0.1' - implementation project(":rosetta") + implementation 'com.github.Fox2Code:RosettaX:46ec630055' // Markdown implementation "io.noties.markwon:core:4.6.2" diff --git a/app/src/main/java/com/fox2code/mmm/MainApplication.java b/app/src/main/java/com/fox2code/mmm/MainApplication.java index 1e0d745..4e2d6b8 100644 --- a/app/src/main/java/com/fox2code/mmm/MainApplication.java +++ b/app/src/main/java/com/fox2code/mmm/MainApplication.java @@ -23,6 +23,7 @@ import com.fox2code.mmm.compat.CompatThemeWrapper; import com.fox2code.mmm.installer.InstallerInitializer; import com.fox2code.mmm.utils.GMSProviderInstaller; import com.fox2code.mmm.utils.Http; +import com.fox2code.rosettax.LanguageSwitcher; import com.google.android.material.color.DynamicColors; import com.topjohnwu.superuser.Shell; @@ -307,6 +308,8 @@ public class MainApplication extends CompatApplication { } else { MainApplication.firstBoot = bootPrefs.getBoolean("first_boot", false); } + // Force initialize language early. + new LanguageSwitcher(this); this.updateTheme(); // Update SSL Ciphers if update is possible GMSProviderInstaller.installIfNeeded(this); diff --git a/app/src/main/java/com/fox2code/mmm/module/ActionButtonType.java b/app/src/main/java/com/fox2code/mmm/module/ActionButtonType.java index 8399883..02d2f98 100644 --- a/app/src/main/java/com/fox2code/mmm/module/ActionButtonType.java +++ b/app/src/main/java/com/fox2code/mmm/module/ActionButtonType.java @@ -31,7 +31,7 @@ public enum ActionButtonType { INFO() { @Override public void update(Chip button, ModuleHolder moduleHolder) { - button.setChipIcon(button.getContext().getResources().getDrawable(R.drawable.ic_baseline_info_24)); + button.setChipIcon(button.getContext().getDrawable(R.drawable.ic_baseline_info_24)); button.setText(R.string.description); } @@ -70,7 +70,7 @@ public enum ActionButtonType { int icon = moduleHolder.hasUpdate() ? R.drawable.ic_baseline_update_24 : R.drawable.ic_baseline_system_update_24; - button.setChipIcon(button.getContext().getResources().getDrawable(icon)); + button.setChipIcon(button.getContext().getDrawable(icon)); if (moduleHolder.hasUpdate()) { button.setText(R.string.update); } else { @@ -150,7 +150,7 @@ public enum ActionButtonType { moduleHolder.hasFlag(ModuleInfo.FLAGS_MODULE_ACTIVE)) ? R.drawable.ic_baseline_delete_24 : R.drawable.ic_baseline_delete_forever_24; - button.setChipIcon(button.getContext().getResources().getDrawable(icon)); + button.setChipIcon(button.getContext().getDrawable(icon)); button.setText(R.string.uninstall); } @@ -190,7 +190,7 @@ public enum ActionButtonType { CONFIG() { @Override public void update(Chip button, ModuleHolder moduleHolder) { - button.setChipIcon(button.getContext().getResources().getDrawable(R.drawable.ic_baseline_app_settings_alt_24)); + button.setChipIcon(button.getContext().getDrawable(R.drawable.ic_baseline_app_settings_alt_24)); button.setText(R.string.config); } @@ -209,7 +209,7 @@ public enum ActionButtonType { @Override public void update(Chip button, ModuleHolder moduleHolder) { ModuleInfo moduleInfo = moduleHolder.getMainModuleInfo(); - button.setChipIcon(button.getContext().getResources().getDrawable(supportIconForUrl(moduleInfo.support))); + button.setChipIcon(button.getContext().getDrawable(supportIconForUrl(moduleInfo.support))); button.setText(R.string.support); } @@ -228,7 +228,7 @@ public enum ActionButtonType { } else if (moduleInfo.donate.startsWith("https://www.patreon.com/")) { icon = R.drawable.ic_patreon; } - button.setChipIcon(button.getContext().getResources().getDrawable(icon)); + button.setChipIcon(button.getContext().getDrawable(icon)); button.setText(R.string.donate); } @@ -266,7 +266,7 @@ public enum ActionButtonType { } public void update(Chip button, ModuleHolder moduleHolder) { - button.setChipIcon(button.getContext().getResources().getDrawable(this.iconId)); + button.setChipIcon(button.getContext().getDrawable(this.iconId)); } public abstract void doAction(Chip button, ModuleHolder moduleHolder); diff --git a/app/src/main/java/com/fox2code/mmm/settings/SettingsActivity.java b/app/src/main/java/com/fox2code/mmm/settings/SettingsActivity.java index 2a01a0a..6b6e2c1 100644 --- a/app/src/main/java/com/fox2code/mmm/settings/SettingsActivity.java +++ b/app/src/main/java/com/fox2code/mmm/settings/SettingsActivity.java @@ -26,7 +26,7 @@ import com.fox2code.mmm.repo.RepoManager; import com.fox2code.mmm.utils.Http; import com.fox2code.mmm.utils.IntentHelper; -import com.ahmedjazzar.rosetta.LanguageSwitcher; +import com.fox2code.rosettax.LanguageSwitcher; import com.mikepenz.aboutlibraries.LibsBuilder; import com.topjohnwu.superuser.internal.UiThreadHandler; @@ -98,9 +98,6 @@ public class SettingsActivity extends CompatActivity { return true; }); - // This is the locale that you wanna your app to launch with. - String firstLaunchLocale = "en"; - // Warning! Locales that are't exist will crash the app HashSet supportedLocales = new HashSet<>(); supportedLocales.add("cs"); @@ -120,13 +117,13 @@ public class SettingsActivity extends CompatActivity { supportedLocales.add("vi"); supportedLocales.add("zh-rCH"); supportedLocales.add("zh-rTW"); - supportedLocales.add(firstLaunchLocale); + supportedLocales.add("en"); Preference languageSelector = findPreference("pref_language_selector"); languageSelector.setOnPreferenceClickListener(preference -> { - LanguageSwitcher ls = new LanguageSwitcher(getActivity(), new Locale(firstLaunchLocale)); - ls.showChangeLanguageDialog(getActivity()); + LanguageSwitcher ls = new LanguageSwitcher(getActivity()); ls.setSupportedStringLocales(supportedLocales); + ls.showChangeLanguageDialog(getActivity()); return true; }); diff --git a/rosetta/.gitignore b/rosetta/.gitignore deleted file mode 100644 index 38cc34a..0000000 --- a/rosetta/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ - -# files for the dex VM -*.dex - -# Java class files -*.class - -# generated files -bin/ -gen/ - -# Local configuration file (sdk path, etc) -local.properties - -# Windows thumbnail db -Thumbs.db - -# OSX files -.DS_Store - -# Eclipse project files -.classpath -.project - -# Android Studio -*.iml -.idea -#.idea/workspace.xml - remove # and delete .idea if it better suit your needs. -.gradle -build/ - -#NDK -obj/ diff --git a/rosetta/build.gradle b/rosetta/build.gradle deleted file mode 100644 index 5b67507..0000000 --- a/rosetta/build.gradle +++ /dev/null @@ -1,66 +0,0 @@ -apply plugin: 'com.android.library' - -ext { - bintrayRepo = 'maven' - bintrayName = 'Rosetta' - - publishedGroupId = 'com.ahmedjazzar.rosetta' - libraryName = 'Rosetta' - artifact = 'rosetta' - - libraryDescription = 'Android library that lets your app supporting multiple languages ' + - 'without any concern from you as a developer.' - - siteUrl = 'https://github.com/ahmedaljazzar/rosetta' - gitUrl = 'https://github.com/ahmedaljazzar/rosetta.git' - - libraryVersion = '1.0.1' - - developerId = 'ahmedaljazzar' - developerName = 'Ahmed Jazzar' - developerEmail = 'me@ahmedjazzar.com' - - licenseName = 'MIT' - licenseUrl = 'https://opensource.org/licenses/MIT' - allLicenses = ["MIT"] -} - -buildscript { - repositories { - google() - mavenCentral() - gradlePluginPortal() - } - dependencies { - classpath 'com.android.tools.build:gradle:7.2.0' - classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.4' - classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' - } -} - -android { - compileSdkVersion 32 - buildToolsVersion "23.0.3" - - defaultConfig { - minSdkVersion 21 - targetSdkVersion 32 - versionCode 3 - versionName "1.0.1" - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } -} - -dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) - testImplementation 'junit:junit:4.13.2' - testImplementation 'org.mockito:mockito-core:1.10.19' - implementation 'com.google.android.material:material:1.6.0' - implementation 'androidx.appcompat:appcompat:1.4.1' -} diff --git a/rosetta/build/generated/source/buildConfig/debug/com/ahmedjazzar/rosetta/BuildConfig.java b/rosetta/build/generated/source/buildConfig/debug/com/ahmedjazzar/rosetta/BuildConfig.java deleted file mode 100644 index cbf889e..0000000 --- a/rosetta/build/generated/source/buildConfig/debug/com/ahmedjazzar/rosetta/BuildConfig.java +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Automatically generated file. DO NOT MODIFY - */ -package com.ahmedjazzar.rosetta; - -public final class BuildConfig { - public static final boolean DEBUG = Boolean.parseBoolean("true"); - public static final String LIBRARY_PACKAGE_NAME = "com.ahmedjazzar.rosetta"; - public static final String BUILD_TYPE = "debug"; -} diff --git a/rosetta/gradle.properties b/rosetta/gradle.properties deleted file mode 100644 index 2649381..0000000 --- a/rosetta/gradle.properties +++ /dev/null @@ -1,23 +0,0 @@ -# Project-wide Gradle settings. -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true -# AndroidX package structure to make it clearer which packages are bundled with the -# Android operating system, and which are packaged with your app"s APK -# https://developer.android.com/topic/libraries/support-library/androidx-rn -android.useAndroidX=true -# Automatically convert third-party libraries to use AndroidX -android.enableJetifier=true - -# Fox builds props mods -org.gradle.parallel=true -android.enableR8.fullMode=true diff --git a/rosetta/proguard-rules.pro b/rosetta/proguard-rules.pro deleted file mode 100644 index 47b5a13..0000000 --- a/rosetta/proguard-rules.pro +++ /dev/null @@ -1,17 +0,0 @@ -# TODO: Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in /Users/ahmedjazzar/Library/Android/sdk/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the proguardFiles -# directive in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} diff --git a/rosetta/src/main/AndroidManifest.xml b/rosetta/src/main/AndroidManifest.xml deleted file mode 100644 index f1b2707..0000000 --- a/rosetta/src/main/AndroidManifest.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - diff --git a/rosetta/src/main/java/com/ahmedjazzar/rosetta/LanguageSwitcher.java b/rosetta/src/main/java/com/ahmedjazzar/rosetta/LanguageSwitcher.java deleted file mode 100644 index 53d286e..0000000 --- a/rosetta/src/main/java/com/ahmedjazzar/rosetta/LanguageSwitcher.java +++ /dev/null @@ -1,179 +0,0 @@ -package com.ahmedjazzar.rosetta; - -import android.app.Activity; -import android.content.Context; - -import androidx.annotation.NonNull; -import androidx.fragment.app.FragmentActivity; - -import java.util.HashSet; -import java.util.Locale; - -/** - * This class is the application door to this Library. It handles the ongoing and outgoing requests, - * initializations, preferences, .. - * I think that there's no need for logging here because other classes already handle logs for these - * actions based on their returned results. - * - * Created by ahmedjazzar on 1/16/16. - */ -public class LanguageSwitcher { - - private Context mContext; - private LocalesPreferenceManager mLocalesPreferences; - private final String TAG = LanguageSwitcher.class.getName(); - - /** - * A constructor that accepts context and sets the base and first launch locales to en_US - * @param context the context of the dealer - */ - public LanguageSwitcher(@NonNull Context context) { - this(context, Locale.US); - } - - /** - * A constructor that accepts context and sets the base and first launch locales to - * firstLaunchLocale. - * - * NOTE: Please do not use unless: - * 1. You wanna set your locales by calling {@link LanguageSwitcher#setSupportedLocales} - * 2. You know for sure that the preferred locale is as same as your base locale - * - * @param context the context of the dealer - * @param firstLaunchLocale the locale that owner wanna use at its first launch - */ - public LanguageSwitcher(@NonNull Context context, Locale firstLaunchLocale) { - this(context, firstLaunchLocale, firstLaunchLocale); - } - - /** - * This is supposed to be more specific; It has three parameters cover all owner needs - * @param context the context of the dealer - * @param firstLaunchLocale the locale that owner wanna use at its first launch - * @param baseLocale the locale that used in the main xml strings file (most likely 'en') - */ - public LanguageSwitcher(@NonNull Context context, Locale firstLaunchLocale, Locale baseLocale) { - this.mContext = context.getApplicationContext(); - - this.mLocalesPreferences = - new LocalesPreferenceManager(context, firstLaunchLocale, baseLocale); - - // initializing Locales utils needed objects (detector, preferences) - LocalesUtils.setDetector(new LocalesDetector(this.mContext)); - LocalesUtils.setLocalesPreferenceManager(mLocalesPreferences); - - // Setting app locale to match the user preferred one - LocalesUtils.setAppLocale(mContext, - mLocalesPreferences - .getPreferredLocale(LocalesPreferenceManager.USER_PREFERRED_LOCALE)); - } - - /** - * Responsible for displaying Change dialog fragment - */ - public void showChangeLanguageDialog(FragmentActivity activity) { - new LanguagesListDialogFragment() - .show(activity.getSupportFragmentManager(), TAG); - } - - /** - * - * @return the application supported locales - */ - public HashSet getLocales() { - return LocalesUtils.getLocales(); - } - - /** - * Sets the app locales from a string Set - * @param sLocales supported locales in a String form - */ - public void setSupportedStringLocales(HashSet sLocales) { - - HashSet locales = new HashSet<>(); - for (String sLocale: sLocales) { - locales.add(new Locale(sLocale)); - } - this.setSupportedLocales(locales); - } - - /** - * set supported locales from the given Set - * @param locales supported locales - */ - public void setSupportedLocales(HashSet locales) { - LocalesUtils.setSupportedLocales(locales); - } - - /** - * Sets the supported locales after fetching there availability using fetchAvailableLocales - * method - * @param stringId the string that this library gonna use to detect current app available - * locales - */ - public void setSupportedLocales(int stringId) { - this.setSupportedLocales(this.fetchAvailableLocales(stringId)); - } - - /** - * Fetching the application available locales inside the resources folder dynamically - * @param stringId the string that this library gonna use to detect current app available - * locales - * @return a set of detected application locales - */ - public HashSet fetchAvailableLocales(int stringId) { - return LocalesUtils.fetchAvailableLocales(stringId); - } - - /** - * Setting the application locale manually - * @param newLocale the locale in a string format - * @param activity the current activity in order to refresh the app - * - * @return true if the operation succeed, false otherwise - */ - public boolean setLocale(String newLocale, Activity activity) { - return setLocale(new Locale(newLocale), activity); - } - - /** - * Setting the application locale manually - * @param newLocale the desired locale - * @param activity the current activity in order to refresh the app - * - * @return true if the operation succeed, false otherwise - */ - public boolean setLocale(Locale newLocale, Activity activity) { - - return LocalesUtils.setLocale(newLocale, activity); - } - - /** - * - * @return the first launch locale - */ - public Locale getLaunchLocale() { - - return LocalesUtils.getLaunchLocale(); - } - - /** - * - * @return the current locale - */ - public Locale getCurrentLocale() { - - return LocalesUtils.getCurrentLocale(this.mContext); - } - - /** - * Return to the first launch locale - * @param activity the current activity in order to refresh the app - * - * @return true if the operation succeed, false otherwise - */ - public boolean switchToLaunch(Activity activity) { - - return setLocale(getLaunchLocale(), activity); - } -} diff --git a/rosetta/src/main/java/com/ahmedjazzar/rosetta/LanguagesListDialogFragment.java b/rosetta/src/main/java/com/ahmedjazzar/rosetta/LanguagesListDialogFragment.java deleted file mode 100644 index b141e36..0000000 --- a/rosetta/src/main/java/com/ahmedjazzar/rosetta/LanguagesListDialogFragment.java +++ /dev/null @@ -1,180 +0,0 @@ -package com.ahmedjazzar.rosetta; - -import android.app.Dialog; -import android.os.Bundle; -import android.widget.Button; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.appcompat.app.AlertDialog; -import androidx.fragment.app.DialogFragment; -import androidx.fragment.app.FragmentActivity; - -import com.google.android.material.dialog.MaterialAlertDialogBuilder; - -import java.util.ArrayList; -import java.util.Locale; - -/** - * This fragment is responsible for displaying the supported locales and performing any necessary - * action that allows user to select, cancel, and commit changes. - * - * Created by ahmedjazzar on 1/19/16. - */ - -public class LanguagesListDialogFragment extends DialogFragment { - - private final int DIALOG_TITLE_ID = R.string.language; - private final int DIALOG_POSITIVE_ID = R.string.ok; - private final int DIALOG_NEGATIVE_ID = R.string.cancel; - - private int mSelectedLanguage = -1; - private final Logger mLogger; - - public LanguagesListDialogFragment() { - String TAG = LanguagesListDialogFragment.class.getName(); - this.mLogger = new Logger(TAG); - } - - /** - * @return a Dialog fragment - */ - @NonNull - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(requireActivity()); - mLogger.debug("Building DialogFragment."); - - builder.setTitle(getString(DIALOG_TITLE_ID)) - .setSingleChoiceItems( - getLanguages(), - getCurrentLocaleIndex(), - (dialogInterface, which) -> onLanguageSelectedLocalized(which)) - .setPositiveButton( - getString(DIALOG_POSITIVE_ID).toUpperCase(), - (dialogInterface, which) -> onPositiveClick()) - .setNegativeButton( - getString(DIALOG_NEGATIVE_ID).toUpperCase(), - (dialogInterface, which) -> onNegativeClick()); - - mLogger.verbose("DialogFragment built."); - return builder.create(); - } - - /** - * @param which the position of the selected locale - */ - protected void onLanguageSelected(int which) { - // just update the selected locale - mSelectedLanguage = which; - } - - /** - * Localizing the dialog buttons and title - * @param which the position of the selected locale - */ - protected void onLanguageSelectedLocalized(int which) { - - // update the selected locale - mSelectedLanguage = which; - AlertDialog dialog = (AlertDialog) getDialog(); - - mLogger.debug("Displaying dialog main strings in the selected " + - "locale"); - - onLanguageSelectedLocalized( - which, - null, - dialog.getButton(AlertDialog.BUTTON_POSITIVE), - dialog.getButton(AlertDialog.BUTTON_NEGATIVE)); - } - - /** - * the position of the selected locale given the ids - * @param which the position of the selected locale - * @param titleView dialog's title text view - * @param positiveButton positive button - * @param negativeButton negative button - */ - protected void onLanguageSelectedLocalized(int which, TextView titleView, Button positiveButton, - Button negativeButton) { - - // update the selected locale - mSelectedLanguage = which; - Locale locale = LocalesUtils.getLocaleFromIndex(mSelectedLanguage); - AlertDialog dialog = (AlertDialog) getDialog(); - FragmentActivity activity = getActivity(); - - mLogger.debug("Displaying dialog main strings in the selected " + - "locale"); - - assert activity != null; - String LocalizedTitle = LocalesUtils.getInSpecificLocale(activity, locale, DIALOG_TITLE_ID); - if(titleView == null) { - // Display dialog title in the selected locale - assert dialog != null; - dialog.setTitle(LocalizedTitle); - } else { - titleView.setText(LocalizedTitle); - } - - // Display positive button text in the selected locale - positiveButton.setText(LocalesUtils.getInSpecificLocale( - activity, locale, DIALOG_POSITIVE_ID)); - - // Display negative button text in the selected locale - negativeButton.setText(LocalesUtils.getInSpecificLocale( - activity, locale, DIALOG_NEGATIVE_ID)); - } - - /** - * called when the user approved changing locale - */ - protected void onPositiveClick() { - - // if the user did not select the same locale go ahead, else ignore - if (mSelectedLanguage != -1 && - mSelectedLanguage != LocalesUtils.getCurrentLocaleIndex()) { - - // Try changing the locale - if (LocalesUtils.setAppLocale( - getActivity(), mSelectedLanguage)) { - - mLogger.info("App locale changed successfully."); - LocalesUtils.refreshApplication(requireActivity()); - } else { - mLogger.error("Unsuccessful trial to change the App locale."); - // TODO: notify the user that his request not placed - } - } else { - dismiss(); - } - } - - /** - * called when the user discarded changing locale - */ - protected void onNegativeClick() { - mLogger.verbose("User discarded changing language."); - mLogger.debug("Return to the original locale."); - this.onLanguageSelectedLocalized(this.getCurrentLocaleIndex()); - } - - /** - * - * @return available languages - */ - protected String[] getLanguages() { - ArrayList languages = LocalesUtils.getLocalesWithDisplayName(); - return languages.toArray(new String[languages.size()]); - } - - /** - * - * @return the index of the locale that app is using now - */ - protected int getCurrentLocaleIndex() { - return LocalesUtils.getCurrentLocaleIndex(); - } - -} \ No newline at end of file diff --git a/rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesDetector.java b/rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesDetector.java deleted file mode 100644 index 61e3171..0000000 --- a/rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesDetector.java +++ /dev/null @@ -1,153 +0,0 @@ -package com.ahmedjazzar.rosetta; - -import android.content.Context; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.os.Build; -import android.util.DisplayMetrics; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Locale; - -/** - * This class detects the application available locales inside the resources based on a string id, - * it's not so accurate and expects another methodologies. Next release may hold a better algorithms - * for detecting strings' languages and availability inside apps. - * - * Created by ahmedjazzar on 1/16/16. - */ -class LocalesDetector { - - private final Context mContext; - private Logger mLogger; - private final String TAG = LocalesDetector.class.getName(); - - LocalesDetector(Context context) { - this.mContext = context; - this.mLogger = new Logger(TAG); - } - - /** - * this method takes an experimental string id to see if it's exists in other available - * locales inside the app than default locale. - * NOTE: Even if you have a folder named values-ar it doesn't mean you have any resources - * there - * - * @param stringId experimental string id to discover locales - * @return the discovered locales - */ - HashSet fetchAvailableLocales(int stringId) { - - DisplayMetrics dm = mContext.getResources().getDisplayMetrics(); - Configuration conf = mContext.getResources().getConfiguration(); - Locale originalLocale = conf.locale; - Locale baseLocale = LocalesUtils.getBaseLocale(); - conf.locale = baseLocale; - - ArrayList references = new ArrayList<>(); - references.add(new Resources(mContext.getAssets(), dm, conf).getString(stringId)); - - HashSet result = new HashSet<>(); - result.add(baseLocale); - - for(String loc : mContext.getAssets().getLocales()) { - if(loc.isEmpty()){ - continue; - } - - Locale l; - boolean referencesUpdateLock = false; - - l = Locale.forLanguageTag(loc); - - conf.locale = l; - - //TODO: put it in a method - String tmpString = new Resources(mContext.getAssets(), dm, conf).getString(stringId); - for (String reference: references) { - if(reference.equals(tmpString)){ - // TODO: check its original locale - referencesUpdateLock = true; - break; - } - } - - if(!referencesUpdateLock) { - result.add(l); - references.add(tmpString); - } - } - - conf.locale = originalLocale; // to restore our guy initial state - return result; - } - - /** - * TODO: return the selected one instead - * @return application current locale - */ - Locale getCurrentLocale() { - return mContext.getResources().getConfiguration().locale; - } - - /** - * TODO: what if a user didn't provide a closer email at all? - * TODO: check the closest locale not the first identified - * - * This method should provide a locale that is close to the given one in the parameter, it's - * currently checking the language only if in case the detector detects the string in other - * language. - * - * @param locale mostly the locale that's not detected or provided - * @return the index of the most close locale to the given locale. -1 if not detected - */ - int detectMostClosestLocale(Locale locale) { - - mLogger.debug("Start detecting a close locale to: "); - - int index = 0; - for (Locale loc: LocalesUtils.getLocales()) { - if(loc.getDisplayLanguage().equals(locale.getDisplayLanguage())) { - mLogger.info("The locale: '" + loc + "' has been detected as a closer locale to: '" - + locale + "'"); - return index; - } - index++; - } - - mLogger.debug("No closer locales founded."); - return -1; - } - - /** - * This method validate locales by checking if they are available of they contain wrong letter - * case and adding the valid ones in a clean set. - * @param locales to be checked - * @return valid locales - */ - HashSet validateLocales(HashSet locales) { - - mLogger.debug("Validating given locales.."); - - for (Locale l:LocalesUtils.getPseudoLocales()) { - if(locales.remove(l)) { - mLogger.info("Pseudo locale '" + l + "' has been removed."); - } - } - - HashSet cleanLocales = new HashSet<>(); - Locale[] androidLocales = Locale.getAvailableLocales(); - for (Locale locale: locales) { - if (Arrays.asList(androidLocales).contains(locale)) { - cleanLocales.add(locale); - } else { - mLogger.error("Invalid passed locale: " + locale); - mLogger.warn("Invalid specified locale: '" + locale + "', has been discarded"); - } - } - mLogger.debug("passing validated locales."); - return cleanLocales; - } -} diff --git a/rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesPreferenceManager.java b/rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesPreferenceManager.java deleted file mode 100644 index 7228a3b..0000000 --- a/rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesPreferenceManager.java +++ /dev/null @@ -1,161 +0,0 @@ -package com.ahmedjazzar.rosetta; - -import android.content.Context; -import android.content.SharedPreferences; -import android.preference.PreferenceManager; - -import java.util.Locale; - -/** - * This class is responsible for setting and getting the preferred locale and manage any related - * actions. I think that there's no need for logging here because the utils class already handles - * logs for these actions based on their returned results. - * - * Created by ahmedjazzar on 1/22/16. - */ -class LocalesPreferenceManager { - - private SharedPreferences mSharedPreferences; - private SharedPreferences.Editor mEditor; - - static final int BASE_LOCALE = 1; - private final String BASE_LANGUAGE_KEY = "base_language"; - private final String BASE_COUNTRY_KEY = "base_country"; - - static final int LAUNCH_LOCALE = 2; - private final String LAUNCH_LANGUAGE_KEY = "launch_language"; - private final String LAUNCH_COUNTRY_KEY = "launch_country"; - - static final int USER_PREFERRED_LOCALE = 3; - private final String USER_PREFERRED_LANGUAGE_KEY = "user_preferred_language"; - private final String USER_PREFERRED_COUNTRY_KEY = "user_preferred_country"; - - LocalesPreferenceManager(Context context, Locale firstLaunchLocale, Locale baseLocale) { - - this.mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); - this.mEditor = this.mSharedPreferences.edit(); - - if (!isLocaleExists(BASE_LOCALE)) { - this.setPreferredLocale(BASE_LOCALE, baseLocale); - } - - if (!isLocaleExists(LAUNCH_LOCALE)) { - this.setPreferredLocale(LAUNCH_LOCALE, firstLaunchLocale); - } - - if (!isLocaleExists(USER_PREFERRED_LOCALE)) { - this.setPreferredLocale(USER_PREFERRED_LOCALE, firstLaunchLocale); - } - } - - boolean isLocaleExists(int key) { - - switch (key) { - case BASE_LOCALE: - return mSharedPreferences.contains(this.BASE_LANGUAGE_KEY); - case LAUNCH_LOCALE: - return mSharedPreferences.contains(this.LAUNCH_LANGUAGE_KEY); - case USER_PREFERRED_LOCALE: - return mSharedPreferences.contains(this.USER_PREFERRED_LANGUAGE_KEY); - default: - return false; - } - } - - /** - * Sets user preferred locale - * - * @param locale user desired locale - * @return true if the preference updated - */ - boolean setPreferredLocale(int key, Locale locale) { - return this.setPreferredLocale(key, locale.getLanguage(), locale.getCountry()); - } - - /** - * - * @return preferred locale after concatenating language and country - */ - Locale getPreferredLocale(int key) { - - String languageKey; - String countryKey; - - switch (key) { - case BASE_LOCALE: - languageKey = this.BASE_LANGUAGE_KEY; - countryKey = this.BASE_COUNTRY_KEY; - break; - case LAUNCH_LOCALE: - languageKey = this.LAUNCH_LANGUAGE_KEY; - countryKey = this.LAUNCH_COUNTRY_KEY; - break; - case USER_PREFERRED_LOCALE: - languageKey = this.USER_PREFERRED_LANGUAGE_KEY; - countryKey = this.USER_PREFERRED_COUNTRY_KEY; - break; - default: - return null; - } - - String language = getPreferredLanguage(languageKey); - String country = getPreferredCountry(countryKey); - - if (language == null) { - return null; - } - - return new Locale(language, country); - } - - /** - * Sets user preferred locale by setting a language preference and a country preference since - * there's no supported preferences for locales - * @param language of the locale; ex. en - * @param country of the locale; ex. US - * @return true if the preferences updated - */ - private boolean setPreferredLocale(int key, String language, String country) { - - String languageKey; - String countryKey; - - switch (key) { - case BASE_LOCALE: - languageKey = this.BASE_LANGUAGE_KEY; - countryKey = this.BASE_COUNTRY_KEY; - break; - case LAUNCH_LOCALE: - languageKey = this.LAUNCH_LANGUAGE_KEY; - countryKey = this.LAUNCH_COUNTRY_KEY; - break; - case USER_PREFERRED_LOCALE: - languageKey = this.USER_PREFERRED_LANGUAGE_KEY; - countryKey = this.USER_PREFERRED_COUNTRY_KEY; - break; - default: - return false; - } - - mEditor.putString(languageKey, language); - mEditor.putString(countryKey, country); - - return mEditor.commit(); - } - - /** - * - * @return preferred language - */ - private String getPreferredLanguage(String key) { - return mSharedPreferences.getString(key, null); - } - - /** - * - * @return preferred country - */ - private String getPreferredCountry(String key) { - return mSharedPreferences.getString(key, null); - } -} diff --git a/rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesUtils.java b/rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesUtils.java deleted file mode 100644 index c93c18c..0000000 --- a/rosetta/src/main/java/com/ahmedjazzar/rosetta/LocalesUtils.java +++ /dev/null @@ -1,302 +0,0 @@ -package com.ahmedjazzar.rosetta; - -import android.annotation.SuppressLint; -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.os.Build; -import android.util.DisplayMetrics; - -import androidx.annotation.NonNull; -import androidx.fragment.app.FragmentActivity; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; - -/** - * This class is a helper class that connects all library classes activities together and make it - * easier for every class in the library to use and look at the shared info without a need to - * initialize a new object from the desired class - * - * Created by ahmedjazzar on 1/19/16. - */ -final class LocalesUtils { - - @SuppressLint("StaticFieldLeak") - private static LocalesDetector sDetector; - private static LocalesPreferenceManager sLocalesPreferenceManager; - private static HashSet sLocales; - private static final Locale[] PSEUDO_LOCALES = { - new Locale("en", "XA"), - new Locale("ar", "XB") - }; - private static final String TAG = LocalesDetector.class.getName(); - private static Logger sLogger = new Logger(TAG); - - /** - * - * @param detector just a setter because I don't want to declare any constructors in this class - */ - static void setDetector(@NonNull LocalesDetector detector) { - LocalesUtils.sDetector = detector; - } - - /** - * - * @param localesPreferenceManager just a setter because I don't want to declare any - * constructors in this class - */ - static void setLocalesPreferenceManager( - @NonNull LocalesPreferenceManager localesPreferenceManager) { - - LocalesUtils.sLocalesPreferenceManager = localesPreferenceManager; - } - - /** - * - * @param stringId a string to start discovering sLocales in - * @return a HashSet of discovered sLocales - */ - static HashSet fetchAvailableLocales(int stringId) { - return sDetector.fetchAvailableLocales(stringId); - } - - /** - * - * @param localesSet sLocales user wanna use - */ - static void setSupportedLocales(HashSet localesSet) { - LocalesUtils.sLocales = sDetector.validateLocales(localesSet); - sLogger.debug("Locales have been changed"); - } - - /** - * - * @return a HashSet of the available sLocales discovered in the application - */ - static HashSet getLocales() { - return LocalesUtils.sLocales; - } - - /** - * - * @return a list of locales for displaying on the layout purposes - */ - static ArrayList getLocalesWithDisplayName() { - ArrayList stringLocales = new ArrayList<>(); - - for (Locale loc: LocalesUtils.getLocales()) { - String langDisplay = loc.getDisplayName(loc); - stringLocales.add(langDisplay.substring(0, 1).toUpperCase() + langDisplay.substring(1).toLowerCase()); - } - return stringLocales; - } - - /** - * - * @return the index of the current app locale - */ - static int getCurrentLocaleIndex() { - Locale locale = LocalesUtils.getCurrentLocale(); - int index = -1; - int itr = 0; - - for (Locale l : sLocales) { - if(locale.equals(l)) { - index = itr; - break; - } - itr++; - } - - if (index == -1) { - //TODO: change the index to the most closer available locale - sLogger.warn("Current device locale '" + locale.toString() + - "' does not appear in your given supported locales"); - - index = sDetector.detectMostClosestLocale(locale); - if(index == -1) { - index = 0; - sLogger.warn("Current locale index changed to 0 as the current locale '" + - locale + - "' not supported." - ); - } - } - - return index; - } - - /** - * - * @see Pseudolocalization for - * more information about pseudo localization - * @return pseudo locales list - */ - static List getPseudoLocales() { - return Arrays.asList(LocalesUtils.PSEUDO_LOCALES); - } - - /** - * - * @return the locale at the given index - */ - static Locale getLocaleFromIndex(int index) { - return LocalesUtils.sLocales.toArray(new Locale[LocalesUtils.sLocales.size()])[index]; - } - - /** - * - * @param context - * @param index the selected locale position - * @return true if the application locale changed - */ - static boolean setAppLocale(Context context, int index) { - return setAppLocale(context, getLocaleFromIndex(index)); - } - - /** - * - * @return true if the application locale changed - */ - static boolean setAppLocale(Context context, Locale newLocale) { - - Resources resources = context.getResources(); - DisplayMetrics displayMetrics = resources.getDisplayMetrics(); - Configuration configuration = resources.getConfiguration(); - - Locale oldLocale = new Locale(configuration.locale.getLanguage(), configuration.locale.getCountry()); - configuration.locale = newLocale; - // Sets the layout direction from the Locale - sLogger.debug("Setting the layout direction"); - configuration.setLayoutDirection(newLocale); - resources.updateConfiguration(configuration, displayMetrics); - - if(oldLocale.equals(newLocale)) { - return false; - } - - if (LocalesUtils.updatePreferredLocale(newLocale)) { - sLogger.info("Locale preferences updated to: " + newLocale); - Locale.setDefault(newLocale); - } else { - sLogger.error("Failed to update locale preferences."); - } - - return true; - } - - /** - * - * @return application's base locale - */ - static Locale getBaseLocale() { - return LocalesUtils.sLocalesPreferenceManager.getPreferredLocale(LocalesPreferenceManager.BASE_LOCALE); - } - - /** - * - * @param stringId the target string - * @return a localized string - */ - static String getInSpecificLocale(FragmentActivity activity, Locale locale, int stringId) { - - Configuration conf = activity.getResources().getConfiguration(); - Locale old = conf.locale; - - conf.locale = locale; - DisplayMetrics metrics = new DisplayMetrics(); - activity.getWindowManager().getDefaultDisplay().getMetrics(metrics); - Resources resources = new Resources(activity.getAssets(), metrics, conf); - conf.locale = old; - - return resources.getString(stringId); - } - - /** - * Refreshing the application so no weired results occurred after changing the locale. - */ - static void refreshApplication(Activity activity) { - - Intent app = activity.getBaseContext().getPackageManager() - .getLaunchIntentForPackage(activity.getBaseContext().getPackageName()); - app.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK); - - Intent current = new Intent(activity, activity.getClass()); - sLogger.debug("Refreshing the application: " + - activity.getBaseContext().getPackageName()); - - sLogger.debug("Finishing current activity."); - activity.finish(); - - sLogger.debug("Start the application"); - activity.startActivity(app); - activity.startActivity(current); - - sLogger.debug("Application refreshed"); - } - - /** - * - * @return the first launch locale - */ - static Locale getLaunchLocale() { - - return sLocalesPreferenceManager.getPreferredLocale(LocalesPreferenceManager.LAUNCH_LOCALE); - } - - /** - * Setting the application locale manually - * @param newLocale the desired locale - * @param activity the current activity in order to refresh the app - * - * @return true if the operation succeed, false otherwise - */ - static boolean setLocale(Locale newLocale, Activity activity) { - if (newLocale == null || !getLocales().contains(newLocale)) { - return false; - } - - if (LocalesUtils.setAppLocale(activity.getApplicationContext(), newLocale)) { - LocalesUtils.refreshApplication(activity); - return true; - } - - return false; - } - - /** - * @param context application base context - * @return the current locale - */ - public static Locale getCurrentLocale(Context context) { - Resources resources = context.getResources(); - Configuration configuration = resources.getConfiguration(); - - return new Locale(configuration.locale.getLanguage(), configuration.locale.getCountry()); - } - - /** - * - * @param locale the new preferred locale - * @return true if the preferred locale updated - */ - private static boolean updatePreferredLocale(Locale locale) { - - return LocalesUtils.sLocalesPreferenceManager - .setPreferredLocale(LocalesPreferenceManager.USER_PREFERRED_LOCALE, locale); - } - - /** - * - * @return current application locale - */ - private static Locale getCurrentLocale() { - return sDetector.getCurrentLocale(); - } -} \ No newline at end of file diff --git a/rosetta/src/main/java/com/ahmedjazzar/rosetta/Logger.java b/rosetta/src/main/java/com/ahmedjazzar/rosetta/Logger.java deleted file mode 100644 index ad40a69..0000000 --- a/rosetta/src/main/java/com/ahmedjazzar/rosetta/Logger.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.ahmedjazzar.rosetta; - -import android.util.Log; - -/** - * This class helps logging app events without a need to rewrite the tag name in every time - * Created by ahmedjazzar on 1/16/16. - */ - -class Logger { - - private final String mTag; - - Logger(String tag) { - this.mTag = tag; - this.verbose("Object from " + this.mTag + " has been created."); - } - - void error(String log) { - Log.e(this.mTag, log); - } - - void warn(String log) { - Log.w(this.mTag, log); - } - - void debug(String log) { - Log.d(this.mTag, log); - } - - void info(String log) { - Log.i(this.mTag, log); - } - - void verbose(String log) { - Log.v(this.mTag, log); - } -} diff --git a/rosetta/src/main/res/values/strings.xml b/rosetta/src/main/res/values/strings.xml deleted file mode 100644 index e13140f..0000000 --- a/rosetta/src/main/res/values/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - Language - Ok - Cancel - diff --git a/settings.gradle b/settings.gradle index 4fd643d..5c996dc 100644 --- a/settings.gradle +++ b/settings.gradle @@ -10,4 +10,3 @@ dependencyResolutionManagement { } rootProject.name = "MagiskModuleManager" include ':app' -include ':rosetta'