使用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的一次填坑的更多相关文章

  1. asp.net core系列 76 Apollo 快速安装模式下填坑和ASP.NetCore结合使用

    前言:由于公司占时没有运维,出于微服务的需要,Apollo只能先装在windows 阿里云上跑起来,由于环境及网络等问题,在安装过程中遇到很多坑,算是一个个坑填完后,最终实现. 一. java jdk ...

  2. 什么是core dump linux下用core和gdb查询出现"段错误"的地方

    什么是core dump   linux下用core和gdb查询出现"段错误"的地方 http://blog.chinaunix.net/uid-26833883-id-31932 ...

  3. Net Core在Linux环境

    Net Core在Linux环境 基础环境和相关软件准备 1.CentOS7.1 64位系统(或者其他CentOS版本的64位系统) 2.WinSCP软件(主要是方便管理和编辑Linux系统的文件) ...

  4. .NET跨平台之旅:博问站点迁移至ASP.NET Core on Linux并发布上线

    Powered by ASP.NET Core on Linux! 我们全站的 .NET Core 迁移工作如火如荼,这是我们今年上半年的重要工作. 今天我们终于完成了博问产品(q.cnblogs.c ...

  5. .net core在Linux下获取AD域信息

    .net core在Linux下获取AD域信息 .net Core 2.1.4 .net core现在System.DirectoryServices只支持Windows平台下使用. 参考: http ...

  6. .net core在linux下图片中文乱码

    不得不吐槽一下,.net core 2.2的System.Drawing在linux有很多坑,又是依赖libgdiplus,又是依赖gdiplus,依赖解决了又来了个中文乱码,怎的一声哀叹 这里做个笔 ...

  7. Asp.Net Core中使用Swagger,你不得不踩的坑

    很久不来写blog了,换了新工作后很累,很忙.每天常态化加班到21点,偶尔还会到凌晨,加班很累,但这段时间,也确实学到了不少知识,今天这篇文章和大家分享一下:Asp.Net Core中使用Swagge ...

  8. MySQL填坑系列--Linux平台下MySQL区分大小写问题

    大家好,我是软件大盗(道),下面开始我们的<MySQL填坑系列>. 笔者最近又在MySQL的边缘试探,然后,试探着,试探着就报错了. 书接上文,系统连接数据库时报错:找不到DB_TIMIN ...

  9. EF Core 3.0 Preview 9 的2个小坑

    之前我们的数据库服务器使用的是 SQL Server 2008 R2 ,由于从 EF Core 3.0 Preview 6 开始不支持 UseRowNumberForPaging ,只能停留在 EF ...

随机推荐

  1. .netcore发布时指定服务器的系统类型

    asp.net core 开发完成后发布,在IIS上面访问,直接报错  系统是windows2008 Application startup exception: System.DllNotFound ...

  2. CORS 跨域 node |XMLHttpRequest 跨域提交数据 node

    node服务端 app.post('/getdata',function(req,res,next){ req.setEncoding('utf8'); res.setHeader('Access-C ...

  3. vue组件通信方式(多种方案)

    一.Props传递数据 components |-Grandson1.vue //孙子1 |-Grandson2.vue //孙子2 |-Parent.vue //父亲 |-Grandson1.vue ...

  4. 关于Java的i++和++i的区别

    之前对于 i++ 和 ++i 的理解就是: int i=1,a=0; 1.i++ 先运算在赋值,例如 a=i++,先运算a=i,后运算i=i+1,所以结果是a==1 2.++i 先赋值在运算,例如 a ...

  5. VS2010中使用boost正则表达式库

    1.下载boost库.http://www.boost.org/ 我下载的是boost_1_51_0版本.放在D:\opensource\boost_1_51_0. 2.编译boost库.     执 ...

  6. learning java FileInputStream

    public class FileInputStreamTest { public static void main(String[] args) throws IOException { var f ...

  7. vue-cli3整体迁移至服务端渲染nuxtjs

    vue项目与nuxt.js实在有着太多的不同,例如项目结构变化很大,router.js没了,vuex store写法有变化,router钩子没了等等.老项目毕竟也有一些体量,这么折腾我可接受不了,不过 ...

  8. queue怎么用咧↓↓↓

    queue(队列) 定义:queue <int> a; 插入队尾:a.push(x); 查询队尾:a.back(); 查询队首:a.front(); 删除队首:a.pop(); 查询长度: ...

  9. mysql 获取字符串的长度

    mysql> select * from test; +----+------------+-------+-----------+ | id | name | score | subject ...

  10. 如果要对img里面的值做特殊处理,可以直接写方法

    html <img :src="getMore('up')" alt=""> data里面定义的 one: 'http://p1.fishqc.ne ...