Thursday, April 02, 2009

!! Simplest Automatic Javascript+CSS Multilingual Selector!!(號外)最簡單的 Javascript+CSS 網站語言自動選擇器



測試:Test:
This is English

這是中文





讓頁面自動選擇browser預設語言,一直是非英語主流部落客要將網站改成雙語環境最重要的功能
標題已經下英文了(我現在英文想得比中文快),當然這篇文章之後也要變成提供雙語

It has always been needed for a multi-lingual blogger to build a site with automatic language selector. Now I have devised a very good way (I believe):


我的目標是 My Aim


blog只要寫一遍,中英文都放在同一篇文章中
但是post出去後,瀏覽器會自動選擇語言
此外,利用cookie做到讓使用者可以選擇希望看到的語言,甚至讓所有語言都呈現出來

We want to write blog once and only once. We want to put all languages into the same post, so it's easy to write/update.
Besdies, auto selection, we also want to select language manually.



原理 How To Do



1. 在文件中使用不同class 的tag包住不同語言:

1. Use tags with different class names to distinguish language.


<div class="lang_en">
This is English
</div>
<div class="lang_zh">
這是中文
</div>



2. 利用 CSS 之 display:none 來隱藏其中一種或多種語言。
Javascript可以讀取browser語言設定: browser.language (FF) / browser.browserLanguage(IE)

定義CSS如下:

2. Then, make use of CSS's display:none to hide text without the language we choose. Javascript can get the browser's language setting: browser.language (FF) / browser.browserLanguage(IE)

The language-selecting CSS:


.lang_zh_off .lang_zh
{ display:none; }

.lang_en_off .lang_en
{ display:none; }



如何利用Javascript修改CSS?最簡單的方法就是修改body(或其他大範圍tag)使其擁有不同className。

But how to modify CSS settings by Javascript? The simplest way it to modify the class name of large-range tag like body.



譬如若要讓body下只顯示中文,那就修改<body class="lang_en_off">
若要兩個都消失,則為 <body class="lang_en_off lang_zh_off">
為什麼要指定消失,而不指定顯示的語言? 因為如果要指定顯示,則必須先預設所有語言文字消失。一旦程式出錯,則整篇文章都沒有了。所以先使預設為全顯示,比較安全。

If we want to show jsut English in body, then change the body tag as:<body class="lang_en_off">. It can be done by Javascript. If we wnat to hide two languages: <body class="lang_en_off lang_zh_off">

A note for the reason why I define the trigger for "off" but not "on": If we let everything "off" but only display some languages triggered by "on", once a program error occurs, no trigger is set. Then nothing will display. We would rather display all text once the program does not work.



注意:class比id好用,因為一個tag可以很容易利用空白分隔,使其包含不同className

PS.
原想利用 <div lang="en"> 這種正規方式來指定語言,但因 IE6 不支援 CSS attribute selector而作罷 (*[lang="en"])

3. 再來重頭戲便是javascript:

3. The most important, the javascript code:




function __set_lang()
{
/*
//simple test:
alert (document.body.className);
document.body.className= "lang_zh_off lang_en_off";

alert (document.body.className);
return;
*/
/*
detectList['zh']='zh';
detectList['en']='en';
detectList['default'] ='en';
*/

// detect browser default language
var langCode = navigator.language || navigator.browserLanguage;
var lang = langCode.toLowerCase();

// detect language
var attr="",found=false;
lang = trim(lang).substr(0,2);

if (lang!="zh") attr+=" lang_zh_off"; else found=true;
//default:en
if (found) attr+=" lang_en_off";

// write body class
var body_attr = body_original_attr;
if (body_attr==null) body_attr="";
document.body.className= body_attr+attr;

// alert ("done:"+document.body.className);
}
function trim(str)
{
return str.replace(/^\s+/, "").replace(/\s+$/, "");
}



利用 .className 修改及讀取body的class屬性。
(原本我用 setAttribute('class',...), 在IE6下竟發現這樣改不能讓CSS正確判斷修改過的class屬性!)



4.最後是把javascript 加到HTML中:

4. Finally, here's the HTML sample code:


<pre>
<body>
<script language="javascript" src="lang.js"></script>
...



這個部份的javascript 一定要加在body之後! (若要使用新版可以直接使用 lang attribute的code, 必須加到HTML最下面</body>附近!!)
另一種方法是修改 body 為 body onload="__set_lang()"

Be aware that this code must be added in the last line before </body> Another way is to modify body tag as: body onload="__set_lang()"



5. 此外cookie和下拉式表單比較簡單 請自行發揮, 或參考我包好的:

5. In addition, we can use cookie to store user preferred language. Display a drop-down list on the page. It is easier and I skip the details. See my packed codes here:

http://www-scf.usc.edu/~chunming/lang.css
http://www-scf.usc.edu/~chunming/lang.js


此blog 和我的首頁就是用這兩個檔案

This site and my personal website are examples that uses the two files above.

No comments:

Post a Comment