JS不完全國際化&本地化手冊 之 理論篇
前言
最近加入到新項目組負責前端技術預研和選型,其中涉及到一個熟悉又陌生的需求——國際化&本地化。熟悉的是之前的項目也玩過,陌生的是之前的實現(xiàn)僅僅停留在"有"的階段而已。趁著這個機會好好學習整理一下,為后面的技術選型做準備。
本篇將闡述國際化和本地化的概念,以及其中一個很重要的概念——Language tag(也叫Language code 或 Culture)。
何為國際化?
國際化我認為就是應用支持多語言和文化習俗(數(shù)字、貨幣、日期和字符比較算法等),而本地化則是應用能識別用戶所屬文化習俗自動適配至相應的語言文化版本。
過去常常以為國際化就是字符串的替換——如"你好!"替換為"What's up, man!",其實具體是分為以下5方面:
- 字符串替換
如"你好!"
替換為"What's up, man!"
. - 數(shù)字表示方式
如1200.01
,英語表示方式為1,200.01
,而法語則為1 200,01
,德語則為1.200,01
. - 貨幣表示方式
如人民幣¥1,200.01
,美元表示方式為$1,200.01
,而英語的歐元則為€1,200.01
,德語的歐元則為1.200,01 €
.
注意: 這里沒有還沒算上匯率呢. - 日期表示方式
如2016年9月15日
,英語表示方式為9/15/2016
, 而法語為15/9/2016
, 德語為15.9.2016
. -
字符比較算法
如ä
和z
比較時,英語、德語中均是ä
排在z
前面,而在瑞典語中則是z
排在ä
前面.本地化的關鍵 —— Language Tag
既然要自動適配至用戶所屬的語言文化版本,那么總得有個根據(jù)才能識別吧?我想大家應該對
zh-CN
和en
等不陌生吧,而它們正是我們所需的根據(jù)了!在我們使用已有i18n庫實現(xiàn)國際化/本地化時,必定會寫下以下文檔{ "en": { "name": "Enter Name" }, "zh-CN": { "name": "輸入姓名" } }
但除了
en
和zh-CN
還有其他鍵嗎?它們的組成規(guī)則又是如何的呢?下面我們來稍微深入的了解這些Language Tag吧!
語法規(guī)則
注意以下采用ABNF語言描述(ABNF的語法請參考語法規(guī)范:BNF與ABNF)
Language-Tag = langtag / privateuse / grandfathered langtag = language ["-" script] ["-" region] *("-" variant) *("-" extension) ["-" privateuse]
可以看到Language-Tag
分為langtag
,privateuse
和 grandfatherd
三個子類,下面我們先了解一般情況用不上的兩個吧!
privateuse
標簽的意思不由subtag registry定義,而是由使用的團隊間私自定義、維護和使用。
格式:
privateuse = "x" 1*("-" (1*8alphanum))
示例:x-zh-CN
是privateuse,其意思不一定與languagezh-CN
一致。
注意: 只作為小集團內(nèi)部用可以,決不能大范圍適用。
grandfathered
用于向后兼容。由于RFC 4646前的標簽無法完全匹配當前registry的標簽語法和意思,因此通過grandfathered來提供向后兼容的特性。
語法:
grandfathered = irregular / regualr irregular = "en-GB-oed" ; irregular tags do not match / "i-ami" ; the 'langtag' production and / "i-bnn" ; would not otherwise be / "i-default" ; considered 'well-formed' / "i-enochian" ; These tags are all valid, / "i-hak" ; but most are deprecated / "i-klingon" ; in favor of more modern / "i-lux" ; subtags or subtag / "i-mingo" / "i-navajo" / "i-pwn" / "i-tao" / "i-tay" / "i-tsu" / "sgn-BE-FR" / "sgn-BE-NL" / "sgn-CH-DE" regular = "art-lojban" ; these tags match the 'langtag' / "cel-gaulish" ; production, but their subtags / "no-bok" ; are not extended language / "no-nyn" ; or variant subtags: their meaning / "zh-guoyu" ; is defined by their registration / "zh-hakka" ; and all of these are deprecated / "zh-min" ; in favor of a more modern / "zh-min-nan" ; subtag or sequence of subtags / "zh-xiang"
注意: 幾乎所有grandfarthered標簽均可被當前registry的標簽及其組合作替代(像i-tao
可以被tao
代替),因此如無意外請使用現(xiàn)行的標簽吧。
下面就到了我們的重頭戲langtag了,首先我們看看langtag下的第一個subtag——language.
Primary language subtag
像en
這種就是Primary language subtag,用于標識資源所對應的語言。
語法:
language = 2*3ALPAH ["-" extlang] / 4ALPHA / 5*8ALPHA extlang = 3ALPHA *2("-" 3ALPHA)
看到language有三種形式,其中讓我比較好奇的是第一種2*3ALPHA ["-" extlang]
。這種形式中前面的2*3ALPHA
稱為macrolanguage,用于標明資源對應一種語言的匯總,而具體的某一種語言/方言則通過extlang指定。而包含extlang部分的language也被稱為encompassed language.
如zh-cmn
和zh-yue
就是encompassed language,其中zh
是macrolanguage,而cmn
和yue
則是extlang。
這里有個很有趣的事情是,我們認為普通話和廣東話等都是漢語的方言,但西方卻認為普通話、廣東話根本就不屬于一種語言,因此像zh-cmn
和zh-yue
在規(guī)范中被設置為redundant,建議直接使用cmn
和yue
等。不過由于歷史原因,我們還是使用zh-CN
代表cmn-CN
。
另外現(xiàn)在可以作為macrolanguage的就只有7個標簽(ar
,kok
,ms
,sw
,uz
,zh
和sgn
)
另外幾個和cmn類似的subtags如下
cmn 普通話(官話、國語) wuu 吳語(江浙話、上海話) czh 徽語(徽州話、嚴州話、吳語-徽嚴片) hak 客家語 yue 粵語(廣東話) nan 閩南語(福建話、臺語) cpx 莆仙話(莆田話、興化語) cdo 閩東語 mnp 閩北語 zco 閩中語 gan 贛語(江西話) hsn 湘語(湖南話) cjy 晉語(山西話、陜北話)
注意: 一般采用全小寫
Script subtag
用于指定字跡或文字系統(tǒng)資源所屬的語言和方言等。
語法:
script = 4ALPHA
注意: 一般采用首字母大寫,后續(xù)字母全小寫
Region subtag
指定與國家、地域對應的語言/方言文化。
語法:
region = 2ALPHA / 3DIGIT
注意: 一般采用全大寫
Variant subtag
指定其他subtag又無法提供的額外信息
語法:
variant = 5*8alphanum / (DIGIT 3alphanum)
示例:de-CH-1996
其中1996是variant subtag,整體意思是在Switzerland使用的自1996改良過的德語。
Extension subtag
提供一種機制讓我們?nèi)U展langtag
語法:
extension = singleton 1*("-" (2*8alphanum)) singleton = DIGIT / %x41-57 / %x59-5A / %x61-77 / %x79-7A
現(xiàn)在僅支持u
作為sigleton的值。
示例:de-DE-u-co-phonebk
表示采用電話本核對的方式對內(nèi)容進行排序等操作。
更多關于language-tag的信息請參考BCP 47
如何選擇Language Tag
硬著頭皮啃下這么多規(guī)范的內(nèi)容,但我還不知道如何組合合適的language-tag呢:(其實選擇和組合的原則就只有一條
在足以區(qū)別當前上下文中其他language-tag的前提下,保持language-tag足夠地短小精干
示例1:下文普通話、粵語并存
<p lang="cmn"> 小陳說:"老大爺,東方廣場怎么走???" 老大爺回答道:"<span lang="yue">你講咩也啊?我聽唔明喔。</span>" </p>
示例2:下文含大陸人講英語、香港人講普通話和美國人說英語
<p lang="cmn"> 小陳說:"<span lang="en-CN">Hi, where are you come from?</span>" 李先生說:"<span lang="cmn-HK">你的英文跟我的普通話一樣普通啊,哈哈!</span>" Simon說:"<span lang="en">Hey, what's up!</span>" </p>
那現(xiàn)在引出另一個問題,那就是我們怎么知道各個subtag具體定義了哪些值呢?
具體都定義在IANA Language Subtag Registry中了。
假如覺得查找起來還是不方便,那么就使用Language Subtag Lookup tool吧!
另外若不清楚各國各地區(qū)所使用的語言或方言時,可通過Ethnologue查看,直接點擊地圖上的區(qū)域即可獲取相應的subtag信息。
總結
現(xiàn)在我們已經(jīng)對國際化和本地化有了更全面的理解,也對Language tag有了更深入的認識,現(xiàn)在是不是迫不及待想挽起袖子擼代碼呢?敬請期待下篇《JS魔法堂:不完全國際化&本地化手冊 之 實戰(zhàn)篇》
感謝
網(wǎng)頁頭部的聲明應該是用 lang="zh" 還是 lang="zh-cn"?
Language Subtag Registry
BCP 47
Language on the Web
Choosing a Language Tag
Language tags in HTML and XML
相關文章
JS基于cookie實現(xiàn)來賓統(tǒng)計記錄訪客信息的方法
這篇文章主要介紹了JS基于cookie實現(xiàn)來賓統(tǒng)計記錄訪客信息的方法,通過javascript記錄訪客信息到cookie的技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-08-08JS中數(shù)組實現(xiàn)代碼(倒序遍歷數(shù)組,數(shù)組連接字符串)
這篇文章主要介紹了JS中數(shù)組實現(xiàn)代碼(倒序遍歷數(shù)組,數(shù)組連接字符串),代碼簡單易懂,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2019-12-12兩種不同的方法實現(xiàn)js對checkbox進行全選和反選
這篇文章主要介紹了通過兩種不同的方法實現(xiàn)js對checkbox進行全選和反選,需要的朋友可以參考下2014-05-05通過BootStrap-select插件 js jQuery控制select屬性變化
bootstrap-select我想大家都不陌生是一個前端下拉框的插件非常好用,在select的標簽中設置屬性可以做很多功能控制,下面通過本文給大家詳細介紹下2017-01-01IE6/IE7中JavaScript json提示缺少標識符、字符串或數(shù)字問題處理
這篇文章主要介紹了IE6/IE7中JavaScript json提示缺少標識符、字符串或數(shù)字問題處理,需要的朋友可以參考下2014-12-12