惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Attack and Defense Labs
Attack and Defense Labs
宝玉的分享
宝玉的分享
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
D
Darknet – Hacking Tools, Hacker News & Cyber Security
V
Vulnerabilities – Threatpost
博客园_首页
Engineering at Meta
Engineering at Meta
F
Fortinet All Blogs
C
Cyber Attacks, Cyber Crime and Cyber Security
罗磊的独立博客
V
Visual Studio Blog
Know Your Adversary
Know Your Adversary
Hacker News - Newest:
Hacker News - Newest: "LLM"
美团技术团队
L
LINUX DO - 最新话题
The Last Watchdog
The Last Watchdog
博客园 - 三生石上(FineUI控件)
T
Tor Project blog
云风的 BLOG
云风的 BLOG
N
Netflix TechBlog - Medium
MyScale Blog
MyScale Blog
The GitHub Blog
The GitHub Blog
有赞技术团队
有赞技术团队
I
InfoQ
Last Week in AI
Last Week in AI
V2EX - 技术
V2EX - 技术
量子位
S
Secure Thoughts
L
LangChain Blog
The Hacker News
The Hacker News
H
Help Net Security
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
小众软件
小众软件
K
Kaspersky official blog
Security Archives - TechRepublic
Security Archives - TechRepublic
Google Online Security Blog
Google Online Security Blog
I
Intezer
Vercel News
Vercel News
Hacker News: Ask HN
Hacker News: Ask HN
Cisco Talos Blog
Cisco Talos Blog
Google DeepMind News
Google DeepMind News
S
Securelist
阮一峰的网络日志
阮一峰的网络日志
G
Google Developers Blog
Help Net Security
Help Net Security
Martin Fowler
Martin Fowler
爱范儿
爱范儿
Y
Y Combinator Blog
C
Check Point Blog

博客园 - 开发手游啦啦啦

用TypeScript开发爬虫程序 ABP导航源码分析 AngularJs自定义指令详解(10) - 执行次序 AngularJs自定义指令详解(9) - terminal AngularJs自定义指令详解(8) - priority AngularJs自定义指令详解(7) - multiElement AngularJs自定义指令详解(6) - controller、require AngularJs自定义指令详解(5) - link AngularJs自定义指令详解(4) - transclude AngularJs自定义指令详解(3) - scope AngularJs自定义指令详解(2) - template AngularJs自定义指令详解(1) - restrict ABP的Zero Sample ABP的工作单元 ABP的数据过滤器(Data Filters) ABP的事件总线和领域事件(EventBus & Domain Events) 初入Cocos2d-x 2.2 quick-cocos2d-x之testlua之VisibleRect.lua quick-cocos2d-x之testlua之mainMenu.lua
ABP的语言切换
开发手游啦啦啦 · 2015-07-16 · via 博客园 - 开发手游啦啦啦

在ABP官网http://www.aspnetboilerplate.com/创建一个Multi Page Web Application项目并打开,在Web项目下可以找到一个Controllers/LayoutController.cs,里面有代码如下:

        [ChildActionOnly]
        public PartialViewResult LanguageSelection()
        {
            var model = new LanguageSelectionViewModel
                        {
                            CurrentLanguage = _localizationManager.CurrentLanguage,
                            Languages = _localizationManager.GetAllLanguages()
                        };

            return PartialView("_LanguageSelection", model);
        }

对,这段控制器代码对应于视图Views/Layout/_LanguageSelection.cshtml,用于页面右上角的语言切换:

控制器传给视图一个LanguageSelectionViewModel对象,用于展示当前默认使用的语言和下拉菜单中支持的语言。

观察上面的代码,就知道LanguageSelectionViewModel对象里的信息其实都是从LocalizationManager传递过来的。查看ABP的源码,信息的源头又可以追溯到ILocalizationConfiguration,原来,语言实际配置的代码放在Web项目的App_Start/某某WebModule.cs的PreInitialize方法里:

       public override void PreInitialize()
        {
            //Add/remove languages for your application
            Configuration.Localization.Languages.Add(new LanguageInfo("en", "English", "famfamfam-flag-england", true));
            Configuration.Localization.Languages.Add(new LanguageInfo("tr", "Türkçe", "famfamfam-flag-tr"));
            Configuration.Localization.Languages.Add(new LanguageInfo("zh-CN", "简体中文", "famfamfam-flag-cn"));

           ...
        }

LanguageInfo构造函数的第三个参数为图标名,从_LanguageSelection视图可以看到:

 <li><a href="/AbpLocalization/ChangeCulture?cultureName=@(language.Name)&returnUrl=@(Request.Url)"><i class="@language.Icon"></i> @language.DisplayName</a></li>

原来在这里使用了一组famfamfam国旗图标,官网:http://www.famfamfam.com/lab/icons/flags/

查看Web项目下的Content/flags/famfamfam-flags.css可以看到对这些国旗图标的定义:

[class^="famfamfam-flag"] {
  display: inline-block;
  width: 16px;
  height: 11px;
  line-height: 11px;
  /* vertical-align: text-top; */
  background-image: url("famfamfam-flags.png");
  background-position: 0 0;
  background-repeat: no-repeat;
}

.famfamfam-flag-zw { background-position: 0px 0px; width: 16px; height: 11px; }
.famfamfam-flag-zm { background-position: -16px 0px; width: 16px; height: 11px; }
.famfamfam-flag-za { background-position: 0px -11px; width: 16px; height: 11px; }
.famfamfam-flag-yt { background-position: -16px -11px; width: 16px; height: 11px; }
.famfamfam-flag-ye { background-position: -32px 0px; width: 16px; height: 11px; }
.famfamfam-flag-ws { background-position: -32px -11px; width: 16px; height: 11px; }
.famfamfam-flag-wf { background-position: 0px -22px; width: 16px; height: 11px; }
...

图标文件:

当我们切换语言时,提交的链接大概是这样的:

http://localhost:61754/AbpLocalization/ChangeCulture?cultureName=en&returnUrl=http://localhost:61754/

问题是,ChangeCulture控制器在哪?

查看ABP源码,可以找到Abp.Web.Mvc.Controllers.Localization.AbpLocalizationController类:

    public class AbpLocalizationController : AbpController
    {
        [DisableAuditing]
        public virtual ActionResult ChangeCulture(string cultureName, string returnUrl = "")
        {
            if (!GlobalizationHelper.IsValidCultureCode(cultureName))
            {
                throw new AbpException("Unknown language: " + cultureName + ". It must be a valid culture!");
            }

            Response.Cookies.Add(new HttpCookie("Abp.Localization.CultureName", cultureName) { Expires = Clock.Now.AddYears(2) });

            if (Request.IsAjaxRequest())
            {
                return Json(new MvcAjaxResponse(), JsonRequestBehavior.AllowGet);
            }

            if (!string.IsNullOrWhiteSpace(returnUrl))
            {
                return Redirect(returnUrl);
            }

            return Redirect(Request.ApplicationPath);
        }
    }

一目了然,ABP把“当前所使用的语言”记录在cookies里了。

再回头翻查LocalizationManager类里定义的GetCurrentLanguage方法:

       private LanguageInfo GetCurrentLanguage()
        {
            if (_configuration.Languages.IsNullOrEmpty())
            {
                throw new AbpException("No language defined in this application. Define languages on startup configuration.");
            }

            var currentCultureName = Thread.CurrentThread.CurrentUICulture.Name;

            //Try to find exact match
            var currentLanguage = _configuration.Languages.FirstOrDefault(l => l.Name == currentCultureName);
            if (currentLanguage != null)
            {
                return currentLanguage;
            }

            //Try to find best match
            currentLanguage = _configuration.Languages.FirstOrDefault(l => currentCultureName.StartsWith(l.Name));
            if (currentLanguage != null)
            {
                return currentLanguage;
            }

            //Try to find default language
            currentLanguage = _configuration.Languages.FirstOrDefault(l => l.IsDefault);
            if (currentLanguage != null)
            {
                return currentLanguage;
            }

            //Get first one
            return _configuration.Languages[0];
        }

上面代码并没发现读取cookies的操作,再翻到ABP源码的Abp.Web.AbpWebApplication类,原来放到了Application_BeginRequest方法里读取:

       protected virtual void Application_BeginRequest(object sender, EventArgs e)
        {
            var langCookie = Request.Cookies["Abp.Localization.CultureName"];
            if (langCookie != null && GlobalizationHelper.IsValidCultureCode(langCookie.Value))
            {
                Thread.CurrentThread.CurrentCulture = new CultureInfo(langCookie.Value);
                Thread.CurrentThread.CurrentUICulture = new CultureInfo(langCookie.Value);
            }
        }