使用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. 删除WordPress菜单wp-nav-menu中li的class或id样式

    我们都知道wordpress已经集成了一些通用的css样式,比如wp-nav-menu菜单会有很多的class,不想看到那么多的选择器,想要清净的世界要如何操作呢?随ytkah一起来看看 <li ...

  2. django-获取购物车商品数量-redis

    视图函数views.py中 from django_redis import get_redis_connection # 连接redis class IndexView(View): '''首页'' ...

  3. am335x system upgrade kernel tf(五)

    1      Scope of Document This document describes TF hardware design 2      Requiremen 2.1     Functi ...

  4. 2019.12.10 switch(){ case: }

    if 适合判断范围 switch 适合判断某个值 两种方法: import java.util.Scanner; class Demo02 { public static void main(Stri ...

  5. Python各种扩展名(py, pyc, pyw, pyo, pyd)区别

    扩展名 在写Python程序时我们常见的扩展名是py, pyc,其实还有其他几种扩展名.下面是几种扩展名的用法. py py就是最基本的源码扩展名 pyw pyw是另一种源码扩展名,跟py唯一的区别是 ...

  6. python 运行当前目录下的所有文件

     查看当前目录下所有py文件(本身除外run) import os file_list = os.listdir(os.getcwd()) # 获取当前目录下所有的文件名print(file_list ...

  7. 剑指offer:两个链表的第一个公共结点

    题目描述: 输入两个链表,找出它们的第一个公共结点. 解题思路: 这道题一开始的题意不太理解,这里的公共结点,实际上指结点指相同,在题目不存在结点值相同的不同结点. 1. 最直接的思路是对链表一的每个 ...

  8. 为什么printf()用%f输出double型,而scanf却用%lf呢?

    转:https://blog.csdn.net/bat67/article/details/52056057 示例:double x:scanf(“%f”,&x):输入“123.4”,输出x的 ...

  9. arcgis python脚本工具实例教程—栅格范围提取至多边形要素类

    arcgis python脚本工具实例教程-栅格范围提取至多边形要素类 商务合作,科技咨询,版权转让:向日葵,135-4855_4328,xiexiaokui#qq.com 功能:提取栅格数据的范围, ...

  10. kubectl -n ingress-nginx exec nginx-ingress-controller-78bd49949c-t22bl -- cat /etc/nginx/nginx.conf

    kubectl -n ingress-nginx exec nginx-ingress-controller-78bd49949c-t22bl -- cat /etc/nginx/nginx.conf