reviewboard 用post 方式发起reveiew时出现查看diff文件时,无法正常显示中文,分析和解决情况如下。另个上传diff无法显示问题,在库属性选项里,设置下库的字体格式就行了。
先说下分析过程,主要是python对中文的处理过程。涉及到decode 和encode函数。
encode是将str编码成指定的编码格式。一般WIN下是GBK,Linux下是GB2312,ASCII码。当然还有一些文本工具直接保存成UTF-8格式。
decode是将str转换成unicode编码,因为python的内置函数只识别unicode。
但是decode的参数,需要根据源值的编码类型来传递,如果源值是gbk,就是decode("gbk");utf-8就填decode("utf-8")
要正确输出,输出的编码格式需要和源值的编码类型相同。就是说在python内部,由于需要decode成unicode,但是在输出时又需要encode成源编码类型。
同时将源值,直接encode某个编码是不行的。如果将一个str直接编码成另一种编码,会先把str解码成unicode,采用的编码为默认编码,一般默认编码是ascii,所以第一次转换的时候会出错。就是说将源码先编码成ASCII再编码成unicode。很多中文就会报out of range错误。所以需要先decode ,再encode。
现在看来文件保存时,svn上保存的revision是UFT-8格式,不需要进行转换,就能直接正常输出中文。而本地的change文件,保存的是Linux下的GB2312.需要进行转换。
解决方法:
vi /usr/lib/python2.7/site-packages/ReviewBoard-2.0-py2.7.egg/reviewboard/reviews/models/base_review_request_details.py
找到DiffSet.objects.create_from_data,添加如下代码:
# add
if isinstance(commit.diff,unicode):
commit.diff=commit.diff
else:
commit.diff=commit.diff.decode("GB2312").encode("GB2312")
/*(这是注释,代码里要去掉)commit.diff做为STR类型的字符流,需要编码成linux下的GB2312.
但是直接转换另种编码,会首先decode成unicode,采用的编码类型默认是ascii码,就是将str从ASCII编成Unicode
这个时候中文字符对应的ASCII码很多都有问题,所以先强制采用GB2312,从GB2312解码成Unicode。
然后再从unicode变成GB2312*/
#add end
DiffSet.objects.create_from_data(
repository=self.repository,
diff_file_name='diff',
diff_file_contents=commit.diff,/*这里进行了更改,直接赋值,不再转换。这个注释,代码里去掉*/
parent_diff_file_name=None,
parent_diff_file_contents=None,
diffset_history=self.get_review_request().diffset_history,
basedir='/',
request=None)