最近因为项目需要又从UWP开发转到了Asp.net mvc 开发,由于也不是什么老手,所以就将项目常见的一些技术问题记录一下自己的解决方案。
第一个需求:用户可以自由切换界面显示语言。
解决方案一:界面字段信息分语言保存在数据库,根据用户选择语言读取。
个人观点:由于需要经过一次数据库,相对比较慢。而且所有界面的字段数据如果一次性读取使用也占用内存,如果分页面读取更慢。
解决方案二:界面字段信息分语言保存在资源文件。
代码地址:https://github.com/NewBLife/Asp.net-MVC/tree/master/MutiLaugage
个人观点:
- 有专门的编辑器编辑字段,相对数据库操作方便!
- 运行时读取内嵌的二进制文件,快!
资源文件运行原理:
- 在向 Visual Studio 项目中添加资源文件时,Visual Studio 会在项目目录中创建一个 .resx 文件。
- 编译时,Visual Studio 首先会将项目中的 .resx 文件转换为二进制资源 (.resources) 文件,然后在项目的 obj 目录的子目录中存储这些文件。
- Visual Studio 会将不包含本地化资源的任何资源文件嵌入项目所生成的主程序集中。 如果任何资源文件包含本地化资源,则 Visual Studio 会将它们嵌入每个本地化区域性的单独附属程序集中。 然后,它会将各个附属程序集存储在其名称与本地化区域性对应的目录中。 例如,本地化的英语(美国)资源将存储在 en-US 子目录中的附属程序集中。
资源文件的多语言实现方式
- 路由设置。(例如:example.com/en-US/Home/Index)
- Cookie设置。
路由设置项目实现:
1,多语言路由设置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | routes.MapRoute( "DefaultLocalized" , "{culture}/{controller}/{action}/{id}" , new { controller = "Home" , action = "Index" , id = "" , culture = "en-US" }); |
2,Request进程语言设置。
一,BaseController的BeginExecuteCore方法设置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | public class BaseController : Controller { protected override IAsyncResult BeginExecuteCore(AsyncCallback callback, object state) { //string language = RouteData.Values["language"].ToString() ?? "nl"; //string culture = RouteData.Values["culture"].ToString() ?? "NL"; string cultureName = RouteData.Values[ "culture" ] as string ; // Attempt to read the culture cookie from Request if (cultureName == null ) cultureName = Request.UserLanguages != null && Request.UserLanguages.Length > 0 ? Request.UserLanguages[0] : null ; // obtain it from HTTP header AcceptLanguages // Validate culture name //cultureName = CultureHelper.GetImplementedCulture(cultureName); // This is safe if (RouteData.Values[ "culture" ] as string != cultureName) { // Force a valid culture in the URL RouteData.Values[ "culture" ] = cultureName.ToLowerInvariant(); // lower case too // Redirect user Response.RedirectToRoute(RouteData.Values); } // Modify current thread's cultures Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(cultureName); Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture; return base .BeginExecuteCore(callback, state); } } |
二,Filter全局设置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public class InternationalizationAttribute : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { //string language = (string)filterContext.RouteData.Values["language"] ?? "nl"; //string cultureName = (string)filterContext.RouteData.Values["culture"] ?? "en-US"; string cultureName = filterContext.RouteData.Values[ "culture" ] as string ; //Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(string.Format("{0}-{1}", language, culture)); //Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(string.Format("{0}-{1}", language, culture)); Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(cultureName); Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture; } } |
3,测试
Cookie设置项目实现:
1,用户选择语言Cookie保存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public ActionResult Change( string language) { if (language != null ) { Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(language); Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture; } HttpCookie cookie = new HttpCookie( "_culture" ); cookie.Value = language; Response.Cookies.Add(cookie); return View(); } |
2,Request进程语言设置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public class BaseController : Controller { protected override IAsyncResult BeginExecuteCore(AsyncCallback callback, object state) { // Cookie Language setting string cultureName = string .Empty; // Attempt to read the culture cookie from Request HttpCookie cultureCookie = Request.Cookies[ "culture" ]; if (cultureCookie != null ) cultureName = cultureCookie.Value; else cultureName = Request.UserLanguages != null && Request.UserLanguages.Length > 0 ? Request.UserLanguages[0] : // obtain it from HTTP header AcceptLanguages null ; // Modify current thread's cultures Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(cultureName); Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture; return base .BeginExecuteCore(callback, state); } } |
3,测试
备注:
1,获取用户浏览器默认语言设置方法
Request.UserLanguages != null && Request.UserLanguages.Length > 0 ? Request.UserLanguages[0] : null
2,Thread.CurrentThread.CurrentCulture与Thread.CurrentThread.CurrentUICulture的区别Thread.CurrentThread.CurrentCulture:各个国家相关表示格式设置,比如 日期格式,通货格式等。Thread.CurrentThread.CurrentUICulture:决定ResourceManager读取那个资源文件。
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 理解Rust引用及其生命周期标识(下)
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 2025成都.NET开发者Connect圆满结束
· 在 VS Code 中,一键安装 MCP Server!
· 后端思维之高并发处理方案
· langchain0.3教程:从0到1打造一个智能聊天机器人
· 千万级大表的优化技巧