.net core在Linux本地化Localization的一次填坑
使用ABP框架开发.net core程序已经有一段时间了,因为之前部署在windows服务器上,使用一直很正常。自从前段时间切换服务器上了Linux的Centos服务器,发现之前中文的语言变成了英文,一直找不到原因。

因为之前windows是好的,所以肯定是环境问题,最直接的就是Linux本地化引起的。如果对Linux本地化命令不了解的,可以看一下这里。

果然是en_US,尝试切换使用 LANG=zh_CN

成功了,这里得要全局设置使用 export LANG=zh_CN ,否则其他session 不会生效。现在好了,从新访问,但还是不行。既然Linux系统的本地化已经设置好了,但程序还是不行,只能从代码入手。
在 Abp.Localization.Dictionaries.DictionaryBasedLocalizationSource 的 GetStringOrNull 中发现,
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 的字典类型,找到我们预定的字体语言集

但是,通过
ILocalizationDictionaryProvider DictionaryProvider = ((IDictionaryBasedLocalizationSource)LocalizationManager.GetSource(CmsIdentityConsts.LocalizationSourceName)).DictionaryProvider;
发现DictionaryProvider.Dictionaries 只有一个en的类型,也就是我们默认第一个的英文字体包,为什么没有了我们定义的中文和繁体包了呢?
通过追查代码在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) 函数,它的结果发现如下:

截取部分,发现并没有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定义的一致,完美解决!
Docker部署
说白了,在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-
POSIX
显然是没有语言包。需要重构建镜像入手Dockerfile文件如下
FROM ubuntu:trusty
RUN locale-gen en_US.UTF-
ENV LANG en_US.UTF-
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-
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-
ENV LANG en_US.UTF-
ENV LANGUAGE en_US.UTF-
大功告成!
.net core在Linux本地化Localization的一次填坑的更多相关文章
- asp.net core系列 76 Apollo 快速安装模式下填坑和ASP.NetCore结合使用
前言:由于公司占时没有运维,出于微服务的需要,Apollo只能先装在windows 阿里云上跑起来,由于环境及网络等问题,在安装过程中遇到很多坑,算是一个个坑填完后,最终实现. 一. java jdk ...
- 什么是core dump linux下用core和gdb查询出现"段错误"的地方
什么是core dump linux下用core和gdb查询出现"段错误"的地方 http://blog.chinaunix.net/uid-26833883-id-31932 ...
- Net Core在Linux环境
Net Core在Linux环境 基础环境和相关软件准备 1.CentOS7.1 64位系统(或者其他CentOS版本的64位系统) 2.WinSCP软件(主要是方便管理和编辑Linux系统的文件) ...
- .NET跨平台之旅:博问站点迁移至ASP.NET Core on Linux并发布上线
Powered by ASP.NET Core on Linux! 我们全站的 .NET Core 迁移工作如火如荼,这是我们今年上半年的重要工作. 今天我们终于完成了博问产品(q.cnblogs.c ...
- .net core在Linux下获取AD域信息
.net core在Linux下获取AD域信息 .net Core 2.1.4 .net core现在System.DirectoryServices只支持Windows平台下使用. 参考: http ...
- .net core在linux下图片中文乱码
不得不吐槽一下,.net core 2.2的System.Drawing在linux有很多坑,又是依赖libgdiplus,又是依赖gdiplus,依赖解决了又来了个中文乱码,怎的一声哀叹 这里做个笔 ...
- Asp.Net Core中使用Swagger,你不得不踩的坑
很久不来写blog了,换了新工作后很累,很忙.每天常态化加班到21点,偶尔还会到凌晨,加班很累,但这段时间,也确实学到了不少知识,今天这篇文章和大家分享一下:Asp.Net Core中使用Swagge ...
- MySQL填坑系列--Linux平台下MySQL区分大小写问题
大家好,我是软件大盗(道),下面开始我们的<MySQL填坑系列>. 笔者最近又在MySQL的边缘试探,然后,试探着,试探着就报错了. 书接上文,系统连接数据库时报错:找不到DB_TIMIN ...
- EF Core 3.0 Preview 9 的2个小坑
之前我们的数据库服务器使用的是 SQL Server 2008 R2 ,由于从 EF Core 3.0 Preview 6 开始不支持 UseRowNumberForPaging ,只能停留在 EF ...
随机推荐
- .netcore发布时指定服务器的系统类型
asp.net core 开发完成后发布,在IIS上面访问,直接报错 系统是windows2008 Application startup exception: System.DllNotFound ...
- CORS 跨域 node |XMLHttpRequest 跨域提交数据 node
node服务端 app.post('/getdata',function(req,res,next){ req.setEncoding('utf8'); res.setHeader('Access-C ...
- vue组件通信方式(多种方案)
一.Props传递数据 components |-Grandson1.vue //孙子1 |-Grandson2.vue //孙子2 |-Parent.vue //父亲 |-Grandson1.vue ...
- 关于Java的i++和++i的区别
之前对于 i++ 和 ++i 的理解就是: int i=1,a=0; 1.i++ 先运算在赋值,例如 a=i++,先运算a=i,后运算i=i+1,所以结果是a==1 2.++i 先赋值在运算,例如 a ...
- VS2010中使用boost正则表达式库
1.下载boost库.http://www.boost.org/ 我下载的是boost_1_51_0版本.放在D:\opensource\boost_1_51_0. 2.编译boost库. 执 ...
- learning java FileInputStream
public class FileInputStreamTest { public static void main(String[] args) throws IOException { var f ...
- vue-cli3整体迁移至服务端渲染nuxtjs
vue项目与nuxt.js实在有着太多的不同,例如项目结构变化很大,router.js没了,vuex store写法有变化,router钩子没了等等.老项目毕竟也有一些体量,这么折腾我可接受不了,不过 ...
- queue怎么用咧↓↓↓
queue(队列) 定义:queue <int> a; 插入队尾:a.push(x); 查询队尾:a.back(); 查询队首:a.front(); 删除队首:a.pop(); 查询长度: ...
- mysql 获取字符串的长度
mysql> select * from test; +----+------------+-------+-----------+ | id | name | score | subject ...
- 如果要对img里面的值做特殊处理,可以直接写方法
html <img :src="getMore('up')" alt=""> data里面定义的 one: 'http://p1.fishqc.ne ...