13 Oracle JETアプリケーションの国際化およびローカライズ
Oracle JETアプリケーションの国際化およびローカライズについて
国際化(I18N)とは、簡単でコスト効率よく、とりわけソフトウェアの技術的な変更をせずに、ソフトウェアを様々な言語および地域に適合できるようにするためのソフトウェア設計プロセスのことです。ローカリゼーション(L10N)とは、実行時にロケール固有の言語および構成を使用することです。
オラクル社では、業界標準のI18NおよびL10N (World Wide Web Consortium (W3C)勧告、Unicode技術、インターネット技術タスク・フォース(IETF)仕様など)を採用して、世界の様々な言語、記述システムおよび地域規則をサポートしています。言語およびロケールは標準言語タグで識別され、BCP 47の定義に従って処理されます。Oracle JETには、次の表に示す言語に対するOracle National Language Support (NLS)の翻訳サポートが含まれています。
Language | 言語タグ |
---|---|
アラビア語 |
|
ポルトガル語(ブラジル) |
|
ブルガリア語 | bg-BG |
フランス語(カナダ) |
|
中国語(簡体字) |
|
中国語(繁体字) |
|
クロアチア語 |
|
チェコ語 | cs |
デンマーク語 |
|
オランダ語 |
|
エストニア語 |
|
フィンランド語 |
|
フランス語 |
|
ドイツ語 |
|
ギリシャ語 |
|
ヘブライ語 |
|
ハンガリー語 |
|
アイスランド語 | is |
イタリア語 |
|
日本語 |
|
韓国語 |
|
セルビア語(ラテン) | sr-Latn |
ラトビア語 |
|
リトアニア語 |
|
マレー語 | ms-MY |
ノルウェー語 |
|
ポーランド語 |
|
ポルトガル語 |
|
ルーマニア語 |
|
ロシア語 |
|
セルビア語 | sr |
スロバキア語 |
|
スロベニア語 | sl |
スペイン語 |
|
スウェーデン語 |
|
タイ語 |
|
トルコ語 |
|
ウクライナ語 | uk-UA |
ベトナム語 | vi |
Oracle JETの翻訳はリソース・バンドルに格納されます。独自の翻訳をバンドルに追加できます。詳細は、「Oracle JETへの翻訳バンドルの追加」を参照してください。
Oracle JETには、196以上のロケールの書式設定サポートも含まれています。Oracle JETのロケール要素はUnicode Common Locale Data Repository (CLDR)に基づき、ロケール・バンドルに格納されます。Unicode CLDRの詳細は、http://cldr.unicode.orgを参照してください。サポートされているロケール・バンドルは、Oracle JET配布の次の場所にあります。
js/libs/oj/17.1.0/resources/nls
ページで使用するロケールを決定するのはアプリケーションの役目です。一般的に、アプリケーションでは、ブラウザのロケール設定からサーバー側で計算したり、アイデンティティ・ストアに格納されているユーザー・ロケール・プリファレンスおよびアプリケーションでサポートされている翻訳言語を使用して、ロケールを決定します。
ロケールが決定したら、ロケール依存操作(リソース・バンドルのロード、日時データの書式設定など)のために、アプリケーションでこのロケールをOracle JETに通知する必要があります。Oracle JETでは、ロケール依存操作用のロケールを次の順序で決定します:
-
RequireJS構成のojL10nプラグインでのロケール指定。
-
html
タグのlang
属性。 -
navigator.language
ブラウザ・プロパティ。
アプリケーションでユーザーがロケールを動的に変更するオプションが提供されない場合は、lang
属性をHTML
タグに設定することをお薦めします。これを設定することで、Oracle JETのロケールを設定するのに加えて、すべてのHTML要素のロケールも設定されるためです。Oracle JETでは、現在の言語の翻訳バンドル、および設定されているロケールのロケール・バンドルが自動的にロードされます。ロケールを設定しない場合、Oracle JETではブラウザ・プロパティにデフォルト設定します。ただし、アプリケーションでロケールを動的に変更するオプションが提供されている場合は、アプリケーションでRequireJSが使用されていれば、ojL10nプラグインでロケール仕様を設定することをお薦めします。Oracle JETは、アプリケーションの初期化時にロケールおよびリソース・バンドルを自動的にロードします。
Oracle JETアプリケーションのモジュール・バンドルとしてRequireJSではなくWebpackを使用する場合は、サポートするロケールごとに1つのコード・バンドルを生成し、サポートするロケールの異なるURLに各バンドルをデプロイすることをお薦めします。たとえば、アプリケーションURLがhttps://www.oracle.com/index.htmlで、フランス語とスペイン語のロケールをサポートする場合は、これらのロケールのバンドルをそれぞれhttps://www.oracle.com/fr/index.htmlおよびhttps://www.oracle.com/es/index.htmlにデプロイします。
最後に、Oracle JETには、ロケール・バンドルを使用するバリデータおよびコンバータが含まれています。ページ上のロケールを変更する場合、Oracle JETコンポーネントには新しいロケールでコンテンツを表示するためのサポートが組み込まれています。Oracle JETのバリデータおよびコンバータの詳細は、「入力の検証および変換」を参照してください。
Oracle JETアプリケーションの国際化およびローカライズ
Oracle JETの国際化およびローカリゼーションの組込みサポートを使用するようにアプリケーションを構成します。
Oracle JETの国際化およびローカリゼーション・サポートの使用
Oracle JETの国際化およびローカリゼーションの組込みサポートを使用するには、ページのhtml
要素のlang
属性に、サポートされている言語またはロケールの1つを指定します。たとえば、次の設定によって、言語がフランス語(フランス)ロケールに設定されます。
<html lang="fr-FR">
フランス語(カナダ)ロケールを指定する場合は、かわりに次のように指定します。
<html lang="fr-CA">
ヒント:
locale
指定は大文字と小文字が区別されません。Oracle JETでは、FR-FR
、fr-fr
なども受け入れて、正しいリソース・バンドル・ディレクトリにマップします。
このようにロケールを指定すると、ページ上のOracle JETコンポーネントは指定された言語で表示され、ロケールに適したロケール構成が使用されます。
ロケールに関連付けられたリソース・バンドルが存在しない場合、Oracle JETでは次に該当する言語バンドルがロードされます。次に該当する言語のバンドルがOracle JETに存在しない場合は、デフォルトのルート・バンドルが使用されます。たとえば、Oracle JETにfr-CA
の翻訳バンドルが存在しない場合は、fr
リソース・バンドルが検索されます。fr
バンドルが存在しない場合、Oracle JETではデフォルトのルート・バンドルが使用され、文字列が英語で表示されます。
次の図では、oj-input-date-time
コンポーネントを使用してページが構成されています。画像は、lang
属性をfr-FR
に変更した結果を示しています。
oj-input-date-time
フィールドに誤った値を入力すると、エラー・テキストが指定の言語で表示されます。この例では、エラーがフランス語で表示されます。
Oracle JETでの双方向(BiDi)サポートの有効化
アラビア語やヘブライ語のように、指定した言語でデフォルトの左から右(LTR)方向ではなく右から左(RTL)方向を使用する場合は、html
タグにdir
属性を指定する必要があります。
<html dir="rtl">
次の画像は、アラビア語(エジプト)の言語コードを指定してdir
属性をrtl
に変更すると表示されるoj-input-date-time
フィールドを示しています。
Oracle JETアプリケーションでBiDiサポートを有効にした場合は、アプリケーションが希望のレイアウトで適切に表示され、文字列が想定どおりにレンダリングされることを確認する必要があります。
ノート:
個々のHTML要素にdir
属性を設定するとページが両方の方向で表示されるため、Oracle JETではサポートしていません。また、ページが初期化された後にdir
属性をプログラムによって変更する場合は、ページをリロードするか、または各JETコンポーネントをリフレッシュする必要があります。
ロケールと方向の動的設定
アプリケーションURLのリロード時にアプリケーションのRequireJS ojL10nプラグインが読み取るアプリケーションのローカル・ストレージにキー値のペアを設定することで、そのロケールおよび方向を動的に変更するようにアプリケーションを構成できます。
次の画像は、クリックすると部門リストが表示されるメニューおよび日付ピッカーを表示するように構成された、Oracle JETアプリケーションを示しています。デフォルトでは、アプリケーションはen-US
ロケールに設定されます。メニューおよび日付ピッカーは英語で表示されています。
JET-Localization.ZIPをダウンロードし、ZIPファイルを抽出するディレクトリでOracle JET CLI ojet restore
およびojet serve
コマンドを実行する場合は、イメージに示されているOracle JETアプリケーションを実行できます。
アプリケーションには、米国、フランス、チェコ共和国およびエジプトの国旗が表示されたボタン群も含まれています。ユーザーがフラグの1つをクリックすると、アプリケーション・ロケールはそのフラグによって表されるロケール(en-US
、fr-FR
、cs-CZ
,またはar-EG
)に設定されます。
ノート:
この例で使用されている国旗は説明目的でのみ使用されています。1つの国で複数の言語が使用されていたり、ある言語が複数の国々で使用される場合があるため、国旗を使用してUI言語を選択することはお薦めできません。実際のアプリケーションでは、国旗アイコンのかわりに、優先言語を示すクリック可能なテキストを使用できます。
次の画像は、ユーザーがエジプトの国旗をクリックした後に更新されたページを示しています。
この動作を実装するには、アプリケーションのビュー、viewModelおよびappRootDir/src/main.js
ファイルを変更する必要があります。アプリケーションのビュー・コードで、on-value-changed
プロパティ変更リスナー属性は、ユーザーが選択したボタンを変更したときにコールされるsetLang
関数を指定します。
<oj-buttonset-one . . . on-value-changed="[[setLang]]">
アプリケーションのviewModelコードでは、このsetLang
関数は、ユーザーが選択したロケールを判断し、ユーザーの選択がブラウザ・セッション全体で保持されるようにwindow.localStorageにエントリを設定します。関数の最後のステップは、location.reload()メソッドを使用して現在のURLをリロードすることです。
setLang = (evt) => {
let newLocale = "";
let lang = evt.detail.value;
switch (lang) {
case "Čeština":
newLocale = "cs-CZ";
break;
case "Français":
newLocale = "fr-FR";
break;
case "عربي":
newLocale = "ar-EG";
break;
default:
newLocale = "en-US";
}
window.localStorage.setItem('mylocale',newLocale);
window.localStorage.setItem('mylang',lang);
location.reload();
};
新しく選択したロケールをアプリケーションのappRootDir/src/main.js
ファイルのojL10nプラグインで設定するには、ローカル・ストレージから更新されたロケール値を読み取ってojL10nプラグインのlocale
指定で設定する次のエントリを記述します。また、指定されたロケールがアラビア語(エジプト)(ar-EG
)の場合、方向をrtl
に設定するチェックも含まれます。
(function () {
...
const localeOverride = window.localStorage.getItem("mylocale");
if (localeOverride) {
// Set dir attribute on <html> element.
// Note that other Arabic locales and Hebrew also use the rtl direction.
// Include a check here for other locales that your app must support.
if(localeOverride === "ar-EG"){
document.getElementsByTagName('html')[0].setAttribute('dir','rtl');
} else {
document.getElementsByTagName('html')[0].setAttribute('dir','ltr');
}
requirejs.config({
config: {
ojL10n: {
locale: localeOverride,
},
},
});
}
})();
...
独自の翻訳文字列の定義、およびその翻訳文字列のOracle JETリソース・バンドルへの追加については、「Oracle JETへの翻訳バンドルの追加」を参照してください。
このアプローチを使用してアプリケーションを国際化およびローカライズする場合は、ページ上のすべてのコンポーネントおよび要素を検討し、必要な場所に翻訳文字列を指定する必要があります。ページに多数の翻訳文字列が含まれる場合は、ページのパフォーマンスが低下する可能性があります。
また、アプリケーションでSEO(検索エンジン最適化)が重要な場合、通常は検索エンジンでJavaScriptは実行されず、静的テキストにのみアクセスすることに注意してください。
ヒント:
パフォーマンスやSEOの問題を回避するために、対象の言語にすでに翻訳されたページをアプリケーションに追加できます。すでに翻訳されたページを使用すると、Knockoutのバインディングは実際に動的な場所に対してのみ実行されます。
通貨、日付、時間および数値の使用
Oracle JETに付属するコンバータを使用すると、ロケール設定に基づいて、日付、時間、数値および通貨が自動的に変換されます。また、Oracle JETコンバータがアプリケーションにとって不十分な場合は、カスタム・コンバータを提供できます。Oracle JETコンバータの詳細は、「Oracle JETコンバータについて」を参照してください。アプリケーションへのカスタム・コンバータの追加については、「Oracle JETでのカスタム・コンバータの使用」を参照してください。
Oracle JETの翻訳バンドルの使用
Oracle JETには、Oracle JETコンポーネントで生成された文字列を、サポートされているすべての言語に翻訳する翻訳バンドルが含まれています。独自の翻訳バンドルは、Oracle JETバンドルにマージすることによって追加します。
Oracle JETの翻訳バンドルについて
Oracle JETには、Oracle JETコンポーネントで生成された文字列を、サポートされているすべての言語に翻訳する翻訳バンドルが含まれています。独自の翻訳バンドルは、Oracle JETで使用される書式と同じ書式に従って追加できます。
Oracle JETの翻訳バンドルは、コンテンツやディレクトリ・レイアウトに対して指定された書式に従いますが、大文字/小文字および特定の文字に関してはある程度の寛大さが許容されます。
翻訳バンドルの場所
ojtranslations.js
という名前のOracle JET翻訳バンドルの場所は、次のディレクトリにあります:
libs/oj/v17.1.0/resources/nls/ojtranslations
サポートされている各言語は、nls
ディレクトリ下にあるディレクトリに格納されます。ディレクトリ名は次の規則に準拠します。
-
言語サブタグは小文字(
zh
、sr
など) -
スクリプト・サブタグはタイトル・ケース(
Hant
、Latn
など) -
地域サブタグは大文字(
HK
、BA
など)
言語、スクリプトおよび地域サブタグは、ハイフン(-)で区切られます。次の図は、ディレクトリ構造の一部を示しています。
最上位レベル・モジュール
ojtranslations.js
ファイルにはOracle JETで翻訳される文字列が格納され、翻訳がある言語がリストされます。これは、最上位レベル・モジュール、つまりルート・バンドルです。ルート・バンドルでは、文字列は英語で、ユーザーの優先言語の翻訳が使用できない場合の実行時デフォルト値です。
翻訳バンドルの書式
Oracle JETでは、最上位レベルのルート・バンドルおよび翻訳が指定の書式に準拠する必要があります。ルート・バンドルには、Oracle JET文字列とデフォルト翻訳、および翻訳があるロケールのリストが格納されています。
define({
// root bundle
root: {
"oj-message":{
fatal:"Fatal",
error:"Error",
warning:"Warning",
info:"Info",
confirmation:"Confirmation",
"compact-type-summary":"{0}: {1}"
},
// ... contents omitted
},
// supported locales.
"fr-CA":1,
ar:1,
ro:1,
"zh-Hant":1,
nl:1,
it:1,
fr:1,
// ... contents omitted
tr:1,fi:1
});
文字列はネストされたJSONオブジェクトに定義されるため、各文字列は、oj-message.fatal
、oj-message.error
などの接頭辞がある名前で参照されます。
言語翻訳リソース・バンドルには、Oracle JET文字列定義と翻訳済文字列が格納されています。たとえば、次のコード・サンプルは、nls/fr-CA/ojtranslations.js
に格納されているフランス語(カナダ)翻訳リソース・バンドルの一部を示しています。
define({
"oj-message":{
fatal:"Fatale",
error:"Erreur",
warning:"Avertissement",
info:"Infos",
confirmation:"Confirmation",
"compact-type-summary":"{0}: {1}"
},
// ... contents omitted
});
ユーザーの方言で使用可能な翻訳がない場合は、基本言語バンドルの文字列が表示されます。ユーザーの優先言語の翻訳がない場合は、ルート言語バンドルである英語が表示されます。
名前付きメッセージ・トークン
メッセージによっては、含まれる値が実行時まで決定しない場合があります。たとえば、"User foo was not found in group bar"
というメッセージ内のfoo
ユーザーおよびbar
グループは実行時に決定します。この場合は、次のコードに示すように、{username}
と{groupname}
を名前付きメッセージ・トークンとして定義できます。
"MyUserKey":"User{username}
was not found in group{groupname}
."
実行時に、1番目の引数としてメッセージのキーが挿入され、2番目の引数としてパラメータが翻訳済パターンに挿入されてTranslations.applyParameters()
メソッドがコールされ、メッセージ内のトークンの位置で実際の値に置換されます。
let parMyUserKey = { 'username': 'Foo', 'groupname': 'Test' };
let tmpString = Translations.applyParameters(MenuBundle.MyUserKey, parMyUserKey);
this.MyUserKey = Translations.getTranslatedString(tmpString);
数値メッセージ・トークン
名前付きトークンのかわりに、数値トークンを定義することもできます。たとえば、"This item will be available in 5 days"
というメッセージ内の数値5
は実行時に決定します。この場合は、次のコードに示すように、メッセージ・トークンの{0}
を使用してメッセージを定義できます。
"MyKey": "This item will be available in {0}
days."
1つのメッセージに最大10個の数値トークンを含めることができます。たとえば、"Sales order
{0}
has
{1}
items"
というメッセージには2つの数値トークンが含まれています。ターゲット言語の文法で必要な場合は、翻訳時にトークンの順序が変更され、翻訳済文字列内でメッセージ・トークン{1}
がメッセージ・トークン{0}
の前に表示される場合があります。applyParameters()
およびgetTranslatedString()
メソッドをコールするコードは、翻訳済文字列内でトークンの順序が変更されていても同じままです。
ヒント:
読みやすさおよび再利用のためには、数値トークンではなく名前付きトークンを使用してください。
リソース・バンドル文字列内のエスケープ文字
ドル記号、中カッコおよび角カッコを出力に表示する場合は、エスケープする必要があります。次の表に示すように、文字の前にドル記号($)を追加します。
エスケープされた形式 | 出力 |
---|---|
$$ | $ |
${ | { |
$} | } |
$[ | [ |
$] | ] |
たとえば、出力に[Date: {01/02/2020}, Time: {01:02 PM}, Cost: $38.99, Book Name: JET developer's guide]
と表示する場合は、リソース・バンドル文字列に次のように入力します。
"productDetail": "$[Date: ${01/02/2020$}, Time: ${01:02 PM$}, Cost: $$38.99, Book Name: {bookName}$]"
さらに、次の例に示すように、Translations.applyParameters()
メソッドを使用して、エスケープされた文字と置換トークン(ある場合)を含む文字列を返してUIに表示します:
let parProductDetail = { bookName: "JET developer's guide"};
this.productDetail = Translations.applyParameters(MenuBundle.productDetail, parProductDetail);
翻訳済文字列の書式設定
状況によっては、UIに表示されるリソース・バンドルの文字列に書式設定を適用できます。たとえば、HTML出力でブック・タイトルがイタリックを使用してレンダリングされるように、<i>
タグを適用するブック・タイトルについて検討します。このシナリオでは、リソース・バンドルに次のエントリを定義できます:
// root bundle
"FormatTranslatedString": "The <i>{booktitle}</i> describes how to develop Oracle JET apps"
その後、次の例のように、Oracle JETのoj-bind-dom要素を使用してUIの文字列をレンダリングします:
<p><span>
<oj-bind-dom config="{{ formatTranslatedString() }}"></oj-bind-dom>
</span></p>
注意:
oj-bind-dom要素は、整合性またはセキュリティ違反について、アプリケーションで提供されるHTML入力を検証しません。安全でないコンテンツがページに追加されないように入力をサニタイズするのは、アプリケーションの責任です。このviewModelでは、Oracle JETのHtmlUtilsユーティリティ・クラスを使用して、リソース・バンドルからの文字列を解析します。
. . .
import * as HtmlUtils from "ojs/ojhtmlutils";
import "ojs/ojbinddom";
. . .
class DashboardViewModel {
. . .
FormatTranslatedString: String;
. . .
formatTranslatedString = () => {
var parBookTitle = { 'booktitle': 'Oracle JET Developer Guide' };
let strTitle = Translations.applyParameters(MenuBundle.FormatTranslatedString, parBookTitle);
this.FormatTranslatedString = Translations.getTranslatedString(strTitle);
return {
view: HtmlUtils.stringToNodeArray(
`<span>${this.FormatTranslatedString}</span>`,
),
};
};
. . .