问题描述
我知道可以使用反射这样的方式迭代给定R java文件的所有字符串(基于 此处 ):
I know it's possible to iterate over all strings of a given R java file, using reflection as such (based on here):
for (Field field : R.string.class.getDeclaredFields()) {
if (Modifier.isStatic(field.getModifiers()) && !Modifier.isPrivate(field.getModifiers()) && field.getType().equals(int.class)) {
try {
int stringResId = field.getInt(null);
Log.d("AppLog", field.getName() + ":" + getResources().getString(stringResId));
} catch (IllegalArgumentException | IllegalAccessException e) {
Log.e("AppLog", e.toString());
}
}
}
这将显示使用当前语言环境的应用程序中使用的所有字符串,包括所有模块在一起(它们合并在一起).
This will show all of the strings used in the app, including of all modules together (they are merged), using the current locale.
是否可以遍历特定模块的所有字符串(或除特定模块以外的所有字符串),还可以使用所有受支持的语言对其进行遍历?
Is it possible to iterate over all strings of specific modules (or all except specific ones), and also iterate over them in all supported languages ?
推荐答案
以下是将我的答案此处与遍历语言环境的代码:
Here is an example combining my answer here with the code to iterate over the locales:
void foo() {
getStringsForResource(R.strings.class, context);
getStringsForResource(com.example.package1.R.strings.class, context);
getStringsForResource(com.example.package2.R.strings.class, context);
getStringsForResource(com.example.package3.R.strings.class, context);
}
void getStringsForResource(Class<?> R_strings, Context initialContext) {
for (String locale : initialContext.getAssets().getLocales()) {
Configuration config = new Configuration();
config.setToDefaults();
config.setLocale(Locale.forLanguageTag(locale));
Context localeSpecificContext = initialContext.createConfigurationContext(config);
getStringsForContext(R_strings, localeSpecificContext);
}
}
void getStringsForContext(Class<?> R_strings, Context context) {
for (Field field : R_strings.getDeclaredFields())
{
if (Modifier.isStatic(field.getModifiers()) && !Modifier.isPrivate(field.getModifiers()) && field.getType().equals(int.class))
{
try
{
int id = field.getInt(null);
String resourceName = field.getName();
String s = context.getString(id);
// Do something with the string here
} catch (IllegalArgumentException e)
{
// ignore
} catch (IllegalAccessException e)
{
// ignore
}
}
}
}
此代码根据资源中存在的语言环境获取语言环境列表(但是,如果您未使用API 21,它将变得比分析它值得的麻烦更多,请参阅 https://developer.android.com/reference/android/content/res/AssetManager.html#getLocales (),您最好使用Locale.getAvailableLocales()
,例如在对问题的评论中;尽管如此,请谨慎对待您的期望,好像您的资源中不存在某种语言一样Android确定的是最接近的匹配项"(对于许多匹配项而言,最可能是en-US
),然后使用反射来获取字符串ID以获取所有字符串.资源类的列表是手动完成的.也可以使用类路径扫描来自动完成此部分,但是在Android中这样做很脆弱;最好只对要扫描的资源类列表进行硬编码.
This code gets the list of locales based on the locales present in the resources (if you are below API 21 though, it will become more trouble than it's worth parsing this, see https://developer.android.com/reference/android/content/res/AssetManager.html#getLocales(), and you may be better off with Locale.getAvailableLocales()
as in a comment on the question; be careful with what you expect out of this, though, as if a language does not exist in your resources you will get whatever Android determines is the "closest match", which will probably be en-US
for a lot of them), and then uses reflection to get the string IDs in order to get all the strings. The list of resource classes is done manually; it is possible to do this part automatically as well using classpath scanning, but doing so in Android is fragile; it is better if you can just hard-code the list of resource classes to scan.
这篇关于如何遍历所有字符串,所有模块和所有语言?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!