How to provide i18n service for developer and e...

Many android applications have quite poor i18n-support, and for an understandable reason, as it adds much work for the developer.

From a both intuitive and cultural point of view it would be a good thing if end-users could translate the apps themself, and OTA share the translation, without reinstalling the app itself.

In concept; as wikipedia, some add content easily, others only use what's there.

It's of course important that the service is as easy as possible to use, both for app-developers, and people willing to transcribe.

To keep it simple, this is the solution I'm concidering;

Developer perspective:

  • Developer uses a customized setContentView when open activities/layouts that will seach for thanslations of xml-entries. (below)

  • The customized version is provided as a free downloadable library/class..., turning the i18n feature to more or less a one liner.

User perspective:

  • User downloads app without any translation

  • As app launches, it checks locale running at phone, and will look for a translated xml-file at shared space in SD.

  • If no or old transcribed xml (above), try to download new from internet-service (ansync). This is all done by library above, no need for intents.

Translator perspective:

  • Separate app to provide translations for any app using the i18n service above. (Could be just a webapp), with some form of QA on translators/input.

QUESTION: Now, for this to work efficiently, it has to be AeasyAP for the developer to even bother, and the most fluent solution would be a customized version of setContentView, that simply loads the translated values from external xml, instead of the ones in the apk.

Is this possible at all, and if not, what's your suggested solutions?

(And of course, Happy New Year, feliz ano novo, blwyddyn newydd dda, Gott Nytt År, kontan ane nouvo, szczęśliwego nowego roku ...)

Regards, /T

asked Dec 30 '10 at 10:46
user247245
2,330 12 28


3 Answers

up vote 0 down vote

Yes, it's possible only if someone (probably you or me or others) will rewritesetContentView()- since I see root of a problem only there. Let me explain:

  1. Layout XML's are stored in res/layout which packaged in APK
  2. There's no way to modify APK runtime (at least I've never heard about it)
  3. That means basically you can't redefine on-line/runtime customized/internationalized layout XML's in res/layout
  4. So you'd need a place where to store customized XML's: either in preferences or in SQLite
  5. In both cases one'd need to inflate XML in Activity/Dialog, which can be done throughsetContentView
  6. So in the end - you have to redefine setContentView

How to do that? 2 options:

  • Heroic: completely rewrite setContentView in Android sources
  • Less heroic: create your ownOwnActivityclass which will redefinesetContentView(int id). For instance:OwnActivity.setContentView()looks inside SQLite for known XML id with current locale, if not found it inflates XML from res/layout

EDIT1:

You can override it like:

public class MyActivity extends Activity { @Override public void setContentView(int id) { if(checkPresenceInStorage(id)) //... else super.setContentView(id); } }
answered Dec 30 '10 at 12:38
barmaley
5,872 2 26 53


Thanks for answering, To clarify, resources aren't hardcoded into layout upon compile, right? Since it would ruin apps that do have i18n, so that's the function that should be hooked. The heroic approach should be done by google I guess, and even if so, it would leave an awful lot current phones (2.1) in the cold. The less heroic approach is what I'm aiming at, if only I could debug with "step into" on setContentView I could recreate a class with the requested extended functionality, but I can't right? –  user247245 Dec 30 '10 at 12:55

Right now in Android resources are hardcoded into app... –  barmaley Dec 30 '10 at 13:15

That doesn't make sense, I understand that everything is inside the apk but not hardcoded into layout. Some linking has to be executed at runtime, or else the drawable-ldpi/mdpi/hdpi wouldn't function. –  user247245 Dec 30 '10 at 13:24

Your task during inflating XML into real device not to intercept how it's working, but inflate needed XML (localized one). So in my opinion it should looks like: read correct XML from storage and during setContentView() inflate it rather than those stored in res/layout –  barmaley Dec 30 '10 at 13:50

I new it, Romain Guy came to rescue, even before asking, at groups.google.com/group/android-developers/browse_thread/thread/…. "ViewInflateClass", androidjavadoc.com/m5-rc15/android/view/…. –  user247245 Dec 30 '10 at 16:25
19165708_O0sv.gif
up vote 0 down vote

Regarding the second part of the question, it is possible to use an existing translation service like Launchpad, which operates on .po files for gettext. There is however android2po, which can transform between Android's XML and the gettext .po format.

There are already some Android translations on Launchpad, e.g. ConnectBot, however the service requires a login to be able to contribute. Alternatively, you should look at the available gettext-based web translator suites you can run yourself as well, like Pootle.

Sorry, I am not allowed to post more than one URL. Please google the rest up :(

answered Dec 30 '10 at 14:32
ge0rg
620 6 16


Thanks for the info. However, for UGC, the approach must be much simpler I belive. –  user247245 Dec 30 '10 at 14:42
up vote 0 down vote accepted

layoutinflator.factory is what I was looking for...

answered Dec 30 '10 at 21:18
user247245
2,330 12 28

转载于:https://my.oschina.net/zhuzihasablog/blog/145666

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
In Android, Looper and Handler work together to execute tasks on a separate thread, also known as a background thread. A Looper is an object that allows a thread to handle incoming messages or tasks. It runs in an infinite loop, waiting for new tasks to arrive. When a new task arrives, the Looper dispatches it to the appropriate Handler for processing. A Handler is an object that receives tasks from the Looper and processes them. It is associated with a specific thread, and when a task is sent to a Handler, it is added to a message queue. The Handler processes the tasks one by one, in the order they were added to the queue. Together, the Looper and Handler allow us to perform time-consuming tasks on a separate thread, without blocking the main thread. The main thread is responsible for handling UI events, and if it is blocked by a long-running task, the user interface will become unresponsive. By using Looper and Handler, we can keep the main thread free to handle UI events while executing time-consuming tasks on a separate thread. Here is an example of how Looper and Handler work together: ``` public class MyThread extends Thread { public Handler handler; @Override public void run() { Looper.prepare(); handler = new Handler() { @Override public void handleMessage(Message msg) { // Process the task here } }; Looper.loop(); } } ``` In this example, we create a new thread called `MyThread`. In the `run()` method, we create a new `Looper` and call `prepare()` to initialize it. We then create a new `Handler` and associate it with the thread. Finally, we call `Looper.loop()` to start the infinite loop and wait for tasks to arrive. To send a task to `MyThread`, we can use the `handler` object: ``` MyThread myThread = new MyThread(); myThread.start(); Message msg = myThread.handler.obtainMessage(); msg.obj = "Hello"; myThread.handler.sendMessage(msg); ``` In this example, we create a new message and set its `obj` property to `"Hello"`. We then send the message to `MyThread` using its `handler` object. When the message arrives, the `handleMessage()` method of the `Handler` will be called, and we can process the task there.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值