diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/MainActivity.java b/app/src/main/java/fr/free/nrw/commons/contributions/MainActivity.java index 51b1042a1..460155cd2 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/MainActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/MainActivity.java @@ -1,7 +1,9 @@ package fr.free.nrw.commons.contributions; +import android.app.Activity; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.os.Build.VERSION; import android.os.Build.VERSION_CODES; 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.NotificationController; 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.upload.worker.UploadWorker; import fr.free.nrw.commons.utils.ViewUtilWrapper; @@ -107,6 +110,7 @@ public class MainActivity extends BaseActivity @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + loadLocale(); setContentView(R.layout.main); ButterKnife.bind(this); setSupportActionBar(toolbar); @@ -365,4 +369,14 @@ public class MainActivity extends BaseActivity BOOKMARK, 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); + } } diff --git a/app/src/main/java/fr/free/nrw/commons/settings/Prefs.java b/app/src/main/java/fr/free/nrw/commons/settings/Prefs.java index 1e09bc37e..f1bc5a8a4 100644 --- a/app/src/main/java/fr/free/nrw/commons/settings/Prefs.java +++ b/app/src/main/java/fr/free/nrw/commons/settings/Prefs.java @@ -7,7 +7,8 @@ public class Prefs { public static final String DEFAULT_LICENSE = "defaultLicense"; public static final String UPLOADS_SHOWING = "uploadsshowing"; 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 TELEMETRY_PREFERENCE = "telemetryPref"; diff --git a/app/src/main/java/fr/free/nrw/commons/settings/SettingsFragment.java b/app/src/main/java/fr/free/nrw/commons/settings/SettingsFragment.java index 2efa09fcd..4ab8696e5 100644 --- a/app/src/main/java/fr/free/nrw/commons/settings/SettingsFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/settings/SettingsFragment.java @@ -1,17 +1,19 @@ package fr.free.nrw.commons.settings; +import static android.content.Context.MODE_PRIVATE; + 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.os.Bundle; -import android.text.InputFilter; -import android.text.InputType; -import androidx.preference.EditTextPreference; import android.view.View; import androidx.preference.ListPreference; import androidx.preference.MultiSelectListPreference; import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; -import com.google.android.material.snackbar.Snackbar; import androidx.preference.PreferenceGroupAdapter; import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceViewHolder; @@ -23,17 +25,17 @@ import com.mapbox.mapboxsdk.Mapbox; import com.mapbox.mapboxsdk.maps.TelemetryDefinition; import fr.free.nrw.commons.R; 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.kvstore.JsonKvStore; 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.ViewUtil; import java.util.ArrayList; -import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Locale; +import java.util.Objects; import javax.inject.Inject; import javax.inject.Named; import org.wikipedia.language.AppLanguageLookUpTable; @@ -48,7 +50,9 @@ public class SettingsFragment extends PreferenceFragmentCompat { CommonsLogSender commonsLogSender; private ListPreference themeListPreference; - private ListPreference langListPreference; + private ListPreference descriptionLanguageListPreference; + private ListPreference appUiLanguageListPreference; + private String keyLanguageListPreference; @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { @@ -73,8 +77,16 @@ public class SettingsFragment extends PreferenceFragmentCompat { }); } - langListPreference = findPreference("descriptionDefaultLanguagePref"); - prepareLanguages(); + appUiLanguageListPreference = findPreference("appUiDefaultLanguagePref"); + assert appUiLanguageListPreference != null; + keyLanguageListPreference = appUiLanguageListPreference.getKey(); + prepareAppLanguages(keyLanguageListPreference); + + descriptionLanguageListPreference = findPreference("descriptionDefaultLanguagePref"); + assert descriptionLanguageListPreference != null; + keyLanguageListPreference = descriptionLanguageListPreference.getKey(); + prepareAppLanguages(keyLanguageListPreference); + Preference betaTesterPreference = findPreference("becomeBetaTester"); betaTesterPreference.setOnPreferenceClickListener(preference -> { 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. - * 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 - * to remember later + * to remember later and recall MainActivity to reflect language changes + * @param keyListPreference */ - private void prepareLanguages() { - List languageNamesList; - List languageCodesList; - AppLanguageLookUpTable appLanguageLookUpTable = new AppLanguageLookUpTable(getContext()); + private void prepareAppLanguages(final String keyListPreference) { + final List languageNamesList; + final List languageCodesList; + final AppLanguageLookUpTable appLanguageLookUpTable = new AppLanguageLookUpTable( + Objects.requireNonNull(getContext())); languageNamesList = appLanguageLookUpTable.getLocalizedNames(); languageCodesList = appLanguageLookUpTable.getCodes(); List languageNameWithCodeList = new ArrayList<>(); @@ -157,35 +172,99 @@ public class SettingsFragment extends PreferenceFragmentCompat { languageNameWithCodeList.add(languageNamesList.get(i) + "[" + languageCodesList.get(i) + "]"); } - CharSequence[] languageNames = languageNameWithCodeList.toArray(new CharSequence[0]); - CharSequence[] languageCodes = languageCodesList.toArray(new CharSequence[0]); + final CharSequence[] languageNames = languageNamesList.toArray(new CharSequence[0]); + final CharSequence[] languageCodes = languageCodesList.toArray(new CharSequence[0]); // Add all languages and languages codes to lists preference as pair - langListPreference.setEntries(languageNames); - langListPreference.setEntryValues(languageCodes); // Gets current language code from shared preferences - String languageCode = getCurrentLanguageCode(); - if (languageCode.equals("")) { - // If current language code is empty, means none selected by user yet so use phone local - langListPreference.setValue(Locale.getDefault().getLanguage()); - } else { - // If any language is selected by user previously, use it - langListPreference.setValue(languageCode); + final String languageCode = getCurrentLanguageCode(keyListPreference); + + if (keyListPreference.equals("appUiDefaultLanguagePref")) { + appUiLanguageListPreference.setEntries(languageNames); + appUiLanguageListPreference.setEntryValues(languageCodes); + + 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; } /** diff --git a/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailFragment.java b/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailFragment.java index b67ecb80b..561a8da84 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailFragment.java @@ -39,8 +39,6 @@ import fr.free.nrw.commons.upload.UploadItem; import fr.free.nrw.commons.utils.DialogUtil; import fr.free.nrw.commons.utils.ImageUtils; import fr.free.nrw.commons.utils.ViewUtil; -import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Locale; import javax.inject.Inject; @@ -182,7 +180,7 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements * init the description recycler veiw and caption recyclerview */ 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.setEventListener(this); rvDescriptions.setLayoutManager(new LinearLayoutManager(getContext())); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3ee598016..337c4deba 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -610,6 +610,7 @@ Upload your first media by tapping on the add button. Media Details View category page View item page + App user interface language Removes a caption and description Read more diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 42a90927c..62019ee4e 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -26,6 +26,12 @@ android:summary="@string/use_external_storage_summary" android:title="@string/use_external_storage" /> + +