diff --git a/README.en.md b/README.en.md
index 3e8ca0a..3576d58 100644
--- a/README.en.md
+++ b/README.en.md
@@ -366,49 +366,51 @@ bash reinstall.sh windows \
```
-Supported languages
+ --lang list
-```text
-ar-sa
-bg-bg
-cs-cz
-da-dk
-de-de
-el-gr
-en-gb
-en-us
-es-es
-es-mx
-et-ee
-fi-fi
-fr-ca
-fr-fr
-he-il
-hr-hr
-hu-hu
-it-it
-ja-jp
-ko-kr
-lt-lt
-lv-lv
-nb-no
-nl-nl
-pl-pl
-pt-pt
-pt-br
-ro-ro
-ru-ru
-sk-sk
-sl-si
-sr-latn-rs
-sv-se
-th-th
-tr-tr
-uk-ua
-zh-cn
-zh-hk
-zh-tw
-```
+Supports these three language format codes. Case insensitive.
+
+| CC Format | CC-CC Format | Language |
+| - | - | - |
+| ar | ar-sa | Arabic |
+| bg | bg-bg | Bulgarian |
+| cs | cs-cz | Czech |
+| da | da-dk | Danish |
+| de | de-de | German |
+| el | el-gr | Greek |
+| gb | en-gb | Eng_Intl |
+| en | en-us | English |
+| es | es-es | Spanish |
+| mx | es-mx | Spanish_Latam |
+| et | et-ee | Estonian |
+| fi | fi-fi | Finnish |
+| | fr-ca | FrenchCanadian |
+| fr | fr-fr | French |
+| he | he-il | Hebrew |
+| hr | hr-hr | Croatian |
+| hu | hu-hu | Hungarian |
+| it | it-it | Italian |
+| ja | ja-jp | Japanese |
+| ko | ko-kr | Korean |
+| lt | lt-lt | Lithuanian |
+| lv | lv-lv | Latvian |
+| no | nb-no | Norwegian |
+| nl | nl-nl | Dutch |
+| pl | pl-pl | Polish |
+| pp | pt-pt | Portuguese |
+| pt | pt-br | Brazilian |
+| ro | ro-ro | Romanian |
+| ru | ru-ru | Russian |
+| sk | sk-sk | Slovak |
+| sl | sl-si | Slovenian |
+| sr | sr-latn / sr-latn-rs | Serbian_Latin |
+| sv | sv-se | Swedish |
+| th | th-th | Thai |
+| tr | tr-tr | Turkish |
+| uk | uk-ua | Ukrainian |
+| cn | zh-cn | ChnSimp |
+| tw | zh-tw | ChnTrad |
+| hk | zh-hk | ChnTrad_Hong_Kong |
diff --git a/README.md b/README.md
index 56e4774..635b6f7 100644
--- a/README.md
+++ b/README.md
@@ -366,49 +366,51 @@ bash reinstall.sh windows \
```
-支持的语言
+ --lang 列表
-```text
-ar-sa
-bg-bg
-cs-cz
-da-dk
-de-de
-el-gr
-en-gb
-en-us
-es-es
-es-mx
-et-ee
-fi-fi
-fr-ca
-fr-fr
-he-il
-hr-hr
-hu-hu
-it-it
-ja-jp
-ko-kr
-lt-lt
-lv-lv
-nb-no
-nl-nl
-pl-pl
-pt-pt
-pt-br
-ro-ro
-ru-ru
-sk-sk
-sl-si
-sr-latn-rs
-sv-se
-th-th
-tr-tr
-uk-ua
-zh-cn
-zh-hk
-zh-tw
-```
+支持这三种语言代码格式,不区分大小写
+
+| CC 格式 | CC-CC 格式 | 语言 |
+| - | - | - |
+| ar | ar-sa | Arabic |
+| bg | bg-bg | Bulgarian |
+| cs | cs-cz | Czech |
+| da | da-dk | Danish |
+| de | de-de | German |
+| el | el-gr | Greek |
+| gb | en-gb | Eng_Intl |
+| en | en-us | English |
+| es | es-es | Spanish |
+| mx | es-mx | Spanish_Latam |
+| et | et-ee | Estonian |
+| fi | fi-fi | Finnish |
+| | fr-ca | FrenchCanadian |
+| fr | fr-fr | French |
+| he | he-il | Hebrew |
+| hr | hr-hr | Croatian |
+| hu | hu-hu | Hungarian |
+| it | it-it | Italian |
+| ja | ja-jp | Japanese |
+| ko | ko-kr | Korean |
+| lt | lt-lt | Lithuanian |
+| lv | lv-lv | Latvian |
+| no | nb-no | Norwegian |
+| nl | nl-nl | Dutch |
+| pl | pl-pl | Polish |
+| pp | pt-pt | Portuguese |
+| pt | pt-br | Brazilian |
+| ro | ro-ro | Romanian |
+| ru | ru-ru | Russian |
+| sk | sk-sk | Slovak |
+| sl | sl-si | Slovenian |
+| sr | sr-latn / sr-latn-rs | Serbian_Latin |
+| sv | sv-se | Swedish |
+| th | th-th | Thai |
+| tr | tr-tr | Turkish |
+| uk | uk-ua | Ukrainian |
+| cn | zh-cn | ChnSimp |
+| tw | zh-tw | ChnTrad |
+| hk | zh-hk | ChnTrad_Hong_Kong |
diff --git a/reinstall.sh b/reinstall.sh
index d4c05d4..e83d366 100644
--- a/reinstall.sh
+++ b/reinstall.sh
@@ -732,99 +732,127 @@ assert_cpu_supports_x86_64_v3() {
fi
}
-# sr-latn-rs 到 sr-latn
-en_us() {
- echo "$lang" | awk -F- '{print $1"-"$2}'
-
- # zh-hk 可回落到 zh-tw
- if [ "$lang" = zh-hk ]; then
- echo zh-tw
- fi
+# 判断语言字符是否合法,允许全名和缩写
+is_valid_lang_chars() {
+ [[ "$1" =~ ^[A-Za-z_-]+$ ]]
}
-# fr-ca 到 ca
-us() {
- # 葡萄牙准确对应 pp
- if [ "$lang" = pt-pt ]; then
- echo pp
- return
- fi
- # 巴西准确对应 pt
- if [ "$lang" = pt-br ]; then
- echo pt
+lang_convert() {
+ local out_format=$1
+ local in=$lang
+
+ if ! is_valid_lang_chars "$in"; then
return
fi
- echo "$lang" | awk -F- '{print $2}'
+ # 如果是 fallback_ 开头的,先得到 fallback 后的 cc-cc
+ if [[ "$out_format" = fallback_* ]]; then
+ in=$(lang_convert_inner "$in" fallback_cc-cc)
+ # 如果要输出 fallback_cc-cc ,直接输出
+ if [ "$out_format" = fallback_cc-cc ]; then
+ printf '%s' "$in"
+ return
+ fi
+ # 去除 fallback_ 前缀
+ out_format=${out_format#fallback_}
+ fi
- # hk 额外回落到 tw
- if [ "$lang" = zh-hk ]; then
- echo tw
+ # 尝试转换成目标格式
+ local out
+ out=$(lang_convert_inner "$in" "$out_format")
+
+ # 如果转换成功,则表示输入的语言在列表里面
+ if [ -n "$out" ]; then
+ printf '%s' "$out"
+ else
+ # 如果没有,则手动截取
+ case "$out_format" in
+ cc) cut -d- -f1 <<<"$in" ;;
+ cc-cc) cut -d- -f1-2 <<<"$in" ;;
+ cc-cc-cc) cut -d- -f1-3 <<<"$in" ;;
+ esac
fi
}
-# fr-ca 到 fr-fr
-en_en() {
- echo "$lang" | awk -F- '{print $1"-"$1}'
+lang_convert_inner() {
+ local in=$1
+ local out_format=$2
- # en-gb 额外回落到 en-us
- if [ "$lang" = en-gb ]; then
- echo en-us
- fi
-}
-
-# fr-ca 到 fr
-en() {
- # 巴西/葡萄牙回落到葡萄牙语
- if [ "$lang" = pt-br ] || [ "$lang" = pt-pt ]; then
- echo "pp"
+ if ! is_valid_lang_chars "$in"; then
return
fi
- echo "$lang" | awk -F- '{print $1}'
+ # 可能得到 / ,用 is_valid_lang_chars 过滤掉
+ local out
+ if out=$(
+ lang_map_with_head | sed 1d | to_lower | awk \
+ -v val="$in" \
+ -v c1="$(get_col_number cc)" \
+ -v c2="$(get_col_number cc-cc)" \
+ -v c3="$(get_col_number cc-cc-cc)" \
+ -v c4="$(get_col_number full_language)" \
+ -v cout="$(get_col_number "$out_format")" \
+ '$c1 == val || $c2 == val || $c3 == val || $c4 == val { print $cout }'
+ ) && is_valid_lang_chars "$out"; then
+ printf '%s' "$out"
+ fi
}
-english() {
- case "$lang" in
- ar-sa) echo Arabic ;;
- bg-bg) echo Bulgarian ;;
- cs-cz) echo Czech ;;
- da-dk) echo Danish ;;
- de-de) echo German ;;
- el-gr) echo Greek ;;
- en-gb) echo Eng_Intl ;;
- en-us) echo English ;;
- es-es) echo Spanish ;;
- es-mx) echo Spanish_Latam ;;
- et-ee) echo Estonian ;;
- fi-fi) echo Finnish ;;
- fr-ca) echo FrenchCanadian ;;
- fr-fr) echo French ;;
- he-il) echo Hebrew ;;
- hr-hr) echo Croatian ;;
- hu-hu) echo Hungarian ;;
- it-it) echo Italian ;;
- ja-jp) echo Japanese ;;
- ko-kr) echo Korean ;;
- lt-lt) echo Lithuanian ;;
- lv-lv) echo Latvian ;;
- nb-no) echo Norwegian ;;
- nl-nl) echo Dutch ;;
- pl-pl) echo Polish ;;
- pt-pt) echo Portuguese ;;
- pt-br) echo Brazilian ;;
- ro-ro) echo Romanian ;;
- ru-ru) echo Russian ;;
- sk-sk) echo Slovak ;;
- sl-si) echo Slovenian ;;
- sr-latn | sr-latn-rs) echo Serbian_Latin ;;
- sv-se) echo Swedish ;;
- th-th) echo Thai ;;
- tr-tr) echo Turkish ;;
- uk-ua) echo Ukrainian ;;
- zh-cn) echo ChnSimp ;;
- zh-hk | zh-tw) echo ChnTrad ;;
- esac
+get_col_number() {
+ local col_name=$1
+
+ # 找出第一行,用 xargs -n 1 转成列,然后用 grep 找到行号,再用 cut 取出行号
+ lang_map_with_head | head -1 | xargs -n 1 | grep -Fxn "$col_name" | cut -d: -f1
+}
+
+lang_map_with_head() {
+ # 没有 gb mx 开头的镜像,列出它们作用是,用户输入时识别成 en-gb es-mx
+ # ca 并非对应 fr-ca
+ # pt 对应 pt-br,而不是 pt-pt
+ # uk 对应乌克兰语而不是英国,如果用户输入 uk ,要识别成乌克兰
+ # 第 5 列是可回落的语言
+ cat <