localization

原文: http://phpadvent.org/2010/localization-by-anthony-gentile
翻译:校长 RoyGu http://roygu.com

当我们创建一个网站时,一个非常重要的考虑是:网站的受众/访客。无论网站是销售商品、提供服务亦或是信息资讯,都须考虑当国外用户访问时页面如何呈现。如果他们想在你的网站上购买商品、使用服务或获取资讯,你的网站能够正常服务他们吗?应该提供正常服务吗?本地化让用户界面符合用户的预期,如:日期格式、货币以及本地语言文本。

许多以英语为母语的人并没有意识到这点,尽管英语的普及率很高,但说英语的人仍只占很小比率。这篇文章统计了世界上分布最广的语言是英语,但英语并不是人们说得最多的语言(现在排第三)。互联网上有如此多的有用信息,很大一部分不是用英文描述的。用计算机解决语言相关的问题是一件困难的事情,但是创建一个国际友好的网站并不是我们想象的那么难。虽然今天介绍的方法不能适用于10种不同语言的网站,但是对于需要提供两三种语言的网站非常有效果。比如,在美国,讲西班牙语的人数在显著增加,拥有一个能用西班牙语言交流的电子商务网站,将扩大你的潜在客户群。

在讲如何为网站实现本地化之前,我想花点时间谈论下字符编码。即使你无法预见你的网站是否需要提供本地化功能,了解字符(charsets)编码相关的知识都是非常有必要的。字符编码是用来帮助软件识别用户期望字符集的。例如,通用的ISO 8859-1字符集是西欧的通用字符集。因此,在这种字符集中可以用英文字母表示德语中的原音。但如果我在这种字符集中想显示可拉伯字符,如:ق,那么很可能会显示成� 或 Ù。这就意味着,在ISO 8859-1字符集下,不能正确识别阿拉伯字符。

一种非常友好的跨语言字符编码是兼容ASCII码的UTF-8编码,它代表Unicode字符集,特别是在传统应用中较为常见。在网站中使用UTF-8,其支持的字符非常多,能够最大地满足用户需求。为了正确地实现一种字符编码,你要确保在你整个应用中编码保持一致。如果你使用UTF-8,那么Apache、数据库、PHP以及PHP可用的功能和文档类型都应该设置成UTF-8。如果这些都不是一致的,你最终可能会得到不同字符编码的混合数据,这种问题即使能补救也比较困难。

// Apache httpd.conf or .htaccess

// This will add a charset to the Content-Type response header.
AddDefaultCharset UTF-8

// php.ini
default_charset = "UTF-8"

// Example PHP function
htmlentities($data, ENT_COMPAT, 'UTF-8');

// XML
<?xml version="1.0" encoding="UTF-8" ?>

// HTML
<meta http-equiv="Content-Type"
    content="text/html; charset=utf-8" />

如果你想了解更多关于UTF-8的内容,并且为什么它如此重要,猛击下面的链接:

刚才我们已经讨论了字符编码,接下来我们进入主题,谈谈如何实现本地化。如何判断为用户加载哪个本地化?如何知道用户来自哪里?一种解决方案是根据IP地址判断地域,但是更好的解决方案是让浏览器告诉我们使用哪个本地化。当用户发起HTTP请求时,HTTP头中的Accept-Language将会被发送,我们通常可以从PHP超全局变量$_SERVER中获取该值。看个示例:

Accept-Language: en-us;en;q=0.5

虽然这是一种检测默认语言的简单方法,但这并不意味着它就是用户期望的语言。所以提供一种简单方法给用户切换语言是非常有必要的。许多开发者认为,在session或cookie中存储本地化编码就足够了,但这种方法不够友好和直接,在URL中加入本地化提示岂不是更好,如:http://example.com/en/blog/http://example.com/de/blog; 或者用子域名来表示,如: http://en.wikipedia.org/.

如何实现呢?不难,在Apache中为网站设置一个重写规则:

RewriteRule ^(en|es)/(.*) /$2 [PT,E=lang:$1]

有了这个重写规则,我们就不需要为每种语言复制一份代码了。我们可以委托Apache查找用户请求的语言,并把它存储在环境变量中,然后转递到代码中。在我们的应用逻辑中,我们可以这样获取本地化编码:

$locale = apache_getenv('lang', true);

这里有一个支持本地化的PHP脚本,仅供参考:

<?php

/**
 * Stick to the codes that are already standard.
 * ISO 3166 - http://en.wikipedia.org/wiki/ISO_3166-1
 * RFC 1766 - http://www.faqs.org/rfcs/rfc1766.html
 */
$accepted_locales = array(

    'en' => 'en_US',
    'es' => 'es_MX'
);

// Get the locale from the browser.
$browser_locale = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);

// For more specific locale codes, e.g., en-us (English, United States), es-mx (Spanish, Mexican), etc.
// $browser_locale = current(explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']));

// Check against a whitelist instead of trusting $_GET['lang'].
// For reference: http://ha.ckers.org/blog/20100128/micro-php-lfi-backdoor/
if (in_array($browser_locale, array_keys($accepted_locales))) {
    $locale_code = $accepted_locales[$browser_locale];
} else {
    $locale_code = 'en_US';
}

// Or, use a URL-based locale designator and a rewrite rule.
// RewriteRule ^(en|es)/(.*) /$2 [PT,E=lang:$1]
// Then, grab that environment variable with PHP.
/*
$locale_code = apache_getenv('lang', true);
if (in_array($locale_code, array_keys($accepted_locales))) {
    $locale_code = $accepted_locales[$locale_code];
} else {
    $locale_code = 'en_US';
}
*/

$locale_entries = array();

// Load the locale file.
if (file_exists($locale_code . '.php')) {
    $locale_entries = include $locale_code . '.php';
}

/*
These locale entries are loaded from files that return an array.
en_US.php
<?php
return array(
    'WELCOME' => 'Hello %s!',
    'GOODBYE' => 'Goodbye!',
);

es_MX.php
<?php
return array(
    'WELCOME' => '¡Hola %s!',
    'GOODBYE' => '¡Adios!',
);

You could store locales in a database as well.
 */

// Now, you can create a simple function that will display the correct text.
function locale($locale_entries, $key, $replacements = array()) {
    if (isset($locale_entries[$key]) && empty($replacements)) {
        return $locale_entries[$key];
    } elseif (isset($locale_entries[$key])) {
        return vsprintf($locale_entries[$key], $replacements);
    }
    throw new Exception("Locale entry for '$key' does not exist.");
}

// echo locale($locale_entries, 'WELCOME', array('Anthony'));
// echo locale($locale_entries, 'GOODBYE');

// A basic class to handle locales
class Locale {

    public $code = 'en_US';
    public $locale_path = '/var/www/';
    protected $_entries = array();

    public function setCode($code)
    {
        $this->code = $code;
        $this->load();
    }

    public function load()
    {
        if (!file_exists($this->locale_path . $this->code . '.php')) {
            throw new Exception("Locale file: {$this->locale_path}{$this->code}.php does not exist.");
        }

        $this->_entries = include $this->locale_path . $this->code . '.php';
    }

    public function fetch($key, $replacements = array())
    {
        if (isset($this->_entries[$key]) && empty($replacements)) {
            return $this->_entries[$key];
        } elseif (isset($this->_entries[$key])) {
            return vsprintf($this->_entries[$key], $replacements);
        }
        throw new Exception("Locale entry {$this->code}:$key does not exist.");
    }
}

$locale = new Locale();
$locale->setCode($locale_code);

//echo $locale->fetch('WELCOME', 'Anthony');
//echo $locale->fetch('GOODBYE');

?>

我希望本文讲述得足够清楚了,能够帮助你养成思考网站访客并最大满足用户的好习惯。我认为绝大多数网站应该使用UTF-8。在项目开始阶段请至少花点时间确保网站是国际友好的。

配置Apache+fcgid_module

请先看VC9,VC6,Thread Safe,Non Thread Safe的意思?。 PHP有两种执行方式:ISAPI 和 FastCGI。

ISAPI 执行方式是以 DLL 动态库的形式使用,可以在被用户请求后执行,在处理完一个用户请求后不会马上消失,所以需要进行线程安全检查,这样来提高程序的执行效率,所以如果是以 ISAPI 来执行 PHP,建议选择 Thread Safe 版本;

而 FastCGI 执行方式是以单一线程来执行操作,所以不需要进行线程的安全检查,除去线程安全检查的防护反而可以提高执行效率,所以,如果是以 FastCGI 来执行 PHP,建议选择 Non Thread Safe 版本。

FastCGI 又有fastcgi和fcgid两个模块,推荐使用fcgid,在apache项目的页面上有单独的链接页面。配置信息如下:

LoadModule fcgid_module modules/mod_fcgid.so

<IfModule fcgid_module>
   FcgidInitialEnv PHPRC "c:/php/"
   FcgidInitialEnv PATH "C:/php;C:/WINDOWS/system32;C:/WINDOWS;C:/WINDOWS/System32/Wbem;"
   FcgidInitialEnv SystemRoot "C:/Windows"
   FcgidInitialEnv SystemDrive "C:"
   FcgidInitialEnv TEMP "C:/WINDOWS/TEMP"
   FcgidInitialEnv TMP "C:/WINDOWS/TEMP"
   FcgidInitialEnv windir "C:/WINDOWS"

   FcgidIOTimeout 40
   FcgidConnectTimeout 10
   FcgidMaxProcesses 1000
   FcgidOutputBufferSize 64
   FcgidProcessLifeTime 120
   FcgidMaxRequestsPerProcess 10000
   FcgidMinProcessesPerClass 0
   FcgidFixPathinfo 1

# Global Config Example
  <Files ~ "\.php$">

    Options Indexes FollowSymLinks ExecCGI
    AddHandler fcgid-script .php
    FcgidWrapper "c:/php/php-cgi.exe" .php
  </Files>
</IfModule>

现在官方都不推荐使用VC6版本了,也不会提供VC6的源码,所以大家都迁移到PHP VC9。这里推荐几个网站,分别提供了Apache VC9, Apache X64, PHP X64。

How to remove www from your URL with mod_rewrite

source link: http://yoast.com/how-to-remove-www-from-your-url-with-mod_rewrite/
I got a hit today for the following search query: how do you get rid of the www in url .

Here’s the code to 301 redirect the www version of your site to the non-www version using Apache’s mod_rewrite:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.example.com$ [NC]
RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]

Adding the www instead of removing it

And, as requested in the comments, the code to add www to your domain name:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^example.com$
RewriteRule (.*) http://www.example.com$1 [R=301]

用C语言写CGI程式-入门篇

原文链接:http://www.cs.tut.fi/~jkorpela/forms/cgic.html

这是一篇用C语言写CGI程式的入门文章。假定读者对C语言有基本的认识,熟悉HTML并且会在WEB服务器上安装CGI脚本。

为什么要用CGI程式?

大家都应该知道如何用HTML写表单,那么写好表单后,为了可靠地使用、处理表单数据,你仍然需要服务端脚本。通常服务端脚本以简单、类似的方式处理表单提交,典型地如向某个邮件地址发送文本数据。

但是,如果你要处理更复杂的问题,如采集数据并写入文件或数据库、或者接收信息然后转发又或者对提交的数据做四则运算,那么你不得不自己写一个的服务端脚本。

简单地说,CGI是HTML表单和服务端脚本的接口。

但CGI不是唯一的选择。建议看下Lars Marius GarsholHow the web works: HTTP and CGI explained 文章,可以使您了解CGI的概念和除CGI外的其他选择。

如果有人建议用javascript写CGI程式,让他看看这篇文章: JavaScript and HTML: possibilities and caveats. 简单说,如果不使用服务端服本备份的话,JavaScript根本不可靠。

Continue reading

博客从域名godpress.cn转到roygu.com域名

博客转来好几天了,但是一直懒于做域名301重定向。为了保留以前的读者,一般情况下,网站换域名后要做相关的SEO处理,最通常的就是把原来网站相应的URL全部转到新网站相应的URL上。 示例:你可以访问http://godpress.cn/?p=328,它会自动重定向到http://roygu.com/?p=328。不多说了,下面直接贴代码:


Options +FollowSymLinks
RewriteEngine on
RewriteCond %{HTTP_HOST} ^godpress.cn$ [OR]
rewritecond %{http_host} ^www.godpress.cn [nc]
rewriterule ^(.*)$ http://roygu.com/$1 [L,R=301]