Links
UJML Language Reference
ロケール依存の回避

UJMLは、ランタイム時にプログラムを異なるロケールに適応させることを可能にする機能を提供しています。

UJMLは使用する言語に関わらず、同じように動作するプログラムの開発を可能にしています。 これはUJMLがデバイスの現在のロケールを検出するための関数やエンティティ属性値を豊富に提供しているためです。 Visual Elements サンプルコードは、ランタイム時にローカリゼーションを行っている良い例です。 関連項目: Visual Elements サンプルコード

ロケールの取得

プログラムをロケールに適応させるために行う最初の手順は、デバイスのロケールを取得することです。 ロケールを取得するには &_PROPERTY_STRING_LOCALE; エンティティを引数に _getStringProperty() 関数を呼びます。 関連項目: _getStringProperty() functionString デバイス情報エンティティ。 この関数は、RFC1766に準拠したロケール文字列を返します。 

備考: この関数は言語コードを必ず返します。国コード(またはその他のサブコード)の有無はデバイスに依存します。

ローカリゼーションを行うべき対象

アプリケーションの中で、言語・ロケール間で異なる部分はすべてローカリゼーションを行わなければなりません。 これは、最低でも次の部分を含みます:

  1. テキストの値。アプリケーションが表示するテキストのほとんどは、ローカリゼーションの対象にすべきです。
  2. メディアファイル。ロケール依存の要素を持つ画像や音声ファイル。
  3. データ形式。例えば日付、時間、数値、通貨、そして住所の各形式はロケールによって異なります。
ロケールに依存しない設計

次のステップは、アプリケーション設計に関する部分です。 アプリケーションのうち、テキストの値やロケールに依存するその他の部分は全て変数にキャッシュします。 関連項目: 変数。 ロケールに依存する画像や音声ファイルを使用する場合はそれぞれのメディアURLに対して変数を用意します。 関連項目: メディアファイル。 各変数には、アプリケーションの起動時にロケールに適した値を代入します。  

データをフォーマットして表示するUJMLはロケールを考慮すべきです。 データのフォーマットは可能な限り一度に留め、フォーマットした結果を変数にキャッシュします。 キャッシュが不可能な場合はロケールを考慮する関数を作成し、必要に応じて使用します。 関連項目: ユーザー定義関数datetime.ujml サンプルコードにはロケールを考慮したフォーマットを行う関数が含まれています。 

またアプリケーションのモジュール化も重要な要素のひとつです。 アプリケーションの各機能をリンクまたはインクルードされるファイルに分割した、 高度にモジュール化されたアプリケーションではそれぞれのモジュールに対してローカリゼーションを行わなくてはなりません。 関連項目: UJMLアプリケーションの構造UJMLファイルの種類。 アプリケーションがUJMLモジュールをリンクする場合、ロケールごとに異なるサブプログラムを複数することも可能です。 

備考: UJMLアプリケーションのメモリ消費量はパーティションの使用数に応じて増えます。 この理由から、メモリ消費量やデバイスが提供しているメモリ量に対して、モジュール化の度合いをうまくバランスさせなければなりません。 インクルードされたファイルも消費メモリの増加につながりますが、 その増加量はリンクされるモジュールほどではありません。

リンクされたパーティションを使用しローカライズ変数の値を設定する

ローカリゼーションを実現する最も優れた手法の1つに、ロケールの値に応じてローカライズ変数の値を設定し その他の処理を行うリンク可能なパーティションを使用する手法があります。 この手法では、アプリケーションの実行時のロケール文字列を基に特定のロケールパーティションをランタイム時にリンクします。 関連項目: ファイルのリンク。 この手法を実現するにはロケール固有のパーティションファイルをサブディレクトリ(ディレクトリ名にはロケール名を使用する)に格納し、 パーティションをリンクするためのURL をランタイム時にロケール名を使用して生成します。  

親パーティションによって読み込まれたロケール用のパーティションファイルは、ロケールの設定に使用される共有の変数に値を設定します。 関連項目: データのスコープと共有。 ロケール用のパーティションは次に、親ファイルから共有されている関数をコールバックし、メニュー項目などの表示を行います。 関連項目: 関数のスコープと共有。 これらの処理が全て終わると、ロケール用のパーティションはロケールの読み込みが完了したことを示すために、 パーティション間で共有されているステート変数の値を true に設定します。これを受けて親パーティションは以前の処理を継続します。 関連項目: ステートトランジション

代替ロケールの提供

デバイスが特定のロケールをサポートしていない場合の対応方法の1つに、デフォルトのロケールに使用があります。 どのロケールが代替として最適であるかは、アプリケーションによって異なります。 

対応方法にはもう1つ、アプリケーションの起動時にデフォルトの言語を使用して適切なエラーメッセージを表示し、 プログラムの実行を中止する方法があります。このエラーメッセージには問い合わせ先の情報や、 問題の切り分けに適切な情報を表示すべきです(現在のロケールの値、プログラムのバージョン、不具合の種類など)。 プログラムがうまく動作しない場合も、ユーザーに良い印象を残すような配慮をすべきでしょう。

その他のテクニック

ロケールパーティションの読み込みが失敗する場合もあります。 そのようなケースを想定し、プログラムを終了する標準的な手段を提供すべきでしょう。 ロケールの読み込みが正常に成功した場合はプログラムの終了手段を非表示にします。

ロケール非依存が重要な理由

UJMLアプリケーションの動作対象のロケールが一種類であっても、アプリケーションの設計時に ロケール依存性を無くすべきです。ロケールに対する依存性を無くすことは次のメリットをもたらします:

  1. 対象とするユーザーを増やした場合のローカリゼーションが容易。
  2. 一般的に好ましいとされる手法を遵守することができる。

アプリケーション設計は多くの場合、一種類ではなく複数の種類の言語やロケールに対応することを要求されます。 それならばロケール依存を可能な限り減らし、ありとあらゆるロケールで動作するように設計してはいかがでしょうか。

次の例では、ロケールの値に応じて日付をフォーマットしている一例です。日付のフォーマットは日本語、米国英語と デフォルトの3種類が容易されています。 このサンプルコードはdatetime.ujml サンプルコードの一部です。

// Format date based on the locale
if (_streq(mLocale, "ja-JP")) // yyyy/mm/dd
{
    formattedDateTime = _strcat(Date.getYear(),
    "/", Date.getMonth(), "/", Date.getDay(), " ",
    Time.getHour24(), ":", Time.getMinute(), ":",
    Time.getSecond());
}
else if (_streq(mLocale, "en-US")) // mm/dd/yyyy
{
    if (Time.isAM())
    {
        formattedDateTime = "AM";
    }
    else
    {
        formattedDateTime = "PM";
    }
     formattedDateTime = _strcat(Date.getMonth(),
    "/", Date.getDay(), "/", Date.getYear(), " ",
    Time.getHour12(), ":", Time.getMinute(), ":",
    Time.getSecond(), " ", formattedDateTime);
}
else // dd/mm/yyyy
{
     formattedDateTime = _strcat(Date.getDay(),
    "/", Date.getMonth(), "/", Date.getYear(), " ",
    Time.getHour24(), ":", Time.getMinute(), ":",
    Time.getSecond());
}

 

次の例ではデバイスのロケールを取得し、ロケールから言語コードを抜き出しています。 言語コードはロケールパーティションにリンクする際に使用します。 このサンプルコードはvisualelements.ujml サンプルコードの一部です。

// Get the locale and language
mLocale = _getStringProperty(&_PROPERTY_STRING_LOCALE;);
mLanguage = _substring(mLocale , 0, 2);

// Load the locale-setting partition
_link("Locale", _strcat(mLanguage, "/velocale.ujbc"));

 

次の例では、親アプリケーションから共有されている変数に値を設定し、共有されている関数を呼び ロケールに特化した値を設定しています。最後に、共有されているステート変数に値を設定し、 ローカリゼーションの完了を指示します。 このサンプルコードは velocale.ujml サンプルコードの一部です。

// Load default text.
mDefaultLabelText = "Hello World!";
mDefaultMultiLabelText =
    "We hold these truths to be self-evident, that all men are created equal, that they are endowed by their Creator with certain unalienable Rights, that among these are Life, Liberty and the pursuit of Happiness.";

// Load UI labels.
mBackLabel = "Back";
mSettingsLabel = "Settings";

// Load menu items.
addMenuItem("Device");
addMenuItem("Label");
addMenuItem("Multi-Label");
addMenuItem("Box");
addMenuItem("Round-Box");
addMenuItem("X-Oval");
addMenuItem("Line");
addMenuItem("Polyline");
addMenuItem("Polygon 1");
addMenuItem("Polygon 2");
addMenuItem("Image");
addMenuItem("Combined");

// Done.
sLocaleLoaded = true;
Copyright (c) 2000-2005 by UIEvolution, Inc. All rights reserved.
この項目に関するフィードバックをお寄せください。 Send feedback!