Files
2020-08-03 20:59:08 +08:00

156 lines
6.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- {% raw %} -->
# 10.2 本地化資源
前面小節我們介紹了如何設定 Locale設定好 Locale 之後我們需要解決的問題就是如何儲存相應的 Locale 對應的資訊呢這裡面的資訊包括文字資訊、時間和日期、貨幣值、圖片、包含檔案以及檢視等資源。那麼接下來我們將對這些資訊一一進行介紹Go 語言中我們把這些格式資訊儲存在 JSON 中,然後透過合適的方式展現出來。(接下來以中文和英文兩種語言對比舉例,儲存格式檔案 en.json 和 zh-CN.json)
## 本地化文字訊息
文字資訊是編寫 Web 應用中最常用到的,也是本地化資源中最多的資訊,想要以適合本地語言的方式來顯示文字資訊,可行的一種方案是 : 建立需要的語言相應的 map 來維護一個 key-value 的關係,在輸出之前按需從適合的 map 中去取得相應的文字,如下是一個簡單的範例:
```Go
package main
import "fmt"
var locales map[string]map[string]string
func main() {
locales = make(map[string]map[string]string, 2)
en := make(map[string]string, 10)
en["pea"] = "pea"
en["bean"] = "bean"
locales["en"] = en
cn := make(map[string]string, 10)
cn["pea"] = "豌豆"
cn["bean"] = "毛豆"
locales["zh-CN"] = cn
lang := "zh-CN"
fmt.Println(msg(lang, "pea"))
fmt.Println(msg(lang, "bean"))
}
func msg(locale, key string) string {
if v, ok := locales[locale]; ok {
if v2, ok := v[key]; ok {
return v2
}
}
return ""
}
```
上面範例示範了不同 locale 的文字翻譯,實現了中文和英文對於同一個 key 顯示不同語言的實現,上面實現了中文的文字訊息,如果想切換到英文版本,只需要把 lang 設定為 en 即可。
有些時候僅是 key-value 替換是不能滿足需要的,例如"I am 30 years old",中文表達是"我今年 30 歲了",而此處的 30 是一個變數,該怎麼辦呢?這個時候,我們可以結合`fmt.Printf`函式來實現,請看下面的程式碼:
```Go
en["how old"] ="I am %d years old"
cn["how old"] ="我今年%d 歲了"
fmt.Printf(msg(lang, "how old"), 30)
```
上面的範例程式碼僅用以示範內部的實現方案,而實際資料是儲存在 JSON 裡面的,所以我們可以透過`json.Unmarshal`來為相應的 map 填充資料。
## 本地化日期和時間
因為時區的關係,同一時刻,在不同的地區,表示是不一樣的,而且因為 Locale 的關係,時間格式也不盡相同,例如中文環境下可能顯示:`2012 年 10 月 24 日 星期三 23 時 11 分 13 秒 CST`,而在英文環境下可能顯示:`Wed Oct 24 23:11:13 CST 2012`。這裡面我們需要解決兩點:
1. 時區問題
2. 格式問題
$GOROOT/lib/time 套件中的 timeinfo.zip 含有 locale 對應的時區的定義,為了獲得對應於當前 locale 的時間,我們應首先使用`time.LoadLocation(name string)`取得相應於地區的 locale比如`Asia/Shanghai``America/Chicago`對應的時區資訊,然後再利用此資訊與呼叫`time.Now`獲得的 Time 物件協作來獲得最終的時間。詳細的請看下面的例子(該例子採用上面例子的一些變數):
```Go
en["time_zone"]="America/Chicago"
cn["time_zone"]="Asia/Shanghai"
loc,_:=time.LoadLocation(msg(lang,"time_zone"))
t:=time.Now()
t = t.In(loc)
fmt.Println(t.Format(time.RFC3339))
```
我們可以透過類似處理文字格式的方式來解決時間格式的問題,舉例如下:
```Go
en["date_format"]="%Y-%m-%d %H:%M:%S"
cn["date_format"]="%Y 年%m 月%d 日 %H 時%M 分%S 秒"
fmt.Println(date(msg(lang,"date_format"),t))
func date(fomate string,t time.Time) string{
year, month, day = t.Date()
hour, min, sec = t.Clock()
//解析相應的%Y %m %d %H %M %S 然後回傳資訊
//%Y 替換成 2012
//%m 替換成 10
//%d 替換成 24
}
```
## 本地化貨幣值
各個地區的貨幣表示也不一樣,處理方式也與日期差不多,細節請看下面程式碼:
```Go
en["money"] ="USD %d"
cn["money"] ="¥%d 元"
fmt.Println(money_format(msg(lang,"money"),100))
func money_format(fomate string,money int64) string{
return fmt.Sprintf(fomate,money)
}
```
## 本地化檢視和資源
我們可能會根據 Locale 的不同來展示檢視這些檢視包含不同的圖片、css、js 等各種靜態資源。那麼應如何來處理這些資訊呢?首先我們應按 locale 來組織檔案資訊,請看下面的檔案目錄安排:
```html
views
|--en //英文範本
|--images //儲存圖片資訊
|--js //儲存 JS 檔案
|--css //儲存 css 檔案
index.tpl //使用者首頁
login.tpl //登陸首頁
|--zh-CN //中文範本
|--images
|--js
|--css
index.tpl
login.tpl
```
有了這個目錄結構後我們就可以在渲染的地方這樣來實現程式碼:
```Go
s1, _ := template.ParseFiles("views/"+lang+"/index.tpl")
VV.Lang=lang
s1.Execute(os.Stdout, VV)
```
而對於裡面的 index.tpl 裡面的資源設定如下:
```html
// js 檔案
<script type="text/javascript" src="views/{{.Lang}}/js/jquery/jquery-1.8.0.min.js"></script>
// css 檔案
<link href="views/{{.Lang}}/css/bootstrap-responsive.min.css" rel="stylesheet">
// 圖片檔案
<img src="views/{{.Lang}}/images/btn.png">
```
採用這種方式來本地化檢視以及資源時,我們就可以很容易的進行擴充套件了。
## 總結
本小節介紹了如何使用及儲存本地資源,有時需要透過轉換函式來實現,有時透過 lang 來設定,但是最終都是透過 key-value 的方式來儲存 Locale 對應的資料,在需要時取出相應於 Locale 的資訊後,如果是文字資訊就直接輸出,如果是時間日期或者貨幣,則需要先透過`fmt.Printf`或其他格式化函式來處理,而對於不同 Locale 的檢視和資源則是最簡單的,只要在路徑裡面增加 lang 就可以實現了。
## links
* [目錄](<preface.md>)
* 上一節:[設定預設地區](<10.1.md>)
* 下一節:[國際化站點](<10.3.md>)
<!-- {% endraw %} -->