2020年6月5日金曜日

Oracle APEXアプリケーションのグローバル化(4) - アプリケーション自体の対応

Oracle APEXアプリケーションをグローバル化する手順の説明です。こちらの記事からの続きになります。

多言語の情報を保持するスキーマ


メニューの情報は表TKY_MENUSに保持されています。この内容は以下になります。

 ID MENU_NAME VOLUME  PRICE
 1 プレミアム牛めし ミニ盛 490
 2 ごろごろ創業ビーフカレー 並盛 790
 3 ビビン丼 大盛 600

今の時点では、ログイン時にどの言語を選択しても、レポートには上記が表示されます。まずはじめに、MENU_NAMEについて翻訳したデータを別表に保持し、選択した言語で表示が切り替わるようにアプリケーションを改変します。

MENU_ITEMを各国語で保存するための表TKY_MENUS_TLを以下のように定義します。
create table TKY_MENUS_TL
(
    ID                          number primary key,
    MENU_ID                 number not null,
    LOCAL_MENU_NAME  varchar2(80) not null,
    LANGUAGE              varchar2(3) not null
);
alter table TKY_MENUS_TL add constraint TKY_MENUS_TL_FK foreign key ("MENU_ID") references TKY_MENUS ("ID") enable;
この表にメニュー名(MENU_ITEM)の翻訳済みの名前を入力します。
begin
  insert into tky_menus_tl(id, menu_id, local_menu_name, language) values(1, 1, 'プレミアム牛めし', 'JA');
  insert into tky_menus_tl(id, menu_id, local_menu_name, language) values(2, 1, '프리미엄 소고기덮밥', 'KO');
  insert into tky_menus_tl(id, menu_id, local_menu_name, language) values(3, 1, 'Premium Gyumeshi', 'US');
  insert into tky_menus_tl(id, menu_id, local_menu_name, language) values(4, 1, '高级牛肉饭', 'ZHS');
  insert into tky_menus_tl(id, menu_id, local_menu_name, language) values(5, 2, 'ごろごろ創業ビーフカレー', 'JA');
  insert into tky_menus_tl(id, menu_id, local_menu_name, language) values(6, 2, '소고기 듬뿍 타케야원조 소고기 카레', 'KO');
  insert into tky_menus_tl(id, menu_id, local_menu_name, language) values(7, 2, 'Takeya Tender Boil Beef Curry', 'US');
  insert into tky_menus_tl(id, menu_id, local_menu_name, language) values(8, 2, '香炖牛肉竹屋原始咖喱套餐', 'ZHS');
  insert into tky_menus_tl(id, menu_id, local_menu_name, language) values(9, 3, 'ビビン丼', 'JA');
  insert into tky_menus_tl(id, menu_id, local_menu_name, language) values(10, 3, '김치소갈비덮밥', 'KO');
  insert into tky_menus_tl(id, menu_id, local_menu_name, language) values(11, 3, 'BBQ Beef & Kimchi Bowl', 'US');
  insert into tky_menus_tl(id, menu_id, local_menu_name, language) values(12, 3, '泡菜五花牛肉盖饭', 'ZHS');
  commit;
end;
LANGUAGEに指定しているJA, KO, US, ZHSといった値ですが、こちらの説明は実装を終えた後に行います。

そして、現在の言語の選択状況にしたがった翻訳結果を表示するビューを以下のように定義します。このビューの要点はSYS_CONTEXT('USERENV','LANG')の使用です。
CREATE OR REPLACE FORCE VIEW "TKY_MENUS_VL" ("ID", "MENU_NAME", "VOLUME", "PRICE")
AS
select o.id, l.local_menu_name as menu_name, o.volume, o.price
from tky_menus o join tky_menus_tl l on o.id = l.menu_id
where l.language = SYS_CONTEXT('USERENV','LANG');
作成したビューTKY_MENUS_VLを使って、作成済みのアプリケーションのレポート定義を置き換えます。TKY_MENUSであった部分をTKY_MENUS_VLに変更します。


元のアプリケーションが変更されたので、再度パブリッシュを行います。


変更されたレポートを確認します。例えばサインインの際に言語セレクタで英語を選択すると、レポートは以下のように表示されます。


メニュー名についてはビュー定義にしたがって、英語で表示されていることが確認できます。同様にして中国語、韓国語についても、それぞれの言語で表示されます。

ビューで使用しているファンクションSYS_CONTEXTですが、これ自体はOracle APEXの機能ではなく、Oracle Databaseによって提供されています。SYS_CONTEXTは、データベースのセッションに設定されている属性を返すファンクションです。引数としてUSERENV、LANGを指定することで、セッションに設定されているOracle Databaseの言語を返します。Oracle Database自体のグローバライゼーション・サポートの詳細についてはマニュアルの記載に譲ります。SYS_CONTEXTについての記載はこちらです。

Oracle APEXが受け付けたHTTPのリクエストは必ずデータベースで処理されます。ですので、処理を行うためにデータベースのセッションが取得されます。一般には、新規に作成されるよりは、すでにあるセッションが再利用されますが、データベースでの処理が始まってすぐに、データベースのセッションにOracle APEXのアプリケーションが認識している言語を反映させます。この処理については、デバッグ・ログから確認することができます。

日本語の場合は次のコマンドが実行されています。

英語の場合は次のコマンドが実行されています。

中国語(簡体字)の場合は次のコマンドが実行されています。

韓国語の場合は次のコマンドが実行されています。

SYS_CONTEXT('USERENV','LANG')は、このようにALTER文を発行することによってセッションに設定されているNLS_LANGUAGEとNLS_TERRITORYの短縮形を返します。
alter session set nls_language = '言語' nls_territory='地域';
短縮形の情報はマニュアル、グローバリゼーション・サポート・ガイドのA. ロケール・データ、A1.言語に対応表が乗っています。対応表の言語の略称は小文字ですが、SYS_CONTEXT('USERENV','LANG')の値は大文字になります。

Oracle APEXはアプリケーションのグローバライゼーションに関して、このような仕組みを持っています。この仕組みを前提として、翻訳したメニュー名を保持する表TKY_MENUS_TLのLANGUAGE列にJA, US, ZHS, KOなどのOracle Databaseがサポートしている言語の短縮名を設定しており、それを参照するビューTKY_MENUS_VLではSYS_CONTEXT('USERENV','LANG')で返される言語に一致する行を選択することで、メニュー名をアプリケーションのサインイン時に設定した言語で表示させています。

動的翻訳


お気づきのように、アプリケーションの翻訳は完全ではありません。サイズの表記が日本語のままです。この翻訳には、Oracle APEXが提供している動的翻訳を使ってみます。

共有コンポーネントのアプリケーションの翻訳より、動的翻訳を開きます。

動的翻訳の準備として、プライマリ言語の文字列と、それを翻訳した文字列を対にして、動的翻訳リポジトリに登録しておきます。そして、APEX_LANG.LANGファンクションをプライマリ言語の文字列を引数にして呼び出し、翻訳済みの文字列を返り値として得ます。

動的翻訳を開くと一覧画面になります。作成をクリックします。

動的翻訳の編集画面になります。翻訳元テキストはつねにアプリケーションのプライマリ言語(この場合は日本語)での文字列です。言語の選択は、翻訳先となる言語で、翻訳先テキストは翻訳元テキストに対応した翻訳済みの文字列です。

サイズの表記は以下ですので、これを動的翻訳として登録します。各言語3行、合計で9行文の登録になります。
 日本語 英語 中国語(簡体字)  韓国語
ミニ盛Mini小碗미니사이즈
並盛Regular平碗보통사이즈
大盛Large大碗곱빼기

すべて登録すると以下のようになります。

では、動的翻訳をアプリケーションに適用します。先ほど作成したビューの定義を修正します。変更点はvolumeをそのまま渡していたところを、APEX_LANG.LANG(volume)として、動的翻訳を適用させている点です。
CREATE OR REPLACE FORCE VIEW "TKY_MENUS_VL" ("ID", "MENU_NAME", "VOLUME", "PRICE") AS 
  select o.id, l.local_menu_name as menu_name, apex_lang.lang(o.volume) as volume, o.price
from tky_menus o join tky_menus_tl l on o.id = l.menu_id
where l.language = SYS_CONTEXT('USERENV','LANG');
変更されたレポートを確認します。例えばサインインの際に言語セレクタで中文(简体)を選択すると、レポートは以下のように表示されます。

サイズの表記が中国語になっていることがわかります。英語、韓国語も同様に言語の選択に応じた表記に変わります。

APEX_LANG.LANGファンクションに関するマニュアルの記載はこちらです。

これでレポートについては、多言語対応が完了しました。

多言語に対応したメッセージ


このアプリケーションはデモ用途で、ユーザー名とパスワードに同じ値を使用するだけでユーザー認証が成功します。それをサインインのダイアログにメッセージとして埋め込んでみます。以下のようなメッセージです。

一番簡単な方法は、リージョンのソースに直接、メッセージを書き込むことです。

日本語だけの対応であれば、これで十分です。Oracle APEXのアプリケーションの多くは、このように直接メッセージを書き込んでいると思います。

このようなケースを多言語に対応させる方法として、共有コンポーネントのアプリケーションの翻訳の中にテキスト・メッセージというリポジトリが提供されています。

テキスト・メッセージを開くと、登録されているメッセージが一覧されます。新規にテキスト・メッセージを登録するには、テキスト・メッセージの作成をクリックします。

テキスト・メッセージの登録には、APEX_LANG.MESSAGEファンクションがテキスト・メッセージを呼び出す際の引数となる名前、メッセージの言語、その言語でのメッセージとして表示されるテキストを指定します。JavaScriptで使用にチェックを入れると、JavaScript APIのapex.langコールでも、ここで指定したメッセージが利用できるようになります。これらを指定した後、テキスト・メッセージの作成(または、作成後、さらに作成)をクリックします。

テキスト・メッセージの名前をT_SIGNIN_MESSAGEとして、以下、4言語分のテキスト・メッセージを登録します。
 言語 テキスト・メッセージ
 ja ユーザー名とパスワードが同じ値であれば認証されます。 例えば %0/%0
 en If the user name and password are the same, you will be authenticated. For example, %0/%0
 zh-cn 如果用户名和密码相同,则将通过身份验证。 例如 %0/%0
 ko 사용자 이름과 암호가 같은 값이면 인증됩니다. 예 %0/%0

結果として以下のように登録されます。

登録されたテキスト・メッセージを使って、サインインのダイアログに表示するメッセージを多言語に対応させます。ページ・デザイナにてサインインのページを開き、リージョンのタイプをPL/SQL動的コンテンツに変更し、ソースのPL/SQLコードに以下を指定します。
htp.p(apex_lang.message('T_SIGNIN_MESSAGE','demo'));


アプリケーションの変更をすべての翻訳済みアプリケーションに反映させるため、パブリッシュを実行します。

アプリケーションを実行して動作を確認します。サインイン画面の言語セレクタで한국어(韓国語)を選択すると、メッセージがハングルで表記されていることが確認できます。英語、中国語も同様です。


APEX_LANG.MESSAGEファンクションの詳細については、マニュアルのこちらに説明があります。

JavaScriptで使用する文字列の翻訳


今回のサンプル・アプリケーションには含まれていませんが、データの編集を行うフォームをウィザードで作成し、そのフォーム上の削除ボタンをクリックすると、以下のポップアップが表示されます。

これはボタンにたいして、以下のJavaScriptを実行することで実現しています。
javascript:apex.confirm(htmldb_delete_message,'DELETE');

「削除操作を実行しますか?」というメッセージは、そのままでは多言語に対応しません。このメッセージを多言語に対応させるには、先ほどのテキスト・メッセージのリポジトリとJavaScript APIのapex.lang.formatMessageを使用します。

まず、先ほどと同様にテキスト・メッセージを登録します。名前はT_CONFIRM_DELETEとします。JavaScriptで使用をONにします。

各言語で対応するテキスト・メッセージを登録します。
 言語 テキスト・メッセージ
 ja この削除操作を実行しますか。
 en Would you like to perform this delete action? 
 zh-cn 是否要执行此删除操作?
 ko 이 삭제 작업을 수행하겠습니까?

全て登録すると、以下のようになります。

テキスト・メッセージの準備ができたので、先ほどのJavaScriptの記述を以下に変更します。
javascript:apex.confirm(apex.lang.getMessage('T_CONFIRM_DELETE'),'DELETE');
アプリケーションの変更があったので、シードとパブリッシュを再実行します。このようにアプリケーションを設定することで、ダイアログの表示が切り替わります。

JavaScript APIを使った翻訳を確認する場合、アプリケーション・ビルダーからアプリケーションを起動せず、直接、ブラウザからアプケーションにアクセスしてください。アプリケーション・ビルダーからアクセスすると、アプリケーション・ビルダーの言語で翻訳されます。つまり開発を日本語で行っている場合、そこからアプリケーションを起動すると、アプリケーション側でセッションの言語を切り替えても、つねに開発画面の言語、この場合は日本語になります。

以下、多言語に対応したダイアログの表示です。

簡体中国語では以下になります。

英語では以下になります。

韓国語では以下になります。

Oracle APEXが提供するJavaScript APIのマニュアルの記載はこちらになります。新しい版については、まだ日本語の翻訳が準備できていません。翻訳に関するAPIでは、

apex.lang.getMessage
apex.lang.formatMessage
apex.lang.formatMessageNoEscape

などが使用できます。

Oracle APEXのアプリケーションで使用できる、文字列の翻訳に関する機能の紹介は以上になります。

2020年6月4日木曜日

Oracle APEXアプリケーションのグローバル化(3) - 言語マッピングの作成

Oracle APEXアプリケーションをグローバル化する手順の説明です。こちらの記事からの続きになります。

Oracle APEXのアプリケーションの各言語への対応は、異なるアプリケーションを内部的に作成し、それに言語をマッピングすることで行われます。

言語の切り替えには、グロバリゼーションの設定に含まれるアプリケーション言語の導出元の設定が使用されます。

それでは、前回作成したOracle APEXのアプリケーションに言語マッピングを追加し、それぞれの言語に対応させる手順を紹介します。

アプリケーション・ビルダーでアプリケーションを開き、共有コンポーネントのグローバリゼーションのグループにあるアプリケーションの翻訳を開きます。


アプリケーションの翻訳に関する作業は、ほぼ全て、このページに集約されています。また、アプリケーションの翻訳作業としては、左にある翻訳方法のリストを上から順番に行っていくことが想定されています。


つまり、
  1. アプリケーション言語の定義
  2. 翻訳可能なテキストのシード
  3. XLIFF翻訳ファイルのダウンロード
  4. テキストの翻訳
  5. XLIFF翻訳ファイルの適用
  6. 翻訳済アプリケーションのパブリッシュ
です。3, 4, 5のXLIFF翻訳ファイルを利用した翻訳作業は、一番下にある翻訳リポジトリを直接編集する作業で置き換えることができます。

では、定義された翻訳ワークフローに沿って、作業を行っていきます。

アプリケーション言語の定義


アプリケーション言語の定義を開きます。最初は何も言語のマッピングは登録されていません。ここで、作成をクリックします。


翻訳アプリケーションの内部的なアプリケーションIDとなる数値と言語を指定して、作成をクリックします。すでに使用済みのアプリケーションIDは指定できないため、空いている番号を自力で探して指定する必要があります。これはOracle APEXをホストしているインスタンス全体で一意(ワークスペースではない)である必要があります。そのため、実際は空いていそうな数値を入力し、作成をクリックしてエラーが発生したら数値を変えてやり直す、という手順にならざるを得ない場合もあります。

アプリケーションIDとなる数値と、マッピングする言語を指定した後、作成をクリックします。


文書方向は左から右です。Oracle APEXは右から左へ記述する言語(ヘブライ語やアラビア語)への対応も機能として持っています。

同様にして、中国語(中国)(zh-cn) - いわゆる簡体字 - と韓国語(ko)も追加します。結果として以下の言語のマッピングが登録されます。



翻訳可能なテキストのシード


翻訳可能なテキストのシードを開きます。


翻訳済アプリケーションに付いているチェックボックスを個別にクリックするか、全体のチェックボックスをクリックして、全ての翻訳済アプリケーションを選択します。そしてシードを実行します。プライマリ言語で作成されたアプリケーションに含まれる、翻訳可能な文字列が翻訳対象となっているアプリケーションにすべてコピーされます。


翻訳対象の文字列は69あり、その中で重複を除く46の個別の文字列がある、とレポートされています。

XLIFF翻訳ファイルのダウンロード


XLIFF翻訳ファイルのダウンロードを開きます。翻訳先になる言語を選び、アプリケーションのXLIFFファイルのエクスポートを実行します。この例では言語として英語(en)を選び、XLIFFターゲット要素を含めるにチェックを入れ、そしてエクスポートにはすべての翻訳可能な要素を含めます。ページ単位でXLIFF翻訳ファイルを出力することも可能です。


XLIFF (XML Localization Interchange File Format) はソフトウェアや文書の国際化、翻訳のために開発された XMLベースのファイル形式です。XLIFFファイル自体については、Wikipediaの該当エントリなどを参照してください。

アプリケーションのXLIFFファイルのエクスポートを実行すると、XLIFFファイルがダウンロードされます。ファイル名は

f翻訳元アプリケーションID_翻訳先アプリケーションID_翻訳元言語_翻訳先言語.xlf

となります。XLIFFファイルの内容は、以下のようなtrans-unit要素の集まりです。
<trans-unit id="S-6-1-20316">
<source>竹家のメニュー</source>
<target>竹家のメニュー</target>
</trans-unit>
<trans-unit id="S-106-21345516472514205825-20316">
<source>メニュー名</source>
<target>メニュー名</target>
</trans-unit> 
<trans-unit id="S-106-21345516575424205826-20316">
<source>サイズ</source>
<target>サイズ</target>
</trans-unit> 
<trans-unit id="S-106-21345516657757205827-20316"> 
<source>値段</source>
<target>値段</target>
</trans-unit>
チェックボックスXLIFFターゲット要素を含めるのチェックを外していると、この中のtarget要素は含まれなくなります。翻訳作業はtarget要素を置き換えるのではなく、target要素の追加になります。また翻訳が必要な要素のみを選ぶと、すでに翻訳済みの文字列はXLIFFファイルに含まれません。

テキストの翻訳


テキストの翻訳として翻訳方法にありますが、これをクリックしてもOracle APEXで実施できる作業はありません。


XLIFFファイルのtarget要素を対象の言語に翻訳する作業は外部に委託する場合が主です。そして、翻訳済みのXLIFFファイルを受け取って、次のステップへ進みます。

この記事での翻訳はXLIFFファイルを使わず、翻訳リポジトリを直接編集する予定ですので、XLIFFファイルの編集作業は行いません。

XLIFF翻訳ファイルの適用


XLIFF翻訳ファイルの適用を開きます。ここでは手順の紹介のみで、実際の作業は行いません。


翻訳済みのXLIFFファイルをアップロードします。先ほどダウンロードしたファイルをそのままアップロードしてみます。最低でもファイルをひとつ選択し、アップロードを実行します。


アップロードされたXLIFFファイルが一覧に現れます。翻訳を適用するファイル名にチェックを入れ、翻訳に適用にて対象言語を選びます。そして、チェックした項目の適用を実行すると、XLIFFファイルの内容が翻訳リポジトリにロードされます。今回はこの実行は不要です。



翻訳リポジトリの直接編集


アプリケーションの翻訳を専門業者に任せるとする、もしくは、分業できる場合はXLIFFファイルを使った手順は有効です。そうでない場合、例えば、ちょっとしたアプリケーションであったり、一部のレポートだけを対象としたり、翻訳だけを任せるリソースがなかったり。そのような場合では、翻訳リポジトリの直接編集が有効です。


翻訳ユーティリティの翻訳リポジトリを開きます。


ここからは力作業で、レポートに含まれる列、言語で指定された言語に翻訳先の文字列を置き換えていきます。鉛筆マークをクリックすると、編集フォームが開きます。


翻訳先の言語に合わせて、翻訳先テキストを入力します。この文字列のすべてのn件の発生を更新しますにチェックを入れると、翻訳元テキストが同じ場合、それらも同時に置き換えます。

グリッド編集を選ぶことで、対話グリッドを使った編集作業も行うことができます。


以下の表に翻訳する文字列と、それぞれの言語への翻訳を一覧します。これらを参考に、翻訳リポジトリを更新します。例えば、英語のみ、または、一部の文字列のみでも、Oracle APEXのアプリケーションの翻訳手順はわかりますので、必ずしも全て更新しなくても大丈夫です。

 日本語(ja) 英語(en) 簡体中国語(zh-cn) 韓国語(ko)
 竹家のメニュー Takeya's Menu 竹屋的菜单 대나무 집의 메뉴
 日本語メニュー English Menu 中文菜单 한국어 메뉴
 ホーム Home 主页 홈
 言語セレクタ Language Selector 语言选择器 언어 선택기
 サインイン Sign In 登录 사인인
 ユーザー名を記憶 Remember username 记住用户名 사용자 이름 기억
 パスワード Password 密码 비밀번호
 ユーザー名 Username 用户名 사용자 이름
 竹家のメニュー - サインイン Takeya's Menu - Sign In 竹屋的菜单 - 登录 대나무 집의 메뉴 - 사인인
 ログイン・ページ Login Page 登录页 로그인 페이지
 メニュー名 Menu Name 菜单名称 메뉴 이름
 サイズ Size 量 양
 値段 Price  价钱 가격
 デスクトップ Desktop 桌面 데스크톱
 サインアウト Sign Out 注销 사인아웃

翻訳済アプリケーションのパブリッシュ


翻訳リポジトリの内容を更新したら、翻訳済アプリケーションのパブリッシュを開きます。


それぞれの言語について、同期化が必要の列がはいであれば、パブリッシュを実行する必要があります。前回パブリッシュしたのち、アプリケーションに変更があった場合は、シードも再実行します。シードとパブリッシュを再実行することで翻訳済みのアプリケーションに変更が適用されます。XLIFFファイルの出力時に、翻訳が必要な要素のみという選択項目がありましたが、これは、このようなアプリケーションの変更に伴う追加の翻訳のために使用するオプションになります。

パブリッシュを実行すると、同期化が必要がいいえに変わります。


動作確認


今までの作業で、Oracle APEXのアプリケーションに含まれる言語リソースの翻訳は完了になります。また、アプリケーション自体も多言語に対応しました。

アプリケーション・プロパティの編集からグローバリゼーション属性の編集を開き、アプリケーション言語の導出元として、一番デバッグが容易なセッションを選択し、変更の適用を行います。


アプリケーションを実行して動作確認をしましょう。


言語セレクタを使って、言語を切り替えてサインインします。Englishを選んでログインした際のレポートは以下のように表示されます。


ページのタイトルやレポートのタイトル、項目名などは翻訳されていますが、データそれ自体は翻訳されていません。Oracle APEXのアプリケーションを多言語に対応させるには、Oracle APEXでの構成だけではなく、アプリケーション自体も多言語に対応させる必要があります。

次のトピックからは、アプリケーション自体を多言語に対応させる方法について紹介します。

Oracle APEXアプリケーションのグローバル化(2) - 初期アプリケーションの作成

Oracle APEXアプリケーションのグローバル化を説明するにあたり、まず最初に元となる日本語のアプリケーションを作成します。Oracle APEXのアプリケーション・ビルダーから作成を選んで、新規アプリケーションの作成を実行します。アプリケーション・ウィザードへの設定項目として、名前(なんでも良いですが、ここでは竹家のメニューとしています)、言語(これは日本語(ja)を選択します)を指定し、アプリケーションの実行を行います。


これでホームページだけの空のアプリケーションが作成されます。

次に、必須の作業ではないのですが、テストをしやすくするため、カスタムの認証スキームを設定します。作成したアプリケーションの共有コンポーネントに含まれる認証スキームを開きます。


認証スキームの一覧から作成をクリックし、以下の認証スキームを新たに定義します。ユーザー名とパスワードが一致していれば、アプリケーションの利用を許可します。名前は任意ですが、ここではユーザー名とパスワードが同じ、としています。スキーム・タイプはカスタムを選びます。認証ファンクション名としてmy_authentication、ソースにmy_authenticationのコードを記述します。
function my_authentication (
    p_username in varchar2,
    p_password in varchar2 )
    return boolean
is
begin
    return upper(p_username) = upper(p_password);
end;
すべて設定したのち、認証スキームの作成を実行します。新規に認証スキームが作成されると、その認証スキームが以降のアプリケーションの認証で使われるようにアクティブ化されます。


認証スキームを新規に作成したのち、アプリケーションを実行します。サインインをするためにユーザー名とパスワードが聞かれますので、ユーザー名とパスワードに同じ値を入力して、アプリケーションにサインインします。この例ではdemo/demoと入力しています。


サインインすると空のホームページが表示されます。


これからは、このアプリケーションに機能を追加していきます。

最初にメニューを保持する表を定義します。
create table TKY_MENUS
(
    ID                number primary key,
    MENU_NAME varchar2(80) not null,
    VOLUME       varchar2(16)  not null,
    PRICE           number        not null
);
メニューそれぞれで、名前(MENU_NAME)、サイズまたは量(VOLUME)、そして値段(PRICE)の情報を持ちます。以下のスクリプトを実行して、データを投入します。SQLワークショップに含まれるSQLコマンドの画面にそのまま貼り付けて実行できるよう、begin/endで囲っています。
begin
insert into tky_menus(id, menu_name, volume, price) values(1,'プレミアム牛めし','ミニ盛',490);
insert into tky_menus(id, menu_name, volume, price) values(2,'ごろごろ創業ビーフカレー','並盛',790);
insert into tky_menus(id, menu_name, volume, price) values(3,'ビビン丼','大盛',600);
commit;
end;
データが投入されているかどうか、SELECT文を実行して確認します。
select * from tky_menus;

以上でデータの準備ができたので、アプリケーションにレポートを追加します。ページ・デザイナでページ番号1、ホームのページを開きます。開いたページにクラシック・レポートのリージョンを追加します。タイトルは日本語メニュー、ソースの表名に先ほど作成した表TKY_MENUSを指定します。


追加したレポートを確認するために、アプリケーションを実行します。


表の列名からヘッダーが決まっているため、英語になっています。日本語のアプリケーションらしくするため、主キーのIDを非表示列に変更し、列のヘッダーであるMenu Nameをメニュー名、Volumeをサイズ、Priceを値段に変更します。


これらの変更を行った結果が以下です。単純ですが、日本語のみに対応しているOracle APEXのアプリケーションはこの例のように作られているでしょう。通常、特に言語については意識せずに、直接アプリケーションに日本語を埋め込んでいると思います。


このように、ひとつの言語だけを考えて作られているアプリケーションを、これから多言語に対応させていきます。


2020年6月1日月曜日

Oracle APEXアプリケーションのグローバル化(1) - はじめに

Oracle APEXには、作成したアプリケーションを色々な言語に対応させる機能が組み込まれています。簡単なシナリオを定義して、それに沿って作成されるアプリケーションを各国語に対応させることで、その手順を紹介します。


一口にグローバル化、といっても、画面に表示されている領域のタイトルや、ボタンに表示されているラベル、入力項目名、レポートの列名、さらにはデータベースに入っているデータそのもの、日時の表記、タイムゾーンなど、検討が必要な事項は多岐に渡ります。これらを項目に分けて解説していきます。 

Oracle APEXアプリケーションのグローバル化として、各種の機能を解説している記事は以下です。

このアプリケーションは、架空のファーストフード店のメニュー(竹家としています)をいくつかの言語でリスト表示するものです。

まず、それぞれの言語でのメニューの表記は以下とします。
 日本語 英語 中国語(簡体字) 韓国語
ごろごろ創業ビーフカレーTakeya Tender Boil Beef Curry香炖牛肉竹屋原始咖喱套餐 소고기 듬뿍 타케야원조 소고기 카레
ビビン丼BBQ Beef & Kimchi Bowl泡菜五花牛肉盖饭김치소갈비덮밥
プレミアム牛めしPremium Gyumeshi高级牛肉饭프리미엄 소고기덮밥

次にサイズの表記は以下とします。
 日本語 英語 中国語(簡体字) 韓国語
ミニ盛Mini小碗미니사이즈
並盛Regular平碗보통사이즈
大盛Large大碗곱빼기

そして、レポートとして表示するデータを、主言語である日本語のデータとして以下を準備します。
 メニュー名 サイズ値段 
 ごろごろ創業ビーフカレー 並盛790 
 ビビン丼 大盛 600
 プレミアム牛めし ミニ盛 490

非常にシンプルな例ですが、ユーザーが選んだ言語にしたがって以下のようなレポート表示が行われる実装を紹介していきます。

日本語での表示です。

英語での表示です。

中国語(簡体字)での表示です。

韓国語(ハングル)での表示です。

日本でOracle APEXのアプリケーションを作成する場合、大抵はプライマリ言語として日本語を選んでいるはずです。ですので、翻訳の手順の紹介も日本語のアプリケーションありきで進めていきます。

2020年5月1日金曜日

簡易URLに含まれるパス接頭辞について

Oracle APEX 20.1では簡易URL(Friendly URLs)として、より一般的な形式のURLによるアクセスが可能になりました。まだ日本語に翻訳されたマニュアルがないため英語ですが、マニュアルのここで説明されています。

今までの形式は以下です。
http://hostname:port/ords/f?p=App:Page:Session:Request:Debug:ClearCache:itemNames:itemValues:PrinterFriendly
簡易URLでは、形式が以下になります。
http://hostname:port/ords/path_prefix/r/app_alias/page_alias?parameters (Such as —
        p7_customer_id=377&clear=7&session=1247058356345&cs=3MdkfQa9NLmkyHAbwGPg3U-nmA7XIw5sWjU2rMzSvOy_wP1_z7BBI-Gbh2JgvffARgcYJy8id4VtL3d0l1tYm0w)
より一般的なURLにすることにより、場合によっては問題になっていたURLのエンコーディングに関する処理や正規表現によるフィルタリングやリライトの難しさといった、今まであったデメリットを解消しています。20.1からは新規にアプリケーションを作成すると、デフォルトで簡易URLが有効になります。

簡易URLにはpath_prefixが含まれます。これはデフォルトではワークスペース名になります。20.1以前には、簡易URLという機能自体がありませんし、また、アプリケーションIDは、インスタンス全体で一意の値ですから、指定されるURLにワークスペース名は含まれません。このため、同じインスタンスのAPEXへのアクセスをワークスペース毎に制限したい、という当然ありそうな要件にも簡単な解決方法はありませんでした。20.1からはフロントのHTTPサーバーの設定で容易に制限をかけることができるでしょう。

このpath_prefixですが、デフォルトのワークスペース名から変更することが可能であることを最近知りました。ワークスペース名は記述的な長い名前を付けたくなりますが、URLに含まれるなら略語のような短縮された名前にしたいと思います。ですので、アプリケーションを公開する上で、これはとても重要なことです。

URLに含まれるパス接頭辞(path_prefix)を変更するのは、アプリケーション・ビルダーの右上、スパナを持った人のアイコンをクリックし、ワークスペースの管理メニューから、サービスの管理、ワークスペース・プリファレンスの設定を開きます。

SQLワークショップのセクションにURL接頭辞の設定があります。こちらを変更するとpath_prefixを含んだ簡易URLが変更されます。ひとつのOracle APEXの実行環境で一意である必要があります。

ORDSによるRESTサービスを開発した経験がある方は、これと同様な設定があることを知っていることでしょう。RESTfulサービスの構成に含まれるスキーマ別名の設定です。

このスキーマ別名が設定されているときは、先ほどのSQLワークショップのセクションの設定が変わります。

ORDSスキーマ別名のオーバーライドという設定項目が現れます。ヘルプを読んでみると
ORDSスキーマ別名とApplication Expressワークスペース・パス接頭辞に異なる値を指定することはお薦めしません。
とのことで、何が起こるかわからないし、それをする理由も思いつかないので、オーバーライドしない方がよいでしょう。この場合は簡易URLのパス接頭辞は、ORDSのRESTfulサービスの構成から指定することになります。ORDSスキーマ別名のオーバーライドをONにすると以下の画面になります。

URLに含まれるパス接頭辞の説明は以上です。余談ですが、簡易URLは翻訳をフレンドリURLとして欲しいです。標準的なURLの形式にそっている、という意味です。簡易というのとは、少々意味が異なります。

完