как получить строку из разных языков в Android?

Поэтому я хочу получить значение String для нескольких языков независимо от текущего параметра языкового стандарта устройства / приложения. Как мне это сделать?

В основном мне нужна функция getString(int id, String locale), а не getString(int id)

Как я мог это сделать?

Спасибо


person cheng yang    schedule 28.02.2012    source источник
comment
как вы это реализовали ?? Пожалуйста, ответьте :)   -  person Rakeeb Rajbhandari    schedule 07.01.2014
comment
как принятый ответ   -  person cheng yang    schedule 08.01.2014
comment
ResourceBundle должны относиться к активам ?? или они могут получить доступ к нашей папке res?   -  person Rakeeb Rajbhandari    schedule 08.01.2014
comment
@chengyang, пожалуйста, измените принятый ответ   -  person jonathanrz    schedule 23.07.2015
comment
Вам нужно указать другой язык, чем обычно? Если вы работаете с ресурсами на разных языках, при выполнении getString(R.strings.text) вы получите строку на языке пользователя (или по умолчанию, если язык пользователя не имеет папки)   -  person Lucas Queiroz Ribeiro    schedule 09.12.2016


Ответы (4)


ПРИМЕЧАНИЕ. Если ваш минимальный API 17+, переходите сразу к нижней части этого ответа. В противном случае читайте дальше ...

ПРИМЕЧАНИЕ. Если вы используете App Bundle, убедитесь, что вы отключили разделение языков или установили другой язык динамически. См. https://stackoverflow.com/a/51054393 для этого. Если вы этого не сделаете, он всегда будет использовать запасной вариант.

Если у вас есть разные папки res для разных языков, вы можете сделать что-то вроде этого:

Configuration conf = getResources().getConfiguration();
conf.locale = new Locale("pl");
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
Resources resources = new Resources(getAssets(), metrics, conf);
String str = resources.getString(id);

В качестве альтернативы вы можете просто перезапустить свою деятельность, используя метод, указанный @jyotiprakash.

ПРИМЕЧАНИЕ. Вызов конструктора Resources таким образом меняет что-то внутри Android. Вам нужно будет вызвать конструктор с исходной локалью, чтобы вернуть все как было.

ИЗМЕНИТЬ. Несколько другой (и несколько более понятный) рецепт получения ресурсов из определенного языкового стандарта:

Resources res = getResources();
Configuration conf = res.getConfiguration();
Locale savedLocale = conf.locale;
conf.locale = desiredLocale; // whatever you want here
res.updateConfiguration(conf, null); // second arg null means don't change

// retrieve resources from desired locale
String str = res.getString(id);

// restore original locale
conf.locale = savedLocale;
res.updateConfiguration(conf, null);

Начиная с уровня API 17, вы должны использовать conf.setLocale() вместо прямого задания conf.locale. Это правильно обновит направление компоновки конфигурации, если вы будете переключаться между языковыми стандартами справа налево и слева направо. (Направление компоновки было введено в 17.)

Нет смысла создавать новый объект Configuration (как предлагает @Nulano в комментарии), потому что вызов updateConfiguration изменит исходную конфигурацию, полученную при вызове res.getConfiguration().

Я не решился бы объединить это в метод getString(int id, String locale), если вы собираетесь загружать несколько строковых ресурсов для локали. Изменение локалей (с использованием любого из рецептов) требует от фреймворка большой работы по повторному связыванию всех ресурсов. Гораздо лучше обновить языковой стандарт один раз, получить все необходимое, а затем вернуть языковой стандарт.

ИЗМЕНИТЬ (спасибо @Mygod):

Если ваш минимальный уровень API 17+, есть гораздо лучший подход, как показано в этом ответе в другом потоке. Например, вы можете создать несколько Resource объектов, по одному для каждой нужной вам локали, с помощью:

@NonNull Resources getLocalizedResources(Context context, Locale desiredLocale) {
    Configuration conf = context.getResources().getConfiguration();
    conf = new Configuration(conf);
    conf.setLocale(desiredLocale);
    Context localizedContext = context.createConfigurationContext(conf);
    return localizedContext.getResources();
}

Затем просто извлеките нужные ресурсы из локализованного объекта Resource, возвращенного этим методом. После получения ресурсов ничего сбрасывать не нужно.

person Ted Hopp    schedule 28.02.2012
comment
Разве вам не следует создать новую конфигурацию из той, что была возвращена getResources().getConfiguration()? Согласно GrepCode, он возвращает локальный экземпляр, хранящийся в ресурсах. Изменение поля локали после этого, вероятно, является истинной причиной сбоя Android. Вероятно, вам следует сделать conf = new Configuration(conf); (чтобы клонировать возвращенную конфигурацию) между первой и второй строкой. - person Nulano; 28.01.2015
comment
@Nulano - стоит попробовать, но я не думаю, что это причина того, почему Android запутался (как вы выразились). Посмотрите на исходный код конструктора Resources, и вы увидите, что создание нового объекта Resources, подобного этому, меняет вещи глубоко в активах процесса (очевидно, синглтон). Как только я понял, что все должно быть перезагружено, я не стал выяснять, почему именно. Альтернативный (возможно, более чистый) подход к созданию нового объекта Resources - вызвать resources.updateConfiguration(conf, null) после изменения локали. - person Ted Hopp; 28.01.2015
comment
На уровне API 17+ есть лучший API: stackoverflow.com/a/33629163/2245107 - person Mygod; 09.12.2016
comment
@Mygod - Да, похоже, это правильный путь. Я обновлю свой ответ, чтобы указать на это. Спасибо! - person Ted Hopp; 09.12.2016
comment
Отредактировал ответ с примечанием о том, что пакеты приложений нарушают эту функциональность по умолчанию, поскольку с пакетами пользователь будет получать только один язык. См. stackoverflow.com/a/51054393 о том, как это исправить. - person Carsten Hagemann; 24.02.2020

Вот комбинированная версия подходов, описанных Тедом Хоппом. Таким образом, код работает для любой версии Android:

public static String getLocaleStringResource(Locale requestedLocale, int resourceId, Context context) {
    String result;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { // use latest api
        Configuration config = new Configuration(context.getResources().getConfiguration());
        config.setLocale(requestedLocale);
        result = context.createConfigurationContext(config).getText(resourceId).toString();
    }
    else { // support older android versions
        Resources resources = context.getResources();
        Configuration conf = resources.getConfiguration();
        Locale savedLocale = conf.locale;
        conf.locale = requestedLocale;
        resources.updateConfiguration(conf, null);

        // retrieve resources from desired locale
        result = resources.getString(resourceId);

        // restore original locale
        conf.locale = savedLocale;
        resources.updateConfiguration(conf, null);
    }

    return result;
}

Пример использования:

String englishName = getLocaleStringResource(new Locale("en"), R.string.name, context);

Примечание

Как уже указывалось в исходном ответе, было бы более эффективно заменить несколько вызовов приведенного выше кода одним изменением конфигурации и несколькими вызовами resources.getString ().

person Johnson_145    schedule 23.05.2017

Основываясь на приведенных выше ответах, которые удивительны, но немного сложны. попробуйте эту простую функцию:

public String getResStringLanguage(int id, String lang){
    //Get default locale to back it
    Resources res = getResources();
    Configuration conf = res.getConfiguration();
    Locale savedLocale = conf.locale;
    //Retrieve resources from desired locale
    Configuration confAr = getResources().getConfiguration();
    confAr.locale = new Locale(lang);
    DisplayMetrics metrics = new DisplayMetrics();
    Resources resources = new Resources(getAssets(), metrics, confAr);
    //Get string which you want
    String string = resources.getString(id);
    //Restore default locale
    conf.locale = savedLocale;
    res.updateConfiguration(conf, null);
    //return the string that you want
    return string;
}

Тогда просто назовите его: String str = getResStringLanguage(R.string.any_string, "en");

Счастливый код :)

person Amr Jyniat    schedule 20.06.2020

поместите эту функцию расширения Kotlin в свой код и используйте ее следующим образом:

getLocaleStringResource (Locale.ENGLISH, R.string.app_name)

fun Context.getLocaleStringResource(
requestedLocale: Locale?,
resourceId: Int,
): String {
val result: String
val config =
    Configuration(resources.configuration)
config.setLocale(requestedLocale)
result = createConfigurationContext(config).getText(resourceId).toString()

return result
}
person Usama Saeed US    schedule 30.04.2021