ラベル グローバリゼーション の投稿を表示しています。 すべての投稿を表示
ラベル グローバリゼーション の投稿を表示しています。 すべての投稿を表示

2026年6月23日火曜日

APEX 26.1のテキスト・メッセージベースの翻訳にXLIFFファイルを使用する

Oracle APEX 26.1ではアプリケーションの翻訳にテキスト・メッセージを使えるようになりました。以前に、OpenAI Codexを使ってAPEXアプリケーションの翻訳を行う方法を紹介しています。この記事のように生成AIに丸投げして翻訳できるのは、APEX 26.1でテキスト・メッセージベースの翻訳が導入されたためです。

記事「APEX 26.1の新しい翻訳モードであるテキスト・メッセージベースでアプリケーションを翻訳する」

APEX 26.1のテキスト・メッセージベースの翻訳でもXLIFF(CSVも可)を使った翻訳ができます。今回は、XLIFFを使って翻訳することを前提として、APEXアプリケーションの翻訳を手順を追って実施してみます。

以下の記事を参照しています。

Oracle Corporationの公式ブログ
Oracle APEX 26.1: Simplifying Application Translation with Text Messages

Oracle APEX Developer's Companion
22 Translating Your Application

作業環境として、ローカルのコンテナで実行しているAPEX 26.1を使用します。翻訳対象とするアプリケーションとして、サンプル・データセットのEMP/DEPTをインストールして作成できる、日本語のAPEXアプリケーションを使用します。

ユーティリティのサンプル・データセットを開き、EMP/DEPTをインストールします。


日本語のアプリケーションを作成するため、インストールする言語として日本語を選択します。

次へ進みます。


データセットをインストールします。


アプリケーションの作成を実行します。


アプリケーション作成ウィザードが開きます。

機能のすべてをチェックをクリックし、標準機能をすべて対象外にします。続いて、言語に日本語(ja)が選択されていることを確認します。

以上でアプリケーションの作成を実行します。


アプリケーションが作成されました。

このプライマリ言語が日本語のアプリケーションに、英語の翻訳を追加します。

共有コンポーネントを開きます。


グローバリゼーションのアプリケーション翻訳を開きます。


まだアプリケーションの翻訳が有効になっていません。翻訳を使用可能にするをクリックします。


アプリケーション定義のグローバリゼーションのタブに遷移します。

アプリケーションの翻訳をオンにし、翻訳モードとしてテキスト・メッセージベースを選択します。翻訳言語の導出元として、アプリケーション側の実装が不要な、ブラウザ(ブラウザの言語プリファレンスを使用)を選択します。

以上で変更を適用します。


変更を適用した後、共有コンポーネントのアプリケーション翻訳に戻ります。

アプリケーション言語として英語を追加します。言語の追加をクリックします。


言語として英語(en)を選択し、言語の追加をクリックします。


プライマリ言語の日本語(ja)と、翻訳を追加する言語として選択した英語(en)が追加されます。

翻訳対象となっているテキスト・メッセージが50個ほどあることが確認できます。


それぞれの言語のアクションよりテキスト・メッセージの同期化を実行する、または、テキスト・メッセージ翻訳のテキスト・メッセージに変換を実行することにより、アプリケーションに含まれる翻訳対象の文字列をテキスト・メッセージに置き換えます。


テキスト・メッセージへの変換(または同期化)が行われる前は、以下のようになっています。以下はページのプロパティですが、識別のタイトルが翻訳対象である文字列です。


テキスト・メッセージへの変換を実行すると、タイトルがテキスト・メッセージ従業員に置換される置換文字列&{従業員}.に置き換えられます。


置換文字列&{従業員}.が従業員に置き換えられるよう、テキスト・メッセージが作成されています。

共有コンポーネントのテキスト・メッセージを開いて確認します。


静的IDが従業員、言語として英語(en)および日本語(ja)のテキスト・メッセージが作成されています。英語、日本語の両方とも、置換後のテキストは従業員となっています。


言語が日本語のテキストは翻訳は不要です。言語が英語でも日本語のテキストがシードされています。この日本語のテキストを英語に翻訳すると、APEXアプリケーションの英語への翻訳が完了します。

しかし、アプリケーションに設定されていた日本語から生成されるテキスト・メッセージの静的IDは、静的IDとして適切とは言えません。

例えばエラー・メッセージ「権限が不十分です。ユーザーは管理者ではありません」が静的IDになっています。


これは認可スキームに設定されているエラー・メッセージです。画面に表示されるメッセージはテキスト・メッセージとして登録されているテキストなので、テキスト・メッセージを更新します。その上で、静的IDを維持する必要があります。

結果として、静的IDは画面に表示される文字列に見えるのに、実際に表示される文字列は異なるということになります。


テキスト・メッセージの静的IDが日本語であっても、APEXアプリケーションの翻訳はできます。なので、気にしないというのもひとつの方法です。アプリケーションのプライマリ言語が英語であれば、概ね気にする必要はないでしょう。

以下よりアプリケーションのプライマリ言語が日本語で、静的IDを日本語から英語の識別子に付け替える手順について検討します。

今回、翻訳の対象としているAPEXアプリケーションのホーム・ページは以下です。


ホーム・ページのタイトルを&{デモ_従業員_部門}.から&{DEMO_EMP_DEPT}.に変更します。


ブレッドクラム・リージョンは、翻訳を考慮して以下のように変更します。

識別.名前: Breadcrumb
識別.タイトル: &{DEMO_EMP_DEPT}.
ソース.HTMLコード: &{HOME.BREADCRUMB.SOURCE}.
詳細.静的ID: breadcrumb


ページ・ナビゲーションのリージョンは以下のように変更します。

識別.名前: Page Navigation
識別.タイトル: &{PAGENAVIGATION}.
詳細.静的ID: pagenavigation


共有コンポーネントのリストのページ・ナビゲーションを開きます。


名前の&{ダッシュボード}.、&{従業員}.、&{部門}.を、&{DASHBOARD}.、&{EMPLOYEES}.、&{DEPARTEMENT}.に置き換えます。


この状態でホーム・ページを開くと、静的IDに対応したテキスト・メッセージが作成されていないため、置き換えた静的IDがそのまま表示されます。

(実際は静的IDのEMPLOYEESとDEPARTMENTはテキスト・メッセージが作成済みなので、EmployeesとDepartmentに置き換わっています)。


テキスト・メッセージの静的IDは翻訳の機能では置き換えられないため、APEXlang形式でアプリケーションをエクスポートして置き換えます。

APEXlang形式のエクスポート時にフォルダ名が英語になるように、アプリケーション定義のアプリケーションの別名をdemonstration-emp-deptに変更します。

SQLclでエクスポートするため、アプリケーションIDを控えておきます。以下の例では103です。


SQLclでAPEXワークスペースのパーシング・スキーマに接続し、APEXアプリケーションをエクスポートします。

apex export -api 103 -exptype apexlang

SQL> apex export -api 103 -exptype apexlang

ワークスペースAPEXDEVをエクスポートしています - アプリケーション103:デモ - 従業員 / 部門

ファイルdemonstration-emp-dept/application.apxが作成されました


SQL> 


テキスト・メッセージはdemonstration-emp-dept/shared-components/messages.apxとして出力されています。

textMessageに続く以下の識別子を見つけ、英語の識別子に置き換えます。EMPLOYEESとDEPARTMENTはすでにテキスト・メッセージが作られているので、そのまま使用します。

デモ_従業員_部門: DEMO_EMP_DEPT
サンプルデータから開発: HOME.BREADCRUMB.SOURCE
ページナビゲーション: PAGENAVIGATION
ダッシュボード: DASHBOARD

テキスト・メッセージEMPLOYEESの日本語は従業員、DEPARTMENTは部門に置き換えます。今回のアプリケーションのプライマリ言語は日本語で、プライマリ言語についてはXLIFFやCSVでの出力ができません(プライマリ言語は翻訳の対象ではないため)。
textMessage HOME.BREADCRUMB.SOURCE (
    message {
        text: サンプルデータから開発
        language: en
    }
)

textMessage HOME.BREADCRUMB.SOURCE (
    message {
        text: サンプルデータから開発
        language: ja
    }
)

textMessage DASHBOARD (
    message {
        text: ダッシュボード
        language: en
    }
)

textMessage DASHBOARD (
    message {
        text: ダッシュボード
        language: ja
    }
)

textMessage DEMO_EMP_DEPT (
    message {
        text: デモ - 従業員 / 部門
        language: en
    }
)

textMessage DEMO_EMP_DEPT (
    message {
        text: デモ - 従業員 / 部門
        language: ja
    }
)

textMessage PAGENAVIGATION (
    message {
        text: ページ・ナビゲーション
        language: en
    }
)

textMessage PAGENAVIGATION (
    message {
        text: ページ・ナビゲーション
        language: ja
    }
)

textMessage EMPLOYEES (
    message {
        text: 従業員
        language: ja
    }
)

textMessage DEPARTMENT (
    message {
        text: 部門
        language: ja
    }
)
その他のテキスト・メッセージも置き換えることはできますが、英語についてはXLIFFを出力して翻訳します。

messages.apxを変更して保存し、APEXワークスペースにインポートします。

apex import -input demonstration-emp-dept

SQL> apex import -input demonstration-emp-dept

アプリケーションID: 103をワークスペース: APEXDEVにインポートしています

インポートに成功しました。


SQL> 


置き換えられたAPEXアプリケーションのホーム・ページを表示します。

日本語はもともと翻訳不要で、翻訳対象のプロパティに設定した静的IDがテキスト・メッセージに紐づけられれば、日本語のテキストに置き換えられて表示されます。


英語への翻訳に使用するXLIFFファイルを出力します。

共有コンポーネントのアプリケーション翻訳を開き、英語のXLIFFファイルをエクスポートします。

英語(en)のアクション・メニューよりXLIFFとしてエクスポートを実行します。


XLIFFファイルとしてf103_ja_en.xlf(アプリケーションIDが103の場合)がダウンロードされます。

最低限、trans-unitのidが以下のメッセージについては、targetを英語に翻訳します。
    <trans-unit id="HOME.BREADCRUMB.SOURCE">
      <source>サンプルデータから開発</source>
      <target>Deeloped from Sample Data</target>
    </trans-unit>
    <trans-unit id="DASHBOARD">
      <source>ダッシュボード</source>
      <target>Dashboard</target>
    </trans-unit>
    <trans-unit id="DEMO_EMP_DEPT">
      <source>デモ - 従業員 / 部門</source>
      <target>Demonstration - EMP / DEPT</target>
    </trans-unit>
    <trans-unit id="PAGENAVIGATION">
      <source>ページ・ナビゲーション</source>
      <target>Page Navigation</target>
    </trans-unit>
targetを翻訳したXLIFFファイルをアップロードします。

テキスト・メッセージのインポートを実行します。


翻訳したファイルを選択し、インポートを実行します。


以上でホーム・ページは英語に翻訳できました。

ブラウザの言語の優先言語を英語にします。(以下はChromeの例です)。


ホーム・ページの表示が以下に変わります。概ね英語の表示切り替わっています。


左上のロゴが日本語のままなので、アプリケーション定義のユーザー・インターフェースのロゴのテキストを&{DEMO_EMP_DEPT}.に変更します。


再度、ホーム・ページを表示すると、すべて英語で表示されます。


ブラウザの優先言語を日本語に戻すと、ホーム・ページの表示は日本語に変わります。


同様の作業を、すべてのページについて繰り返すと、アプリケーション全体の翻訳が完了します。

Oracle APEXはアプリケーション・ビルダーなどが複数の言語に対応しているため、辞書を持っています。APEXのインストール時にload_trans.sqlを実行してロードした言語については、APEXのスキーマ(APEX 26.1であればAPEX_260100)以下の表WWV_FLOW_MESSAGES$に翻訳されたメッセージが保存されています。

ボタンのラベルなどは、標準のメッセージを流用できます。

ページ4のフォームには、以下のラベルが付いたボタンが配置されています。

取消、削除、変更の適用、作成


フォームに作成されているボタンCANCELのラベルは&{キャンセル}.となっています。


同様に、ボタンCREATEは&{作成}.、SAVEは&{変更の適用}.、DELETEは&{削除}.となっています。

これらは、標準でインストールされているメッセージを参照するように、以下のテキスト・メッセージに置き換えることができます。

&{APEXAPP.BUTTON.CANCEL}.
&{APEXAPP.BUTTON.DELETE}.
&{APEXAPP.BUTTON.APPLY}.
&{APEXAPP.BUTTON.CREATE}.

優先言語を英語に切り替えると、ボタンのラベルも英語に変わります。


標準のメッセージを流用すると、テキスト・メッセージを作成する手間は省けますが、APEXの製品の都合で翻訳結果が変わるリスクもあります。また、APEXに含まれているテキスト・メッセージの静的IDについても、リファレンスなどはない(一部は22.6.3 Translating Messages Used Internally by APEXなどで説明されている)ので、面倒でもテキスト・メッセージは自前で用意した方が安全でしょう。

今回の記事は以上になります。

Oracle APEXのアプリケーション作成の参考になれば幸いです。

完

2026年6月22日月曜日

APEXlang形式のエクスポート・ファイルに含まれる日本語について

Oracle APEX 26.1ではエクスポート・フォーマットとしてAPEXlangが採用されています。それまでもYAML形式などでエクスポートはできましたがインポートはできなかったため、出力されたファイルを積極的に読んだり、Gitで管理する(Gitに置くだけではなく、差分やマージを行う)ことは行われていなかったと思います。

APEXlang形式のファイルを扱っていて、ファイルに含まれる日本語について気になった点を記述します。APEXlangでのエクスポートやアプリケーションの翻訳を行わない場合は、あまり意識する必要はないでしょう。

APEXlangについては、以下のAPI Referenceを参照します。


アプリケーションの名前と別名



アプリケーション・ビルダーを使ってAPEXアプリケーションを作成する際に、アプリケーションの名前を日本語にします。通常、意識せずにアプリケーションの名前は日本語にしていると思います。


作成されたアプリケーションの名前とアプリケーション別名に、作成時に指定したアプリケーションの名前が使用されます。(この他にもユーザー・インターフェースのロゴ、ホーム・ページのブレッドクラムの名前、ログイン・ページのリージョンの名前などにも反映されます)。


この部分のAPEXlangでの出力は以下でした。
app 世界食堂 (
    name: 世界食堂
    logo {
        type: text
        text: 世界食堂
    }
日本語のアプリケーション別名がappに続く識別子になっています。アプリケーションの名前も本来、翻訳の対象とはならないため、日本語では無い方が望ましいと思います。

SQLclでapex exportを実行すると、アプリケーション別名が出力フォルダ名になるため、アプリケーション別名が日本語だと、日本語のフォルダが作成されます。フォルダ名が日本語だと、Gitで管理する上でも望ましく無いでしょう。

SQL> apex export -api 105 -exptype apexlang

ワークスペースAPEXDEVをエクスポートしています - アプリケーション105:世界食堂

ファイル世界食堂/application.apxが作成されました


SQL> !ls

世界食堂


SQL> 


APEX 26.1以前でも、簡易URL(friendly URLs)が有効な場合、URLにアプリケーション別名が現れます。そのため、日本語のアプリケーション別名は(アクセスできないわけでは無いが)、避けるべきでした。


上記より、APEXアプリケーションを作成したら、すぐにアプリケーション別名は英数字(およびURLに含めることが許される一部の記号)による識別子として設定すべきです。


アプリケーション別名を変更すると、エクスポートされるフォルダ名およびURLに含まれる文字列は、英数字の識別名に変わります。

SQL> apex export -api 105 -exptype apexlang

ワークスペースAPEXDEVをエクスポートしています - アプリケーション105:世界食堂

ファイルworld-diner/application.apxが作成されました


SQL> !ls

world-diner

世界食堂


SQL> 


ビューAPEX_APPLICATIONSの列ALIASおよびAPEXlangの出力では、アプリケーション別名は英大文字ですが、フォルダ名やURLとなる文字列は英子文字になります。

SQL> select application_name, alias from apex_applications;


APPLICATION_NAME    ALIAS          

___________________ ______________ 

世界食堂                WORLD-DINER    


SQL>


APEXlangのリファレンスのappの項目を見ると、appに続く名前とは別にaliasが必須プロパティとなっていますが、APEX 26.1での出力はそのようになっていません。

アプリケーション別名の変更はプロパティの変更ではなく、識別子の変更にあたります。識別子の変更は、Gitなどでアプリケーションを管理している場合は影響が大きいです。アプリケーションの名前はアプリケーションのプロパティのひとつという扱いで、翻訳の対象ではありません。


ページの名前と別名



新規にページを作成する際に、ページ定義の名前は日本語にすると思います。以下ではページの名前をダッシュボードとしています。


作成されたページでは、名前はダッシュボード、別名はダッシュボード、タイトルもダッシュボードになります。


APEXlang形式でエクスポートすると、ファイル名にp00002-ダッシュボード.apxのように日本語が含まれ、プロパティname、alias、titleが日本語になります。
page 2 (
    name: ダッシュボード
    alias: ダッシュボード
    title: ダッシュボード
    appearance {
        pageTemplate: @/standard
        templateOptions: #DEFAULT#
    }
名前をDashboard、別名をDASHに変更します(別名をDASHBOARDにするとファイル名にどちらが採用されている分からないので、あえて名前と別名を変えています)。タイトルはページに表示される文字列で、アプリケーションの翻訳を行わない限り変更する必要はありません。


APEXlang形式の出力ファイルの名前はページの別名が使用され、p00002-dash.apxでした。ページの内容は以下のように変更されています。
page 2 (
    name: Dashboard
    alias: DASH
    title: ダッシュボード
    appearance {
        pageTemplate: @/standard
        templateOptions: #DEFAULT#
    }
ビューAPEX_APPLICATION_PAGESの列PAGE_ALIASを確認すると、別名は英大文字で保存されていますが、ファイル名およびURLに現れる文字列ともに英子文字になります。


ページの識別子はページ番号なので(API Referenceのpage参照)、ページ番号が変わらなければ同じページですが、ページの別名が変わると出力ファイルが変わります。結果として差分やマージが困難になります。ページの名前はページのプロパティのひとつですが、これも翻訳対象ではありません。


リージョンの名前と静的ID



リージョンの名前とタイトルは、ページ・デザイナではリージョンを作成した後にそれぞれ設定します。タイトルを設定していないとリージョンの名前がページに表示されるため、以前からのAPEX開発者であれば、リージョンにタイトルを設定せず名前をそのまま使用している場合も多いでしょう。


APEX 26.1ではAPEXlangのサポートの関係で、それまでの詳細の静的IDをHTML DOM IDという名称に変更し、新たに静的IDをプロパティとして加えています。

静的IDはリージョンの新規作成時に設定した名前から決まります。上記の例であれば、リージョンの名前をMENUとしているため、静的IDはmenuとなっています。

一度設定されたリージョンの静的IDはロック(変更禁止)され、リージョンの名前を変更しても静的IDは変更されません。


静的IDを変更するには、最初にロックを解除する必要があります。


APEXlang形式の出力を意識せず、APEX 26.1以前と同じようにリージョンの名前に日本語(ここではメニュー)を使用し、タイトルを空白としてリージョンを作成したとします。


この場合、静的IDは日本語のメニューになります(リージョンの新規作成後、編集するページを切り替えるまでは静的IDはロックされません)。


APEXlangでの出力は以下になります。静的IDがリージョンの識別子であるため、日本語が識別子に採用されます。
    region メニュー (
        name: メニュー
        type: classicReport
        source {
            location: localDatabase
            tableName: WR_MENUS_VL
        }
リージョンの識別子を後から変更すると、別のリージョンという扱いになります。そのため、リージョンの新規作成時には、設定される静的IDに注意する必要があります。


ウィザードが割り当てるデフォルトの識別子について



アプリケーション・ビルダーを日本語で使用していると、アプリケーション作成ウィザードやページ作成ウィザードいった、APEXのウィザードが生成するページやコンポーネントの識別子が日本語になっているものがあります。

例えば認証スキームのOracle APEXアカウントは、名前が識別子となるためAPEXlangにそのまま出力されます。


APEXlangでの出力は以下になります。authenticationの識別子に日本語が含まれます。
authentication oracle-apexアカウント (
    name: Oracle APEXアカウント
    type: oracleApexAccounts
)
リストの出力例です。
list ナビゲーション-バー (
    name: ナビゲーション・バー

    entry app-user (
        label: &APP_USER.
        icon {
            imageIconCssClasses: fa-user
        }
        layout {
            sequence: 10
        }
        link {
            target: {
                type: url
                url: #
            }
        }
        userDefinedAttributes {
            2: has-username
        }
    )

    entry list_item (
        label: ---
        layout {
            sequence: 20
            parentEntry: @app-user
        }
        link {
            target: {
                type: url
                url: separator
            }
        }
        serverSideCondition {
            type: userIsAuthenticated
        }
    )

    entry サインアウト (
        label: &{サインアウト}.
        icon {
            imageIconCssClasses: fa-sign-out
        }
        layout {
            sequence: 30
            parentEntry: @app-user
        }
        link {
            target: {
                type: url
                url: &LOGOUT_URL.
            }
        }
        serverSideCondition {
            type: userIsAuthenticated
        }
    )

)

list ナビゲーション-メニュー (
    name: ナビゲーション・メニュー

    entry ホーム (
        label: &{ホーム}.
        icon {
            imageIconCssClasses: fa-home
        }
        layout {
            sequence: 10
        }
        link {
            target: {
                page: 1
            }
        }
    )

)
アプリケーション作成ウィザードの機能や、ページ作成ウィザードの機能で追加したページも、ページ名やページに含まれるリージョンの静的IDは日本語になります。


ページの名前、別名、タイトルともに日本語になります。


リージョンの名前や静的IDも日本語になります。


APEXlang形式のファイルをGitで管理したりテキスト・メッセージベースの翻訳を検討する場合は、これらの標準コンポーネントについても対応を検討する必要があるでしょう。

今回の記事は以上になります。

完