在 Windows Perl 5.8 下的簡繁轉字

上篇文章使用 Windows 系統的 API 在 Unicode 與 ANSI 字元轉換。接下來就是簡體與繁的互換了。

雖然在 Perl 中可以 use Encode::HanConvert 來轉換。但還是同樣的問題,若要打包成執行檔會包出一大包怪物。在速度效能上的考量,Sean 還是使用 Windows API 來轉換。

在 GBK 字集中包含所有簡體與繁體字,所以 Sean 的程式都先轉成 GBK 再呼叫系統的 LCMapString。

這個函不該稱「簡繁轉碼」,應該稱「簡繁轉『字』」。因為編碼並沒有改變。函式傳入的字串使用 Unicode (Perl預設UTF8),回傳值也是 Unicode 字串,僅做簡繁字互轉。

Sean 已寫成 Perl 模組,完整的程式在這裡

題外話,簡繁體字並非一對一的關係唷,因為無法100%逆轉。
例如繁體「干」「幹」「乾」簡體皆為「干」,再轉回繁體還是「干」。






use Encode qw(encode decode);
use Win32::API;

use utf8;
use strict;

use constant LOCALE_SYSTEM_DEFAULT => 0x0800;
use constant LANG_CHINESE_SIMPLIFIED => 0x0804;
use constant LANG_CHINESE_TRADITIONAL => 0x0404;
use constant LCMAP_SIMPLIFIED_CHINESE => 0x02000000;
use constant LCMAP_TRADITIONAL_CHINESE => 0x04000000;

# Perl 的 Unicode 字串正體中文轉簡體中文
sub ToCHS {
my $source = ToANSI(shift,'GBK');
my $len = length($source);
my $target = "\0" x $len;

$API_LCMapString = new Win32::API('kernel32','LCMapString','NNPNPN','N') unless defined $API_LCMapString;

my $ret = $API_LCMapString->Call(LANG_CHINESE_SIMPLIFIED,LCMAP_SIMPLIFIED_CHINESE,$source,$len,$target,$len);
return undef unless $ret;

return(ToUnicode($target,'GBK'));
}


# Perl 的 Unicode 字串簡體中文轉正體中文
sub ToCHT {
my $source = ToANSI(shift,'GBK');
my $len = length($source);
my $target = "\0" x $len;

$API_LCMapString = new Win32::API('kernel32','LCMapString','NNPNPN','N') unless defined $API_LCMapString;

my $ret = $API_LCMapString->Call(LANG_CHINESE_SIMPLIFIED,LCMAP_TRADITIONAL_CHINESE,$source,$len,$target,$len);
return undef unless $ret;

return(ToUnicode($target,'GBK'));
}