PHP 通常會用 gettext 或 intl
Java, JSP, Servlet 通常會用 Locale + ResourceBundle 配合 Properties file
另外還有各種 Framework 都各自有一套 I18N 寫法
但是若果由一種 I18N 寫法至另一種 I18N 寫法顯然是需要一點點時間學習……
大部分高階電腦語言都擁有 XML Parser 而且寫法都大同小異,因此在下便覺得用 XML 製作語言檔是一種不錯的選擇
再用非常直觀的 XML 語法編製語言檔,例如
en.xml
<?xml version="1.0" encoding="UTF-8"?> <i18n lang="en"> <text id="how-are-you"><![CDATA[How are you ?]]></text> </i18n>zh-tw.xml
<?xml version="1.0" encoding="UTF-8"?> <i18n lang="zh-tw"> <text id="how-are-you"><![CDATA[你好嗎?]]></text> </i18n>zh-cn.xml
<?xml version="1.0" encoding="UTF-8"?> <i18n lang="zh-cn"> <text id="how-are-you"><![CDATA[你好吗?]]></text> </i18n>語法顯而易見
利用 i18n 的 lang 定義語言檔的語言種類,雖然檔案名已經根據語言命名,但於檔案中再宣告多次比較準確
再利用 text 的 id 作為唯一鍵,以 id 屬性給 DOM 的 getElementById 使用,加快 XML Parser 的速度
(在 XML 中 & " 之類特殊符號,必須以 &#nnnnn; 或 &entity; 的寫法才可以編制
但透過 <![CDATA[]]> 這種語法可以讓 XML 直接以 & " 編製在 CDATA[] 中)
PHP
<?php class XMLI18N{ private $document; public function __construct($file){ $document = new DOMDocument(); $document->load($file); if (is_null($document) === true){ throw new Exception(); } else { $this->document = $document; } } public function getText($id){ //$element = $this->document->getElementById($id); $xpath = new DOMXPath($this->document); $element = $xpath->query('//*[@id="' . $id . '"]')->item(0); if (is_null($element) === true){ return null; } else { return $element->nodeValue; } } } $xmli18ns = array(new XMLI18N('en.xml'), new XMLI18N('zh-tw.xml'), new XMLI18N('zh-cn.xml')); foreach ($xmli18ns as $xmli18n){ echo $xmli18n->getText('how-are-you') . "<br/>\n"; } ?>
Java
package xmli18n; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.xml.sax.SAXException; public class XMLI18N{ private Document document; public XMLI18N(String filename) throws IOException, ParserConfigurationException, SAXException{ try{ document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File(filename)); this.document = document; } catch (IOException ex){ throw new IOException(ex.getMessage()); } catch (ParserConfigurationException ex){ throw new ParserConfigurationException(ex.getMessage()); } catch (SAXException ex){ throw new SAXException(ex.getMessage()); } } public String getText(String id){ Element element = document.getElementById(id); if (element == null){ return null; } else { return element.getTextContent(); } } public static void main(String[] args){ try{ XMLI18N[] xmli18ns = {new XMLI18N("en.xml"), new XMLI18N("zh-tw.xml"), new XMLI18N("zh-cn.xml")}; for (XMLI18N xmli18n : xmli18ns){ System.out.println(xmli18n.getText("how-are-you")); } } catch (Exception ex){ ex.printStackTrace(); } } }
其他如 C, C++, C#, ActionScript 有具有由 W3C 所提供的 XML DOM Parser,因此不一一詳盡編寫
重點是先編制任意一類別或函式庫等前置程式,方便從 XML 解釋語言檔
另外在下還建議設立一個 DTD 檔,好讓 XML 檔有一套統一語法,可讓使用者知道 XML 的編製格式
i18n.dtd
<!-- declare DOCTYPE named "i18n" --> <!DOCTYPE i18n [ <!-- the root element of this XML must named "i18n" contains 1 or more than 1 "text" elements --> <!ELEMENT i18n (text+)> <!-- the "i18n" element must have "lang" attribute which accept Character Data --> <!ATTLIST i18n lang CDATA #REQUIRED> <!-- "text" element accepts any objects in its body --> <!ELEMENT text (#PCDATA)> <!-- the "text" element must have "id" attribute which accept an unique element id --> <!ATTLIST text id ID #REQUIRED> ]>
再利用 DOCTYPE 引入 dtd 來規範 XML 的結構
<!DOCTYPE i18n SYSTEM "i18n.dtd">
沒有留言 :
張貼留言