バグ #257
未完了Scene Builder 15.0.1 Windowsインストーラー版でメニュー(日本語)が化ける
80%
説明
現象¶
Scene Builder 15.0.1 Windows版を、Windows 10 日本語版の上で実行すると、画面に表示される文字が化けてしまっている。
再現手順¶
- Gluon社のScene Builder配布サイトから入手した Scene Builder 15.0.1 Windowsインストーラー版を日本語版Windowsにインストール
https://gluonhq.com/products/scene-builder/ - Scene Builderを実行
関連¶
- Scene Builder 10.0、11.0で発生した事象[#89]が解決されていない。
- scenebuilder の githubリポジトリのissue
https://github.com/gluonhq/scenebuilder/issues/194
調査結果¶
- 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への修正案の提示(プルリクエスト)¶
- 本家Scene BuilderのGitHubリポジトリを個人GitHubにフォーク
https://github.com/torutk/scenebuilder - ローカルリポジトリ(自宅PC)にクローン
- ブランチ fix-194-b を作成
- 修正を入れてローカルリポジトリにコミットし、個人GitHubフォークにプッシュ
https://github.com/torutk/scenebuilder/commit/ed4329975b47b4b9a4caecddd35315755e6c2638 - プルリクエストを作成
https://github.com/gluonhq/scenebuilder/pull/322
プルリクエストの反映¶
プルリクエストに対し、
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 で問題が解消されました。
ファイル
高橋 徹 さんが約4年前に更新
- ファイル SceneBuilderApp_ja.properties SceneBuilderApp_ja.properties を追加
- ファイル clipboard-202102062151-geowf.png clipboard-202102062151-geowf.png を追加
- ステータス を 新規 から 進行中 に変更
- 進捗率 を 0 から 50 に変更
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
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つがある。
- SceneBuilderApp.properties
- SceneBuilderApp_ja.properties
- SceneBuilderApp_zh_CN.properties
1. は英語(ASCIIコード)
2. は問題となっている日本語
3. は中国語
ここで、1.と3.はソースコード上でもユニコードエスケープされているが、2.はユニコードエスケープされていない。
高橋 徹 さんが約4年前に更新
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 |
高橋 徹 さんが約4年前に更新
- 説明 を更新 (差分)
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)
を適用している。
高橋 徹 さんが約4年前に更新
ビルドの実施
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のシステムエンコーディングでビルドを実行すると、別なエンコーディングで解釈する。
高橋 徹 さんが約4年前に更新
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)
おお、やっと文字化けの原因となる日本語ロケールのリソースバンドル・プロパティファイルを再現することができた。
高橋 徹 さんが約4年前に更新
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) }
生成されたプロパティファイルは文字化けしていない!!
高橋 徹 さんが約4年前に更新
- 説明 を更新 (差分)
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解釈が入っている