Start fixes for last PR.
parent
1ee0aa31ab
commit
5d2a08d818
@ -1,15 +0,0 @@
|
|||||||
# LEGALS
|
|
||||||
|
|
||||||
## Fox's Magisk Module Manager
|
|
||||||
- Maintained: Yes
|
|
||||||
- Maintainers
|
|
||||||
- [Fox2Code](https://github.com/Fox2Code)
|
|
||||||
- [androidacybot](https://github.com/androidacybot)
|
|
||||||
- License: [<svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-law mr-2"><path fill-rule="evenodd" d="M8.75.75a.75.75 0 00-1.5 0V2h-.984c-.305 0-.604.08-.869.23l-1.288.737A.25.25 0 013.984 3H1.75a.75.75 0 000 1.5h.428L.066 9.192a.75.75 0 00.154.838l.53-.53-.53.53v.001l.002.002.002.002.006.006.016.015.045.04a3.514 3.514 0 00.686.45A4.492 4.492 0 003 11c.88 0 1.556-.22 2.023-.454a3.515 3.515 0 00.686-.45l.045-.04.016-.015.006-.006.002-.002.001-.002L5.25 9.5l.53.53a.75.75 0 00.154-.838L3.822 4.5h.162c.305 0 .604-.08.869-.23l1.289-.737a.25.25 0 01.124-.033h.984V13h-2.5a.75.75 0 000 1.5h6.5a.75.75 0 000-1.5h-2.5V3.5h.984a.25.25 0 01.124.033l1.29.736c.264.152.563.231.868.231h.162l-2.112 4.692a.75.75 0 00.154.838l.53-.53-.53.53v.001l.002.002.002.002.006.006.016.015.045.04a3.517 3.517 0 00.686.45A4.492 4.492 0 0013 11c.88 0 1.556-.22 2.023-.454a3.512 3.512 0 00.686-.45l.045-.04.01-.01.006-.005.006-.006.002-.002.001-.002-.529-.531.53.53a.75.75 0 00.154-.838L13.823 4.5h.427a.75.75 0 000-1.5h-2.234a.25.25 0 01-.124-.033l-1.29-.736A1.75 1.75 0 009.735 2H8.75V.75zM1.695 9.227c.285.135.718.273 1.305.273s1.02-.138 1.305-.273L3 6.327l-1.305 2.9zm10 0c.285.135.718.273 1.305.273s1.02-.138 1.305-.273L13 6.327l-1.305 2.9z"></path></svg> 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: [<svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-law mr-2"><path fill-rule="evenodd" d="M8.75.75a.75.75 0 00-1.5 0V2h-.984c-.305 0-.604.08-.869.23l-1.288.737A.25.25 0 013.984 3H1.75a.75.75 0 000 1.5h.428L.066 9.192a.75.75 0 00.154.838l.53-.53-.53.53v.001l.002.002.002.002.006.006.016.015.045.04a3.514 3.514 0 00.686.45A4.492 4.492 0 003 11c.88 0 1.556-.22 2.023-.454a3.515 3.515 0 00.686-.45l.045-.04.016-.015.006-.006.002-.002.001-.002L5.25 9.5l.53.53a.75.75 0 00.154-.838L3.822 4.5h.162c.305 0 .604-.08.869-.23l1.289-.737a.25.25 0 01.124-.033h.984V13h-2.5a.75.75 0 000 1.5h6.5a.75.75 0 000-1.5h-2.5V3.5h.984a.25.25 0 01.124.033l1.29.736c.264.152.563.231.868.231h.162l-2.112 4.692a.75.75 0 00.154.838l.53-.53-.53.53v.001l.002.002.002.002.006.006.016.015.045.04a3.517 3.517 0 00.686.45A4.492 4.492 0 0013 11c.88 0 1.556-.22 2.023-.454a3.512 3.512 0 00.686-.45l.045-.04.01-.01.006-.005.006-.006.002-.002.001-.002-.529-.531.53.53a.75.75 0 00.154-.838L13.823 4.5h.427a.75.75 0 000-1.5h-2.234a.25.25 0 01-.124-.033l-1.29-.736A1.75 1.75 0 009.735 2H8.75V.75zM1.695 9.227c.285.135.718.273 1.305.273s1.02-.138 1.305-.273L3 6.327l-1.305 2.9zm10 0c.285.135.718.273 1.305.273s1.02-.138 1.305-.273L13 6.327l-1.305 2.9z"></path></svg> MIT license](https://github.com/iamjazzar/rosetta/blob/master/LICENSE)
|
|
@ -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/
|
|
@ -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'
|
|
||||||
}
|
|
@ -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";
|
|
||||||
}
|
|
@ -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
|
|
@ -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 *;
|
|
||||||
#}
|
|
@ -1,5 +0,0 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
package="com.ahmedjazzar.rosetta">
|
|
||||||
|
|
||||||
<application android:supportsRtl="true" />
|
|
||||||
</manifest>
|
|
@ -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<Locale> getLocales() {
|
|
||||||
return LocalesUtils.getLocales();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the app locales from a string Set
|
|
||||||
* @param sLocales supported locales in a String form
|
|
||||||
*/
|
|
||||||
public void setSupportedStringLocales(HashSet<String> sLocales) {
|
|
||||||
|
|
||||||
HashSet<Locale> 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<Locale> 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<Locale> 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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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<String> 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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<Locale> 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<String> references = new ArrayList<>();
|
|
||||||
references.add(new Resources(mContext.getAssets(), dm, conf).getString(stringId));
|
|
||||||
|
|
||||||
HashSet<Locale> 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<Locale> validateLocales(HashSet<Locale> locales) {
|
|
||||||
|
|
||||||
mLogger.debug("Validating given locales..");
|
|
||||||
|
|
||||||
for (Locale l:LocalesUtils.getPseudoLocales()) {
|
|
||||||
if(locales.remove(l)) {
|
|
||||||
mLogger.info("Pseudo locale '" + l + "' has been removed.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HashSet<Locale> 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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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<Locale> 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<Locale> fetchAvailableLocales(int stringId) {
|
|
||||||
return sDetector.fetchAvailableLocales(stringId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param localesSet sLocales user wanna use
|
|
||||||
*/
|
|
||||||
static void setSupportedLocales(HashSet<Locale> 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<Locale> getLocales() {
|
|
||||||
return LocalesUtils.sLocales;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @return a list of locales for displaying on the layout purposes
|
|
||||||
*/
|
|
||||||
static ArrayList<String> getLocalesWithDisplayName() {
|
|
||||||
ArrayList<String> 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 <a href="http://en.wikipedia.org/wiki/Pseudolocalization">Pseudolocalization</a> for
|
|
||||||
* more information about pseudo localization
|
|
||||||
* @return pseudo locales list
|
|
||||||
*/
|
|
||||||
static List<Locale> 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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<string name="language">Language</string>
|
|
||||||
<string name="ok">Ok</string>
|
|
||||||
<string name="cancel">Cancel</string>
|
|
||||||
</resources>
|
|
Loading…
Reference in New Issue