Made locale non dependent on phone OS settings, but choosable on app settings (#4366)

* setLocale added

* localization added

* test complete

* resolved conflicts

* issues resolved

* minor issues fixed

* Made methods concise

* Issues fixed
This commit is contained in:
Ayan Sarkar 2021-05-15 20:00:03 +05:30 committed by GitHub
parent 9562fd1f2c
commit 1408fe5e53
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 139 additions and 40 deletions

View file

@ -1,7 +1,9 @@
package fr.free.nrw.commons.contributions; package fr.free.nrw.commons.contributions;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build.VERSION; import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES; import android.os.Build.VERSION_CODES;
import android.os.Bundle; import android.os.Bundle;
@ -37,6 +39,7 @@ import fr.free.nrw.commons.nearby.fragments.NearbyParentFragment.NearbyParentFra
import fr.free.nrw.commons.notification.NotificationActivity; import fr.free.nrw.commons.notification.NotificationActivity;
import fr.free.nrw.commons.notification.NotificationController; import fr.free.nrw.commons.notification.NotificationController;
import fr.free.nrw.commons.quiz.QuizChecker; import fr.free.nrw.commons.quiz.QuizChecker;
import fr.free.nrw.commons.settings.SettingsFragment;
import fr.free.nrw.commons.theme.BaseActivity; import fr.free.nrw.commons.theme.BaseActivity;
import fr.free.nrw.commons.upload.worker.UploadWorker; import fr.free.nrw.commons.upload.worker.UploadWorker;
import fr.free.nrw.commons.utils.ViewUtilWrapper; import fr.free.nrw.commons.utils.ViewUtilWrapper;
@ -107,6 +110,7 @@ public class MainActivity extends BaseActivity
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
loadLocale();
setContentView(R.layout.main); setContentView(R.layout.main);
ButterKnife.bind(this); ButterKnife.bind(this);
setSupportActionBar(toolbar); setSupportActionBar(toolbar);
@ -365,4 +369,14 @@ public class MainActivity extends BaseActivity
BOOKMARK, BOOKMARK,
MORE MORE
} }
/**
* Load default language in onCreate from SharedPreferences
*/
private void loadLocale(){
final SharedPreferences preferences = getSharedPreferences("Settings", Activity.MODE_PRIVATE);
final String language = preferences.getString("language", "");
final SettingsFragment settingsFragment = new SettingsFragment();
settingsFragment.setLocale(this, language);
}
} }

View file

@ -7,7 +7,8 @@ public class Prefs {
public static final String DEFAULT_LICENSE = "defaultLicense"; public static final String DEFAULT_LICENSE = "defaultLicense";
public static final String UPLOADS_SHOWING = "uploadsshowing"; public static final String UPLOADS_SHOWING = "uploadsshowing";
public static final String MANAGED_EXIF_TAGS = "managed_exif_tags"; public static final String MANAGED_EXIF_TAGS = "managed_exif_tags";
public static final String KEY_LANGUAGE_VALUE = "languageDescription"; public static final String DESCRIPTION_LANGUAGE = "descriptionLanguage";
public static final String APP_UI_LANGUAGE = "appUiLanguage";
public static final String KEY_THEME_VALUE = "appThemePref"; public static final String KEY_THEME_VALUE = "appThemePref";
public static final String TELEMETRY_PREFERENCE = "telemetryPref"; public static final String TELEMETRY_PREFERENCE = "telemetryPref";

View file

@ -1,17 +1,19 @@
package fr.free.nrw.commons.settings; package fr.free.nrw.commons.settings;
import static android.content.Context.MODE_PRIVATE;
import android.Manifest; import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.text.InputFilter;
import android.text.InputType;
import androidx.preference.EditTextPreference;
import android.view.View; import android.view.View;
import androidx.preference.ListPreference; import androidx.preference.ListPreference;
import androidx.preference.MultiSelectListPreference; import androidx.preference.MultiSelectListPreference;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceFragmentCompat;
import com.google.android.material.snackbar.Snackbar;
import androidx.preference.PreferenceGroupAdapter; import androidx.preference.PreferenceGroupAdapter;
import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceScreen;
import androidx.preference.PreferenceViewHolder; import androidx.preference.PreferenceViewHolder;
@ -23,17 +25,17 @@ import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.maps.TelemetryDefinition; import com.mapbox.mapboxsdk.maps.TelemetryDefinition;
import fr.free.nrw.commons.R; import fr.free.nrw.commons.R;
import fr.free.nrw.commons.Utils; import fr.free.nrw.commons.Utils;
import fr.free.nrw.commons.contributions.MainActivity;
import fr.free.nrw.commons.di.ApplicationlessInjection; import fr.free.nrw.commons.di.ApplicationlessInjection;
import fr.free.nrw.commons.kvstore.JsonKvStore; import fr.free.nrw.commons.kvstore.JsonKvStore;
import fr.free.nrw.commons.logging.CommonsLogSender; import fr.free.nrw.commons.logging.CommonsLogSender;
import fr.free.nrw.commons.upload.Language;
import fr.free.nrw.commons.utils.PermissionUtils; import fr.free.nrw.commons.utils.PermissionUtils;
import fr.free.nrw.commons.utils.ViewUtil; import fr.free.nrw.commons.utils.ViewUtil;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Objects;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import org.wikipedia.language.AppLanguageLookUpTable; import org.wikipedia.language.AppLanguageLookUpTable;
@ -48,7 +50,9 @@ public class SettingsFragment extends PreferenceFragmentCompat {
CommonsLogSender commonsLogSender; CommonsLogSender commonsLogSender;
private ListPreference themeListPreference; private ListPreference themeListPreference;
private ListPreference langListPreference; private ListPreference descriptionLanguageListPreference;
private ListPreference appUiLanguageListPreference;
private String keyLanguageListPreference;
@Override @Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
@ -73,8 +77,16 @@ public class SettingsFragment extends PreferenceFragmentCompat {
}); });
} }
langListPreference = findPreference("descriptionDefaultLanguagePref"); appUiLanguageListPreference = findPreference("appUiDefaultLanguagePref");
prepareLanguages(); assert appUiLanguageListPreference != null;
keyLanguageListPreference = appUiLanguageListPreference.getKey();
prepareAppLanguages(keyLanguageListPreference);
descriptionLanguageListPreference = findPreference("descriptionDefaultLanguagePref");
assert descriptionLanguageListPreference != null;
keyLanguageListPreference = descriptionLanguageListPreference.getKey();
prepareAppLanguages(keyLanguageListPreference);
Preference betaTesterPreference = findPreference("becomeBetaTester"); Preference betaTesterPreference = findPreference("becomeBetaTester");
betaTesterPreference.setOnPreferenceClickListener(preference -> { betaTesterPreference.setOnPreferenceClickListener(preference -> {
Utils.handleWebUrl(getActivity(), Uri.parse(getResources().getString(R.string.beta_opt_in_link))); Utils.handleWebUrl(getActivity(), Uri.parse(getResources().getString(R.string.beta_opt_in_link)));
@ -141,14 +153,17 @@ public class SettingsFragment extends PreferenceFragmentCompat {
/** /**
* Prepares language summary and language codes list and adds them to list preference as pairs. * Prepares language summary and language codes list and adds them to list preference as pairs.
* Uses previously saved language if there is any, if not uses phone local as initial language. * Uses previously saved language if there is any, if not uses phone locale as initial language.
* Get ListPreference key and act accordingly for each ListPreference.
* Adds preference changed listener and saves value chosen by user to shared preferences * Adds preference changed listener and saves value chosen by user to shared preferences
* to remember later * to remember later and recall MainActivity to reflect language changes
* @param keyListPreference
*/ */
private void prepareLanguages() { private void prepareAppLanguages(final String keyListPreference) {
List<String> languageNamesList; final List<String> languageNamesList;
List<String> languageCodesList; final List<String> languageCodesList;
AppLanguageLookUpTable appLanguageLookUpTable = new AppLanguageLookUpTable(getContext()); final AppLanguageLookUpTable appLanguageLookUpTable = new AppLanguageLookUpTable(
Objects.requireNonNull(getContext()));
languageNamesList = appLanguageLookUpTable.getLocalizedNames(); languageNamesList = appLanguageLookUpTable.getLocalizedNames();
languageCodesList = appLanguageLookUpTable.getCodes(); languageCodesList = appLanguageLookUpTable.getCodes();
List<String> languageNameWithCodeList = new ArrayList<>(); List<String> languageNameWithCodeList = new ArrayList<>();
@ -157,35 +172,99 @@ public class SettingsFragment extends PreferenceFragmentCompat {
languageNameWithCodeList.add(languageNamesList.get(i) + "[" + languageCodesList.get(i) + "]"); languageNameWithCodeList.add(languageNamesList.get(i) + "[" + languageCodesList.get(i) + "]");
} }
CharSequence[] languageNames = languageNameWithCodeList.toArray(new CharSequence[0]); final CharSequence[] languageNames = languageNamesList.toArray(new CharSequence[0]);
CharSequence[] languageCodes = languageCodesList.toArray(new CharSequence[0]); final CharSequence[] languageCodes = languageCodesList.toArray(new CharSequence[0]);
// Add all languages and languages codes to lists preference as pair // Add all languages and languages codes to lists preference as pair
langListPreference.setEntries(languageNames);
langListPreference.setEntryValues(languageCodes);
// Gets current language code from shared preferences // Gets current language code from shared preferences
String languageCode = getCurrentLanguageCode(); final String languageCode = getCurrentLanguageCode(keyListPreference);
if (languageCode.equals("")) {
// If current language code is empty, means none selected by user yet so use phone local if (keyListPreference.equals("appUiDefaultLanguagePref")) {
langListPreference.setValue(Locale.getDefault().getLanguage()); appUiLanguageListPreference.setEntries(languageNames);
} else { appUiLanguageListPreference.setEntryValues(languageCodes);
// If any language is selected by user previously, use it
langListPreference.setValue(languageCode); assert languageCode != null;
if (languageCode.equals("")) {
// If current language code is empty, means none selected by user yet so use phone local
appUiLanguageListPreference.setValue(Locale.getDefault().getLanguage());
} else {
// If any language is selected by user previously, use it
appUiLanguageListPreference.setValue(languageCode);
}
appUiLanguageListPreference.setOnPreferenceChangeListener((preference, newValue) -> {
final String userSelectedValue = (String) newValue;
setLocale(Objects.requireNonNull(getActivity()), userSelectedValue);
saveLanguageValue(userSelectedValue, keyListPreference);
getActivity().recreate();
final Intent intent = new Intent(getActivity(), MainActivity.class);
startActivity(intent);
return true;
});
} else if (keyListPreference.equals("descriptionDefaultLanguagePref")) {
descriptionLanguageListPreference.setEntries(languageNames);
descriptionLanguageListPreference.setEntryValues(languageCodes);
assert languageCode != null;
if (languageCode.equals("")) {
// If current language code is empty, means none selected by user yet so use phone local
descriptionLanguageListPreference.setValue(Locale.getDefault().getLanguage());
} else {
// If any language is selected by user previously, use it
descriptionLanguageListPreference.setValue(languageCode);
}
descriptionLanguageListPreference.setOnPreferenceChangeListener((preference, newValue) -> {
final String userSelectedValue = (String) newValue;
saveLanguageValue(userSelectedValue, keyListPreference);
return true;
});
} }
langListPreference.setOnPreferenceChangeListener((preference, newValue) -> {
String userSelectedValue = (String) newValue;
saveLanguageValue(userSelectedValue);
return true;
});
} }
private void saveLanguageValue(String userSelectedValue) { /**
defaultKvStore.putString(Prefs.KEY_LANGUAGE_VALUE, userSelectedValue); * Changing the default app language with selected one and save it to SharedPreferences
*/
public void setLocale(final Activity activity, final String userSelectedValue) {
final Locale locale = new Locale(userSelectedValue);
Locale.setDefault(locale);
final Configuration configuration = new Configuration();
configuration.locale = locale;
activity.getBaseContext().getResources().updateConfiguration(configuration,
activity.getBaseContext().getResources().getDisplayMetrics());
final SharedPreferences.Editor editor = activity.getSharedPreferences("Settings", MODE_PRIVATE).edit();
editor.putString("language", userSelectedValue);
editor.apply();
} }
private String getCurrentLanguageCode() { /**
return defaultKvStore.getString(Prefs.KEY_LANGUAGE_VALUE, ""); * Save userselected language in List Preference
* @param userSelectedValue
* @param preferenceKey
*/
private void saveLanguageValue(final String userSelectedValue, final String preferenceKey) {
if (preferenceKey.equals("appUiDefaultLanguagePref")) {
defaultKvStore.putString(Prefs.APP_UI_LANGUAGE, userSelectedValue);
} else if (preferenceKey.equals("descriptionDefaultLanguagePref")) {
defaultKvStore.putString(Prefs.DESCRIPTION_LANGUAGE, userSelectedValue);
}
}
/**
* Gets current language code from shared preferences
* @param preferenceKey
* @return
*/
private String getCurrentLanguageCode(final String preferenceKey) {
if (preferenceKey.equals("appUiDefaultLanguagePref")) {
return defaultKvStore.getString(Prefs.APP_UI_LANGUAGE, "");
}
if (preferenceKey.equals("descriptionDefaultLanguagePref")) {
return defaultKvStore.getString(Prefs.DESCRIPTION_LANGUAGE, "");
}
return null;
} }
/** /**

View file

@ -39,8 +39,6 @@ import fr.free.nrw.commons.upload.UploadItem;
import fr.free.nrw.commons.utils.DialogUtil; import fr.free.nrw.commons.utils.DialogUtil;
import fr.free.nrw.commons.utils.ImageUtils; import fr.free.nrw.commons.utils.ImageUtils;
import fr.free.nrw.commons.utils.ViewUtil; import fr.free.nrw.commons.utils.ViewUtil;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import javax.inject.Inject; import javax.inject.Inject;
@ -182,7 +180,7 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
* init the description recycler veiw and caption recyclerview * init the description recycler veiw and caption recyclerview
*/ */
private void initRecyclerView() { private void initRecyclerView() {
uploadMediaDetailAdapter = new UploadMediaDetailAdapter(defaultKvStore.getString(Prefs.KEY_LANGUAGE_VALUE, "")); uploadMediaDetailAdapter = new UploadMediaDetailAdapter(defaultKvStore.getString(Prefs.DESCRIPTION_LANGUAGE, ""));
uploadMediaDetailAdapter.setCallback(this::showInfoAlert); uploadMediaDetailAdapter.setCallback(this::showInfoAlert);
uploadMediaDetailAdapter.setEventListener(this); uploadMediaDetailAdapter.setEventListener(this);
rvDescriptions.setLayoutManager(new LinearLayoutManager(getContext())); rvDescriptions.setLayoutManager(new LinearLayoutManager(getContext()));

View file

@ -610,6 +610,7 @@ Upload your first media by tapping on the add button.</string>
<string name="media_detail_step_title">Media Details</string> <string name="media_detail_step_title">Media Details</string>
<string name="menu_view_category_page">View category page</string> <string name="menu_view_category_page">View category page</string>
<string name="menu_view_item_page">View item page</string> <string name="menu_view_item_page">View item page</string>
<string name="app_ui_language">App user interface language</string>
<string name="remove">Removes a caption and description</string> <string name="remove">Removes a caption and description</string>
<string name="read_help_link">Read more</string> <string name="read_help_link">Read more</string>

View file

@ -26,6 +26,12 @@
android:summary="@string/use_external_storage_summary" android:summary="@string/use_external_storage_summary"
android:title="@string/use_external_storage" /> android:title="@string/use_external_storage" />
<ListPreference
android:key="appUiDefaultLanguagePref"
app:useSimpleSummaryProvider="true"
app:singleLineTitle="false"
android:title="@string/app_ui_language" />
<ListPreference <ListPreference
android:key="descriptionDefaultLanguagePref" android:key="descriptionDefaultLanguagePref"
app:useSimpleSummaryProvider="true" app:useSimpleSummaryProvider="true"