SonarQube Java rule の日本語化を試みる (軽い動作確認をした結果報告)


SonarQube の メニュ- 等は、java プロパティファイルにより、
多言語化対応がなされています。
各ルールについては、Japanese Pack - SonarQube Pluginsソースコード を見る限り、
一部日本語化されたルールがあって、
「あれ ? これルールも日本語化されるんじゃねえ ?」と思うのですが、特に日本語化されません。

メニュ-の日本語化はもちろん、
ルールに日本語化は確実にできたほうがよいので、なんとかできないか試みた結果を記載します。


日本語化したい背景

  • できない人対策
    Sonar を使って英語の警告が出ていたとしても、英語が読めてしまったり、
    あまり得意でなくても Web 検索を駆使し、解決ができる人がいます。
    その人には特にルールの日本語訳はあまり必要ないし、そうあるのが理想に思います。
    しかしながら、職業プログラマの中には英語が読めず、Web 検索も駆使できない人が(たまに)存在し、
    その人は、英語で指摘事項述べられても、どうしようもなかったりします。
    いわゆる SI 的な話だと、商流を下れば下るほど、単金が下がれば下がるほど、
    できない人の割合が高まる傾向がありますが、(個人調べ) 、 いろいろな理由から、事前に排除しておくことが難しかったりします。
    そのため、できない人向けの救済措置が必要だと考えます。1
    [1] 勿論、そうでないできる技術者の方もたくさんいます。

ルールが日本語化されない理由

Github をまさぐった感じですと、
SonarQube の ルールファイルの国際化処理には、以下の Java クラスが関係しているように、思われます。

ソースを見ていると、Locale を引数に取るメソッドが軒並み以下のように、@Deprecated が付与されていて、
且つ、引数の Locale は捨てられております。

  /**
   * @deprecated in 4.1. Rules are not localized anymore. See http://jira.sonarsource.com/browse/SONAR-4885
   */
  @Override
  @Deprecated
  public String getName(String repositoryKey, String ruleKey, Locale locale) {
    return getName(repositoryKey, ruleKey);
  }

コメントに See http://jira.sonarsource.com/browse/SONAR-4885 の記載があり、対象の Issue を見ると、

I18n of rule descriptions and titles is a costly feature that is barely used. Dropping this support will allow to simplify code and to prevent wasting time on nasty bugs.

ルールの説明とタイトルのほとんどは、あまり使われていないコストの高い機能です。  
このサポートを中止することで、コードを単純化し、厄介なバグに時間を浪費するのを防ぐことができます。

というような内容が記載されていて、
いやいや、結構重要な機能だと思うから、あきらめないで作ってくれよと思いましたが、
関連 Issue に、

Plugin が削除された時に、ルールも消えるので、過去の SonarQube 上の、
ルールが閲覧できるように、Sonar 起動時に、DB 上に保持するようにしたようなことが書かれており、
確かに一筋縄ではいかなそうな気がしてみました。


  • 案1 ルール html、 ルール json の日本語ファイルを作り、 英語ファイルと差し替えてみる。 ルールファイルを翻訳し、Sonar の jar 内に含まれる英語ルールから差し替えて動かしてみます。
    起動時にルールを DB に登録しているようなので、この段階でダメな可能性はあります。

  • 案2 DB に格納されたルール定義を直接書き換えてみる。
    案1で駄目なら、案2でルールファイルが登録されているテーブルの内容を日本語に書き換えます。
    正直、内部構造変更の影響を案1より、受けるので、辛すぎるかもしれません。

  • 案3 Rule の画面表示前に差し込む隙を作る。
    Rule の内容が表示される直前に、Rule ファイルを参照する口を作る。
    Eclipse Pleiades のような仕組みのイメージです。

  • 案4 http://jira.sonarsource.com/browse/SONAR-4885 でなかったことになった Rule ファイル国際化を実装する
    正攻法で頑張るイメージです。

案4 が最終系と思いますが、どの案でも、日本語ルールファイルは必要になるため、
案1 が上手くいきそうかを試してみます。


案1 を試す。

まず、1ファイル差し替えてみて動作するかを検証してみます。
jar 内のファイル差し替えは以下のQiita記事が参考になりました。

0. 前提

小生は MAC を使用しており、こちら の手順でインストールを行っています。
インストール後の、SonarQube のディレクトリは、
/usr/local/Cellar/sonarqube/6.1 となっており、
その前提で話が進みます。

1. jar のファイルから、ルールファイルを取得

jarファイルから、ルールファイルを取得します。

  • 作業ディレクトリ作成し、ディレクトリ移動
    mkdir WORK
    cd WORK
    
  • sonar-java-plugin-4.0.jar を 作業ディレクトリに持ってきて解凍
    cp /usr/local/Cellar/sonarqube/6.1/libexec/lib/bundled-plugins/sonar-java-plugin-4.0.jar . 
    cp /usr/local/Cellar/sonarqube/6.1/libexec/extensions/plugins/sonar-java-plugin-4.3.0.7717.jar .
    
  • 中身を確認 2

    jar tf sonar-java-plugin-4.3.0.7717.jar | grep java-checks
    ------------------------------------------
    META-INF/lib/java-checks-4.3.0.7717.jar
    -----------------------------------------
    
    [2] java-checks-4.3.0.7717.jarに、ルールファイルが含まれています。

  • java-checks-4.3.0.7717.jar を 取り出し、オリジナルをバックアップ。

    jar -xvf sonar-java-plugin-4.3.0.7717.jar META-INF/lib/java-checks-4.3.0.7717.jar
    cd META-INF/lib/
    cp java-checks-4.3.0.7717.jar java-checks-4.3.0.7717.jar.org
    

  • 中身の確認

    jar tf java-checks-4.3.0.7717.jar | grep org/sonar/l10n/java/rules/squid/S | head
    -----------------
    org/sonar/l10n/java/rules/squid/S100_java.html
    org/sonar/l10n/java/rules/squid/S100_java.json
    org/sonar/l10n/java/rules/squid/S101_java.html
    org/sonar/l10n/java/rules/squid/S101_java.json
    org/sonar/l10n/java/rules/squid/S103_java.html
    org/sonar/l10n/java/rules/squid/S103_java.json
    org/sonar/l10n/java/rules/squid/S104_java.html
    org/sonar/l10n/java/rules/squid/S104_java.json
    org/sonar/l10n/java/rules/squid/S105_java.html
    org/sonar/l10n/java/rules/squid/S105_java.json
    -----------------
    

コンソールには出てませんが、以下のファイルを翻訳対象をしました。

org/sonar/l10n/java/rules/squid/S2221_java.html
org/sonar/l10n/java/rules/squid/S2221_java.json

  • ファイル取り出し
    jar -xvf java-checks-4.3.0.7717.jar org/sonar/l10n/java/rules/squid/S2221_java.html
    jar -xvf java-checks-4.3.0.7717.jar org/sonar/l10n/java/rules/squid/S2221_java.json
    

2. jar内のファイルの書き換え、sonarqubeへコピーする。

取り出したファイルを翻訳し、保存し、 jar 内のファイルを書き換えます。

  • ファイル書き換え

    jar -uf java-checks-4.3.0.7717.jar org/sonar/l10n/java/rules/squid/S2221_java.html
    jar -uf java-checks-4.3.0.7717.jar org/sonar/l10n/java/rules/squid/S2221_java.json
    

  • jarバックアップと、jarファイルの書き換え、sonarqube内にコピーする。

cd ../../
cp sonar-java-plugin-4.3.0.7717.jar sonar-java-plugin-4.3.0.7717.jar.org
jar -uf sonar-java-plugin-4.3.0.7717.jar META-INF/lib/java-checks-4.3.0.7717.jar
cp sonar-java-plugin-4.3.0.7717.jar /usr/local/Cellar/sonarqube/6.1/libexec/extensions/plugins/sonar-java-plugin-4.3.0.7717.jar 

3. SonarQube起動して画面表示を確認する。

SonarQubeを起動し、反映されているか確認します。

  • SonarQubeを起動して、ルール説明ウィンドウを開いてみる。
    sonar console
    

S2221 Rules's View

あっさり変わりました。。
もしかしたら別に普通に使えるのかもしれません。

厳密には、Rule 説明窓の内容はHTML、JSONの内容の変更が効いてきていて、
Ruleの、Index (Issue?) の部分については英語のママです。3
[3] Catch a list of specific exception subtypes instead. のことです。

文言 Catch a list of specific exception subtypes instead. がどこで設定されているのか気になったので、
Github をまさぐったところ、以下のソースコードがヒットしました。

対象箇所の抜粋ですが、
Iessue として、ソース直書きでメッセージを登録しているようです。4
[4] propetiesファイルで外だしできれば、日本語化が可能かもしれません。

  @Override
  public void visitNode(Tree tree) {
    TryStatementTree tryStatement = (TryStatementTree) tree;
    for (CatchTree catchTree : tryStatement.catches()) {
      TypeTree catchType = catchTree.parameter().type();
      if (catchesException(catchType, tryStatement.block())) {
        reportIssue(catchType, "Catch a list of specific exception subtypes instead.");
      }
    }
  }

4. SonarQube の Database 上の起動して画面表示を確認する。

SonarQube のデータベースに接続して、翻訳した結果データがどうなっているのか確認します。

  • SQL ルール定義は、rules というテーブルに設定されてます。

        select 
               plugin_name,
               name
        from rules 
        where 
               plugin_name = 'squid' 
               and 
               name = '"Exception" 呼び出されたメソッドで必要とされないときに捕まえるべきではない'
        order by name;
    

  • OUTPUT 日本語化したルールが設定されているのが確認できました。

     plugin_name |                                    name                                    
    -------------+----------------------------------------------------------------------------
     squid       | "Exception" 呼び出されたメソッドで必要とされないときに捕まえるべきではない
    (1 row)
    


まとめ

案1 ルールファイルを翻訳して、英語ファイルと入れ替える で、日本語化できました。
動作確認等厳密にできたわけではないですが、
いけそうに思われます。
ある特定の文字列だと登録できない。
別の機能で不具合が出るなども考えられますが、翻訳ファイルだけはあっても困らないので、
ちまちま作っていくのも悪くない気がします。
以上です。

コメント