android - Android - 定义默认语言环境
问题描述
我正在开发一个支持德语和意大利语的双语安卓应用程序。
目前我有一个values-it
意大利弦和一个values
德国弦。这很好用,除非您在设备上使用德语和意大利语。在这种情况下,应用程序始终是意大利语,遵循以下计算:
User Setting: de_DE, it_IT
App Resources: default(en), it
Try de_DE -> fail
Try de -> fail
Try it_IT -> fail
Try it -> Success
这可能是因为默认值被隐式处理为values-en
,而在我的情况下它实际上是values-de
.
有没有办法告诉android,我的应用程序默认语言环境de
不是en
?
解决方案
我不知道是否还有其他选择,一种方法是以编程方式进行。根据Ricardo 的出色解决方案,我创建了以下类来更改默认本地:
public class LocaleHelper {
public static Context onAttach(Context context) {
String lang = Locale.getDefault().getLanguage();
if(lang.equals("it") || lang.equals("de"))
return context;
String locale = "de";
return setLocale(context, locale);
}
private 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 {
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;
}
}
您应该在 Activity 类上使用它:
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(LocaleHelper.onAttach(base));
}
如果您使用uk.co.chrisjenx.calligraphy
更改字体,您应该执行以下操作:
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(CalligraphyContextWrapper.wrap(LocaleHelper.onAttach(base)));
}
更新
使用这篇出色的帖子,我设法自动找到了提供的语言。it
因此,de
每当您向资源添加新翻译时,您都无需再进行硬编码或其他提供的翻译。
public class LocaleHelper {
public static Context onAttach(Activity context) {
Set<String> providedLangs = getProvidedLanguages(context);
String lang = Locale.getDefault().getLanguage();
if(providedLangs.contains(lang))
return context;
String locale = "de";
return setLocale(context, locale);
}
private static Set<String> getProvidedLanguages(Activity activity){
DisplayMetrics metrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
Resources r = activity.getResources();
Configuration c = r.getConfiguration();
String[] loc = r.getAssets().getLocales();
Set<String> providedLangs = new HashSet<String>();
for (int i = 0; i < loc.length; i++) {
Timber.e("LOCALE: " + i + ": " + loc[i]);
c.locale = new Locale(loc[i]);
Resources res = new Resources(activity.getAssets(), metrics, c);
String s1 = res.getString(R.string.app_name);
c.locale = new Locale("");
Resources res2 = new Resources(activity.getAssets(), metrics, c);
String s2 = res2.getString(R.string.app_name);
if(!s1.equals(s2)){
if(!providedLangs.contains(loc[i]))
providedLangs.add(loc[i]);
}
}
return providedLangs;
}
private 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 {
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;
}
}
推荐阅读
- ssl - 我正在尝试将 ESP8266 与 HTTPS python 服务器连接,但 ESP 未与服务器连接并给出服务器名称错误的 Bearssl 错误代码
- c# - ASP.NET Core appsettings.json reloadOnChange 不适用于符号链接文件?
- python - 如何让我的机器人发送图像以及如何创建关闭它的命令?
- laravel - 为什么我得到一个整数而不是数组?
- cmake - CMake MacOS 通用二进制构建:链接到某个库仅适用于 x86_64,不适用于 ARM
- angular - 如何在 Angular/Jasmine 中测试 Filereader.onload 回调函数?
- java - 为什么jmeter不能解析哈希字符?
- database - 使用不同的用户和密码创建多个 PostgreSQL 数据库
- r - 将数字的命名向量乘以R中的单个数字
- azure - 几分钟后使用 azure SQL 连接时,ADF 中出现连接关闭错误