本文提出一個不需要高深技術的文件翻譯方法,可以用來幫助使用者閱讀外文文件,其辦法是透過英文與中文對照的方式,配合簡單的 HTML 排版格式,使得英文與中文得以在同一畫面中對照顯示以方便閱讀。
找翻譯軟體幫忙做翻譯是一個讀懂外文網頁的辦法,但是、目前翻譯軟體的品質通常很差,無法正確的將整篇文章翻譯成通順的的中文,其問題是因為目前的電腦還無法理解像中文、英文等的自然語言,因此、無法提升翻譯品質。
然而、要讓電腦理解自然語言,一直是許多資訊科學研究者的夢想,但這個夢想實在太難實現了,從 1940 年代開始,電腦的開山始祖 Alan Turing 就提出了這個問題,後續的科學家又前仆後繼進行了很長的研究,始終無法製作出可以理解英文文章的軟體,因而也無法進行良好的自然語言翻譯。
但是、電腦不能理解英文,就不可能做出一個實用的英翻中系統嗎,其實、並不盡然,透過中英對照的模式,懂中文的人很容易就可以讀懂翻譯出來的文件,以下是這種翻譯方式的一個範例。
本翻譯系統,其方法十分簡單,完全只是利用程式自動查出英文字典中的字詞,然後再把這些字詞的對照中文以 HTML 中的 <sub> 標籤框住,如此一來,即可完成中英對照的翻譯動作,以下是其核心的程式碼。
// 比對樣式,用來取得下一個應翻譯或應略過的部份。
static final String[] patterns=
{ /*0. comment*/ "<!--.*?-->", // 略過 HTML 中的註解不要翻譯.
/*1.script*/ "<script.+?</script>", // 略過 HTML 中的Script不要翻譯.
/*2.style*/ "<style.+?</style>", // 略過 HTML 中的Style不要翻譯.
/*3.mark-up*/ "<.+?>", // 略過 HTML 中的標籤部分不要翻譯.
/*4.digit*/ "\\d+", // 略過數字部份不要翻譯.
/*5.email*/ "\\w{1,20}@\\w{1,20}\\.\\w{1,20}\\.", // 略過 email 部份不要翻譯.
/*6.name : Abel, John*/ "\\s+[A-Z][a-z]+\\s+,\\s+[A-Z][a-z]+", // 略過姓名部份不要翻譯.
/*7.path : a.b.c or a/b/c */ "[\\./]\\w{1,20}[\\./]", // 略過路徑不要翻譯.
/*8.url*/ "http://[\\w\\.]{1,30}", // 略過網址不要翻譯.
/*9.phrase=three words*/"\\w+\\s+\\w+\\s+\\w+", // 三個英文字的片語,要翻譯。
/*10.phrase=two words*/ "\\w+\\s+\\w+", // 兩個英文字的片語,要翻譯。
/*11.word*/"\\w+", // 一個英文字,要翻譯。
/*12.six character*/"[^\\w\\s\\d]{6,6}", // 六個中文字,要翻譯(中翻英時使用)。
/*13.five character*/"[^\\w\\s\\d]{5,5}", // 五個中文字,要翻譯(中翻英時使用)。
/*14.four character*/"[^\\w\\s\\d]{4,4}", // 四個中文字,要翻譯(中翻英時使用)。
/*15.three character*/"[^\\w\\s\\d]{3,3}", // 三個中文字,要翻譯(中翻英時使用)。
/*16.two character*/"[^\\w\\s\\d]{2,2}", // 二個中文字,要翻譯(中翻英時使用)。
/*17.one character*/"[^\\w\\s\\d]{1,1}", // 一個中文字,要翻譯(中翻英時使用)。
/*18.one symbol character*/"." // 一個符號,略過不用翻譯。
};
static final int WORD_BEGIN=9, WORD_END=17, ENGLISH_WORD=11;
public static String translate(String pText, Map pMap, int pMinRank) {
StringBuffer rzText = new StringBuffer();
for (int i=0; i<pText.length(); ) { // 從文章開頭一直掃描到結尾。
String token=null, toToken=null;
for (int pi=0; pi<patterns.length; pi++) {
token = matchAt(pText, i, patterns[pi]);// 對每一個可能的比對樣式進行比對。
if (token == null) continue; // 比對失敗,繼續比對下一個樣式。
if (pi<WORD_BEGIN || pi>WORD_END) // 比對成功的樣式不是詞彙,略過。
break;
else if (pi>=WORD_BEGIN&&pi<=WORD_END) {// 比對成功的樣式是詞彙,進行翻譯動作。
token = STR.replace(token, "-", " ");
toToken = translateWord(token, pMap, pMinRank); // 將原文詞彙翻譯為對照文字。
if (toToken != null) break;
if (pi == ENGLISH_WORD) break;
}
}
if (toToken == null) toToken = "";
if (toToken.length() == 0) // 沒有翻譯出來,將原文直些輸出。
rzText.append(token);
else
rzText.append(" "+token + "{["+toToken+"]} "); // 有翻譯出來,將原文與譯文以 "原文{[譯文]}" 格式輸出。
i+=token.length();
}
return rzText.toString();
}
static final String[] suffixMacros = {";= ", "s;= ", "es;= ", "ies;=y ", "ing;= ", "ing;=e ", "er;=e ",
"est;=e;", "ed;= ", "d;= ", "ly;= ", "ies;=y ", "al;= ", "able;= "};
// 將一個英文詞彙翻譯成中文。
public static String translateWord(String pWord, Map pMap, int pMinRank) {
if (pWord == null) return null;
String extWord = pWord.toLowerCase()+";";
for (int i=0; i<suffixMacros.length; i++) { // 對於每一種可能的詞尾,將其轉回原型後再進行比對。
String suffix = STR.head(suffixMacros[i], "=");
String toSuffix= STR.tail(suffixMacros[i], "=");
String word = STR.replace(extWord, suffix, toSuffix).trim();
String toTerm = (String) pMap.get(word);
if (toTerm == null)
continue;
else {
String toWord = STR.head(toTerm, ";");
int toRank = Integer.parseInt(STR.tail(toTerm, ";"));
if (toRank < pMinRank) return ""; // 對於太常出現的字詞,不要進行翻譯 (例如:of, is, ...)
// 對於譯文太長的字詞,不要進行翻譯 (例如:ant:一種在地上爬行的昆蟲,有六隻腳且有一個皇后)。
if (toWord.length() > 30) return "";
return toWord.replace('_', ' ').trim();
}
}
return null;
}
在上述的翻譯範例中,由於一些專有名詞 (包含公司名與人名例如:Time Warner) 的影響,常使得其中文翻譯有明顯的錯誤,另外、有些詞彙具有多重意義者,本系統也將只輸出一個譯文,因而使得中文部份文章讀起來不夠通順,然而、由於人腦很明顯的能夠快速分辨對的部分與錯誤的部份,因此、即使有這些錯誤,一個稍微懂英文的中文讀者,即可順利且快速的讀懂文章的內容,因此、本翻譯系統其實是一個輔助閱讀系統,是一個可以幫助非英語系的人員,快速讀懂英文文章的工具。
如何辨識專有名詞,將其翻譯正確,或者乾脆就不翻譯保留原文,是本程式值得改進的一個地方,另外、如何對多個意義的詞彙,選取其正確的意義,以解決歧義性的問題,也是本程式尚待改進的一個功能。
Post preview:
Close preview