• .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-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

     大功告成!

  • 相关阅读:
    PyTorch之前向传播函数自动调用forward
    pytorch 调用forward 的具体流程
    Xcode5下使用纯代码构建简单的HelloWorld程序
    浅谈iOS 5的StoryBoard
    iOS单例
    instancetype 对比 id 的好处
    JSP的7个动作指令
    IOS UIView子类UIScrollView
    XCODE4.6从零开始添加视图
    NSSet类型 以及与NSArray区别
  • 原文地址:https://www.cnblogs.com/Hai--D/p/11121640.html
Copyright © 2020-2023  润新知