管理动态本地化资源 [英] Managing dynamic localisation resources

查看:95
本文介绍了管理动态本地化资源的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

出于这个问题,假设我的应用程序可以帮助用户练习外语.

他们按下按钮以启动文本到语音"简介,该对话的内容为:

<string name="repeat_after_me" translatable="true">Repeat after me</string>

该字符串将以常规方式进行本地化,并根据设备的区域设置从相应的res/values-lang/strings.xml文件中获取该字符串.

引入后,该应用需要说出随机数的任意一种字符串,使用他们当前希望学习的语言/语言.问题就在这里.

假设文字转语音"是从一种简单的方法开始的,例如:

private void startLearning(Locale learningLocale)

以及以下伪代码:

TTS.speak(getString(R.string.repeat_after_me)

其次:

TTS.speak(getRandomLearningString(learningLocale))

位置:

String getRandomLearningString(Locale learningLocale) {
// return a random string here
}

以上是我停留在如何最好地引用xml资源的地方,该资源包含用户正在学习的语言的字符串数组"(以便随机选择一种).

<string-array name="en_EN" translatable="false">
    <item>"Where is the nearest hospital?"</item>
    <item>"What's the time please?"</item>
    <item>"Only if you promise to wear protection and we have a safe word"</item>
</string-array>

假设每种语言都有大量字符串,并且我支持多种语言,那么问题:

我应该如何存储这些字符串以使其在开发中易于管理和读取?我应该如何动态地"从方法中引用它们?

要澄清-主要问题不仅在于我如何解决:

getStringArray(R.array.(variableLocale);

还有如何存储这些字符串数组的方式/位置,以便实现可伸缩和组织化.

我先谢谢你.

编辑-切换语言的实际文本到语音"实现不是问题,我已经解决了.

解决方案

Scalebale解决方案

如果要保持此可伸缩性,则需要将字符串保存为支持随机访问的格式,而无需将所有内容加载到内存中.因此,普通文件(本质上是strings.xml)将无法完成工作.

我建议您检查是否可以使用 SQLite数据库完成所需的操作.

这将导致类似的情况

SELECT text FROM table WHERE locale = yourlocale ORDER BY RANDOM() LIMIT 1

(请参见从sqlite表中选择随机行).


此解决方案需要大量的工作来创建所需的数据库,因此对于已知的小情况,请使用下面的解决方案.

有限的解决方案

如果您知道您不会有太多的条目,我建议您使用纯文本文件(每种语言一个).它们最容易管理.

您可以将它们另存为原始资源或保存在资产文件夹中.两者都相对易于阅读成字符串.然后,您只需要调用String.split("\n")并拥有一个数组,您可以从中随机选择一个数组.

或者,您可以将字符串放入每个本地化的 strings.xml 中的 string-array中,并使用如下资源加载所需的数组:

Resources standardResources = context.getResources();
AssetManager assets = standardResources.getAssets();
DisplayMetrics metrics = standardResources.getDisplayMetrics();
Configuration config = new Configuration(standardResources.getConfiguration());
config.locale = yourLocale;
Resources resources = new Resources(assets, metrics, config);

(请参阅:从资源中加载语言特定的字符串?)

如消息来源评论中所述,这似乎覆盖了context.getResources()返回的资源,也许您此后必须重置为先前的语言环境.

从豆形软糖开始,还有

This string will be localised in the normal way, fetching the string from the appropriate res/values-lang/strings.xml file according to the device Locale.

After the introduction, the app needs to speak any one of a random number of strings, in the language/locale of which they are currently wishing to learn. Herein lies the problem.

Assuming the Text to Speech starts from a simple method such as:

private void startLearning(Locale learningLocale)

And the pseudo code of:

TTS.speak(getString(R.string.repeat_after_me)

followed by:

TTS.speak(getRandomLearningString(learningLocale))

Where:

String getRandomLearningString(Locale learningLocale) {
// return a random string here
}

The above is where I'm stuck on how to best reference the xml resource, that contains the 'string-array' of the language the user is learning (in order to pick one at random).

<string-array name="en_EN" translatable="false">
    <item>"Where is the nearest hospital?"</item>
    <item>"What's the time please?"</item>
    <item>"Only if you promise to wear protection and we have a safe word"</item>
</string-array>

Assuming I have a large number of strings for each language and I support a vast number of languages, the question:

How should I store these strings to keep them manageable and readable in development? How should I 'dynamically' reference them from a method?

To clarify - the main problem is not only how I resolve:

getStringArray(R.array.(variableLocale);

But also how/where I store these string arrays so that the implementation is scalable and organised.

I thank you in advance.

Edit - The actually Text to Speech implementation of switching languages is not a problem, I have that covered.

解决方案

Scalebale Solution

If you want to keep this scaleble, you need to save your strings in a form which supports random access without loading everything into memory. So, a plain file (which strings.xml is essentially) won't do the job.

I recommend you check if you can accomplish what you want with an SQLite Database.

This would result in something like:

SELECT text FROM table WHERE locale = yourlocale ORDER BY RANDOM() LIMIT 1

(see Select random row from an sqlite table).


This solution requires quite a lot of work to create the needed database, so for known small situations, use the solution below.

Limited solution

If you know you won't have too many entries I would recommend to use plain textfiles (one per language). They are easiest to manage.

You can either save them as raw resource or in the assets folder. Both are relatively easy to read into a String. Then you just need to call String.split("\n") and have an array from which you can select one at random.

Alternatively, you can put the strings in a string-array in each localized strings.xml and load the wanted array using resources like this:

Resources standardResources = context.getResources();
AssetManager assets = standardResources.getAssets();
DisplayMetrics metrics = standardResources.getDisplayMetrics();
Configuration config = new Configuration(standardResources.getConfiguration());
config.locale = yourLocale;
Resources resources = new Resources(assets, metrics, config);

(see : Load language specific string from resource?)

As noted in the sources comments this seems to override the resources returned from context.getResources(), maybe you have to reset to the previous locale afterwards.

Starting from Jellybean there is also context.createConfigurationContext, which doesn't seem to have this problem.

In all cases it might be a good idea to cache the array if you need to select entries repeatedly.


Note: This solution doesn't scale well, because the whole array has to be loaded into memory just to select one entry. So large collections might exceed your heap or at least use a lot of memory.

这篇关于管理动态本地化资源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆