使用ABP框架開發.net core程序已經有一段時間了,由於以前部署在windows服務器上,使用一直很正常。自從前段時間切換服務器上了Linux的Centos服務器,發現以前中文的語言變成了英文,一直找不到緣由。linux
由於以前windows是好的,因此確定是環境問題,最直接的就是Linux本地化引發的。若是對Linux本地化命令不瞭解的,能夠看一下這裏。docker
果真是en_US,嘗試切換使用 LANG=zh_CNshell
成功了,這裏得要全局設置使用 export LANG=zh_CN ,不然其餘session 不會生效。如今好了,重新訪問,但仍是不行。既然Linux系統的本地化已經設置好了,但程序仍是不行,只能從代碼入手。ubuntu
在 Abp.Localization.Dictionaries.DictionaryBasedLocalizationSource 的 GetStringOrNull 中發現,windows
var cultureName = culture.Name; var dictionaries = DictionaryProvider.Dictionaries; //Try to get from original dictionary (with country code) ILocalizationDictionary originalDictionary; if (dictionaries.TryGetValue(cultureName, out originalDictionary)) { var strOriginal = originalDictionary.GetOrNull(name); if (strOriginal != null) { return strOriginal.Value; } }
它是經過DictionaryProvider.Dictionaries 的字典類型,找到咱們預約的字體語言集bash
可是,經過服務器
ILocalizationDictionaryProvider DictionaryProvider = ((IDictionaryBasedLocalizationSource)LocalizationManager.GetSource(CmsIdentityConsts.LocalizationSourceName)).DictionaryProvider;
發現DictionaryProvider.Dictionaries 只有一個en的類型,也就是咱們默認第一個的英文字體包,爲何沒有了咱們定義的中文和繁體包了呢?session
經過追查代碼在Abp.Localization.Dictionaries.Xml.XmlEmbeddedFileLocalizationDictionaryProvider 的 Initialize 中發現,它的代碼以下:框架
var allCultureInfos = CultureInfo.GetCultures(CultureTypes.AllCultures);
var resourceNames = _assembly.GetManifestResourceNames().Where(resouceName => allCultureInfos.Any(culture => resouceName.EndsWith($"{sourceName}.xml", true, null) || resouceName.EndsWith($"{sourceName}-{culture.Name}.xml", true, null))).ToList();
主要是這個CultureInfo.GetCultures(CultureTypes.AllCultures) 函數,它的結果發現以下:ide
截取部分,發現並無zh-CN,取而代之的是zh-Hans-CN。而咱們判斷當前線程是什麼語言,使用的是Thread.CurrentThread.CurrentUICulture 或者 CultureInfo.CurrentUICulture 或者 CultureInfo.CurrentCulture 這三個函數,分別得到的結果是
這兩個對不上,是否是很奇怪,爲何CultureInfo.GetCultures(CultureTypes.AllCultures) 和CultureInfo.CurrentCulture 這兩個結果盡然不一致。那爲何咱們在windows時候是好的呢,再在windows下執行以下:
發現原來windows是有的,linux就沒有了。這就解釋了爲何windows是好的,而Linux則出問題。網上查了好多資料,說是zh-CN過期了,不推薦,新的標準的zh-Hans-CN,反正都是沒什麼用的。
經過代碼發現它是經過拼接,獲得咱們定義的語言集的 {sourceName}-{culture.Name}.xml , 那咱們不是改如下文件的命名就能夠了,說幹就幹。
果真,如今加載的時候可以得到三個語言包了。可是zh-Hans-CN和zh-CN的名字對不上怎麼辦?嘗試設置線程
var currentCulture = System.Globalization.CultureInfo.CreateSpecificCulture("zh-Hans-CN"); Thread.CurrentThread.CurrentCulture = currentCulture; Thread.CurrentThread.CurrentUICulture = currentCulture.GetConsoleFallbackUICulture();
很不幸,三個函數中只有最後一個才能得到:
上ABP官網論壇和網上找了半天,別人都沒有說這裏有問題,摒着不改源代碼,相信廣大碼農的原則下,自我排查,是否是還有別的方法。靈感一現,文件名對應着語言的包名,XML裏面不是還定義了一個參數麼,把它改爲zh-CN會不會好使:
再訪問網站
結果,哈哈成功了!證實它經過當前線程查找的語言包是和內部XML定義的一致,完美解決!
說白了,在linux下運行,那Docker是必不可少的。可是直接運行在ubuntu 上面的鏡像是沒有語言包的。
sudo docker run -i -t <id> /bin/bash root@<id>:/# locale LANG= LANGUAGE= LC_CTYPE="POSIX" LC_NUMERIC="POSIX" LC_TIME="POSIX" LC_COLLATE="POSIX" LC_MONETARY="POSIX" LC_MESSAGES="POSIX" LC_PAPER="POSIX" LC_NAME="POSIX" LC_ADDRESS="POSIX" LC_TELEPHONE="POSIX" LC_MEASUREMENT="POSIX" LC_IDENTIFICATION="POSIX" LC_ALL=
或者
root@4acd55cd86a7:/# locale -a C C.UTF-8 POSIX
顯然是沒有語言包。須要重構建鏡像入手Dockerfile文件以下
FROM ubuntu:trusty RUN locale-gen en_US.UTF-8 ENV LANG en_US.UTF-8 ENV LANGUAGE en_US:en ENV LC_ALL en_US.UTF-8 CMD ["/bin/bash"]
這樣就能夠了,可是若是直接在ubuntu 上構建不行
須要以下處理,簡單說就是安裝語言包locales 命令
FROM ubuntu RUN apt-get update RUN apt-get install -y locales locales-all ENV LC_ALL en_US.UTF-8 ENV LANG en_US.UTF-8 ENV LANGUAGE en_US.UTF-8
大功告成!