Files
build-web-application-with-…/zh-tw/10.1.md
2019-02-26 01:40:54 +08:00

6.1 KiB
Raw Blame History

10.1 設定預設地區

什麼是Locale

Locale是一組描述世界上某一特定區域文字格式和語言習慣的設定的集合。locale名通常由三個部分組成第一部分是一個強制性的表示語言的縮寫例如"en"表示英文或"zh"表示中文。第二部分,跟在一個下劃線之後,是一個可選的國家說明符,用於區分講同一種語言的不同國家,例如"en_US"表示美國英語,而"en_UK"表示英國英語。最後一部分,跟在一個句點之後,是可選的字符集說明符,例如"zh_CN.gb2312"表示中國使用gb2312字符集。

GO語言預設採用"UTF-8"編碼集所以我們實現i18n時不考慮第三部分接下來我們都採用locale描述的前面兩部分來作為i18n標準的locale名。

在Linux和Solaris系統中可以透過locale -a命令列舉所有支援的地區名讀者可以看到這些地區名的命名規範。對於BSD等系統沒有locale命令但是地區資訊儲存在/usr/share/locale中。

設定Locale

有了上面對locale的定義那麼我們就需要根據使用者的資訊(訪問資訊、個人資訊、訪問域名等)來設定與之相關的locale我們可以透過如下幾種方式來設定使用者的locale。

透過域名設定Locale

設定Locale的辦法之一是在應用執行的時候採用域名分級的方式例如我們採用 www.asta.com 當做我們的英文站(預設站),而把域名 www.asta.cn 當做中文站。這樣透過在應用裡面設定域名和相應的locale的對應關係就可以設定好地區。這樣處理有幾點好處

  • 透過URL就可以很明顯的識別
  • 使用者可以透過域名很直觀的知道將訪問那種語言的站點
  • 在Go程式中實現非常的簡單方便透過一個map就可以實現
  • 有利於搜尋引擎抓取能夠提高站點的SEO

我們可以透過下面的程式碼來實現域名的對應locale


if r.Host == "www.asta.com" {
	i18n.SetLocale("en")
} else if r.Host == "www.asta.cn" {
	i18n.SetLocale("zh-CN")
} else if r.Host == "www.asta.tw" {
	i18n.SetLocale("zh-TW")
}

當然除了整域名設定地區之外,我們還可以透過子域名來設定地區,例如"en.asta.com"表示英文站點,"cn.asta.com"表示中文站點。實現程式碼如下所示:


prefix := strings.Split(r.Host,".")

if prefix[0] == "en" {
	i18n.SetLocale("en")
} else if prefix[0] == "cn" {
	i18n.SetLocale("zh-CN")
} else if prefix[0] == "tw" {
	i18n.SetLocale("zh-TW")
}

透過域名設定Locale有如上所示的優點但是我們一般開發Web應用的時候不會採用這種方式因為首先域名成本比較高開發一個Locale就需要一個域名而且往往統一名稱的域名不一定能申請的到其次我們不願意為每個站點去本地化一個配置而更多的是採用url後面帶引數的方式請看下面的介紹。

從域名引數設定Locale

目前最常用的設定Locale的方式是在URL裡面帶上引數例如 www.asta.com/hello?locale=zh 或者 www.asta.com/zh/hello 。這樣我們就可以設定地區:i18n.SetLocale(params["locale"])

這種設定方式幾乎擁有前面講的透過域名設定Locale的所有優點它採用RESTful的方式以使得我們不需要增加額外的方法來處理。但是這種方式需要在每一個的link裡面增加相應的引數locale這也許有點複雜而且有時候甚至相當的繁瑣。不過我們可以寫一個通用的函式url讓所有的link地址都透過這個函式來產生然後在這個函式裡面增加locale=params["locale"]引數來緩解一下。

也許我們希望URL地址看上去更加的RESTful一點例如www.asta.com/en/books (英文站點)和 www.asta.com/zh/books (中文站點)這種方式的URL更加有利於SEO而且對於使用者也比較友好能夠透過URL直觀的知道訪問的站點。那麼這樣的URL地址可以透過router來取得locale(參考REST小節裡面介紹的router外掛實現)


mux.Get("/:locale/books", listbook)

從客戶端設定地區

在一些特殊的情況下我們需要根據客戶端的資訊而不是透過URL來設定Locale這些資訊可能來自於客戶端設定的喜好語言(瀏覽器中設定)使用者的IP地址使用者在註冊的時候填寫的所在地資訊等。這種方式比較適合Web為基礎的應用。

  • Accept-Language

客戶端請求的時候在HTTP頭資訊裡面有Accept-Language一般的客戶端都會設定該資訊下面是Go語言實現的一個簡單的根據Accept-Language實現設定地區的程式碼:


AL := r.Header.Get("Accept-Language")
if AL == "en" {
	i18n.SetLocale("en")
} else if AL == "zh-CN" {
	i18n.SetLocale("zh-CN")
} else if AL == "zh-TW" {
	i18n.SetLocale("zh-TW")
}

當然在實際應用中,可能需要更加嚴格的判斷來進行設定地區

  • IP地址

    另一種根據客戶端來設定地區就是使用者訪問的IP我們根據相應的IP函式庫對應訪問的IP到地區目前全球比較常用的就是GeoIP Lite Country這個函式庫。這種設定地區的機制非常簡單我們只需要根據IP資料庫查詢使用者的IP然後返回國家地區根據返回的結果設定對應的地區。

  • 使用者profile

    當然你也可以讓使用者根據你提供的下拉選單或者別的什麼方式的設定相應的locale然後我們將使用者輸入的資訊儲存到與它帳號相關的profile中當用戶再次登陸的時候把這個設定複寫到locale設定中這樣就可以保證該使用者每次訪問都是基於自己先前設定的locale來獲得頁面。

總結

透過上面的介紹可知設定Locale可以有很多種方式我們應該根據需求的不同來選擇不同的設定Locale的方法以讓使用者能以它最熟悉的方式獲得我們提供的服務提高應用的使用者友好性。