เตรียม parallel corpus สำหรับ word alignment จาก .po
วิธีที่ก็ใช้ polib อ่าน .po ของ GNOME มาแล้วก็พยายาม ตัดเครื่องหมายทิ้ง. แม้แต่ string ที่มีหลายบรรทัดก็ตัดทิ้ง.
ขั้นแรกเลยคือเข้าไปที่ web L10N ของ GNOME http://l10n.gnome.org/languages/th/gnome-2-22 หลังจาก copy & paste และแก้ด้วยความถึกนิดหน่อย ผมก็ได้รายการของ .po มา.
Download po file pessulus 100% (30/0/0)
Download po file Sabayon 100% (230/0/0)
GNOME developer platform (66% translated)
Download po file atk 95% (117/0/6)
Download po file gail 100% (103/0/0)
…
…
พอได้แบบนี้มาแล้วก็เขียนโปรแกรมมาตัดๆ หน่อย
get_pkg.rbwhile gets if $_ =~ /Download po file ([^s]+)/ print "wget http://l10n.gnome.org/POT/#{$1}.HEAD/#{$1}.HEAD.th.pon" end endก็ได้ script ที่ load .po ออกมา
$ ruby get_pkg.rb > download.sh && sh download.sh
พอได้แบบนี้มาแล้วผมก็เขียนโปรแกรมมา extract ของใน .po มาชื่อ ext_po.py
#-*- coding: UTF-8 -*- import sys import polib import getopt import re class Params: def __init__(self, o_eng_path, o_tha_path, i_po_paths): self.o_eng_path = o_eng_path self.o_tha_path = o_tha_path self.i_po_paths = i_po_paths def __str__(self): return str(self.__dict__) def usage(): print "Usage: " + sys.argv[0] + " -e -t …" def usage_and_exit(): usage() sys.exit(2) def get_params(): try: opts, args = getopt.getopt(sys.argv[1:], "e:t:") keys = [o[0] for o in opts] if not "-e" in keys: print "Require English output filename" usage_and_exit() if not "-e" in keys: print "Require Thai output filename" usage_and_exit() if len(args) < 1: print "Require po filename" usage_and_exit() return Params(o_eng_path = filter(lambda o: o[0] == "-e", opts)[0][1], o_tha_path = filter(lambda o: o[0] == "-t", opts)[0][1], i_po_paths = args) except getopt.GetoptError, err: print str(err) usage_and_exit() def entry_constraints(entry): return not entry.translated() and entry.msgstr != "" and entry.msgid != "" def remove(txt, sym): return re.sub(sym, " ", txt) def convert_text(txt): syms = ["_", "...", ":", "|", "-+", "/+", "%w", "", """, "©", "~", "(", ")"] return reduce(remove, syms, txt) def split_line(txt): return filter(lambda tok: not re.match("^ *$", tok), re.split("n", txt)) def split_line_in_entry(ans, entry): e_lines = split_line(entry[0]) t_lines = split_line(entry[1]) if len(e_lines) == 1 and len(t_lines) == 1: return ans + [(e_lines[i], t_lines[i]) for i in range(len(e_lines))] else: return ans def ext_po_file(o_eng_file, o_tha_file, po): entries = filter(entry_constraints, list(po)) entries = [(entry.msgid, entry.msgstr) for entry in entries] entries = [(convert_text(e[0]), convert_text(e[1])) for e in entries] entries = reduce(split_line_in_entry, entries, []) for entry in entries: o_eng_file.write(entry[0] + "n") o_tha_file.write(entry[1] + "n") def ext_with_ofiles(o_eng_file, o_tha_file, i_po_paths): for i_po_path in i_po_paths: po = polib.pofile(i_po_path) ext_po_file(o_eng_file, o_tha_file, po) def ext(o_eng_path, o_tha_path, i_po_paths): o_tha_file = open(o_tha_path, 'w') o_eng_file = open(o_eng_path, 'w') ext_with_ofiles(o_eng_file, o_tha_file, i_po_paths) o_eng_file.close() o_tha_file.close() def init_charset(): reload(sys) sys.setdefaultencoding('utf-8') def main(): init_charset() params = get_params() ext(params.o_eng_path, params.o_tha_path, params.i_po_paths) if __name__ == '__main__': main()
จากนั้นก็สั่ง (โดยสมมุติว่า .po ทั้งหมดอยู่ใน folder เดียวกัน)
$ python ext_po.py -e e -t t *.po
cut.sh เอาไว้ตัดคำโดยใช้ kucut อีกที
#!/bin/sh
iconv -f UTF-8 -t TIS-620 < $1 > $1.tis
kucut –line=” ” $1.tis
iconv -f TIS-620 -t UTF-8 < $1.tis.cut > $1.cut
แล้วก็ใช้ cut.sh โดยเรียก
$ ./cut.sh t && mv t.cut t
จากนั้นก็ไปเรียก GIZA++ แบบที่แก้ๆไปแล้ว ได้เลย
$ plain2snt e t
$ train-giza++ e.vcb t.vcb e_t.snt
เป็นอันเรียบร้อย
ได้ผลออกมาแบบนี้
# Sentence pair (1) source length 6 target length 6 alignment score : 0.000163118
รายการ เมนู ใหม่ ต้อง มี ชื่อ
NULL ({ }) New ({ 3 }) menu ({ 2 }) items ({ 1 }) need ({ 4 5 }) a ({ }) name ({ 6 })
# Sentence pair (2) source length 5 target length 5 alignment score : 0.00022357
เมนู ใหม่ ต้อง มี ชื่อ
ผลอ่ายากนิดนึงแบบ New ({3}) หมายถึงว่า new ตรงกับคำภาษาไทยตัวที่ 3 ใน “รายการ เมนู ใหม่ ต้อง มี ชื่อ” ก็คือใหม่นั่นเอง.
