在實作多國語言網頁的時候,除了網頁後端程式需要擁有多國語言支援之外,前端程式也要跟著支援才行。怎麼說呢?假設有個支援中文、英文的網頁,我們在程式後端必須要想辦法判斷訪客所使用的語言來決定前端網頁到底要顯示中文還是英文。而在網頁上出現的文字可能會有兩種情形:第一種,文字是直接顯示在網頁上的,後端程式所得到的中文或是英文文字可以透過HTML模板引擎,直接將文字填入HTML中,顯示在網頁上。第二種,文字一開始不會顯示在網頁,而是要透過網頁跟使用者互動之後才顯示出來的訊息,這種文字訊息通常會需要經過JavaScript程式來判斷要輸出哪個文字,或是要組合出什麼文字,後端程式就必須要有一個方式將中文或是英文文字預先餵給前端的JavaScript程式來使用。



第一種情況的實作方式很簡單,只要參考這篇文章,讓Rust程式擁有多國語言的語庫之後,再根據訪客所使用的語言來搜尋要填空到HTML模板引擎的文字即可。這篇文章會著重介紹第二種情況的實作方式。

Map to JavaScript in HTML

「Map to JavaScript in HTML」是筆者開發的套件,可以將任意key-value形式的字串所組成的Map結構實體,轉成JavaScript的物件,並填寫至HTML語法中。

Crates.io

https://crates.io/crates/map-to-javascript-html

Cargo.toml

map-to-javascript-html = "*"

使用方法

為了要將JavaScript程式插入至HTML語法中,建議使用HTML模板引擎來進行。假設HTML模板引擎是Handlebars,我們可以在要處理文字的Javascript程式之前,插入以下這段語法:

<script>
var _text = {};
{{{text}}}
</script>

語法中的_text這個變數名稱,可以設定成其它的名稱,但不要跟已存在的名稱重複。

map_to_javascript_html這個crate提供的MapToJavaScriptHTML特性,可以讓Map相關的結構實體用有以to_javascript_html為名稱前綴的方法,能將自身轉成類似以下的JavaScript程式語法:

_text['key1'] = 'value1';
_text['key2'] = 'value2';
_text['key3'] = 'value3';

舉例來說:

extern crate map_to_javascript_html;

use std::collections::BTreeMap;

use map_to_javascript_html::MapToJavaScriptHTML;

let mut map = BTreeMap::new();

map.insert("hello", "Hello world!");
map.insert("welcome", "Welcome to my website.");
map.insert("other keys", "Hello world!");

let text = map.to_javascript_html("_text");

程式執行完第13行後,text變數所儲存的值是一個字串,這個字串就是將map這個BTreeMap結構實體,轉成HTML語法中的JavaScript程式語法的結果。

「HTML語法中的JavaScript程式語法」是什麼意思?跟一般的「JavaScript程式碼」有什麼不同嗎?

這樣說好了,如果我們直接把一般的「JavaScript程式碼」貼到HTML語法中的<script>標籤內,如果這段「JavaScript程式碼」內出現</script>這段子字串,那麼這整個HTML語法會出現嚴重的問題。而「Map to JavaScript in HTML」套件,會幫忙進行字元跳脫處理,可以確保任意字串都可以轉成能直接嵌入在HTML語法中的JavaScript程式語法。

透過Handlebars,用text變數所儲存的字串取代模板中的{{{text}}},可以得到以下的HTML語法:

<script>
var _text = {};
_text['hello']='Hello world!';_text['other keys']='Hello world!';_text['welcome']='Welcome to my website.';
</script>

如此一來,在JavaScript程式中,我們就可以藉由讀取_text變數的方式,來動態取得需要用到的文字了!

_to_string_to_vec_to_writer為名稱後綴的方法,可以用來產生HTML。

另外還有以to_javascript_html_with_keys為名稱前綴的方法,可以用來過濾要輸出的key-value組合。

extern crate map_to_javascript_html;

use std::collections::BTreeMap;

use map_to_javascript_html::MapToJavaScriptHTML;

let mut map = BTreeMap::new();

map.insert("hello", "Hello world!");
map.insert("welcome", "Welcome to my website.");
map.insert("other keys", "Hello world!");

let text = map.to_javascript_html_with_keys("_text", &["hello", "welcome"]);

assert_eq!("_text['hello']='Hello world!';_text['welcome']='Welcome to my website.';", text);

Serde框架支援

啟用serde特色即可讓這個套件也支援Serde框架提供的一些Map結構體。

[dependencies.map-to-javascript-html]
version = "*"
features = ["serde"]