как получить строку из разных локалей в Android? - PullRequest
58 голосов
/ 28 февраля 2012

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

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

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

Спасибо

Ответы [ 3 ]

117 голосов
/ 28 февраля 2012

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

Если у вас есть разные папки 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.Вам нужно будет вызвать конструктор с вашей первоначальной локалью, чтобы вернуть вещи такими, какими они были.

EDIT Немного другой (и несколько более чистый) рецепт для извлечения ресурсов из определенной локали::

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, возвращенного этим методом.Не нужно ничего сбрасывать после того, как вы получили ресурсы.

19 голосов
/ 24 мая 2017

Вот комбинированная версия подходов, описанных Тедом Хоппом . Таким образом, код работает для любой версии 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 ().

0 голосов
/ 17 июля 2019

Не будет проще с одной строкой кода?

String.format(Locale("en"), getString(R.string.your_string))

И у вас есть доступ к строкам из ваших переводов без каких-либо изменений конфигурации и других магических вещей.

...