對HTML標準的思考-記解決H5隨機顯示簡繁體漢字問題

ruuui發表於2017-07-19

遇到問題

上個月在開發淘票票專業版過程中,我們遇到了一個奇怪的問題:

H5容器裡的漢字被顯示為一些奇怪的樣子

IMG_1653.png
IMG_1654.png

首先:
1)這個問題不能準確復現,同型號同系統的兩臺 iPhone 6s Plus 有一臺會出現;
2)不確定是否在 Android 上出現;
3)如果出現問題,重灌 APP 則有可能恢復正常。

介紹下出問題的環境:

目前只在 iOS 系統中復現,H5 使用 Windvane 容器

真機不好除錯,模擬器不能準確復現,暫時不知如何進行了。

跳進了一個坑

以為是簡繁體問題,開啟輸入法看看繁體「票房」怎麼寫,似乎並不是繁體字:

image.png

直到專案進入了測試用例編寫階段,我發現 Aone 上能準確復現這個字型問題,如圖。

image.png

馬上開啟 Chrome 進行除錯,看到了一個陌生字型:AppleGothic

image.png

上字型網站預覽 AppleGothic 效果:

image.png

確實和截圖裡的字型非常相似。知乎搜尋 AppleGothic ,其中有一條:

/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreText.framework/Resources/DefaultFontFallbacks.plist
對應日/韓/簡/繁分別是 AquaHiraKaku/AppleGothic/STHeitiSC-Light/STHeitiTC-Light。

於是幾天時間一直在搜尋相關資料,仍然無解。

跳出坑

開始想到是 iOS 系統字型顯示的優先順序問題,在「設定-通用-語言與地區」可以看到。找到幾臺復現問題的機器查了顯示順序發現,首選語言均是「簡體中文」、「繁體中文」、「English」,不太可能顯示「韓文」。

到底哪裡出了問題?

我又拿出截圖逐個對比了下字型,很明顯「排片」倆字的顯示效果不一致:

image.png

image.png

問題仍然沒解決。

定位問題

回到起點,幾乎沒有任何進展。

無奈,從程式碼層面分析:

影響文字顯示的主要是:

  1. 系統語言與區域設定;
  2. 瀏覽器字型順序設定;
  3. font-family 屬性;
  4. lang 屬性。

排除 1、2 不可改變因素,定位到第3、4點,發現問題:

其中第3點,我們選擇 reset 的 CSS 重置方案,body 節點設定了:

font-family: `Helvetica Neue`, sans-serif;

字型棧設定了 Helvetica 和 「非襯線」字型族,如果是中文字型,Helvetica 預設 Fallback 到下一字型,而下一個字型 sans-serif 則根據系統設定進行渲染。iOS 系統裡對於中文字型預設使用 「PingFang」,簡體為「PingFang SC」,繁體為「PingFang TC」。

聯絡客戶端同學幫忙查了下 APP 區域設定,預設為 en-US

這一點我不太確定:

「如果 html 文件沒有設定語言區域,會從瀏覽器或系統環境取到當前所在區域的字型作為顯示字型」

第4點,容器沒有找到 lang ,且檢測到當前環境為 en,而文件內容是「漢字」,則預設在「簡」、「繁」的「PingFang」中選擇,如:

font-family: `Helvetica Neue`, `PingFang SC`;
font-family: `Helvetica Neue`, `PingFang TC`;

預覽「PingFang TC」字型:

image.png

確實完全匹配。

解決

上面提到的第 4 點,結合定位的 font-family 問題,主要有兩種解決方案。

  1. 設定 lang
  2. 設定 PingFang SC

操作第二點,侷限性比較大。因為僅針對一種字型進行設定,如果未來引入了新字型,則同樣會出現這個問題;

我比較傾向於設定 lang 屬性解決:更新 html 的 <html> 標籤為 <html lang="cmn-Hans">,使瀏覽器預設使用普通話的簡體中文作為顯示語言進行渲染。

對於 lang 屬性的最佳實踐,可以參考:BCP 47

取值順序:language-extlang-script-region-variant-extension-privateuse
來自:https://www.w3.org/International/articles/language-tags/

釋出到預發環境下連續測試了一週,問題沒有復現,基本可確定問題解決。

對於 lang 屬性的設定,過去我們一直設定為 zh-cmn-Hans,查閱了 IANA

Type: redundant

Tag: zh-cmn-Hans
Description: Mandarin Chinese (Simplified)
Added: 2005-07-15
Deprecated: 2009-07-29
Preferred-Value: cmn-Hans

已被標記為「不推薦使用」,需要調整為「cmn-Hans」。如果為了相容,可以加上「zh-」:「zh-cmn-Hans」

參考

  1. IANA language-subtag-registry
  2. IETF BCP 47
  3. W3C language-tags


相關文章