ページテンプレートと日本語
Up to table of contentsZopeのコア開発者に、マルチバイトコード圏の開発者がほとんどいないため、Zopeの仕組みが変更されるたびにマルチバイトコード関連の問題が起きています。この問題は、ZMIにおけるエンコードと、公開ページ表示時のエンコードの問題の2つがあります。
問題は大きく分けて、 Zope-2.7系, Zope-2.8,2.9系, Zope-2.10系 に分類することが出来ます。
Zope-2.7系
2.7系の問題
PageTemplateをZMI上で編集するときに日本語文字列を使用すると、保存後に文字列が文字実体参照に置き換えられてしまう問題があります。この問題は、ZopeがZMIで扱う文字コードを認識できていないために発生します。
2.7系の対策
そこで、ZMIで扱う文字コードを設定することでこの問題を回避することが出来ます。ZMIでルートのプロパティーに management_page_charset というプロパティーを追加してください。値には、そのサイトで扱う文字コードを設定します(例: utf-8)。設定方法について詳しくは、 ZopeでWebページを作る を参照してください。
Zope-2.8,2.9系
2.8,2.9系の問題
Zope-2.8系、Zope-2.9系 では、PageTemplate内に日本語文字列を使用すると、閲覧ページ表示時に以下のようなエラーが発生します:
'charmap' codec can't encode characters in position 11-24: character maps to
これは、Zope-2.8.0や2.9.0でZope内部の仕組みとしてPageTemplateをUnicode文字列として格納する仕組みが取り入れられたためです(詳細は Zope28PageTemplateIssue を参照)。この仕組みはPageTemplateに使われている文字列が一意にunicodeに変換できる前提で作られています。しかし、日本語だけで考えてもエンコードはeuc-jp,shift-jis,iso-2022jp,utf-8...とあり、変換元エンコードを自動的に見分けるのは難しい問題で、Zopeは全エンコードを見分ける仕組みを持っていません。このため、日本語文字列をunicodeに変換しようとした時点で、'charmap'コーデックが解釈に失敗して前述のエラーが発生します。
2.8,2.9系の対策
Zope-2.8.2以降、部分的な対策が行われ、 zope.conf に default-zpublisher-encoding 設定が追加されました。この値を utf-8 にしておくことで、PageTemplate内の文字列をレンダリングする段階でutf-8として扱われるようになり、エラーが起こらなくなります。
なお、zope.conf内には default_zpublisher_encoding とコメントアウトで記述されている場合がありますが、区切り文字はアンダースコアではなく、ハイフンで区切る default-zpublisher-encoding が正しい表記です。この綴り間違いは、Zope-2.8系では2.8.6以降、Zope-2.9系では2.9.1以降で修正されています。
Zope-2.10系
2.10系の問題
Zope-2.10.0でPageTemplateの実装がzope3のコードに入れ替わったことによる対応の不足により、Zope-2.10.0, 2.10.1では management_page_charset や default-zpublisher-encoding を正しく設定していても、日本語等の非Asciiコードを含むページテンプレートを編集画面で保存できない問題がありました。
2.10.2での状況
Zope-2.10.2で問題は解消され、PageTemplate編集画面の入力文字列がmanagement_page_charsetに設定された文字コードとして解釈されるようになりました。
2.10.0, 2.10.1での対策
積極的な理由がなければZope-2.10.2以降の使用をお勧めします。どうしても2.10.0,2.10.1を使わなければいけない場合は、Zope-2.10.2のコードを持ってくるか、暫定的に手動で以下のパッチを当てる方法がありますが、自己責任でお願いします。以下のパッチにより、management_page_charsetを使うように修正します:
--- Zope-2.10.0/lib/python/Products/PageTemplates/PageTemplate.py.orig Tue Oct 03 15:08:17 2006
+++ Zope-2.10.0/lib/python/Products/PageTemplates/PageTemplate.py Sun Nov 12 13:50:14 2006
@@ -127,3 +127,16 @@
if not hasattr(getattr(self, 'aq_base', self), 'is_html'):
return self.content_type == 'text/html'
return self.is_html
+
+ def pt_edit(self, text, content_type):
+ if content_type:
+ self.content_type = str(content_type)
+ if hasattr(text, 'read'):
+ text = text.read()
+ charset = getattr(self, 'management_page_charset', None)
+ if isinstance(charset, type(text)):
+ try:
+ unicode(text, 'us-ascii')
+ except UnicodeDecodeError:
+ text = unicode(text, charset)
+ self.write(text)
This FAQ applies to: Zope 2.10.x, Zope 2.9.x, Zope 2.8.x, Zope 2.7.x