2007-4-12 22:03 | by 2ndboy
用 PHP 实现多语言的正途似乎是 gettext 函数族,但是用 gettext 也有很多不方便的地方,今天实现了一种利用 Smarty 来实现多语言 B/S 应用的方法。最后希望达到的效果是程序中除了切换语言的地方,其它地方能够完全不用关心当前的显示语言,比如同样的 $Tmpl->display( ‘welcome.tpl’ ) 在中文状态下会显示中文的欢迎页面,而在英文状态下就显示英文欢迎页面。
既然对 Smarty 对象的调用方式在不同语言下保持一致,那么就要拿 Smarty 类来开刀啦。Smarty 里面把模版“实例化”的接口有两个,一个是 display(),另外一个是 fetch(),而 display() 内部其实调用了 fetch(),所以关键点就在于改造这里。从 Smarty 派生一个新类 CSmarty,重载其中的 fetch() 和 display() 接口:
- class CSmarty extends Smarty
- {
- function CSmarty()
- {
- $this->Smarty();
- }
- function set_dirs( $lang )
- {
- $base_path = '2ndboy/';
- $this->template_dir = $base_path . $lang . '/templates/';
- $this->compile_dir = $base_path . $lang . '/templates_c/';
- $this->config_dir = $base_path . $lang . '/configs/';
- $this->cache_dir = $base_path . $lang . '/cache/';
- }
- function fetch( $template, $cache_id = null, $compile_id = null, $display = false )
- {
- $this->set_dirs( $_SESSION['lang'] );
- if( !$this->template_exists( $template ) )
- $this->set_dirs( 'en' ); // Default language is English
-
- return( parent::fetch( $template, $cache_id, $compile_id, $display ) );
- }
- function display( $template, $cache_id = null, $compile_id = null )
- {
- $this->fetch( $template, $cache_id, $compile_id, true );
- }
- }
- ?>
可以看出,上述代码把当前的显示语言设置放在 session 里面,所以还要有针对语言切换操作设置 session 的响应代码:
- if( isset( $_REQUEST['lang'] ) )
- {
- if( 0 == strcasecmp( 'cn', $_REQUEST['lang'] ) )
- $_SESSION['lang'] = 'cn';
- else
- $_SESSION['lang'] = 'en';
-
- header( 'Location: ' . $_SERVER['HTTP_REFERER'] );
- exit;
- }
- ?>
假设上述代码放在 index.php 里面,那么用 index.php?lang=en 就可以实现把当前语言切换成英文的操作,注意代码里设置完显示语言后会跳转到 referer 所指的页面,这样处理可以实现切换语言后所在位置不变的效果。
以上的代码实现要求模版路径下的目录结构这样布局:第一级目录采用语言名,如 cn,en 等,各个语言目录内部再按 Smarty 的惯例分成 templates、templates_c、cache 等等。
下面再发挥一下想象力,让程序自动识别用户熟悉的语言,比如老外访问看到的是英文内容,国人访问看到的是中文内容:
- session_start();
- if( !isset( $_SESSION['lang'] ) )
- {
- if( strstr( $_SERVER['HTTP_ACCEPT_LANGUAGE'], 'zh' ) )
- $_SESSION['lang'] = 'cn';
- else
- $_SESSION['lang'] = 'en';
- }
- ?>
其实就是通过分析客户端浏览器可接受的语言来设定默认显示的语言:)
呵呵,其实两年多以前就实现过这个功能,今天是旧瓶装新酒,把之前的实现加以改进放上来晒晒,不知各位看官有收获没?:D
Posted in PHP | 6 Comments »
2007-4-7 12:09 | by 2ndboy
Posted in 随便说说 | No Comments »
2007-4-3 22:00 | by 2ndboy
在 China-Pub 订的《Programming Ruby 中文版:第 2 版》上周末送到,没想到居然是那么厚的一个大部头,貌似英文电子版没有那么多内容吧?书买来了总不能浪费,以后要抽时间把参考部分之前的内容读完。BTW,这本书的函数参考部分真是多,居然占了全书的一半!
最近右手手腕不太舒服,究其原因还是职业病,用非人体工程学的键盘和鼠标的时间过长,正好,以后打算减少在电脑前的时间,咱改成看书啦:)
—–
MSIL 就是 .NET 时代的汇编呀,想当初靠着 IDA 看懂过不少没代码的东西,也破解过简单的小东西,但是第一次看到 MSIL 的代码还是晕啦,跟 Win32 汇编完全不是一码事。当然,在 Google 的帮助下找了一些文档看了看终于还是入了 MSIL 的道,其实这东西还是比汇编简单很多的,没有那么多寄存器的习惯约定,只有一个栈,只要时刻搞清楚栈里有什么就没问题。在这一点上,MSDN 的资料就好多啦,我一开始从网上下载了一个 MSIL 指令参考手册,但是对照着 MSIL 代码还是看不明白,等看到了 MSDN 上对 MSIL 每条指令的栈操作解释以后,一切都水落石出!
—–
最近看过的电影有《风语者(Wind Talkers)》、《我们俩(You And Me)》、《爱情呼叫转移》、《无间道风云(The Departed)》和《少年汉尼拔(Hannibal Rising)》,基本上除了最后一部之外都挺喜欢。
每周固定的节目还包括看最新的《Lost》和《Prison Break》,很着急的想知道 Lost 里面的小岛到底是怎么一回事,虽然不断有东西被掀去幕布,但还是有太多的未解之谜。
—–
上周末终于买了婚戒,订了婚纱照,一个月后就是已婚人士了:D
Posted in 随便说说 | 6 Comments »
2007-3-27 21:23 | by 2ndboy
昨天为了实现一个很好玩的应用而不得不花将近两个小时的时间破解了一个网站的登录图片验证,现记录心得如下:)
这个图片验证属于特别规整的那种,除了在背景上加了些跟文字同色的干扰点之外,内容全部为数字,数字的颜色固定,数字的位置固定,数字本身没有经过变形,所以特别容易下手:)
识别图片中的文字首先肯定要排除干扰因素,一开始想到了一种方法——扫描图片,去掉面积小于 3 的色块(把一个象素点的面积算作 1)。其实基本上这种办法是完全可行的,因为数字的笔划都是连续的,所以面积肯定不小,这样一来面积小的色块就一定是干扰点啦。但是对于跟数字连在一起的干扰点,这种方法无效。去掉干扰点之后就可以通过取一些特征点判断出是那个数字了。
但是后来想到的另外一种更简单有效的方法立刻让我打消了实现上述方法的念头。那就是:取到所有 10 个数字的字模(点阵信息)保存在程序里,之后把每一个待识别数字跟字模进行比较,只要其中任何一个象素不符合就表示不是这个数字。这样一来就根本不用管图片上的干扰点啦:D
由于认证图片中的数字位置固定,所以可以先多保存几个认证图片,用程序把每个数字单独切分保存。当积累到一定数量的样本之后就可以采集字模啦(我每个数字采集了 4 张样本图)。
取字模也用程序实现,只要挨个扫描样本,取前景色象素的交集就可以得到字模。现在取到了字模,图片中每个数字的位置又是固定的,只要按照上面说的思路写段非常简单的图片跟字模比较的代码就可以实现认证图片识别啦(完全不用管图片中的干扰点!)。程序写好后做了一下测试,可以百分之百识别该网站认证图片中的内容,哈哈!
从这个破解过程中得到一些关于好的认证图片生成算法的特征:
* 文字颜色、干扰颜色跟背景颜色要随机产生
* 文字位置和文字间距也要随机调整
* 文字要做旋转和变形
* 如果用汉字的话,效果会更好:)(当然,不适用于国际化网站)
做了如上处理的认证图片,基本上应该是很难被程序识别啦,除非你用那些深奥如模式识别或者什么神经网络算法吧?!这里有个例子,不知是真是假:)
Posted in 三句话不离本行 | No Comments »
2007-3-23 21:40 | by 2ndboy
最近的项目需要找到一款跨平台的 2D 图形库,最好能在使用接口上兼容 MicroSoft 的 GDI+,经过一番搜寻跟对比,总结了一些这方面的信息放在这里做个笔记。
首先介绍一下 Cairo 库,没听说过没关系,FireFox 总听说过吧?!FireFox 的 render 引擎用的就是这个库。Cairo 是一个跨平台的 2D 图形库,支持很多 GDI+ 的高级特性,比如 Anti-alias,矩阵变换等等,但是据说 Cairo 的效率不是很好,跟其它库有一定的差距。
用 Cairo 最爽的地方在于有个跟它相配合的 libGDIPlus 库,这个库对 Cairo 进行了封装,对外提供了一个 GDI+ Flat API 兼容的使用接口,这样就为把 Windows 平台下的 GDI+ 代码移植到 Unix 或者 Mac 平台下提供了一条捷径。
下面要介绍的是 AGG(Anti-Grain Geometry),这个库貌似效率很好,可以去它的 Demo 展示页面去看看,里面的小例子都非常的酷!
AGG 也有一个类似于 libGDIPlus 那样的封装,叫做 AggPlus。但是美中不足的是 AggPlus 对 GDI+ 接口的封装充其量只实现了 20%,基本上没有实用价值,但是拿来跟 GDI+ 做性能比较测试还是比较方便的。其实在 AggPlus 的下载包里面就有这么个性能测试程序,在某些基本图形的 render 测试中 AGG 居然比 GDI+ 快 10 倍以上!
Cairo 跟 AGG 都是非常不错的 2D 图形库,虽然我始终没办法在 Cairo 跟 AGG 之间做性能测试,但是貌似 AGG 比 Cairo 的性能要好;在特性方面,他俩似乎不分伯仲,GDI+ 1.0 里有的 feature 几乎都能在这两个库里找到对应物;在 interface 方面,Cairo + libGDIPlus 是一对黄金搭档,只要你熟悉 GDI+ 的 Flat interface,很快就能把 Cairo 加到自己的项目里面;AGG 的 interface 比较另类,完全基于 C++ Template 写就,基本上属于看了文档还感觉很晕的那种,有人说要想把 AGG 用起来,要有比较好的图形学知识,深以为然!
从跨平台和编译上比,AGG 全面胜出,在 Windows/Unix/Mac 三个平台下都轻松通过,Cairo 就稍差一点点,在 Windows 平台下需要经过一定的修改(当然首先要熟悉一下才能修改)。在 Windows 下编译 libGDIPlus 貌似就是不可能完成的任务,至少我花了一些时间后放弃了这个念头。
在跟同事解释 Cairo + libGDIPlus 和 AGG 的最显著区别时我打了个比方,前者就像是一辆整装待命的国产车,后者就像是一堆精致的进口汽车配件。把前者用起来比较容易,但是可能性能一般;把后者用起来需要花很多时间,还要有专业知识,但是一旦跑起来那就很爽!
Posted in 三句话不离本行 | 23 Comments »