Изменить язык во время выполнения?

У нас есть приложение для Android, которое работает как клиент для удаленной программы для ПК. Мы хотели бы добавить функцию, чтобы ПК мог проинструктировать приложение Android изменить свой язык во время выполнения, то есть запустить приложение; связать его с ПК; Спустя некоторое время ПК сообщает, что приложение переключается на, скажем, на испанский или китайский.

У нас уже есть все макеты и строковые ресурсы, настроенные для их соответствующих локалей. Наше приложение является единственным приложением, которое видит пользователь, поэтому не имеет значения, остальное устройство остается на английском языке.

Существует еще один поток на программном программировании в Android, но, похоже, он не приходит к выводу.

Я могу положить.,

Locale locale = new Locale(sTheNewLocale);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
      getBaseContext().getResources().getDisplayMetrics());

., в onCreate() перед setContentView(), но это действительно не помогает, если я хочу изменить локаль после того, как мой экран запущен и работает. Есть ли способ загрузить представление содержимого после того, как активность уже запущена? Таким образом, -, существует какой-либо практический способ надежного изменения локалей на лету или я должен сказать своему боссу, что это невозможно сделать, кроме установки всего устройства в новый локаль перед запуском приложения

Ответ 1

С API 11 вы можете использовать recreate, поэтому можете сделать этот метод в своей деятельности:

private void restartInLocale(Locale locale)
{
    Locale.setDefault(locale);
    Configuration config = new Configuration();
    config.locale = locale;
    Resources resources = getResources();
    resources.updateConfiguration(config, resources.getDisplayMetrics());
    recreate();
}

Ответ 2

Вы можете запустить новый экземпляр своей деятельности и выйти из старого. Вот полный (непроверенный) пример того, как вы можете сохранить любой желаемый язык и перезапустить приложение. Вам просто нужно позвонить restartInLanguage с вашим предпочтительным языком.

public class YourMainActivity extends Activity {
    private static final String APP_SHARED_PREFS = "com.example.test";
    private SharedPreferences settings;
    private Editor editor;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        settings=getSharedPreferences(APP_SHARED_PREFS, Activity.MODE_PRIVATE);
        editor=settings.edit();

        Locale locale = new Locale(settings.getString("lang", "default-lang"));
        Locale.setDefault(locale);
        Configuration config = new Configuration();
        config.locale = locale;
        getResources().updateConfiguration(config, getResources().getDisplayMetrics());

        // your stuff...
    }

    public void restartInLanguage(String lang) {
        editor.putString("lang", lang);
        editor.commit();
        Intent intent = getIntent();
        finish();
        startActivity(intent);
    }

    // ...
}

Ответ 3

Я объединил @weston и @rekire (оба +1) и расширил его для обработки этого прецедента:

  • ActivityA = > ActivityB = > SettingsActivity-changeLocale

После changeLocale в SettingsActivity родительские действия ActivityA и ActivityB также должны быть воссозданы, чтобы отразить новую локаль.

Мое решение: ActivityA и ActivityB наследуют от LocalizedActivity, который проверяет в onResume, если локаль изменилась, и при необходимости запускает recreate()

Таким образом, каждое действие, которое наследует от LocalizedActivity, автоматически обрабатывает изменение локального приложения, специфичное для приложения.

/**
 * An activity that can change the locale (language) of its content.
 *
 * Inspired by http://stackoverflow.com/questions/13181847/change-the-locale-at-runtime
 *
 * Created by k3b on 07.01.2016.
 */
public class LocalizedActivity extends Activity {
    /** if myLocale != Locale.Default : activity must be recreated in on resume */
    private Locale myLocale = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        fixLocale(this);
        super.onCreate(savedInstanceState);
    }

    @Override
    protected void onResume() {
        super.onResume();

        // Locale has changed by other Activity ?
        if ((myLocale != null) && (myLocale.getLanguage() != Locale.getDefault().getLanguage())) {
            myLocale = null;
            recreate();
        }
    }

    /**
     * Set Activity-s locale to SharedPreferences-setting.
     * Must be called before onCreate
     * @param context
     */
    public static void fixLocale(Context context)
    {
        final SharedPreferences prefs = PreferenceManager
                .getDefaultSharedPreferences(context);
        String language = prefs.getString(Global.PREF_KEY_USER_LOCALE, "");
        Locale locale = Global.systemLocale; // in case that setting=="use android-locale"
        if ((language != null) && (!language.isEmpty())) {
            locale = new Locale(language); // overwrite "use android-locale"
        }

        if (locale != null) {
            Locale.setDefault(locale);
            Configuration config = new Configuration();
            config.locale = locale;
            Resources resources = context.getResources();
            resources.updateConfiguration(config, resources.getDisplayMetrics());
            // recreate();

            if (context instanceof LocalizedActivity) {
                ((LocalizedActivity) context).myLocale = locale;
            }
        }
    }
}

Вот источник LocalizedActivity.java и SettingsActivity.java, которые используются в моем Проект Менеджера фотографий

Ответ 4

Решение состоит в том, чтобы использовать setContentView и controlLanguage (вы также можете вызвать этот метод из методов глобального класса) в КАЖДОЙ деятельности в методе onResume после установки вашей локали. Пример:

@Override
    public void onClick(View v) {
        SharedPreferences.Editor editor;
        editor = sharedPref.edit();
        Configuration config = new Configuration(getBaseContext().getResources().getConfiguration());
        String language = "";
        switch (v.getId()){
            case R.id.turkceButton:
                editor.putString("language", "tr");
                language="tr";
                break;
            case R.id.englishButton:
                editor.putString("language", "en");
                language="en";
                break;
        }
        Locale locale = new Locale(language);
        Locale.setDefault(locale);
        config.locale = locale;
        getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
        editor.commit();


@Override
    protected void onResume() {
        super.onResume();
        controlLanguage(getApplicationContext(), getResources());
        setContentView(R.layout.main);
    }

public void controlLanguage(Context context, Resources res){
        SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context);
        String language = sharedPref.getString("language","en");
        Locale locale = new Locale(language);
        Locale.setDefault(locale);
        res.getConfiguration().locale = locale;
        res.updateConfiguration(res.getConfiguration(), res.getDisplayMetrics());
    }

Ответ 5

Представленное решение работает хорошо, но если вы планируете поддерживать дневную/ночную смену тем во время выполнения, вам также необходимо выполнить этот обходной путь.