首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
V2EX  ›  问与答

PHP 的多语言支持一般怎么做?

  •  
  •   lincanbin · 2014-11-19 13:47:25 +08:00 · 3625 次点击
    这是一个创建于 1819 天前的主题,其中的信息可能已经有所发展或是发生改变。
    前几天Github上不知道为什么跑过来个人,资料上写着加州,说想他很喜欢我的程序想让我做个多语言支持。(这点很奇怪,我的项目是全中文的,他是怎么跑过来的?)
    我从来没做过多语言支持,想问问怎么做兼容性和性能最好?(因为是开源项目要在大部分机器上都能跑,例如IIS、Apache还有PHP5.3~5.6的各个版本的组合,所以靠外挂C拓展是不行了)

    搞个language的dict,然后替换掉模板里的中文?这样怎么样?如果是这样,那么用dict好还是用一长串的常量好?
    14 回复  |  直到 2014-11-20 08:50:13 +08:00
        1
    breestealth   2014-11-19 16:31:22 +08:00
    这不就是最基本的语言包功能么?将所有的字符串提取出来当作语言包,然后挨个替换就可以了。
    具体可以看看 Kohana 或者其他框架对多语言的实现也就是了。
        2
    kmvan   2014-11-19 16:41:59 +08:00 via Android
    wp可参考
        3
    Showfom   2014-11-19 16:43:15 +08:00
    现在的网站都很先进的根据浏览器第一第二语言来适配了
        4
    loserwn   2014-11-19 16:46:11 +08:00
    可以考虑使用 gettext 和 po 来实现。
        5
    regmach   2014-11-19 16:55:14 +08:00
    某框架使用数据库或者文本存储翻译信息
    界面所有文字都使用方法调用
    用户访问时根据设置自动调用即可
        6
    unidotnet   2014-11-19 16:58:09 +08:00
    1.需要翻译的全部用英文,自定义函数输出。
    2.创建一堆对应的模版,比如,locale.en locale.zh_cn
    3.文件里写 hello=你好
        7
    lincanbin   2014-11-19 17:01:06 +08:00
    @breestealth 我看他们都用的hashtable,常量有什么缺陷吗?
    @regmach gettext不少虚拟主机不带的吧。
        8
    raincious   2014-11-19 17:25:56 +08:00
    @lincanbin

    常量你要一个个定义,会让程序变得很复杂。

    另外如果你使用常量,就等于定义了一个全局量(无论const还是define),这样很明显会污染Scope。

    联系到你之前论坛的实现方法,可能对Scope污染不敏感,但是减少全局量和Public Accessable量有助于降低非规范的调用,借此提高程序质量。(这就是有些东西需要封装的原因)

    而Hashtable本身其实不慢,只是内存占用的问题比较突出。(所以要简化和最小化加载的数据)。

    多语言还是用gettext这样成熟的方案然后产生语言包就好了。如果需要自己做,自己写个格式来读取语言表(比如$lang->get_my_text('this is a test')),然后放到模板里就行了。

    (是的,我已经开始想实现方案了)

    $lang = new Lang($request->get_client_language(), $setting);

    <? echo $lang->get_text('this is a text %s', $value) ?>

    // 哈哈,其实这就是框架的作用,打包好底层功能,然后愉快的使用就行了

    =====================================================================

    下面是我的实现方法,没用gettext,仅供参考:

    // 加载方法,加载好存到LanguageMap里
    https://github.com/raincious/facula/blob/master/src/Facula/Base/Prototype/Core/Template.php#L1264

    // 编译模板的时候主动强制加载(如果未加载过)
    https://github.com/raincious/facula/blob/master/src/Facula/Base/Prototype/Core/Template.php#L1165

    // 后面的工作交给模板编译器自行决定如何处理,这是框架自带的标准模板编译器的处理方法
    https://github.com/raincious/facula/blob/master/src/Facula/Unit/Paging/Compiler/Operator/Language.php#L131

    // 按照上面那个模板引擎的Tag写的HTML模板,注意lang标签,比如“{lang TITLE_HOME_WELCOME /}”
    https://github.com/raincious/facula/blob/master/examples/BasicStart/privated/Templates/template.home.htm

    // 语言格式文件
    https://github.com/raincious/facula/blob/master/examples/BasicStart/privated/Templates/language.zh%2Bhome.txt

    语言文件仅在需要的时候(需要重新渲染或者需要读出用户消息)加载(并缓存),因此开销不算太大。我正在想着如何将其中“用户消息”的语言格式独立出来,这样开销会更低,但是一直苦于实现不太优雅。
        9
    lincanbin   2014-11-19 17:45:01 +08:00
    @raincious 我做了一个循环50万次的测试,HashTable相比常量性能差距并不是太多,即使是循环50万次性能也相当接近。
    而且我一个页面里的需要翻译的字符串也不多,最多就几十个,用HashTable应该也是比较划算的,一个页面多开销的时间应该不会超过50μs,内存开销也差不了几个Bytes,在可以接受的范围内。
        10
    cougar   2014-11-19 18:00:41 +08:00
    joomla 和 Drupal里面的多语言支持做的很棒。可以下个看看
        11
    raincious   2014-11-19 18:02:59 +08:00
    @lincanbin 我也说了,HashTale和const之前的区别在于管理性。常量定义这么大的数据很明显是不合适的。

    而且常量是不能注销的(除非你用Runkit),因此如果你加载了一个用常量定义的语言文件,那么它就一直在那了。

    所以综合各种迹象,你不应该纠结常量和HashTable的问题。直接用HashTable(Array)是最好的方案。

    当然,如果你是自己的小项目,管理语言文件还是挺复杂的,考虑用gettext(_())实现好了,很多成熟的开源系统都有应用,有很多例子。自己去弄,每次项目变更都需要同步修改很多的语言文件,负担比较大。
        12
    learnshare   2014-11-19 18:09:28 +08:00
    Gettext 是比较普遍的方案,网上也有一些提供翻译资源托管的地方,可以让不同国家的人来翻译,like https://www.transifex.com/
        13
    regmach   2014-11-19 19:37:37 +08:00
    不是gettext, 就是PHP框架自带的适配方法而已.
        14
    breestealth   2014-11-20 08:50:13 +08:00
    @lincanbin 常规做法是使用 array 而已,常量的用法没有做过。从程序逻辑来看是可以满足需求,但与 array 方法比没有什么明显优势。
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   4106 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 22ms · UTC 08:34 · PVG 16:34 · LAX 00:34 · JFK 03:34
    ♥ Do have faith in what you're doing.