tedshd's DevNote

tedshd's DevNote

Develop & Design Note by Ted

在數位中所定義與使用語言與文字的規範

on 2020-05-25

前言

因為最近在做一些語系的整理

為了字型的關係

就整理了一下一些在數位資訊上面有關於文字與語言的一些規範

這裡會概括了系統與軟體開發與輸入裝置的處理

因為資訊量太廣

所以不一定會有個脈絡

基本上只有大概分一段一段的說明

初心者的誤區

  1. 國家和語言有很強的關聯

這是很多人一開始處理多國語系都會有個誤解的

常常在系統中看到 en-US, zh-TW, ja-jp

就會下意識的把語言和國家綁定在一起

然後結果就是在該國家只能顯示該語言

但現實是每個國家都不一定都只有使用一個語言啊~~

新加坡同時普遍用中文和英文(官方語言是英文)

  1. 以為在限定的國家或系統才能使用限定的語言

這和上一個很類似, 以為用到某個國家的系統或是使用某個系統設定在某些國家就會限制了語言

這是錯誤的觀念

記住

語言和國家沒絕對關係

語言和國家沒絕對關係

語言和國家沒絕對關係

  1. 拉丁文就是英文

這後面會提到

  1. 語言和文字在定義上的有強烈的關係

在廣義的定義下確實如此

但真正探究下去其實不應該這樣說

這後面會提到

  1. 鍵盤上沒有注音符號還是可以打中文啊

那現在很多鍵盤都沒有倉頡符號

那不就沒辦法用倉頡輸入法了嗎?

來講一下文字

有時大家常常聽到拉丁文這個東西

那麼拉丁文究竟是什麼文字?

相信不少人就會說英文啊

沒錯

但不太正確

英文就是拉丁文字的其中一部分

那拉丁文又是從哪裡來呢?

這又有點牽扯到語言了

現在最廣泛的語系算是印歐語系

而其中的拉丁語系在古歐洲經由羅馬帝國向外發展

所以拉丁字母也就很廣泛的使用(文化侵略的結果)

上面提到英文是拉丁文部分之一

是因為實際上拉丁文不只是 A ~ Z 26 個字母

德文, 法文等也是用拉丁字母

但是這些語言額外多有各種音對應的字母

所以會有所謂的延伸拉丁字母

尖音 重音 折音 分音/德語變音 軟音 鼻音 鼻化元音 合字 來自盧恩字母
Á É Í Ó Ú Ý À È Ì Ò Ù Â Ê Î Ô Û Ä Ë Ï Ö Ü Ÿ Ç Ş Ã Õ Ñ Ą Ę Į Ų Æ Œ Ø IJ Þ
á é í ó ú ý à è ì ò ù â ê î ô û ä ë ï ö ü ÿ ç ş ã õ ñ ą ę į ų æ œ ø ij ß þ

這邊後面再輸入裝置時會在特別提到

語言與地區規範

文字

ISO 15924

也有應用在字型上

字型的 metadata 會跟你說該字型有哪些文字可以用

下圖為 Google 有名的字體 noto 的繁體字型所帶有的資訊

image

額外補充一下

因為大部分會是用 opentype 的字型

opentype 是微軟和 Adobe 共同開發的, 所以微軟的文件有詳細的介紹

所以這裡也貼一下 metadata 裡面的 table format 介紹

OpenType™ Layout Common Table Formats

這裡有個網站可以上傳字型檔(必須是 opentype 格式, 即 .otf, .ttf, .ttc) 確認該字型的資訊

font-inspector

語言

ISO 639

普遍使用於各個系統中的語言代碼

底下目前有定義到 ISO 639-6

但是普遍使用的是 639-1 到 639-3

ISO 639-1 列表

國家(地區)

ISO 3166-1

定義國家的代碼

都需要大寫

上述兩者常常以 語言-國家語言_國家 的形式組合在一起

而大多的語言編碼都是基於 BCP 47

language-extlang-script-region-variant-extension-privateuse

  • language - 語言
  • extlang - 地方語言擴充
  • script - 文字
  • region - 地區
  • variant - 方言 IANA 定義
  • extension
  • privateuse

大多數的組合會是 language-extlang-region

在其中 RFC 3066 主要定義了用 - 連接

這邊得先提醒

在不同的系統中所採用的規範是略有所不同的

所以必須要清楚在哪些系統平台上是採用哪些規範

以免在程式處理上出現問題

這裡列舉一下常見的系統平台

Web

通常是以 Accept-Language 為判定基礎

BCP 47 定義了語系區域的呈現格式

W3C - Language tags in HTML and XML 有具體的說明

比較特別的一點是其實關於 region 並沒有規範強制要大寫

只是因為在 ISO 3166-1 中規定都要大寫

所以約定成俗

Android

開發文件其實就有說明了

也一樣遵循 BCP 47

但是有的人應該會發現為何 toString 後會是

language + "_" + country + "_" + (variant + "_#" | "#") + script + "-" + extensions

這樣的組合

ex: **zh_CN_#Hans**

因為這是基於 ICU - International Components for Unicode 定義的規則

裡面的 Locale

iOS

Language and Locale IDs

由 language 和 locale 組成

language 走 ISO 639-1 / 639-2

locale 走 ISO 3166-1

但是比較特別的是

locale

Locale ID syntax Examples Description
[language designator] en, fr An unspecified region where the language is used.
[language designator]_[region designator] en_GB, zh_HK The language used by and regional preference of the user.
[language designator]-[script designator] az-Arab, zh-Hans An unspecified region where the script is used.
[language designator]-[script designator]_[region designator] zh-Hans_HK The script used by and regional preference of the user.

這條規則目前沒找到規範

但是文件也提到如果要更詳細的話也是要遵循 BCP 47 的格式定義

Linux

走 POSIX 平台所定義的標準 ISO/IEC 15897

地區設定

language[_territory[.codeset]][@modifier]

language 用 ISO 639-1

territory 用 ISO 3166-1

Mac OS

一樣走 POSIX 平台所定義的標準 ISO/IEC 15897

Windows

Windowa Vista 之後使用 RFC 4646

<language>-<Script>-<REGION>_<sort order>

來聊一下鍵盤輸入法

鍵盤上面所有的按鍵都是有定義標準的 key code

基本上就是那兩大家 MS 和 Apple 定義出來的

當然還有些按鍵因應各個廠商的需求會自己去定義, 這邊就不討論

所以這就有個問題了

鍵盤到底可不可以打出任何語言的文字?

答案是可以的

而且不分系統

以 Mac 為例

Mac 已經內建了所有語言的輸入法

只要切到該輸入法就可以輸入該語言的文字了

但會發現一個問題

有的文字沒有按鍵可以按

這又要牽扯到一個問題

鍵盤的 layout

有分 ISO, ANSI, JIS

有在用 Mac 外接鍵盤的應該都有看過

Mac 在外接鍵盤時會叫你按左 shift 右邊和右 shift 左邊

之後就會叫你選 layout

ISO 對應歐規(歐洲的國家)

image

ANSI 對應美規(大部分的國家)

image

JIS 對應日規(日本)

image

為何要分這三種 layout 是因為打字區需要的按鍵數量是不一樣的

ISO 需要有延伸拉丁字母

ANSI 只要 A ~ Z

JIS 也有一些獨立使用的按鍵

這些按鍵在系統都是讀得到 key code 的

只是輸入法有沒有對應的輸出而已

所以鍵盤底層的韌體會定義好該按鍵是要送什麼 key code

而判定 key code 是系統和輸入法的工作

所以真正影響的實際上只有鍵盤的 layout 和輸入法會打出什麼

和作業系統設定的語言與國家無關, 也和鍵盤上面的印字無關

結語

在整理字型時, 如果上述的東西需要有大概的了解

這樣對整理字型的使用會是更佳的容易

比較可惜的是我目前沒找到文字與語言對應的表(可能是搜尋的太少了?

所以目前只有針對幾個國家自己做對應表

Read more

如何在網頁載入比較大量的資料時增加效能?

on 2020-05-21

前言

在後台系統會常遇到的問題就是要呈現大量的資料(表單)

通常在這情況下會有兩種方式呈現資料

  1. 分頁

  2. 無限滾動

但是這都要在 model 額外做不少工

例如: 處理分頁, 處理排序, 處理搜尋

這些都是要再花時間處理的

這邊將會介紹一下如何在不太改動 model 的情況下提升前端效能

當然在真的是非常的大量的資料時還是真的要在 model 提供參數去 query DB

現況

因為新的需求需要添加到不少的資料

但是因為時程短加上再添加的資料量也不會大的誇張(約共 2000 左右的量

所以還是一次全部載入

問題點

首先會先遇到的問題就是

一次載入 2000 多筆資料頁面就開始變很慢(因為還有圖片)

打開 chrome developtool 就會發現 DOMContentLoaded 要到 13s 左右

慢到爆炸

這 13s 還不包含之後要執行的 JavaScript 與畫面渲染

因為還有圖片

所以 2000 多個圖片載完後

整個頁面花了 1 分鐘多…

screenshot image

解決方案

先把圖片改成 lazyload

從瀏覽器一次載入 2000 多筆資料瞬間變成只載入頁面會呈現的圖片

但是 DOMContentLoaded 還是要 12s 左右啊~~

screenshot image

解決 DOMContentLoaded 問題

因為後台的資料表單是 SSR(server side render) 從 PHP 噴的

所以一定會有個問題就是 2000 多筆的 table HTML DOM 很多

然後因為是從 server side 噴到瀏覽器上

所以會有一個卡的點就是 DB query 的效能(這部分已經優化過了, 在這次的案例是一次全撈出來是要優化什麼啊)

那只要 DB query 卡到的話

就會延遲頁面的呈現

因為 server side 是把所有的 response content 都好了才會噴回去瀏覽器

當然在 PHP 可以用 ob_flushflush 來處理

Refer - 強迫 PHP 將 Buffer 的資料提前輸出

Refer - PHP flush()與ob_flush()的區別詳解

但是目前沒有想要這樣做

因為目前的程式結構有點複雜, 所以就沒有用這方法實作

所以最後是決定把這一頁改成 CSR(client side render)

用 AJAX 拉資料下來

JavaScript 優化

因為是後台的操作會有 CRUD 的行為, 原本這些行為就都是 AJAX 處理

所以在 JavaScript 有很多操作行為的事件綁定(event binding)

所以就把這些行為改成事件委派(event delegation)

關於分頁, 排序和搜尋的處理

資料量變多後 PM 最喜歡說我希望有搜尋和排序這樣比較方便看資料誒

但是我們已經把所以資料經由 AJAX 取回到瀏覽器上了

這時就可以用一個 jQuery 超好用的 plugin DataTables

這 plugin 可以把 client 的 data 重新處理成具有分頁排序和搜尋的 table

也支援把已經在頁面上的 table 或 AJAX response 或是在 JavaScript 中的 data 重新處理

結論

當上述的東西處理完後

screenshot image

DOMContentLoaded 因為改成 AJAX 所以會少很多(12s -> 2s)

因為資料改成 AJAX 產生, 這速度比 SSR 快多了

再不看畫面 render 的情況下整個 loading 速度已經也提高很多

至於 render 時間不太好測試比較所以這邊就不比較了

基本上上述這些只會動用到前端的程式即可達到成效不錯的優化

也可以在 chrome 裝上 lighthouse 來檢測

因為光是這樣改在體感上就提升許多了, 也就沒有再用 lighthouse 測試

額外補充

測試 JavaScript 效能

可以用 runtime 來測試

var startTime = new Date().getTime();

var endTime = new Date().getTime();
console.log('testName: ' + (endTime - startTime) + 'ms');

DataTables AJAX 處理

Refer - ajax

Refer - columns.data

Refer - columns.render

Refer - [jQuery] jQuery DataTables 資料行加入checkbox、按鈕,關閉資料行排序、改變下拉選單的每頁顯示幾筆、變更DataTables樣式…等功能 Part5 final

套用 DataTables 後的 image lazyload 處理

因為現在使用的 image lazyload 會是觀察當前畫面的圖片後在確認這些圖片是否在可視範圍才會加載

所以當有分頁時

因為換分頁時會是新的 table DOM(table DOM 會重建) 所以換分頁後的圖片是之前沒有被觀察的

所以換分頁後得再重新觀察當前頁面的圖片

DataTables 有 page 的 event 可以監聽分頁切換

Refer - page

但是當使用 搜尋 , 排序等會造成畫面重新出現的情況的話

要有效地處理就是使用 datatable 的 draw event

Refer - page

只要表單重繪就會觸發

這邊圖片延遲載入是使用自己參照 Google 的開發文件寫的 code simpleImgLazyLoad

這邊 image lazy 只要圖片載完後 observer 物件就會回收

不過沒有載到的圖片還是會持續觀察

只是應該是不會有太大的影響

DataTables 版面寬度問題

因為 DataTables 處理完後有時會自動加上寬度

所以可以直接先使用 width: 100% 處理

Refer - DataTables example - Flexible table width

因為 datatable 預設的 table 是固定的

如果有 responsive 的需求

要額外用 responsive 的套件來協助

Refer - responsive

Read more