2013/04/14

Titanium module Android の国際化リソースはどう配置すべきなのか?

前回のTitanium module ios の国際化リソースはどう配置すべきなのか?に続いて、Androidの場合には、どうすべきなのか調べた。

アプローチとしては、
1)モジュールのプロジェクトディレクトリの
/platform/android/res/
に言語リソースを配置する。
2)モジュールのプロジェクトディレクトリの
/assets/
に言語リソースを配置する。
の2通りが考えられる。

まず、1)の方法では、
/platform/android/res/
      values/
            strings.xml
      values-ja/
            strings.xml
のように、言語リソースを配置しておくと、モジュールを読み込んだTiアプリ内の
/res/
以下に配置される。これは、Androidアプリの通常の言語リソースの配置場所なので、プログラムからは、
mContext.getString(R.string.rate_title)
のようにR経由で取得するのがAndroidアプリの通常のやり方だ。
しかし、モジュールの場合、platformディレクトリ内のリソースから、R.javaは、生成されないので、このままでは、コンパイルエラーとなる。
そうした場合、Tiには便利な方法が用意してあって、
mContext.getString(TiRHelper.getApplicationResource("string.rate_message")
の様にTiRHelper#getApplicationResource()を使用して、リソースIDを文字列として与えておいて、Tiアプリ実行時に解決することができる。

これで、無事言語リソースを同梱したモジュールが完成する訳だが、このままだと実用にならない。
i18nを持つTiアプリの場合、ビルド過程で、アプリ側で指定した言語リソースとモジュールの言語リソースが競合してしまうことがある。例えば、

Ti アプリのプロジェクト
/i18n/
    en/
       strings.xml
    ja/
       strings.xml

の様にTi アプリ側の言語リソースがあると、


values/
      strings.xml  <---- アプリケーション由来
      styles.xml
      theme.xml
values-ja/
      strings.xml  <---- アプリケーション由来
の様になってしまう。strings.xmlのマージは行われず、モジュールのstrings.xmlは欠落している。
こうなってくると、上記のTiRHelper#getApplicationResource()に与える引数に対応するものが存在しない状態になってしまう。

解決方法としては、モジュールに同梱するplatformディレクトリ内の言語リソースにあらかじめモジュールを示す接頭辞をつけて置くことだ。これでファイルとしての競合は避けられる。
/platform/android/res/
      values/
            <module name>strings.xml
      values-ja/
            <module name>strings.xml

TiRHelper#getApplicationResource()に与える引数は、xmlで指定された<resources/><string/>のidなので、変更せず

mContext.getString(TiRHelper.

getApplicationResource("string.rate_message")


のままで良い。

言語リソースに限らず、platformディレクトリ内で、モジュール側から呼ばなければならないリソースについては、この方法をとったほうが、競合の問題を避けることができると思われる。

さて、配置問題は解決したけれど、モジュールのユーザが文字列リソースとして、モジュール内で使われているidと競合するidを使う場合はあり得る。その場合は、Ti アプリビルド時にビルドエラーを引き起こすだろう。
[exec] [ERROR] ..(省略)..appirater/build/android/res/values/strings.xml:4: error: Resource entry rate_title is already defined.
[exec] [ERROR] ..(省略)..appirater/build/android/res/values/appiraterstrings.xml:3: Originally defined here.
[exec] [ERROR] Error generating R.java from manifest
[exec] [ERROR] Build Failed.
よくログを読めば、わかることだが、モジュールユーザーにあらかじめモジュール内で使用しているidを知らせておく必要があるかもしれない。

少し長くなったので2)については項を改めて。

1)の方法を取り入れたモジュールの作例として

isis / TiAppiraterAndroid
を作ったので、参考にされたし。






0 件のコメント:

コメントを投稿