プロジェクト

全般

プロフィール

バグ #257

未完了

Scene Builder 15.0.1 Windowsインストーラー版でメニュー(日本語)が化ける

高橋 徹 さんが約3年前に追加. ほぼ3年前に更新.

ステータス:
解決
優先度:
通常
担当者:
カテゴリ:
-
対象バージョン:
-
開始日:
2021/02/06
期日:
進捗率:

80%

予定工数:
重要度:

説明

現象

Scene Builder 15.0.1 Windows版を、Windows 10 日本語版の上で実行すると、画面に表示される文字が化けてしまっている。

SceneBuilderScreen-1.jpg

再現手順

  1. Gluon社のScene Builder配布サイトから入手した Scene Builder 15.0.1 Windowsインストーラー版を日本語版Windowsにインストール
    https://gluonhq.com/products/scene-builder/
  2. Scene Builderを実行

関連

  • Scene Builder 10.0、11.0で発生した事象[#89]が解決されていない。

調査結果

  • Scene Builderのソースコードリポジトリ内では、日本語ロケールのリソースバンドル・プロパティファイル(SceneBuilderApp_ja.properties)は、ユニコードエスケープではなくUTF-8文字コードで日本語文字列が記述されている。[#257-3]
  • 同ソースコードリポジトリ内では、デフォルトロケールと中国語ロケールのリソースバンドル・プロパティファイルはユニコードエスケープで記述されている[#257-3]
  • 文字化け後の文字は、UTF-8日本語文字をSJIS(Windows-31j)と誤認して解釈したものとは異なるので、単純なエンコードまちがいではないと思われる[#257-5]
  • Windows のロケールを日本語から英語に切り替えて、ビルドの実施をしたところ、Windowsインストーラー版に含まれる文字化けしたプロパティファイルが生成(再現)できた[#257-11]

文字化けの事象

UTF-8で記述された日本語ロケールの文字列リソース(プロパティファイル)を、Windows環境でのビルド時にUTF-8ではなくCP1252(ラテン文字)で解釈してしまい、誤ったユニコードエスケープを実施している。

UTF-8で記述した文字列「ファイル」がどのように変化するかを次の表に示す。

1 ソース中の文字
2 UTF-8符号化 e3 83 95 e3 82 a1 e3 82 a4 e3 83 ab
3 CP1252解釈 ã ƒ ã ¡ ã ¤ ã ƒ «
4 ユニコードエスケープ \u00e3 \u0192 \u2022 \u00e3 \u201a \u00a1 \u00e3 \u201a \u00a4 \u00e3 \u0192 \u00ab
  • プロパティファイル中にUTF-8エンコーディングで日本語文字を記述 (1), (2)
  • gradle がプロパティファイルをWindows英語版のロケール(Cp1252)として解釈し(3)、ユニコードスケープを生成(4)
  • (4)のユニコードエスケープを日本語ロケールで実行したScene Builderが画面に表示(結果、(3)の文字が表示)

バグの解決案

想定した解決案を次に列挙。他にもあるかも

  • 案1) Gradleがユニコードエスケープをしないようにビルド設定を修正する[#247-17]
  • 案2) Gradleが正しくユニコードエスケープをするようにビルド設定を修正する[#247-15]
  • 案3) ソースリポジトリのプロパティファイルを、UTF-8ではなくユニコードエスケープ済みに修正する

案1は、別な問題が生じたため却下
案2は、OK
案3は、JDK 9以降から削除されてしまったnative2asciiコマンドが必要となるので、最後の手段としていた。案2がOKとなったので案3は未実施。

Scene Builderへの修正案の提示(プルリクエスト)

プルリクエストの反映

プルリクエストに対し、
Gluon CLA(Gluon Individual Contributor License Agreement)に署名を求められたのでざっと読んで署名。
https://docs.google.com/forms/d/16aoFTmzs8lZTfiyrEm8YgMqMYaGQl0J8wA0VJE2LCCY/viewform?edit_requested=true

CLAの中を見ると、会社の業務としてソフトウェア開発をしている中でプルリクエスト(修正コード)を提供する場合は、そのコードが法人著作となるので雇用者(会社)がそのコードの知的財産権を放棄するか、雇用者(会社)がGluonとの法人CLAを結ぶかが必要となるようです。

しばらくすると、プルリクエストがマージされました。
これで次回リリースから日本語が化けなくなるかと期待。
→ MSIパッケージへのビルド手順が見えないので一抹の不安あり。

問題解消

プルリクエストがマージされた後のリリースとなる Scene Builder 16 で問題が解消されました。


ファイル

SceneBuilderScreen-1.jpg (532 KB) SceneBuilderScreen-1.jpg 文字化け画面 高橋 徹, 2021/02/06 11:35
SceneBuilderApp_ja.properties (100 KB) SceneBuilderApp_ja.properties SceneBuilder-15.0.1-all.jarに含まれているファイル 高橋 徹, 2021/02/06 21:46
clipboard-202102062151-geowf.png (2.34 KB) clipboard-202102062151-geowf.png 高橋 徹, 2021/02/06 21:51
clipboard-202102070929-vhvsd.png (164 KB) clipboard-202102070929-vhvsd.png 高橋 徹, 2021/02/07 09:29

関連するチケット 1 (1件未完了0件完了)

関連している バグ #89: Scene Builder 10.0.0 及び 11.0.0 Windowsインストーラー版でメニュー(日本語)が化ける進行中高橋 徹2018/08/25

操作

高橋 徹 さんが約3年前に更新

  • 関連している バグ #89: Scene Builder 10.0.0 及び 11.0.0 Windowsインストーラー版でメニュー(日本語)が化ける を追加

高橋 徹 さんが約3年前に更新

高橋 徹 さんが約3年前に更新

SceneBuilderアプリケーションが内蔵しているJava実行環境の調査

Scene Builder 15.0.1 Windowsインストーラー版をインストールすると、
C:\Program Files\Scene Builder\ ディレクトリにインストールされた。
中を見ると、JDKの自己完結型アプリケーションパッケージとして構成されている。

C:\Program Files\Scene Builder\
  ├ app\
  │   ├ SceneBuilder-15.0.1-all.jar
  │   └ SceneBuilder.cfg
  ├ runtime\
  │   ├ bin\
  │   ├ conf\
  │   ├ legal\
  │   └ lib\
  ├ SceneBuilder.exe
  └ SceneBuilder.ico

runtime ディレクトリ下には、JavaVMが一式入っており、そのバージョンは、OpenJDK 15.0.2

C:\Program Files\SceneBuilder>runtime\bin\java --version
openjdk 15.0.2 2021-01-19
OpenJDK Runtime Environment AdoptOpenJDK (build 15.0.2+7)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 15.0.2+7, mixed mode)

SceneBuilderアプリケーションの日本語表示に使用するリソース調査

画面に表示される化けてしまった文字列は、日本語ロケールで使用するリソース(プロパティファイル)に定義された文字列である。そこで、SceneBuilderの中に含まれる日本語ロケールのプロパティファイルを調べてみる。

SceneBuilder-15.0.1-all.jarファイルの中の次のパス

com\oracle\javafx\scenebuilder\app\i18n\SceneBuilderApp_ja.properties

SceneBuilderApp_ja.properties

SceneBuilderの画面のファイルメニューは次の様に文字化けしている。

SceneBuilderApp_ja.properties ファイルの中で、ファイルメニューの文字列を定義しているプロパティは次の行

menu.title.file = \u00e3\u0192\u2022\u00e3\u201a\u00a1\u00e3\u201a\u00a4\u00e3\u0192\u00ab(F)

ASCII文字以外(日本語文字)がユニコードエスケープされている。
各ユニコード文字を見ると、次の通り画面上で文字化けしているコードそのものとなっている。

ユニコードエスケープ 文字
\u00e3 ã
\u0192 ƒ
\u2022
\u00e3 ã
\u201a
\u00a1 ¡
\u00e3 ã
\u201a
\u00a4 ¤
\u00e3 ã
\u0192 ƒ
\u00ab «

SceneBuilderのソースコードリポジトリに格納されているプロパティファイル(次のURL)
https://github.com/gluonhq/scenebuilder/blob/15.0.1/app/src/main/resources/com/oracle/javafx/scenebuilder/app/i18n/SceneBuilderApp_ja.properties

ファイルメニューの文字列定義は次

menu.title.file = ファイル(F)

ということで、ソースファイルではUTF-8エンコーディングとなっているプロパティファイルがインストーラでインストールされるアプリケーションJARファイルの中ではユニコードエスケープされて、しかも別な文字となっている(いわゆる文字化け)。

日本語以外のプロパティファイルの調査

文字列リソースを定義するプロパティファイルはSceneBuilderには次の3つがある。

  1. SceneBuilderApp.properties
  2. SceneBuilderApp_ja.properties
  3. SceneBuilderApp_zh_CN.properties

1. は英語(ASCIIコード)
2. は問題となっている日本語
3. は中国語

ここで、1.と3.はソースコード上でもユニコードエスケープされているが、2.はユニコードエスケープされていない。

高橋 徹 さんが約3年前に更新

高橋 徹 さんが約3年前に更新

UTF-8文字コード、SJIS(ここではWindows-31JをSJISと言う)文字コード

「ファイル」は、UTF-8文字コードでは次のバイナリで表現される

文字 UTF-8 Unicode
0xe38395 0x30d5
0xe382a1 0x30a1
0xe382a4 0x30a4
0xe383ab 0x30eb

UTF-8のコードを、SJISとして解釈してしまった場合を想定すると、

SJIS 文字
0xe383
0x95e3
0x82a1
0xe382
0xa4
0xe383
0xab

これは文字化けで表示されたものとは異なるので、単純にUTF-8符号化されたバイナリコードをSJISで解釈したものではないことが分かる。

UTF-8文字コード を、SJISとして解釈した後、その文字をユニコードエスケープしてみたら

文字 ユニコードエスケープ
\u7e5d
\u8f14
\u3043
\u7e67
\uff64
\u7e5d
\uff6b

高橋 徹 さんが約3年前に更新

Scene Builderのソースコード(GitHubリポジトリ)は、Gradleビルドツールの設定が含まれている。

app\build.gradle を見ると、次の記述がある

processResources {
    def buildDate = new Date().format(buildDateFormat)
    from ('src/main/resources') {
        include '**/*.properties'
        expand([
            version: version,
            javaVersion: System.getProperty('java.runtime.version') + ', ' + System.getProperty('java.vendor'),
            buildDate: buildDate
        ])
        filter(EscapeUnicode)
    }
    into buildDir
}

ここで、 src/main/resources 以下にある ファイル名 *.properties について

        filter(EscapeUnicode)

を適用している。

高橋 徹 さんが約3年前に更新

ビルドの実施

SceneBuilder 15.0.1が内蔵しているJDKと同じバージョンでビルドを実施してみる。
OSは、日本語版Windows 10なのでシステムエンコーディングはShiftJIS(Windows-31j)となる。

gradlew assemble
  :

app\build\resources\main\com\oracle\javafx\scenebuilder\app\i18n の下に、SceneBuilderApp_ja.properties が置かれる。

中身はユニコードエスケープされているが、SceneBuilder 15.0.1のインストーラーでインストールしたものとは異なっている。

menu.title.file = \u7e5d\u8f14\u3043\u7e67\uff64\u7e5d\uff6b(F)

これは、UTF-8文字をShiftJISで解釈した時の文字と同じになっている。

仮説)
英語版Windows 10のシステムエンコーディングでビルドを実行すると、別なエンコーディングで解釈する。

高橋 徹 さんが約3年前に更新

Windows 10のロケールを日本から米国に変更してみた。

  • コントロールパネルの [時計と地域] > [地域] で「地域」ダイアログを表示
  • [管理]タブ > [システムロケールの変更」ボタンを押し、「地域の設定」ダイアログを表示
  • [現在のシステムロケール]欄を、[英語(米国)]に変更

Javaのシステムプロパティでfile.encodingを調べるとMS932となっていた。どうやらJavaが認識するロケールは別にあるらしい。

高橋 徹 さんが約3年前に更新

高橋 徹 さんが約3年前に更新

Windows 10のロケールを日本から米国に変更してみた(別法)。

[スタート]メニュー > [設定] > [時刻と言語] > [地域] で、地域設定を [英語(米国)]に変更

再起動は促されないので、コマンドプロンプトで再度 jshell 起動しデフォルトエンコーディングを確認

D:\work> jshell
|  JShellへようこそ -- バージョン15.0.1
|  概要については、次を入力してください: /help intro

jshell> System.out.println(System.getProperty("file.encoding"))
Cp1252

jshell>

デフォルトエンコーディングはCp1252になった。これは、Microsoft Windowsの英語版、西欧言語版のラテン文字。

Windows 英語版ロケールでビルドを実施

D:\work\scenebuilder> gradlew assemble
  :

app\build\resources\main\com\oracle\javafx\scenebuilder\app\i18n\SceneBuilderApp_ja.properties の内容確認(ファイルメニューの文字列)

menu.title.file = \u00e3\u0192\u2022\u00e3\u201a\u00a1\u00e3\u201a\u00a4\u00e3\u0192\u00ab(F)

おお、やっと文字化けの原因となる日本語ロケールのリソースバンドル・プロパティファイルを再現することができた。

高橋 徹 さんが約3年前に更新

  • 説明 を更新 (差分)
  • 担当者高橋 徹 にセット

高橋 徹 さんが約3年前に更新

高橋 徹 さんが約3年前に更新

高橋 徹 さんが約3年前に更新

GradleがWindows環境で正しくユニコードエスケープできるようビルド設定を変更

  • フォークしたリポジトリのクローンに、ブランチ fix-194-b を作成
  • app/build.gradle
    @@ -46,6 +46,7 @@ processResources {
                 javaVersion: System.getProperty('java.runtime.version') + ', ' + System.getProperty('java.vendor'),
                 buildDate: buildDate
             ])
    +        filteringCharset = 'UTF-8'
             filter(EscapeUnicode)
         }
    

生成されたプロパティファイルは文字化けしていない!!

高橋 徹 さんが約3年前に更新

ユニコードエスケープをするコマンドが・・・

ユニコードエスケープをするJDKのコマンド native2ascii は、JDK 9以降削除されているので使えない。

高橋 徹 さんが約3年前に更新

Gradleがユニコードエスケープをしないようにビルド設定を修正(失敗)

  • フォークしたリポジトリのクローンに、ブランチ fix-194-a を作成
  • app/build.gradleの修正
    --- a/app/build.gradle
    +++ b/app/build.gradle
    @@ -46,7 +46,6 @@ processResources {
                 javaVersion: System.getProperty('java.runtime.version') + ', ' + System.getProperty('java.vendor'),
                 buildDate: buildDate
             ])
    -        filter(EscapeUnicode)
         }
         into buildDir
     }
    

メモ)build.gradleはリポジトリ中で改行コードがCRLFになっている。

filter(EscapeUnicode)を削除してビルドを実行すると、プロパティファイルは別な壊れ方をした。
menu.title.file = 繝輔ぃ繧、繝ォ(F)

推測:リソースファイルをコピーする際、SJIS解釈が入っている

高橋 徹 さんが約3年前に更新

高橋 徹 さんが約3年前に更新

  • 説明 を更新 (差分)
  • ステータス進行中 から 解決 に変更
  • 進捗率50 から 80 に変更

高橋 徹 さんがほぼ3年前に更新

他の形式にエクスポート: Atom PDF