雑記

2000|01|
2003|05|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|
2007|01|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|09|11|
2009|02|03|05|06|07|08|10|11|12|
2010|01|03|04|05|06|07|08|09|10|
2011|05|06|09|10|
2012|03|07|09|12|
2013|01|02|04|05|07|08|10|11|
2014|04|05|08|10|12|
2015|01|05|
2016|09|

2009-07-08 [長年日記]

[Ruby]「〜」のUTF-8からISO-2022-JPへの変換で文字化け

Ruby on Rails 1.2.6 + GetText でActionMailerを使ってフォームから入力された内容をメールで送信するような実装をしていたところ、「〜」を入力すると文字化けするとの連絡が。

調べたところ、Windowsで「〜」を入力すると、fullwidth tilde(U+FF5E, EFBD9E)のコードが渡されるんですが、GetTextから呼ばれているrubyのNKFモジュールはこれをJIS補助漢字の(2237)に変換するため、補助漢字を表示できないメールクライアントでは文字化けするようでした。より文字化けしにくいと思われるJIS基本漢字の(2141)の方はwave dash(U+301C, E3809C)に割り当てられているようです。 さらに探るとどろどろした歴史が垣間見えてきたのでこれはこういうもんだと納得することに。

かといって、全Windowsユーザーがらみで発生する問題を無視するわけにもいかないので、fullwidth tildeをwave dashに変換してしまうことに。

具体的には、

1. 以下の内容のファイルをRAILS_ROOT/lib/gettext_ext.rbという名前で保存

if defined? ActionMailer
  module ActionMailer #:nodoc:
    class Base #:nodoc:
      def create!(*arg) #:nodoc:
        create_without_gettext!(*arg)
        if Locale.get.language == "ja"
          require 'nkf'
          @mail.subject = base64(@mail.subject)
          part = @mail.parts.empty? ? @mail : @mail.parts.first
          if part.content_type == 'text/plain'
            part.charset = 'iso-2022-jp'
            if NKF.guess(part.body) == NKF::UTF8
               part.body = part.body.gsub("\xef\xbd\x9e", "\xe3\x80\x9c")
            end
            part.body = NKF.nkf('-j', part.body)
          end
        end
        @mail
      end
    end
  end
end

2. environment.rbに次の1行を追加

require 'lib/gettext_ext.rb'

3. Rails再起動で完了

ところで、

part.body = part.body.gsub("\xef\xbd\x9e", "\xe3\x80\x9c")

の行が

part.body.gsub!("\xef\xbd\x9e", "\xe3\x80\x9c")

では駄目だったんですけど、なぜ??