PHP 通常會用 gettext 或 intl
Java, JSP, Servlet 通常會用 Locale + ResourceBundle 配合 Properties file
另外還有各種 Framework 都各自有一套 I18N 寫法
但是若果由一種 I18N 寫法至另一種 I18N 寫法顯然是需要一點點時間學習……
大部分高階電腦語言都擁有 XML Parser 而且寫法都大同小異,因此在下便覺得用 XML 製作語言檔是一種不錯的選擇
再用非常直觀的 XML 語法編製語言檔,例如
en.xml
1 2 3 4 | <? xml version = "1.0" encoding = "UTF-8" ?> < i18n lang = "en" > < text id = "how-are-you" > <![CDATA[How are you ?]]> </ text > </ i18n > |
1 2 3 4 | <? xml version = "1.0" encoding = "UTF-8" ?> < i18n lang = "zh-tw" > < text id = "how-are-you" > <![CDATA[你好嗎?]]> </ text > </ i18n > |
1 2 3 4 | <? 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | <?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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | 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
1 2 3 4 5 6 7 8 9 10 11 | <!-- 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 的結構
1 | <!DOCTYPE i18n SYSTEM "i18n.dtd"> |
沒有留言 :
張貼留言