65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.79/5 (46投票s)

2011年4月14日

CPOL

10分钟阅读

viewsIcon

392253

downloadIcon

8505

本文提供了一个简单的双语网站全球化机制。第一部分创建一个简单的双语网站。

引言

本文是关于 ASP.NET MVC 3 中基本双语网站的两篇文章中的第一篇。我将文章分为两部分,因为我觉得一步到位会过于冗长和复杂。这两部分是

  1. 创建一个简单的全球化 MVC3 应用程序
  2. 基于路由的 MVC3 应用程序全球化

本文是初学者使用国际化资源的介绍。代码的编写旨在清晰,而非生产质量。我将使用阿拉伯语作为第二语言,这是因为我最初工作的网站使用阿拉伯语,并且它引出了左右方向支持,否则可能会被忽略。如果您会说阿拉伯语,对任何错误表示歉意,我确实会说一点,但大部分文本都使用了 Google 翻译!

第二篇文章(在此处提供)将涵盖基于路由的国际化,并将更高级。两篇文章都假设对 MVC 的工作原理(特别是相关组件:视图、控制器和 RouteHandler)以及 .NET 如何处理本地化和文化有基本了解。示例将侧重于默认的 ASPX 视图引擎而不是 Razor,但会在 Razor 标记不同之处提供信息。该机制可以稍微努力扩展以允许多语言网站。

要运行代码,您必须安装 VS2010(和 .NET 4 :-)) 以及 MVC 3 框架。

背景

本文源于我为当前雇主使用 MVC 3 编写的一个概念验证网站。在此之前,我对 ASP.NET MVC 3 几乎没有经验。我的雇主要求他们的网站提供英语和阿拉伯语版本,本文记录并分享了在该过程中实现的内容。网上有一些关于 MVC 3 中本地化的文章,但我没有找到能完全实现我想要的(一个具有类似于 MSDN 的路由策略的双语网站,如第二部分所述)。尽管如此,我必须感谢这些文章的巨大贡献

在我的应用程序中实现本地化时,我发现这个过程远不如普通的 ASP.NET 那么完善和直观。没有办法自动生成 RESX 文件,而且必须采取额外的步骤才能使内容对视图可用。我也找不到 Microsoft 关于 MVC 3 中本地化和全球化的最佳实践。

代码

原则上,使资源与 MVC3 配合工作的过程相当简单,但不如普通 ASP.NET 应用程序那样

  1. 创建 RESX 文件来保存文本。
  2. 使 RESX 内容公开可用。
  3. 对其他支持的语言和每个视图重复步骤 1 和 2。
  4. 从视图或控制器(或视图模型!)中的 RESX 获取文本。
  5. 根据浏览器默认设置文化。

在这篇解释性文章和代码中,我使用了母版页(或 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 用户,请参阅本节末尾的红色注意事项),因此右键单击资源文件夹并遵循这些选项

Adding a new Item: Right click the folder, select 'Add' then 'New Item'

选择“常规”选项卡,“资源文件”,并更改文件名

Adding a resource file: Select the General Tab then Resource File

完成此操作后,您需要将文本移动到资源文件中,给它一个合理的名称,在本例中为“Heading”,然后输入文本(“Welcome”)。现在将访问修饰符设置为 public,没有此步骤,视图将无法访问它

The contents of the resx file: a name 'Heading' with a value 'Welcome'

通常,您会为每个要本地化的文本部分重复此操作,但我只输入了一个值以使示例故意简单。下一步是将 RESX 文件复制到其自身所在的同一目录中(记得提前保存!),并根据您希望支持的文化重命名它。在我的例子中,我使用阿拉伯语,所以“MasterPage.resx”有一个伴随的 MasterPage.ar.resx。请注意,复制的文件继承了公共访问修饰符,因此无需重新设置。现在我们所需要做的就是重复创建剩余视图的 RESX 文件的过程。完成后,我们应该有“镜像”的 Views 和 Resources 文件夹,每个视图为每种语言一个 RESX 文件

The resource file contents showing the views and the matching pair of resource files under a mirrored file structure

Razor 用户注意事项:由于 Razor 默认使用名为“_Layout.cshtml”的布局文件,而不是 MasterPage.Master,我已在可下载项目中反映了这一点;RESX 文件名为“Layout.resx”和“Layout.ar.resx”,而 ASPX 引擎的文件名为“MasterPage.resx”和“MasterPage.ar.resx”,延续了镜像“视图”及其资源的策略。适用于 MasterPage 及其资源的原则也适用于等效的 Razor 资源。命名空间也不同,InternationalizedMvcApplicationRazor 而不是 InternationalizedMvcApplication。文章中的代码片段反映了这些差异,但为了清晰起见,我在正文中没有这样做。

将文本添加到视图

通过标记将文本从 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.configsystem.web 下添加以下内容

<globalization culture="en-GB" uiCulture="auto:en-GB" />

现在,UI 文化将设置为浏览器的默认文化,并回退到英式英语。在编程示例和基于配置的示例中,我都没有设置主应用程序文化,您可能需要这样做。

测试和方向支持

现在我们可以测试我们所做的工作了。运行应用程序会产生

The Page rendered in English

现在我们交换默认语言;要在 IE 9 中执行此操作

  1. 选择“工具”图标,然后选择“Internet 选项”。
  2. 单击“外观”下的“语言”按钮。您将看到此屏幕
  3. The IE9 Language Selection Screen

  4. 如果尚未添加(在此屏幕中我已添加),请单击“添加”并添加任何阿拉伯语变体。
  5. 选择您要使用的阿拉伯语版本,然后单击“上移”直到它位于列表顶部。
  6. 关闭对话框屏幕。

现在,浏览器的默认语言是阿拉伯语,刷新我们的页面显示

The Page rendered in Arabic, but the text is formatted left to right

这是一个很好的测试!尽管我们有阿拉伯语文本,但页面仍然从左到右显示。这很容易修复,步骤类似于创建原始 RESX 文件

  1. /Resources 文件夹中创建 Common.resx 资源文件。
  2. 添加 TextDirection 作为名称,并将其值设置为 ltr不是 rtl;此文件定义了英语的方向!)。
  3. 将 RESX 文件的访问修饰符设置为 public 并保存。
  4. 复制 RESX 文件并将其扩展名重命名为 .ar.resx
  5. 记住在阿拉伯语资源中将方向值更改为 rtl :-)

现在我们可以将以下内容放入视图 HTML 的任何标签中

dir="<%= InternationalizedMvcApplication.Resources.Common.TextDirection %>"

同样适用于 Razor 引擎

dir="@InternationalizedMvcApplicationRazor.Resources.Common.TextDirection"

在示例代码中,这已放置在根 HTML 标签中,使整个页面要么从右到左,要么从左到右。遗憾的是,这里没有智能感知功能,因此您必须依靠记忆。再次运行后提供

The Page rendered in Arabic, but the text correctly formatted right to left

记得将语言换回英语,并检查文本是否从左到右运行。我们现在拥有了一个基本的英/阿双语网站。

结论

我们已经创建了一个简单的全球化 MVC 3 应用程序,这并非生产质量(例如,我们没有覆盖机制),但我们所拥有的可以很容易地适应生产环境。其原则与标准 ASP.NET 实践相似,但不如其流畅

  1. 为每种文化创建资源。
  2. 将它们设为公共(请注意,这是我第 n 次提到这一点:我经常忘记!)。
  3. 从标记中的资源获取文本。
  4. 将服务器上的 UI 文化(至少,您可能需要设置主文化)设置为请求中传入的浏览器默认设置。
  5. 根据语言,您可能需要添加双向支持。

下一篇文章中,我们将继续使用浏览器的默认文化,因此页面将最初以该语言显示,但我们将通过单击链接使其可覆盖。然后可以通过其 URL 选择语言。例如,英语将是:https:///(默认)或 https:///en,而阿拉伯语将是 https:///ar。URL 将完全忽略语言的细分(例如,沙特阿拉伯语或约旦阿拉伯语)。基于 URL 的选择比参数化 URL 或 Cookie 更符合 MVC 模式,它还将帮助搜索引擎根据语言对您的网站进行排名。

感兴趣的朋友请看:第二部分可在此处获取

如果您有任何意见或反馈,请随时提出。我希望会有更简洁的机制建议,尽管我认为这里的机制非常轻量级。

历史

如果您编辑本文,请在此处保留您所做更改或改进的运行更新。

  • 2011 年 4 月 12 日:初稿。
  • 2011 年 4 月 31 日:添加了 Razor 版本和详细信息。
  • 2011 年 6 月 5 日:添加了对第二篇文章的引用。
  • 2011 年 6 月 15 日:添加了指向第二篇文章的显式链接。
© . All rights reserved.