输入法环境变量的故事

有时候我想想,我是不是应该写一些比较普及的文档(你懂得,我特意纠结了一下措辞)。

那么这次先来介绍一下关于输入法的环境变量配置问题:

在远古时代,世界一片混沌,那时世界上还没有 X 窗口下的输入法支持。

神说,要有输入法,于是就有了 XIM 协议。

这个时代(当然还有个几个XIM协议的版本更新),需要设置的环境变量有

XMODIFIERS=”@im=imname”

比较现代的程序的话,是不用纠结imname这个值的,输入法自己会自己也检测一把这个值,然后启动xim的时候也把自己变成这个值。印象中一定要这个环境变量的程序有xterm。

然后XIM有诸多缺点,至少在输入法程序关闭(不一定是死掉)的时候,可能让程序freeze,或者崩溃。

于是神看到XIM是坏的,授意GTK和QT自己做自己的IM Module。

从此天下大乱。

先来看 Gtk 这边,假设没有环境变量,Gtk是读取一些配置文件里面记录的im module的。每个im module都有指定语言,也就是按环境的语言设置匹配。这里来第一个常见问题:英语环境为什么默认不能用输入法而要纠结 LC_CTYPE=”zh_CN.UTF-8″。就是为了让 Gtk 的匹配能够匹配中文的IM Module。当然我个人是反对这种配置的,因为其实只要 GTK_IM_MODULE 足以。世界上据我所知唯一一个奇葩程序一定要这么设置那就是emacs。(因为作为gtk界面的emacs其实是用XIM协议……鬼知道里面hardcode了啥)

第二个常见问题,为什么卸载了ibus就可以用 fcitx,那是因为系统中同时有两个zh的im module(其实是三个,还包括了xim),你不设置环境变量的话,那就会让gtk自己选择了,这个顺序似乎也不确定,如果选到ibus但你用fcitx,或者选到fcitx你用ibus,都会导致你输入法不能正常使用。

设置了GTK_IM_MODULE之后呢?假设匹配到对应的im module,就会使用对应的im module,假设没匹配到,那就返回之前的没有设置的情况。

LC_CTYPE和设置*_IM_MODULE两种方式我偏好后者。

这里还有个很脑残的问题,GTK一定会去读取 /etc/gtk-2.0/gtk.immodules (按发行版,和cpu架构,以及gtk版本可能不同)里面记录的im module,尽管gtk-query-immodules-2.0和gtk-query-immodules-3.0是可以自己查询的。所以打包者必须自己在安装后脚本内更新这些文件。可能当初Gtk想做缓存……不过现在这年头不缓存也没啥大不了的了。

回到 Qt 这边,情况稍好,首先挑选规则还是如之前所述,按语言。但如果没有环境变量QT_IM_MODUE的干预,这个可以通过 qtconfig 进行选择。以及发行版的打包者们可以不用纠结更新类似GTK那些文件。就这样。

另外顺带一提,QT的环境变量检测是分QT和QT4的,不知道为什么Gtk3发布的时候为什么没有把GTK2和GTK3一起考虑进去。虽然说因此而遭殃的只有一个,那就是scim。如果你不知道它为什么会遭殃的话,请重新学习上文的匹配规则。

(顺带一提其实世界上还有 Clutter 的 IM Module 这种东西。)

话说眺望未来什么的话,那假设进入到了 Wayland 时代,不幸,Wayland 还没有类似 XIM 的统一协议,于是如果程序想支持输入法,最好还是选择 Gtk / Qt 来开发。

This entry was posted in fcitx development and tagged , , . Bookmark the permalink.

11 Responses to 输入法环境变量的故事

  1. 右京样一 says:
    Opera Mini 6.5.27049 Android

    于是乎,为了稳定性,即使要处理这些麻烦事还是要做qt/gtk im module……

    如果freedesktop有相应标准就好了。

    [Reply]
  2. henryhu says:
    Android Webkit 4.0 Motorola Xoom

    最好直接扔了缓存和query之类,一个immodule设定搞定一切问题。。。

    [Reply]
  3. csslayer says:
    Firefox 8.0.1 GNU/Linux

    @henryhu 真要我说的话gtk3本来是个机会……可能没人觉得这是个问题吧。

    [Reply]
  4. foolegg says:
    Firefox 8.0 Ubuntu

    @csslayer
    Gtk3发布后满怀期待地去看过immodule模块,指望能有些进步,看完之后一声痛骂:“靠,还是那个鸟样!”

    [Reply]
  5. litkt says:
    IceWeasel 8.0 GNU/Linux

    世界上唯一需要IM的就是汉字,日文是因为汉字才被迫使用IM,不夹带汉字的朝鲜文可以直接用Compose或Pango解决。
    所以世界上除了中力日本没人关心IM,所以XIM很烂。
    中国人总想拿来主义,还偏偏拒绝拼音文字,这就叫哪壶不开提哪壶,专跟自己过不去。
    其实,汉语拼音已经很好用了,无非就是汉语拼音键盘规范化的问题,确定声调的死键位置并做好Compose表。
    为什么要拒绝拼音呢?因为拼音只能拼汉语普通话,要拼方言(对我来说南方各方言干脆就是另一些语言,不仅是发音差异,词汇语法也不同)要用方言自己的拼音才行,要拼文言文和大量夹杂文言的白话文完全不可能(中国复古派就是凭这一条而判处汉语拼音做为文字应用也就是汉语拉丁化进程的死刑的,究其原因,就是他们想在白话文中大量夹杂或大量引用旧时文言词句)。
    所以呢,于其纠缠IM,不如抵制大一统观念和复古情结,推行汉语拼音在计算机上的应用。

    [Reply]
  6. litkt says:
    IceWeasel 8.0 GNU/Linux

    汉语拼音在计算机上的应用的最大障碍就是IM,因为IM挤占了Compose的位置,使无论在zh_CN.UTF-8还是en_US.UTF-8的Compose里设汉语拼音带调字母都无效。
    另外要把24个汉语拼音带调字母排布在26个英文字母键位上用AltGr键输入理论上虽然可行,可这个排布谁来制定?如何规范统一?谁制作物理键盘(改造现有美式英文键盘生产线的键帽印制程序虽不复杂却也影响键盘厂商的利润空间)?不印到键帽上又如何记忆这24个字母的排布?这都是问题。这是中国人自己的问题,中国人自己不解决没人会为你解决是。

    [Reply]
  7. henryhu says:
    Firefox 8.0 FreeBSD

    其实GTK3还是有改进的,从前要> etc/gtk-2.0/gtk.immodules,现在只要–update-cache……

    [Reply]
  8. Ma Xiaojun says:
    Firefox 10.0 Windows 7 x64 Edition

    @litkt
    許多平臺IM都用得好好得,沒有願意完全用漢語拼音這樣自我閹割的,想法改進Unix的世界的IM吧。

    [Reply]
  9. litkt says:
    IceWeasel 10.0.2 GNU/Linux

    @Ma Xiaojun
    汉语拼音不是“自我閹割”,相反表意文字才是摆脱不掉的包袱,当然这个包袱是你的,不是我的。
    Unix世界的IM真的没人关心,Unix世界是不适应放着简单方案不用,非要追求复杂实现这种思维方式的。

    [Reply]
  10. litkt says:
    IceWeasel 10.0.2 GNU/Linux

    @Ma Xiaojun
    另外强调,很多用汉语拼音的人未必是“自我”阉割,这些人本来就不太用汉语,系统上可能连汉字字体都没有,临时需要引用几个汉语词,要阉割也是阉割你,如果你非要认为这是“阉割”的话。

    [Reply]
  11. pingz says:
    Google Chrome 17.0.963.56 GNU/Linux x64

    @litkt 你这个观点在七、八十年代的时候比较流行。那个时候,汉字世界的电子化遇到了大难题。不过现在关心的人就不多了。现在问题大部分已经解决了,方案也早就有,而且不少。事实上,这方面的多数关键专利都已经过期了。所以,现在做这个工作连法律风险都很少了。当然,由商业利益引起的法律问题的确阻碍了这方面的工作。目前的一个例子是字体。

    [Reply]

Leave a Reply

Your email address will not be published. Required fields are marked *

Note: Commenter is allowed to use '@User+blank' to automatically notify your reply to other commenter. e.g, if ABC is one of commenter of this post, then write '@ABC '(exclude ') will automatically send your comment to ABC. Using '@all ' to notify all previous commenters. Be sure that the value of User should exactly match with commenter's name (case sensitive).