এই সমস্যার সমাধান করার জন্য বর্তমানের কোনও উত্তর সম্পূর্ণ না হওয়ায় আমি একটি সম্পূর্ণ সমাধানের জন্য নির্দেশ দেওয়ার চেষ্টা করি। কিছু অনুপস্থিত বা আরও ভাল কিছু করা যেতে পারে দয়া করে মন্তব্য করুন।
সাধারণ জ্ঞাতব্য
প্রথমত, কিছু লাইব্রেরি রয়েছে যা সমস্যার সমাধান করতে চায় তবে সেগুলি পুরানো বলে মনে হয় বা কিছু বৈশিষ্ট্য অনুপস্থিত:
আরও আমি মনে করি গ্রন্থাগারটি লেখার সমস্যাটি সমাধান করার জন্য ভাল / সহজ উপায় নাও হতে পারে কারণ খুব বেশি কিছু করার নেই এবং যা করতে হবে তা সম্পূর্ণরূপে ডিউপলড কিছু ব্যবহার না করে বিদ্যমান কোড পরিবর্তন করা। অতএব আমি নিম্নলিখিত নির্দেশাবলী রচনা করেছি যা সম্পূর্ণ হওয়া উচিত।
আমার সমাধানটি মূলত https://github.com/gunhansancar/ChangeLanguageExample উপর ভিত্তি করে (যেমন ইতিমধ্যে লোকালহোস্ট দ্বারা যুক্ত )। এটিতে আমি ওরিয়েন্টেট করতে পেলাম সেরা কোড। কিছু মন্তব্য:
- প্রয়োজনীয় হিসাবে এটি অ্যান্ড্রয়েড এন (এবং উপরের) এবং নীচে লোকেল পরিবর্তন করতে বিভিন্ন বাস্তবায়ন সরবরাহ করে
updateViews()
লোকাল পরিবর্তনের পরে সমস্ত স্ট্রিং ম্যানুয়ালি আপডেট করার জন্য এটি প্রতিটি ক্রিয়াকলাপের একটি পদ্ধতি ব্যবহার করে (সাধারণ ব্যবহার করে getString(id)
) যা নীচে দেখানো পদ্ধতির ক্ষেত্রে প্রয়োজনীয় নয়
- এটি কেবলমাত্র ভাষাগুলি সমর্থন করে এবং সম্পূর্ণ লোকেলগুলি নয় (এতে অঞ্চল (দেশ) এবং বৈকল্পিক কোডগুলিও অন্তর্ভুক্ত রয়েছে)
আমি এটিকে কিছুটা পরিবর্তন করেছি, অংশটি ছড়িয়ে দিয়েছি যা নির্বাচিত লোকেলটি অব্যাহত রেখেছে (যেহেতু নীচে প্রস্তাবিত হিসাবে আলাদাভাবে কেউ এটি করতে চাইবে)।
সমাধান
সমাধানটি নিম্নলিখিত দুটি পদক্ষেপ নিয়ে গঠিত:
- অ্যাপ্লিকেশন দ্বারা ব্যবহৃত লোকেল স্থায়ীভাবে পরিবর্তন করুন
- পুনরায় আরম্ভ না করেই অ্যাপটিকে কাস্টম লোকেল সেটটি ব্যবহার করুন
পদক্ষেপ 1: লোকেল পরিবর্তন করুন
গুনহানসানার লোকালহেল্পারেরLocaleHelper
ভিত্তিতে ক্লাসটি ব্যবহার করুন :
- একটি যোগ করুন
ListPreference
একটি PreferenceFragment
প্রাপ্তি সাধ্য ভাষাসমূহ সঙ্গে (যখন ভাষায় পরে যোগ করা হবে তা বজায় রাখা হবে)
import android.annotation.TargetApi;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.preference.PreferenceManager;
import java.util.Locale;
import mypackage.SettingsFragment;
/**
* Manages setting of the app's locale.
*/
public class LocaleHelper {
public static Context onAttach(Context context) {
String locale = getPersistedLocale(context);
return setLocale(context, locale);
}
public static String getPersistedLocale(Context context) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
return preferences.getString(SettingsFragment.KEY_PREF_LANGUAGE, "");
}
/**
* Set the app's locale to the one specified by the given String.
*
* @param context
* @param localeSpec a locale specification as used for Android resources (NOTE: does not
* support country and variant codes so far); the special string "system" sets
* the locale to the locale specified in system settings
* @return
*/
public static Context setLocale(Context context, String localeSpec) {
Locale locale;
if (localeSpec.equals("system")) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
locale = Resources.getSystem().getConfiguration().getLocales().get(0);
} else {
//noinspection deprecation
locale = Resources.getSystem().getConfiguration().locale;
}
} else {
locale = new Locale(localeSpec);
}
Locale.setDefault(locale);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return updateResources(context, locale);
} else {
return updateResourcesLegacy(context, locale);
}
}
@TargetApi(Build.VERSION_CODES.N)
private static Context updateResources(Context context, Locale locale) {
Configuration configuration = context.getResources().getConfiguration();
configuration.setLocale(locale);
configuration.setLayoutDirection(locale);
return context.createConfigurationContext(configuration);
}
@SuppressWarnings("deprecation")
private static Context updateResourcesLegacy(Context context, Locale locale) {
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration();
configuration.locale = locale;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
configuration.setLayoutDirection(locale);
}
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
return context;
}
}
SettingsFragment
নিম্নলিখিতগুলির মতো একটি তৈরি করুন :
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import mypackage.LocaleHelper;
import mypackage.R;
/**
* Fragment containing the app's main settings.
*/
public class SettingsFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
public static final String KEY_PREF_LANGUAGE = "pref_key_language";
public SettingsFragment() {
// Required empty public constructor
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_settings, container, false);
return view;
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
switch (key) {
case KEY_PREF_LANGUAGE:
LocaleHelper.setLocale(getContext(), PreferenceManager.getDefaultSharedPreferences(getContext()).getString(key, ""));
getActivity().recreate(); // necessary here because this Activity is currently running and thus a recreate() in onResume() would be too late
break;
}
}
@Override
public void onResume() {
super.onResume();
// documentation requires that a reference to the listener is kept as long as it may be called, which is the case as it can only be called from this Fragment
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
@Override
public void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}
}
locales.xml
নিম্নলিখিত উপায়ে উপলভ্য অনুবাদগুলির সাথে সমস্ত লোকেলের তালিকা তৈরি করার একটি সংস্থান তৈরি করুন ( স্থানীয় কোডের তালিকা ):
<!-- Lists available locales used for setting the locale manually.
For now only language codes (locale codes without country and variant) are supported.
Has to be in sync with "settings_language_values" in strings.xml (the entries must correspond).
-->
<resources>
<string name="system_locale" translatable="false">system</string>
<string name="default_locale" translatable="false"></string>
<string-array name="locales">
<item>@string/system_locale</item> <!-- system setting -->
<item>@string/default_locale</item> <!-- default locale -->
<item>de</item>
</string-array>
</resources>
PreferenceScreen
ব্যবহারকারীকে উপলভ্য ভাষাগুলি নির্বাচন করতে আপনার নীচে আপনি নিম্নলিখিত বিভাগটি ব্যবহার করতে পারেন:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="@string/preferences_category_general">
<ListPreference
android:key="pref_key_language"
android:title="@string/preferences_language"
android:dialogTitle="@string/preferences_language"
android:entries="@array/settings_language_values"
android:entryValues="@array/locales"
android:defaultValue="@string/system_locale"
android:summary="%s">
</ListPreference>
</PreferenceCategory>
</PreferenceScreen>
যা নিম্নলিখিত স্ট্রিংগুলি থেকে ব্যবহার করে strings.xml
:
<string name="preferences_category_general">General</string>
<string name="preferences_language">Language</string>
<!-- NOTE: Has to correspond to array "locales" in locales.xml (elements in same orderwith) -->
<string-array name="settings_language_values">
<item>Default (System setting)</item>
<item>English</item>
<item>German</item>
</string-array>
পদক্ষেপ 2: অ্যাপ্লিকেশনটিকে কাস্টম লোকেলটি ব্যবহার করুন
কাস্টম লোকেল সেট ব্যবহার করতে এখন প্রতিটি ক্রিয়াকলাপ সেটআপ করুন। এটি সম্পাদন করার সহজতম উপায় হ'ল নিম্নলিখিত কোড (যেখানে গুরুত্বপূর্ণ কোডটি রয়েছে attachBaseContext(Context base)
এবং onResume()
) সহ সমস্ত ক্রিয়াকলাপের জন্য একটি সাধারণ বেস শ্রেণি রাখা :
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import mypackage.LocaleHelper;
import mypackage.R;
/**
* {@link AppCompatActivity} with main menu in the action bar. Automatically recreates
* the activity when the locale has changed.
*/
public class MenuAppCompatActivity extends AppCompatActivity {
private String initialLocale;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initialLocale = LocaleHelper.getPersistedLocale(this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_settings:
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(LocaleHelper.onAttach(base));
}
@Override
protected void onResume() {
super.onResume();
if (initialLocale != null && !initialLocale.equals(LocaleHelper.getPersistedLocale(this))) {
recreate();
}
}
}
এটা কি করে
attachBaseContext(Context base)
পূর্বে অব্যাহত লোকেলটি ব্যবহার করতে ওভাররাইড করুনLocaleHelper
- লোকেলটির একটি পরিবর্তন সনাক্ত করুন এবং এর স্ট্রিংগুলি আপডেট করতে ক্রিয়াকলাপটি পুনরায় তৈরি করুন
এই সমাধান সম্পর্কে নোট
ক্রিয়াকলাপ পুনরুদ্ধার করা অ্যাকশনবারের শিরোনাম আপডেট করে না (যেমনটি ইতিমধ্যে এখানে পর্যবেক্ষণ করা হয়েছে: https://github.com/gunhansancar/ChangeLanguageExample/issues/1 )।
- এই কেবল একটি থাকার অর্জন করা যেতে পারে
setTitle(R.string.mytitle)
যে onCreate()
প্রতিটি কার্যকলাপ পদ্ধতি।
এটি ব্যবহারকারীকে সিস্টেম ডিফল্ট লোকেল, পাশাপাশি অ্যাপ্লিকেশনটির ডিফল্ট লোকেল (এই ক্ষেত্রে "ইংরাজী" নাম দেওয়া যেতে পারে) বেছে নিতে দেয়।
কেবলমাত্র ভাষা কোডগুলি, কোনও অঞ্চল (দেশ) এবং বৈকল্পিক কোডগুলি (যেমন fr-rCA
) এখন পর্যন্ত সমর্থিত নয়। পূর্ণ স্থানীয় স্পেসিফিকেশন সমর্থন করার জন্য, অ্যান্ড্রয়েড-ল্যাঙ্গুয়েজ লাইব্রেরিতে অনুরূপ পার্সার ব্যবহার করা যেতে পারে (যা অঞ্চলটিকে সমর্থন করে তবে কোনও ভেরিয়েন্ট কোড নেই)।
- যদি কেউ ভাল পার্সার খুঁজে পান বা লিখেছেন তবে একটি মন্তব্য যুক্ত করুন যাতে আমি এটি সমাধানে অন্তর্ভুক্ত করতে পারি।