10
7
2012
0

拼音声调数字转字符

Suǒwèide 「pīnyīn shēngdiào shùzì zhuǎn zìfú」 jiùshì bǎ 「pīnyīn+shùzìdiàbiǎo de shēngdiào」 zhuǎnchén Unicode zìfú biǎoshì.

所谓的「拼音声调数字转字符」就是把「拼音+数字表示的声调」转成 Unicode 字符表示,为了是做成 fcitx 的拼音输入插件,以方便输入上段的内容。

算法是参考别人的,把所有带声调的音节后缀穷举出来再转换,简单暴力好用。我改写的 Python 3 版在 github/winterpy 上,支持大写和「ü」。

为了在 fcitx 中使用,我又改写了一 Lua 版本,代码如下:

#!/usr/bin/env lua

-- http://www.robertyu.com/wikiperdido/Pinyin%20Parser%20for%20MoinMoin

-- definitions
-- For the pinyin tone rules (which vowel?), see
-- http://www.pinyin.info/rules/where.html

local strsub = string.gsub
local _strupper = string.upper

-- map (final) constanant+tone to tone+constanant
mapConstTone2ToneConst = {
  n1 = '1n',
  n2 = '2n',
  n3 = '3n',
  n4 = '4n',
  ng1 = '1ng',
  ng2 = '2ng',
  ng3 = '3ng',
  ng4 = '4ng',
  r1 = '1r',
  r2 = '2r',
  r3 = '3r',
  r4 = '4r',
}

-- map vowel+vowel+tone to vowel+tone+vowel
mapVowelVowelTone2VowelToneVowel = {
  ai1 = 'a1i',
  ai2 = 'a2i',
  ai3 = 'a3i',
  ai4 = 'a4i',
  ao1 = 'a1o',
  ao2 = 'a2o',
  ao3 = 'a3o',
  ao4 = 'a4o',
  ei1 = 'e1i',
  ei2 = 'e2i',
  ei3 = 'e3i',
  ei4 = 'e4i',
  ou1 = 'o1u',
  ou2 = 'o2u',
  ou3 = 'o3u',
  ou4 = 'o4u',
}

-- map vowel-number combination to unicode
mapVowelTone2Unicode = {
  a1 = 'ā',
  a2 = 'á',
  a3 = 'ǎ',
  a4 = 'à',
  e1 = 'ē',
  e2 = 'é',
  e3 = 'ě',
  e4 = 'è',
  i1 = 'ī',
  i2 = 'í',
  i3 = 'ǐ',
  i4 = 'ì',
  o1 = 'ō',
  o2 = 'ó',
  o3 = 'ǒ',
  o4 = 'ò',
  u1 = 'ū',
  u2 = 'ú',
  u3 = 'ǔ',
  u4 = 'ù',
  v1 = 'ǜ',
  v2 = 'ǘ',
  v3 = 'ǚ',
  v4 = 'ǜ',
}

function strupper(c)
  local specials = {
    ['ā'] = 'Ā',
    ['á'] = 'Á',
    ['ǎ'] = 'Ǎ',
    ['à'] = 'À',
    ['ē'] = 'Ē',
    ['é'] = 'É',
    ['ě'] = 'Ě',
    ['è'] = 'È',
    ['ī'] = 'Ī',
    ['í'] = 'Í',
    ['ǐ'] = 'Ǐ',
    ['ì'] = 'Ì',
    ['ō'] = 'Ō',
    ['ó'] = 'Ó',
    ['ǒ'] = 'Ǒ',
    ['ò'] = 'Ò',
    ['ū'] = 'Ū',
    ['ú'] = 'Ú',
    ['ǔ'] = 'Ǔ',
    ['ù'] = 'Ù',
    ['ǜ'] = 'Ǜ',
    ['ǘ'] = 'Ǘ',
    ['ǚ'] = 'Ǚ',
    ['ǜ'] = 'Ǜ',
  }
  if specials[c] then
    return specials[c]
  else
    return _strupper(c)
  end
end

function ConvertPinyinToneNumbers(lineIn)
  local lineOut = lineIn

  -- first transform
  for x, y in pairs(mapConstTone2ToneConst) do
    lineOut = strsub(strsub(lineOut, x, y), strupper(x), strupper(y))
  end

  -- second transform
  for x, y in pairs(mapVowelVowelTone2VowelToneVowel) do
    lineOut = strsub(strsub(lineOut, x, y), strupper(x), strupper(y))
  end

  -- third transform
  for x, y in pairs(mapVowelTone2Unicode) do
    lineOut = strsub(strsub(lineOut, x, y), strupper(x), strupper(y))
  end

  return strsub(strsub(lineOut, 'v', 'ü'), 'V', 'Ü')
end

local function main()
  local lineOut
  for lineIn in io.stdin:lines() do
    lineOut = ConvertPinyinToneNumbers(lineIn)
    print(lineOut)
  end
end

main()

很可惜的是,fcitx 的 Lua 模块目前不支持屏蔽数字键选字,所以暂无法在 fcitx 中使用。

Category: 编程 | Tags: Lua Python 中文支持 拼音
9
18
2012
12

截短 UTF-8 字符串

用于显示时,经常会遇到显示的文本太长需要截短的情况。如果是如 ASCII 这样的定长编码,截短到指定长度自然不成问题。可如果源字符串是 UTF-8 编码的呢?ANSI C 里只管字节不管编码,所以如果想只用 ANSI C 提供的功能的话,就只能自己写了。因为需求仅仅是截短字符串而已,也不要求多么精确,所以没有去做编解码,只是丢弃按字节截短后的字符串最后的无效编码而已。而且目标语种是 Lua,也不方便搞位操作。

维基百科可知,UTF-8 多字节字符第一字节的最高两位为11,而其它字节的最高两位均为10。所以就把后面那些10xxxxxx连同最开始的11xxxxxx去掉好了。这样会多截掉一个多字节字符,但无所谓了。

function truncateUTF8String(s, n)
  local r = string.sub(s, 1, n)
  local last = string.byte(r, n)
  if not last then return r end
  while last >= 128 and last <= 192 do
    n = n - 1
    r = string.sub(r, 1, n)
    last = string.byte(r, n)
  end
  if last >= 128 then
    r = string.sub(r, 1, n-1)
  end
  return r
end

2012年9月27日更新:感谢Fermat618提供的思路,更新了更简洁、准确的代码如下:

function truncateUTF8String(s, n)
  local dropping = string.byte(s, n+1)
  if not dropping then return s end
  if dropping >= 128 and dropping < 192 then
    return truncateUTF8String(s, n-1)
  end
  return string.sub(s, 1, n)
end
Category: 编程 | Tags: 乱码 Lua 中文支持
3
16
2011
22

关于“Linux”被翻译为“你牛叉”等的一些想法

昨天,我就在我所建立的vim-cn Gtalk群上看到了在Debian官方简体中文首页将“Debian”翻译为“蝶变”、“Linux”翻译为“你牛叉”,当时还以为是某人的恶作剧。今天,又见到这篇文章,才知道真相。

最开始读的时候,看到大量的翻译破坏,我想到是不是使用的机器翻译,随后意识到不可能。又以为是Linux反对者的发泄。但我还是错了。

做这件事的人是“沈卓斌”,在多个 Wiki 上的 ID 是“jobinson99”。他除了做这些莫名其妙的翻译更改外,也做了一些妥当的翻译,让恢复变得困难起来。我在ArchLinux上的几个页面改掉了他的一些翻译,更多的翻译还得依靠Google来找出了。在改的过程中我发现部分页面有相互复制的情况。不过我没精力管了。至于维基百科,其中文社区比较强大,针对其的破坏已经被恢复。其他的Debian啊、FreeBSD啊我就没心思去管了。

有些人可能对此不太在意,但我很早就读了中文维基百科的一些方针指引之类的,很快便认定这是“破坏行为“。尽管他的这些翻译看起来是善意的,但是其行为却不会被接受。首先不说他的翻译是否准确恰当,首先一点就是——没有共识。我认为,再好的翻译,只有极少数人知道,它也不应当被作为通用或者正式的名称,不然,就像使用世界语一样,大部分人根本就不知道你在说什么,更别说搜索引擎了。哪天你有某个Linux问题,Google数日未解决,却蓦然发现,原来写有解决方案的Wiki中使用的是“你牛叉”而导致你没有找到,岂不郁闷!更何况,这些翻译多似恶搞,不是所有人都会接受的,我最开始就以为是反对者来着。

我很不明白,各开源项目的维基上尚有大量资料需要翻译,中文 man 手册既少又旧以至于我都不敢用了,wget 的中文翻译错误虽然在 Ubuntu 下已经更正了,但在 ArchLinux 下依旧存在。还有这么多可以做的,他却以为无聊的翻译可以推广开源?新手安装 Linux,谁不需要安装指导?遇到问题了,为什么可能的解决办法都是用英文写的?命令不会用,man 一下,为什么没有中文翻译?很多新手在尝试Linux时都遇到各种困难而放弃,很多老鸟都在遇到问题时苦苦挣扎,我多么希望所有的开源资料能有中文翻译!很多人说Linux难用。是啊,不会英语又没人指导就根本无法使用的系统怎么会好用呢?

至于jobinson99,我想说,如果你真的蛋疼得不行的话,就把翻译放伪基百科上去啊。


附:我在 ArchWiki 上发现的不妥翻译列表:

%s/开天辟地你牛叉/LFS/ge
%s/你牛叉龙骨/ArchLinux/ge
%s/龙骨/Arch/ge
%s/你牛叉/Linux/ge
%s/共努/GNU/ge
%s/荟萃/Wiki/ge
%s/有奔头/Ubuntu/ge
%s/蝶变/Debian/ge
%s/合成/编译/gce
%s/优盘/U盘/gce

 

Category: Linux | Tags: linux 中文支持
9
9
2010
21

成功实现Linux控制台(纯终端)中文显示与宽屏支持

这里的Linux控制台中文显示,当然不是指安装个zhcon/fbterm/fbiterm之类的东东啦。这些东西在我这里都有些bug。zhcon显示效果不错,还支持输入法,但是滚屏的时候文本几乎不动,根本无法正常使用w3m。fbterm显示的字体很丑,特别是在宽屏下。这个可以调,但我没能调出自己觉得满意的。fbiterm显示要好看点。记得都是有些显示上的问题的。在Ubuntu软件源里还有一个日本人做的jfbterm,在我这里有严重bug——启动Vim后无响应,退出出现段错误,然后无论怎么折腾键盘,就是没任何响应了……

我多想控制台能直接支持中文显示啊!

所以,经过长时间的磨砺后,我终于决定自动给内核打上中文显示的补丁。内核源码在http://www.kernel.org/下载,补丁在这里,我只下了前两个补丁。

这里说一下,打补丁的时候可以直接bzcat xxx|patch -p1,不需要先解压(我终于知道bzcat/zcat这种东西有什么用了 =_=!)。另外,记得参数加-p1哦。我不小心用-p0了,结果N多failed,吓到我了呢。

补丁打好后看看README文件就知道怎么编译了,在Arch的Wiki上有更详细的编译和安装说明。下面是我用过的命令——

mkdir ../build
make O=../build menuconfig
# 注意备份 ../build/.config 文件
make O=../build
sudo make O=../build modules_install
cd ../build
sudo cp -v arch/x86/boot/bzImage /boot/vmlinuz-2.6.35.3-lily
sudo cp -v System.map /boot/System.map-2.6.35.3-lily

#Ubuntu 用,注意有个 - 没了。。。
sudo mkinitramfs -k 2.6.35.3lily -o /boot/kernel26-lily
#Arch 用
#sudo mkinitcpio -k 2.6.35.3-lily -g /boot/kernel26-lily

首先是建立了个输出目录。以后几乎所有的make都要加上O=这个目录。第一个make是配置内核,N多选项,一项项看很费时的,而且似乎是根据系统情况生成的。这里和本文主题息息相关的是要记得选上framebuffer支持,然后选个字体编译进去。我还设置了分辨率的,不知道和后来支持宽屏有没有关系。另外,在这里可以启用启动时的图片。不知道是什么的请移步这里。默认的图片是Tux,当然是可以改的,直接替换drivers/video/logo下相应的图片就可以了,比如我替换的是logo_linux_clut224.ppmppm图片可以使用如下命令生成(via):

pngtopnm linuxlogo.png > linuxlogo.pnm
pnmquant 224 linuxlogo.pnm > linuxlogo224.pnm
pnmtoplainpnm linuxlogo224.pnm > linuxlogo224.ppm

这些弄好后就开始make了,很耗时的,我这里大约用了一个多小时。

这些弄完后就可以重启了(要祈祷的哦 :-))。记得给内核传个vga=791之类的参数,虽然说不传这个也是可以显示汉字的。

幸运的话就这么就OK了,不过还不是宽屏的。我这里进X时会出现“工作在低画质模式”的提示,重启X后正常了,再回到控制台下,发现分辨率莫名地变成宽屏的了~~

后来lsmod看到加载了以前安装了但没有用的nouveau驱动,于是把/etc/X11/xorg.conf也给改了:

Section "Device"
        Identifier      "Configured Video Device"
        Driver  "nouveau"
        # Driver        "nvidia"
        Option  "NoLogo"        "True"
EndSection

Section "Module"
        Load    "drm" # 这个是后来加的
        Load    "glx"
EndSection

这样启用nouveau驱动,不用每次进图形界面时重启X了。控制台表现相当完美,除了不知道为什么登录前的那些文字变成了黄色的。。。而且,在图形界面与控制台界面切换相当迅速,不会先黑一下了。

但是——

但是,不能启动compiz了。compiz的有些窗口管理功能还是相当不错的。我尝试重装安装nvidia的官方驱动,新立得告诉我子进程返回了错误号10。去看了下日志:

*** Unable to determine the target kernel version. ***

也就是说,相应的内核模块无法编译了,不知道应该怎么hack,只好暂时放弃了。555...


2012年10月8日更新:在 ChinaUnix 上的补丁已经失效了。这里有另外的人维护的 cjktty 分支可直接使用。说明

2013年10月25日更新:repo.or.cz 上的 cjktty 不再更新了。新的仓库在 GitHub 上

2021年02月28日更新:Gentoo-zh 上的 cjktty 不再更新了。新的仓库在 zhmars/cjktty-patches

Category: Linux | Tags: linux 中文支持 编译

Mastodon | Theme: Aeros 2.0 by TheBuckmaker.com