Trac のファイル文字化け修正の記録
はじめに
Trac のレポジトリブラウザは、1つのプロジェクトにエンコーディングが混在(コミットメッセージが utf-8 で、登録ファイルがShiftJISなど)しているとファイル内容の表示が文字化けすることがあります。これを修正します。
下記参考資料のパッチをそのまま適用しました。
参考資料
Tracはリポジトリブラウザによるファイル表示や添付ファイルの表示の際、
MIMEタイプの"charset="属性による判定
BOMコードによるUnicode判定
の順に判定を行い、 判定不能の場合は設定ファイルの[trac]default_charsetを使用します。
プロジェクト内で文字コードが統一されていれば [trac]default_charsetを適切に設定することで問題無いのですが、 Windows向けとLinux向けのソースが混在するプロジェクトを管理する必要が生じたため、以下のパッチを作成しました。
既存の判定処理で判定不能な場合に追加で以下の判定処理を行います。EmacsやVIMのエンコード指定が存在すれば使用する。
(例: "# -- coding: ENCODING_NAME --"あるいは"# vim:fileencoding=ENCODIG_NAME")
chardetモジュール(Universal Encoding Detector)が利用可能であれば、これを用いて判定する。
これでも判定できない場合、[trac]default_charset設定を使用します。
環境
- Ubuntu 18.04LTS
- Trac 1.2
昔はTracのインストールは大変でしたが、今は apt install 一発で済むので楽です.
sudo apt install subversion subversion-tools libapache2-mod-svn
sudo apt install trac libapache2-mod-wsgi
修正手順
# Tracのパッチ対象を探して、そこへ移動する.
locate trac/mimeview/api.py
cd /usr/lib/python2.7/dist-packages/trac/mimeview/
# バックアップを作成する.
sudo cp -p api.py api.py.orig
sudo cp -p api.pyc api.pyc.orig
# エディタにて手動でパッチ修正する.
# 参考資料のdiffは差分元の内容が古くて前後のコンテキストが一致せず、patch や git apply で扱えなかった.
sudo vim api.py
# 文字エンコーディング判定ライブラリを入れる(Ubuntu18.04LTSでは最初から入っている)
sudo apt install python-chardet
# 修正結果をコンパイルして、アパッチを再起動する.
sudo python -m py_compile api.py
sudo systemctl restart apache2
今回の修正差分
次回は、これを patch
に与えて自動でパッチ修正できるはず.
diff --git a/api.py b/api.py
index 856ba26..6c1a248 100644
--- a/api.py
+++ b/api.py
@@ -76,6 +76,19 @@ from trac.util import Ranges, content_disposition
from trac.util.text import exception_to_unicode, to_unicode
from trac.util.translation import _, tag_
+# --- PATCH START hkuno from http://blog.livedoor.jp/yamamb/archives/50613027.html
+# For charset detection.
+CHARSET_RE = re.compile(r'coding[=:]\s*(\S+)')
+
+try:
+ # Universal Encoding Detector
+ # http://chardet.feedparser.org/
+ import chardet
+ CHARDET_CONFIDENCE_LIMIT = 0.8
+ CHARDET_MAX_SAMPLE = 1000
+except ImportError:
+ pass
+# --- PATCH END
__all__ = ['Context', 'Mimeview', 'RenderingContext', 'get_mimetype',
'is_binary', 'detect_unicode', 'content_to_unicode', 'ct_mimetype']
@@ -920,6 +933,16 @@ class Mimeview(Component):
utf = detect_unicode(content)
if utf is not None:
return utf
+ # --- PATCH START hkuno from http://blog.livedoor.jp/yamamb/archives/50613027.html
+ m = CHARSET_RE.search(content, 0, 200)
+ if m:
+ return m.group(1)
+
+ if 'chardet' in globals():
+ result = chardet.detect(content[:CHARDET_MAX_SAMPLE])
+ if CHARDET_CONFIDENCE_LIMIT < result['confidence']:
+ return result['encoding']
+ # --- PATCH END
return self.default_charset
@property