Zen Cart 乱码 解决方案

2011年07月06日 - KIRA

字号: 

成天跟程序 源码打交道, 想想能有什么事会让你抓狂无比! 当你无端端的面对一片一片 貌若天书的 蝌蚪文时 想想看~~ 会有一种什么样的感觉! 一定满脑袋小星星了吧, 没错 这就是传说中的乱码~ 说起乱码 首先我们得明白什么是文件的编码; 这里要详细把这事儿说明白了 估计 可以出本儿书了 这里简要引用 一段 百科介绍里的说法

计算机中的信息包括数据信息和控制信息,数据信息又可分为数值和非数值信息。非数值信息和控制信息包括了字母、各种控制符 号、图形符号等,它们都以二进制编码方式存入计算机并得以处理,这种对字母和符号进行编码的二进制代码称为字符代码(Character Code)。计算机中常用的字符编码有ASCII码(美国标准信息交换码)和EBCDIC码(扩展的BCD交换码)

有闲心 可以在百科里 稍为的对这个概念了解掌握一下 (技多不压身吗) http://baike.baidu.com/view/1204863.htm

So ' 上面啰嗦这么多 貌似都太大道理了 下面我们进入正题 在 Zen cart 应用中 经常会碰上乱码问题的困扰 造成 Zen cart 乱码的原因 经过我个人接触 Zen Cart 这么久以来 基本上 总结出 有下列这几种原因所至 下面 就一一列出 针对不同原因导致的乱码问题的解决方法:

程序声明编码 与 程序文件编码不一至 所至

出现这种情况的大多数是使用了 英文源版的程序 而又安装了中文模板或模块或其他国家地区小语种语言文件模板模块所至

英文源版程序 默认头部的声明编码格式为 ISO 8859-1 这是一种涵盖西欧大多国家地区语种语言字符的区域性编码

他的另外一种叫法 称之为 Latin-1 筒子们 这个叫法 很有必要记住 因为 以后我们或许会常用到他

而中文或其他小语种字符编码也有着自己对应的区域性编码 这些编码想要在国际上通用 哪就需要使用 UTF8编码格式

什么是 UTF8 编码 这里不赘述了 有兴趣可以参见本文最后给出的 科普 传送门

我们使用 Zen Cart 自然是要尽可能国际化 地域专属编码肯定不是首选, 所以一般我们使用 UTF8 编码,

So' 问题出来了, 当我们使用 UTF8编码的时候 这是一种国际化通用编码, 他兼容其他区域性编码 但其他区域性编码却不能兼容他,

也就是说 程序虽然是 Latin-1 编码 但当头部声明 UTF8 编码时 哪么一切显示都会很正常 而反过来 就不行了, 所以 就乱码了 , 知道了原因 哪就针对的去解决吧 !

对于因这种原因导致的乱码 解决方案相对容易 我们只要把文件编码与程序声明编码保持一至或保持一个向下兼容就可以了

动手操家伙 开干吧 打开 includes/languages/english.php 文件

查找 CHARSET 这个词,

找到这段代码 define('CHARSET' , 'iso-8859-1'); iso-8859-1 替换成 UTF-8

OK 问题解决!

需要注意的一点是 当有多个语言同时启用的时候 需要在 includes/languages/下 将不同的语言文件 全部替换 为 UTF-8

这里是前台的修改 如果后台也有乱码 哪么 还需要将后台 语言文件也作对应的修改

后台对应的修改 在 你的管理目录/includes/languages/english.php 或 其他对应的语言文件中

Tips 三个很重要的小提示:

1. 不要用记事本 去编辑 UTF8编码的 PHP 文件 哪 怕是简单的打开再关闭, 虽然对哪些以经去除了BOM信息的 文件来说 出错的机率较小, 但这不是一个好习惯. 很容易给你造成各种莫名其妙的小问题, 具体原因,可以度大娘哪问问谷大叔, 啥是 PHP文件中UTF8的BOM信息及为啥记事本不能处理这东西等之类的, 相信结果, 不会让你失望滴!

2. 保存文件时 请一定要注意看看保存文件对话框下面哪里的编码格式, 不要希里糊涂的 把本来是UTF8编码的文件保存成了 gbk或gb2312 编码. 什么,你哪没有, 只是显示出 ANSI 项, 好吧, 哪继续看后面的 科普传送门吧 ....

3. 当你按上面的方法修改了对应的语言文件时,乱码依然存在, 哪么在考虑到是否有因其他原因所至外,请先检查你修改的文件所对应的模板是否使用了 Zen Cart 的替代机制, 嗯~~~, 在我接触的很多童鞋中 貌似这样的马大哈不在少数!

PS: 本来打算一篇文章写完这个乱码的破事儿, 没曾想我这么能啰嗦, 貌似一篇文章说不完了, 好吧! 我败给我自己了, 今天先到这里, 其他的 待后续补上 !!! 在解决这个问题新的文字没有码好前, 先给出几个 常识性的 科普传送门

什么是 字符的编码: http://baike.baidu.com/view/1204863.htm

ISO 8859-1 编码 及其 涵盖的语种字符: http://baike.baidu.com/view/758577.htm

UTF8 编码: http://baike.baidu.com/view/742823.htm

ANSI : http://baike.baidu.com/view/185282.htm

有时候我们在应用 Zen Cart 时, 本来好好的, 就因为挪了个窝儿, 搬了个家, 他具然就乱码了, 出现这种问题 一般 是由于 新空间数据库 编码与程序配置声明编码不一至 而导致的问题.

这里又分两种情况
第一种情况 是程序配置 文件编码声明缺失或与新空间数据库 编码不相符
对于这种情况的解决相对较容易 也无甚风险
解决方法为 打开 includes/configure.php 文件
查找 define('DB_TYPE', 'mysql');
在其后 将 define('DB_CHARSET', ''); 项 赋予一个与当前数据库编码一至的编码
define('DB_CHARSET', 'utf8');
这是针对前台乱码的修改
后台 的修改也大同小异 唯一有所区别的是 文件的不同
后台的配置文件为 你的管理目录/includes/configure.php
可能有时候 这两个文件中 并无 define('DB_CHARSET', ''); 这项 ,
这没关系 没有就自己添加上好了 但一定要保持与当前数据库编码一至

说到这里 不得不提一下 Lightinthebox (LB/兰亭) 这个怪胎 ,
在某些目前尚不清楚的情况下, 如果包含LB模板的整站程序 两个配置文件中 没有这项
自己 手动 加上这项时 反到使程序无法正常和数据库通讯, 原因不明!

对于第二种情况, 操作上相对较麻烦些, 同时对大数据库的转换也有一定的风险性,
所以在如此操作前,备份当前数据库是很重要很重要的事儿
这种情况 与 前文 所说的 编码兼容的道理是一样的,
即 程序声明编码为 某一种 区域性编码 而数据库 为 另一种区域性编码或通用编码(UTF8),
如果两者都是特定的区域性编码, 哪么最终输出页面肯定是一塌糊涂,
即便数据库采用的是UTF8编码 也会因程序所采用的区域性声明编码不兼容而导致乱码,

这时候, 我们要尽可能采用上面说的方法,在程序上作变动,
让程序声明编码尽可能与数据库保持一至, 而不动数据库
但是, 什么事儿就怕有个但是,
如果有时候,一些特殊的原因让我们无法变更程序编码声明的时候,
哪么下面的方法就派上用场了

再一次的提醒 本方法的操作有一定的风险性, 操作前 切记 备份 备份 备份 还是备份!!!!!
本操作的目的是将当前数据库中的全部数据重新转换编码 以达到保持与程序声明编码一至
操作方法为 进入当前的数据库 以当前最有代表性的 PHPMyadmin 的操作为例,

点击上面的 操作 然后往下看 最下面有个 整理 在这里 选择想要转换的编码 (保持与程序配置声明一至)
有点奇怪是吗 这里的编码命名称呼似乎与常见的编码声明名称有点不一样,
没的关系, 当你不能确定两者的关系时, 百度大婶和谷哥大叔 哪有最佳的答案
如果你有足够懒 懒的去查 哪还有更直接的方法可以明了
把鼠标放在你不确定的编码名称上一会儿 然后看小黄条提示 应该就清楚了

选择好后 点击执行 剩下的 就是等待 就可以了,
直到上面 出现一个绿色的 对号 提示 "您的 SQL 语句已成功运行" 至此,你就可以放心的舒一口气了,

然后回到当前数据库操作界面首页 找 MySQL 连接校对 的哪一项 然后这里 选择 与程序配置 声明一至的编码 即可
当然这步 也可以先作 这个没有必然的顺序关系

附一张图: 上面介绍的都是以中文界面来说, 碰上英文界面 各选项 参照下图 就明白了
图中的 Latin1 编码 即为 前文 所述中的 ISO 8859-1 两者实际上是一回事儿

 

小提示:

PHPMyadmin 默认是多语言 如果当前操作界面为英文,可以在当前数据库首页 Language 选择 中文 - Chinese simplified 项,就会切换到中文操作界面 这里还可以设置界面皮肤 字体大小 等项 有兴趣的可以自己偿试下

前面说过因为 程序页面页头声明编码与当前文件编码不一至导致的乱码解决方法
也提到过因为程序声明编码与 数据库 编码不一至导致的乱码解决方法

这里再说说最后这两种情况导致的 Zen Cart 乱码,
如果说 前面两篇文章 是因为技术性原因造成的乱码
哪么这里提到的两种原因 基本就属于是 典型的 操作粗心大意而导致的乱码

第一种情况 当在编辑处理UTF8 编码 的 PHP 文档时 在保存的时候
当前使用的编辑器默认配置的是保存包含 BOM 信息的UTF8 文档
因此而造成乱码

对于因这种原因造成的乱码 只需要重新打开这个文件 再另存为 同名文件覆盖
在保存的时候 在下面的编码选择框中 选择 保存为不包含 BOM信息的UTF8 文档 即可
这种操作方法 如果只是个别文件 相对数量较少时 可以采用

如果是全站成千上万个文件, 而又不确定具体哪个文件被自己保存为 包含BOM 信息的UTF8文档时,
哪么 下面提供的小工具 就派上用场了

展开下列代码框 将其内代码复制保存或 点击 Code.php下载到本地
上传到当前网站程序下 任意路径下
然后通过 浏览器 直接访问本文件 即可快速批量清除全站包含BOM信息的UTF8文档
从而解决乱码问题

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<?php
/**
	*
	*	 @	使用方法:
	*	 @	重命名本文件 文件名中不要包含有中文和特殊字符
	*	 @	把命名后的文件上传到网站程序安装的根目录下
	*	 @	浏览器 地址栏输入 http://你的域名/文件名.php
	*
	*	 @	功用:
	*	 @	清除全站UTF8编码格式的PHP文件中的 BOM信息 以免出现乱码问题
	*
	* @ By KIRA
	* @ QQ: 6171718
	* @ Email: kira@kpa7.net
	* @ http://zcbk.org/
	*
	*/
?>
<?php
		//remove the utf-8 boms
		//by magicbug at gmail dot com
		if (isset($_GET['dir'])){ //config the basedir
			$basedir=$_GET['dir'];
		}else{
			$basedir = '.';
		}
		$auto = 1;
		checkdir($basedir);
		function checkdir($basedir){
			if ($dh = opendir($basedir)) {
				while (($file = readdir($dh)) !== false) {
					if ($file != '.' && $file != '..'){
						if (!is_dir($basedir."/".$file)) {
							echo "filename: $basedir/$file ";
							echo checkBOM("$basedir/$file")." <br>";
						}else{
							$dirname = $basedir."/".$file;
							checkdir($dirname);
						}
					}
				}
				closedir($dh);
			}
		}
		function checkBOM ($filename) {
			global $auto;
			$contents = file_get_contents($filename);
			$charset[1] = substr($contents, 0, 1);
			$charset[2] = substr($contents, 1, 1);
			$charset[3] = substr($contents, 2, 1);
			if (ord($charset[1]) == 239 && ord($charset[2]) == 187 && ord($charset[3]) == 191) {
				if ($auto == 1) {
					$rest = substr($contents, 3);
					rewrite ($filename, $rest);
					return ("<font color=red>BOM found, automatically removed.</font>");
				} else {
					return ("<font color=red>BOM found.</font>");
				}
			}
			else return ("BOM Not Found.");
		}
		function rewrite ($filename, $data) {
			$filenum = fopen($filename, "w");
			flock($filenum, LOCK_EX);
			fwrite($filenum, $data);
			fclose($filenum);
		}
?>

第二种情况 也是典型的粗心大意造成的乱码
比如 本来是 当前网站程序声明的编码为 ISO 8859-1 而自己在编辑修改文档时 画蛇添足 特意保存为 UTF8编码文档
或者 本来声明是 UTF8编码 结果在编辑修改文件时 看都不看 直接保存成编辑器默认的 ANSI
对于因为这类粗心大意造成的乱码 只需要重新将文件 保存为对应的编码文档 即可
如果自己不记得了 哪么可以去网上找个批量转码工具来将整个程序文件批量重新转码 来解决
这里 给个 转码小工具的 传送门

http://www.onlinedown.net/soft/46844.htm

顺带再提一个 可能出现的 不太严重的乱码现像
即使用了 PHP输出字符截断功能 时 最后一个字符 变成小方块或小黑点儿 等乱码,
目前在英文数字字符上 貌似还没听说过 但在 汉字字符截断处理上 可能就会碰上这种问题,

解决方法我个人的建议就是截断数值尽量设置为 偶数
还有无其他更完美的方法, 还有待进一步的收集整理

基本上 目前 造成 Zen Cart 乱码的各种原因总结就到此为止了
本来打算一篇文章说完的事儿 结果浪费了三篇篇幅才码完!

最后, 来作个总结吧

想要 Zen Cart 不乱码 记住两个一定 和一个注意 一个不要

两个一定为

一定要保持页面页头声明编码与程序文件和输出内容编码的一至性或声明编码与文件内容编码相兼容

一定要保持程序的配置 声明编码 与 数据库 编码的 一至性 或 与数据库编码相兼容

注意 保存文件时的默认编码

切记不要用记事本来编辑处理UTF8编码的PHP文档 哪怕是简单的打开与关闭

 

小常识传送门:

什么是 BOM:

http://zh.wikipedia.org/wiki/%E4%BD%8D%E5%85%83%E7%B5%84%E9%A0%86%E5%BA%8F%E8%A8%98%E8%99%9F

再啰嗦一次:
为什么不能使用 Windows 系统下的记事本 来编辑处理 UTF8 编码 的 PHP文档

我们都知道,计算机使用编码系统来表示不同的字符集。比如最为基本的 ASCII 编码,共包括127个常用字符,可用于处理英语以及其他西欧语言。我们国家则采用 gb2312, gbk, 以及后来 gb18030 等编码系统来处理汉字。其他国家也都分别制定了相应的编码系统,来表示他们自己的文字。所有的这些编码系统,统称为 ANSI 编码。也就是说,在简体中文系统下,ANSI 编码代表简体中文 gb2312 编码;在日本操作系统下,ANSI 编码则代表其常用的编码。

这样,各个国家使用不同的文字,也就有不同的编码系统,不便交流弊病就诞生了。假如你在国内使用 gb2312 编码的系统,发了一封情意绵绵的 email 发给了远在美国留学的女友,如果她所使用的电脑没有 gb2312 编码系统的话,她所看到的将只是一篇乱码。

因此,为了解决全世界各种语言的编码问题,人们提出了 UNICODE 编码,支持全世界 650 多种语言。这样,全世界的计算机上都将安装上这一套编码系统,可以方便地支持不同语言进行书面交流。UTF 8 编码是 UNICODE 编码的一个分支;除了 UTF8 之外,UNICODE 还有 UTF 16, UTF 32 等各种不同的编码方式。

UTF 8 编码比较简单,因为它是用单字节作为编码单元;但是对于 UTF 16 和 UTF 32 而言,则分别使用双字节和四字节作为编码单元,这就涉及到一个编码顺序的问题。例如收到一个“奎”的Unicode编码是594E,“乙”的 Unicode编码是4E59。那么对于 UTF 16 编码系统而言,4E59 究竟是“奎”还是“乙”?这就需要 BOM (Byte Order Mark)来标记字节顺序。

对于 UTF 8 而言,它只有一个字节,显然不必要使用 BOM 来标记字节顺序。但是 BOM 可以用来表明,这是一个 UTF 8 编码的文件。Windows 系统的记事本就喜欢在 UTF 8 文件里面添加一个 BOM 标记。但是,对于包括记事本在内的绝大多数编辑器而言,不管你是 UTF8 with BOM 还是 UTF8 no BOM 编码,都可以正常打开。

看起来晴空万里,但远处却飘来一朵乌云。如果所有的事情都像上面这样一帆风顺的话,那么也就没有必要絮絮叨叨说这么多了。问题的关键在于,WordPress 所使用的动态语言,PHP,在设计的时候没有考虑 UTF8 编码的问题。因此如果是 UTF 8 no BOM 的文件,它可以正常识别;但是如果遇到一个 UTF 8 with BOM 的文件,也就无法识别在文件开头的 BOM 标志。

日常应用中, 当我们将一个文件 保存成了 UTF8 no BOM 格式, 这种格式本身并没有任何问题。但问题在于,大部分网友使用的编辑器,可能都是 Windows 操作系统所自带的记事本程序(Notepad.exe),而这个程序所支持的编码格式只有 ANSI, UTF8, Unicode 和 Unicode big endian 四种。因此,当用户修改为 youfile.php 文件,另存为 youfile.php 文件的时候,原本的 UTF8 no BOM 格式,就是自动保存为 UTF8 ( with BOM )格式。记事本给文件自动添加 BOM (字节顺序标志),因此 youfile.php 第一行就多出了一个 php 无法识别的标志,因此也就带来了上述的困扰。也就是这些莫名的问题根源所在, 所以, 对于UTF8编码格式的PHP文件, 不要用记事本去编辑他, 哪怕是简单的打开再关闭 !!!

posted @ 2013-05-08 17:51  也许明天  阅读(488)  评论(0编辑  收藏  举报