Rubyのエラーメッセージを日本語に差し替えてみた

はじめに

Rubyの初学者の方から「エラーメッセージの読み方がよくわからない」という話を聞き、「Rubyのエラーメッセージを日本語化できないか」試してみた記事です。

作ったもの

Konnyakuというgemを作りました。

github.com

rubygems.org

gem install konnyakuでインストールできます。

このgemではRubyのエラーメッセージを日本語に変換して出力することができます。 例えば、以下のようなコードがあったとします

puts Hoge # => 未定義の定数 Hogeがputsに渡されている

このコードを実行すると以下のようなエラーが表示されます

uninitialized constant Hoge (NameError)

実行結果: [Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ

定義されていない定数Hogeを参照しているのでエラーになっているわけですね 慣れていれば問題はないのですが、初学者の方には英語表記であるため読みにくさを感じるようです

そこで、Konnyaku出番です! 先ほどのコードにrequire "konnyaku"を追加すると以下のようにエラーメッセージが日本語で表示されます

require "konnyaku"

p Hoge
#=> 例外:NameError が発生しました
#=> ソースコード: bug.rb の 3 行目にエラーの原因があります
#=> 定義されていない定数 Hoge があります

Konnyakuを使うことで、こんな感じでエラーメッセージを日本語として表示してくれます

やったこと

TracePointを使って、例外が発生したタイミングでエラーメッセージを日本語に強制的に書き換えることをしています。

class Konnyaku
  class << Konnyaku
    def run
        tp = TracePoint.new(:raise) do |tp|
            lineno = tp.lineno
            path   = tp.path
            msg = tp.raised_exception.message
            puts "例外:#{tp.raised_exception.class} が発生しました"
            puts "ソースコード: #{path}#{lineno.to_s} 行目にエラーの原因があります"
            
            msg = translate(msg) 
            puts msg
        end
        tp.enable
    end
  end
end

エラーメッセージなどの変換はKonnyaku.translateで以下のように無理やり置換しています(このへんもう少しきれいにしたい……)

class Konnyaku
  class << Konnyaku
    def translate(msg)
        case msg
            when /uninitialized constant/
                return msg.gsub(/#{$&}/, "定義されていない定数") + " があります"
            when /undefined local variable or method/
                return msg.gsub(/#{$&}/, "定義されていない変数またはメソッド").gsub(/ for /, "").sub(/`|'/, "").gsub(/for/, "") + " にあります"
            when /undefined method/
                return msg.gsub(/#{$&}/, "定義されていないメソッド").gsub(/ for /, "").gsub(/`|'/, "") + " にあります"
            when /uninitialized class variable/
                return msg.gsub(/#{$&}/, "初期化されていないクラス変数").gsub(/ for.+$/, "").gsub(/ in /, "") + " クラスにあります"
        end 
    end
  end
end

今後

とりあえず、対応していないエラーメッセージとかまだまだあるので追加していこうかと思います。 あと、テスト書けてないのでその辺も進めていきたい……