创建双语 ASP.NET MVC 3 应用程序 – 第一部分






4.79/5 (46投票s)
本文提供了一个简单的双语网站全球化机制。第一部分创建一个简单的双语网站。
引言
本文是关于 ASP.NET MVC 3 中基本双语网站的两篇文章中的第一篇。我将文章分为两部分,因为我觉得一步到位会过于冗长和复杂。这两部分是
- 创建一个简单的全球化 MVC3 应用程序
- 基于路由的 MVC3 应用程序全球化
本文是初学者使用国际化资源的介绍。代码的编写旨在清晰,而非生产质量。我将使用阿拉伯语作为第二语言,这是因为我最初工作的网站使用阿拉伯语,并且它引出了左右方向支持,否则可能会被忽略。如果您会说阿拉伯语,对任何错误表示歉意,我确实会说一点,但大部分文本都使用了 Google 翻译!
第二篇文章(在此处提供)将涵盖基于路由的国际化,并将更高级。两篇文章都假设对 MVC 的工作原理(特别是相关组件:视图、控制器和 RouteHandler
)以及 .NET 如何处理本地化和文化有基本了解。示例将侧重于默认的 ASPX 视图引擎而不是 Razor,但会在 Razor 标记不同之处提供信息。该机制可以稍微努力扩展以允许多语言网站。
要运行代码,您必须安装 VS2010(和 .NET 4 :-)) 以及 MVC 3 框架。
背景
本文源于我为当前雇主使用 MVC 3 编写的一个概念验证网站。在此之前,我对 ASP.NET MVC 3 几乎没有经验。我的雇主要求他们的网站提供英语和阿拉伯语版本,本文记录并分享了在该过程中实现的内容。网上有一些关于 MVC 3 中本地化的文章,但我没有找到能完全实现我想要的(一个具有类似于 MSDN 的路由策略的双语网站,如第二部分所述)。尽管如此,我必须感谢这些文章的巨大贡献
- Shaun Xu: ASP.NET MVC 中的本地化 – 3 天调查,1 天工作 [^]
- Nadeem Afana 的博客:ASP.NET MVC 3 国际化 [^]
- Alexander Adamyan: ASP.NET MVC 本地化补充 - 使用路由 [^]
在我的应用程序中实现本地化时,我发现这个过程远不如普通的 ASP.NET 那么完善和直观。没有办法自动生成 RESX 文件,而且必须采取额外的步骤才能使内容对视图可用。我也找不到 Microsoft 关于 MVC 3 中本地化和全球化的最佳实践。
代码
原则上,使资源与 MVC3 配合工作的过程相当简单,但不如普通 ASP.NET 应用程序那样
- 创建 RESX 文件来保存文本。
- 使 RESX 内容公开可用。
- 对其他支持的语言和每个视图重复步骤 1 和 2。
- 从视图或控制器(或视图模型!)中的 RESX 获取文本。
- 根据浏览器默认设置文化。
在这篇解释性文章和代码中,我使用了母版页(或 Razor 版本的布局)作为示例。同样的方法适用于子视图,我在下载项目中包含了这方面的一个简单示例,但文章中没有体现。
创建 RESX 文件
我将首先假设应用程序有一个母版页(或 Razor 的布局),我将描述使其准备好进行本地化的过程。普通视图以相同的方式工作,因此此处应用的所有内容都可以应用于视图。让我们将母版页“视图”中的初始标记设置为类似
<body>
<h1>Welcome</h1>
<div>
<asp:ContentPlaceHolder ID="MainContent" runat="server">
</asp:ContentPlaceHolder>
</div>
</body>
等效的 Razor 布局可能如下所示
<body>
<h1>Welcome</h1>
<div>
@RenderBody()
</div>
</body>
我们需要将标题文本(“欢迎”)转移到资源文件。与 ASP.NET 不同,我们无法直接从上下文菜单创建资源。我的建议是镜像您的视图文件夹;我的母版页在名为 Views/Shared 的文件夹中,因此我将创建一个目录结构 Resources/Shared。母版页名为“MasterPage.Master”(Razor 用户,请参阅本节末尾的红色注意事项),因此右键单击资源文件夹并遵循这些选项
选择“常规”选项卡,“资源文件”,并更改文件名
完成此操作后,您需要将文本移动到资源文件中,给它一个合理的名称,在本例中为“Heading”,然后输入文本(“Welcome”)。现在将访问修饰符设置为 public,没有此步骤,视图将无法访问它
通常,您会为每个要本地化的文本部分重复此操作,但我只输入了一个值以使示例故意简单。下一步是将 RESX 文件复制到其自身所在的同一目录中(记得提前保存!),并根据您希望支持的文化重命名它。在我的例子中,我使用阿拉伯语,所以“MasterPage.resx”有一个伴随的 MasterPage.ar.resx。请注意,复制的文件继承了公共访问修饰符,因此无需重新设置。现在我们所需要做的就是重复创建剩余视图的 RESX 文件的过程。完成后,我们应该有“镜像”的 Views 和 Resources 文件夹,每个视图为每种语言一个 RESX 文件
将文本添加到视图
通过标记将文本从 RESX 文件获取到视图中是相当容易的,我们现在实际上是在获取一个类的属性。在母版页中,我们将单词“Welcome”替换为神奇的咒语
<body>
<h1><%= InternationalizedMvcApplication.Resources.Shared.MasterPage.Heading %></h1>
<div>
<asp:ContentPlaceHolder ID="MainContent" runat="server">
</asp:ContentPlaceHolder>
</div>
</body>
对于 Razor,标记是
<body>
<h1>@InternationalizedMvcApplicationRazor.Resources.Shared.Layout.Heading %>
</h1>
<div>
@RenderBody()
</div>
</body>
请注意,该值像类上的属性一样被访问(事实上,资源被编译成 DLL):InternationalizedMvcApplication.Resources.Shared
是一个命名空间(遵循目录结构),MasterPage
(或 Razor 的 Layout
)是类名(遵循 RESX 文件名),而 Heading
是属性名(遵循我们给它的名称键)。由于资源对应用程序中的类公开可用,您也可以通过编程方式访问它们
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using InternationalizedMvcApplication.Resources.Shared;
//using InternationalizedMvcApplicationRazor.Resources.Shared; //For Razor
namespace InternationalizedMvcApplication.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
//Note using InternationalizedMvcApplication.Resources.Shared; for brevity
ViewBag.InternationalizedHeading = MasterPage.Heading;
//Layout.Heading for razor
return View();
}
}
}
请注意,在示例中,视图不访问 ViewBag
,但如果需要,可以通过正常方式访问它。
确定要使用的文化
最后一步是定义要使用的文化;在本文中,为了简单起见,我将使用浏览器的默认语言,然后在第二篇文章中扩展该机制。在生产代码中,您应该提供一种方法来覆盖浏览器的默认文化;例如,在国外网吧时,它可能不是用户想要的文化。
一旦定义了文化,它的工作方式与标准 ASP 大致相同:如果特定于文化的 RESX 可用,它会使用其中的值;如果没有 RESX 可用,它会回退到默认文化(请记住,我将 .ar.resx 指定为阿拉伯语的文件扩展名,但英语只需要 .resx,因为默认将是英语)。就像标准 ASP.NET 一样,如果某个单独的条目缺失,它会回退到默认值。您还可以扩展名称以提供英式英语(与默认美式英语相对)或约旦阿拉伯语(与默认沙特阿拉伯语相对)的变体。
与 ASP.NET 不同,我们无法覆盖页面的 InitializeCulture
方法:没有代码隐藏,而这是许多开发人员的首选方法。我们可以将其添加到 global.asax
protected void Application_BeginRequest(object sender, EventArgs e)
{
//Note everything hardcoded, for simplicity!
if (Request.UserLanguages.Length == 0)
return;
string language = Request.UserLanguages[0];
if (language.Substring(0, 2).ToLower() == "ar")
Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture("ar");
}
然而,有一种更简洁的机制,我在示例代码中将此代码块注释掉了,因为我不会继续使用它。我采用的机制是在 web.config 的 system.web
下添加以下内容
<globalization culture="en-GB" uiCulture="auto:en-GB" />
现在,UI 文化将设置为浏览器的默认文化,并回退到英式英语。在编程示例和基于配置的示例中,我都没有设置主应用程序文化,您可能需要这样做。
测试和方向支持
现在我们可以测试我们所做的工作了。运行应用程序会产生
现在我们交换默认语言;要在 IE 9 中执行此操作
- 选择“工具”图标,然后选择“Internet 选项”。
- 单击“外观”下的“语言”按钮。您将看到此屏幕
- 如果尚未添加(在此屏幕中我已添加),请单击“添加”并添加任何阿拉伯语变体。
- 选择您要使用的阿拉伯语版本,然后单击“上移”直到它位于列表顶部。
- 关闭对话框屏幕。
现在,浏览器的默认语言是阿拉伯语,刷新我们的页面显示
这是一个很好的测试!尽管我们有阿拉伯语文本,但页面仍然从左到右显示。这很容易修复,步骤类似于创建原始 RESX 文件
- 在 /Resources 文件夹中创建 Common.resx 资源文件。
- 添加 TextDirection 作为名称,并将其值设置为 ltr(不是 rtl;此文件定义了英语的方向!)。
- 将 RESX 文件的访问修饰符设置为 public 并保存。
- 复制 RESX 文件并将其扩展名重命名为 .ar.resx。
- 记住在阿拉伯语资源中将方向值更改为 rtl :-)
现在我们可以将以下内容放入视图 HTML 的任何标签中
dir="<%= InternationalizedMvcApplication.Resources.Common.TextDirection %>"
同样适用于 Razor 引擎
dir="@InternationalizedMvcApplicationRazor.Resources.Common.TextDirection"
在示例代码中,这已放置在根 HTML 标签中,使整个页面要么从右到左,要么从左到右。遗憾的是,这里没有智能感知功能,因此您必须依靠记忆。再次运行后提供
记得将语言换回英语,并检查文本是否从左到右运行。我们现在拥有了一个基本的英/阿双语网站。
结论
我们已经创建了一个简单的全球化 MVC 3 应用程序,这并非生产质量(例如,我们没有覆盖机制),但我们所拥有的可以很容易地适应生产环境。其原则与标准 ASP.NET 实践相似,但不如其流畅
- 为每种文化创建资源。
- 将它们设为公共(请注意,这是我第 n 次提到这一点:我经常忘记!)。
- 从标记中的资源获取文本。
- 将服务器上的 UI 文化(至少,您可能需要设置主文化)设置为请求中传入的浏览器默认设置。
- 根据语言,您可能需要添加双向支持。
在下一篇文章中,我们将继续使用浏览器的默认文化,因此页面将最初以该语言显示,但我们将通过单击链接使其可覆盖。然后可以通过其 URL 选择语言。例如,英语将是:https:///(默认)或 https:///en,而阿拉伯语将是 https:///ar。URL 将完全忽略语言的细分(例如,沙特阿拉伯语或约旦阿拉伯语)。基于 URL 的选择比参数化 URL 或 Cookie 更符合 MVC 模式,它还将帮助搜索引擎根据语言对您的网站进行排名。
感兴趣的朋友请看:第二部分可在此处获取。
如果您有任何意见或反馈,请随时提出。我希望会有更简洁的机制建议,尽管我认为这里的机制非常轻量级。
历史
如果您编辑本文,请在此处保留您所做更改或改进的运行更新。
- 2011 年 4 月 12 日:初稿。
- 2011 年 4 月 31 日:添加了 Razor 版本和详细信息。
- 2011 年 6 月 5 日:添加了对第二篇文章的引用。
- 2011 年 6 月 15 日:添加了指向第二篇文章的显式链接。