Как получить строку из разных локалей в Android?
Поэтому я хочу получить значение String в нескольких локалях независимо от текущей настройки локали устройства / приложения. Как мне это сделать?
В основном мне нужна функция getString(int id, String locale)
скорее, чем getString(int id)
Как я мог это сделать?
Спасибо
9 ответов
ПРИМЕЧАНИЕ Если ваш минимальный 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. Вам придется вызывать конструктор с исходным языком, чтобы вернуть вещи такими, какими они были.
РЕДАКТИРОВАТЬ Немного другой (и несколько более чистый) рецепт для извлечения ресурсов из определенной локали:
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
объект, возвращаемый этим методом. Там нет необходимости сбрасывать что-либо, как только вы получили ресурсы.
Вот комбинированная версия подходов, описанных Тедом Хоппом. Таким образом, код работает для любой версии 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().
Основываясь на приведенных выше ответах, которые удивительны, но немного сложны. попробуйте эту простую функцию:
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");
Счастливый код:)
поместите эту функцию расширения 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
}
object Language {
var locale: Locale? = null
fun getLocaleStringResource(
resourceId: Int,
requestedLocale: Locale? = locale,
): String = with(game.activity) { Configuration(resources.configuration).run {
setLocale(requestedLocale)
createConfigurationContext(this).getText(resourceId).toString()
} }
}
Вы можете использовать эту функцию расширения, чтобы получить языковой стандарт вашей строки
fun Context.getLocaleStringResource(
localeName: String,
resourceId: Int,
): String {
val config = Configuration(resources.configuration)
config.setLocale(Locale(localeName))
return createConfigurationContext(config).getText(resourceId).toString()
}
Затем позвоните:
getLocaleStringResource("en", R.string.app_name)
Я создал эти две функции расширения для Kotlin:
fun Context.getString(locale: Locale, @StringRes resId: Int, vararg formatArgs: Any): String {
var conf: Configuration = resources.configuration
conf = Configuration(conf)
conf.setLocale(locale)
val localizedContext = createConfigurationContext(conf)
return localizedContext.resources.getString(resId, *formatArgs)
}
fun Context.getString(locale: Locale, @StringRes resId: Int): String {
var conf: Configuration = resources.configuration
conf = Configuration(conf)
conf.setLocale(locale)
val localizedContext = createConfigurationContext(conf)
return localizedContext.resources.getString(resId)
}
И вы можете использовать его следующим образом:
getString(Locale("PT"), R.string.some_string, foo, bar)
getString(Locale.FRANCE, R.string.some_other_string)
Можно ли это сделать, например?
String stringFormat = getString(stringId);
String string = String.format(Locale.ENGLISH, stringFormat, 6);
То, что вы ищете, называется классом ResourceBundle. Вот ссылка: