我从一个非常小的ASP.NET WebForms项目继承而来,我的客户希望为它添加第二种语言。
对于每个“somepage.aspx”,我想支持它的“第二语言路径”版本,例如“fr / somepage.aspx”。我想使用正常的全球化(CurrentCulture +两种语言的资源文件)来处理这个问题,并避免重复每个页面。我必须保持原始路径有效,因此我暂时排除了ASP.NET MVC(因为我不知道是否可以继续支持“.aspx”路径)。
这可能吗?
答案 0 :(得分:2)
您可以创建一个调用HttpContext.RewritePath
的ASP.NET HTTP模块,将请求从“fr / somepage.aspx”映射到“somepage.aspx”。这种技术最适用于集成模式下的IIS 7.0,因为脚本和样式表的相对URL将解析为实际路径,如“/fr/jquery.js”,这些也应映射到“/jquery.js”。
namespace SampleApp
{
public class LocalizationModule : IHttpModule
{
private HashSet<string> _supportedCultures =
new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "de", "es", "fr" };
private string _appPath = HttpRuntime.AppDomainAppVirtualPath;
public void Dispose()
{
}
public void Init(HttpApplication application)
{
application.BeginRequest += this.BeginRequest;
_appPath = HttpRuntime.AppDomainAppVirtualPath;
if (!_appPath.EndsWith("/"))
_appPath += "/";
}
private void BeginRequest(object sender, EventArgs e)
{
HttpContext context = ((HttpApplication)sender).Context;
string path = context.Request.Path;
string cultureName = this.GetCultureFromPath(ref path);
if (cultureName != null)
{
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(cultureName);
context.RewritePath(path);
}
}
private string GetCultureFromPath(ref string path)
{
if (path.StartsWith(_appPath, StringComparison.OrdinalIgnoreCase))
{
int startIndex = _appPath.Length;
int index = path.IndexOf('/', startIndex);
if (index > startIndex)
{
string cultureName = path.Substring(startIndex, index - startIndex);
if (_supportedCultures.Contains(cultureName))
{
path = _appPath + path.Substring(index + 1);
return cultureName;
}
}
}
return null;
}
}
}
的Web.config:
<!-- IIS 7.0 Integrated mode -->
<system.webServer>
<modules>
<add name="LocalizationModule" type="SampleApp.LocalizationModule, SampleApp" />
</modules>
</system.webServer>
<!-- Otherwise -->
<system.web>
<httpModules>
<add name="LocalizationModule" type="SampleApp.LocalizationModule, SampleApp" />
</httpModules>
</system.web>
答案 1 :(得分:2)
对于ASP.NET,URL路由是可用的。
您可以创建两条路线,第一条是捕捉您语言的路线:
{语言} / {页}
第二条路线只是
{页}
在MVC中,我们可以创建路由约束来强制语言具有特定的值(如en,en-us等)如果在常规ASP.NET WebForms路由中可以做到同样的话,我不肯定
以下是两篇描述WebForms(非MVC)中路由主题的文章
http://msdn.microsoft.com/en-us/magazine/dd347546.aspx
和
编辑添加代码示例
在我的Global.asax中,我注册了以下内容:
void RegisterRoutes(RouteCollection routes)
{
routes.Ignore("{resource}.asxd/{*pathInfo}");
routes.Add(
new Route(
"{locale}/{*url}", //Route Path
null, //Default Route Values
new RouteValueDictionary{{"locale", "[a-z]{2}"}}, //constraint to say the locale must be 2 letters. You could also use something like "en-us|en-gn|ru" to specify a full list of languages
new Utility.Handlers.DefaultRouteHandeler() //Instance of a class to handle the routing
));
}
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
RegisterRoutes(RouteTable.Routes);
}
我还创建了一个单独的类(请参阅asp.net 4.0 web forms routing - default/wildcard route作为指南。)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Compilation;
using System.Web.Routing;
using System.Web.UI;
namespace SampleWeb.Utility.Handlers
{
public class DefaultRouteHandeler:IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
//Url mapping however you want here:
string routeURL = requestContext.RouteData.Values["url"] as string ;
string pageUrl = "~/" + (!String.IsNullOrEmpty(routeURL)? routeURL:"");
var page = BuildManager.CreateInstanceFromVirtualPath(pageUrl, typeof(Page))
as IHttpHandler;
if (page != null)
{
//Set the <form>'s postback url to the route
var webForm = page as Page;
if (webForm != null)
webForm.Load += delegate
{
webForm.Form.Action =
requestContext.HttpContext.Request.RawUrl;
};
}
return page;
}
}
}
这是有效的,因为当URL中没有指定区域设置时,Web窗体的默认视图引擎将接管。当使用2个字母的区域设置(en?us?etc)时,它也有效。在MVC中,我们可以使用IRouteConstraint进行各种检查,例如确保区域设置在列表中,检查路径是否存在等,但在WebForms中,约束的唯一选项是使用RouteValueDictonary。
现在,我知道代码存在问题,默认文档无法加载。因此http://localhost:25436/en/不会加载default.aspx的默认文档,但http://localhost:25436/en/default.aspx确实有效。我会留给你解决。
我用子目录对它进行了测试,结果正常。
答案 2 :(得分:0)
您可以使用此代码更新Global.Asax中的Application_BeginRequest。如果global.asax不存在,请创建它。
Visual Studio项目虚拟路径必须是/
protected void Application_BeginRequest(object sender, EventArgs e)
{
string file_path = Request.RawUrl.ToLower();
char[] separator = new char[] { '/' };
string[] parts = file_path.Split(separator, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length > 0 && parts[0] == "fr")
{
System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.CreateSpecificCulture("fr-FR");
Context.RewritePath("~/" + file_path.Substring(4), true);
}
else
{
System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.CreateSpecificCulture("en-US");
}
}
答案 3 :(得分:0)
一种选择是将aspx的文本放在<%$ Resources: My translated text %>
标记内。将使用ResourceProviderFactory解析资源标记以获取转换后的值。您可以自己创建这个ResourceProviderFactory,从资源文件或数据库中获取转换的工作(例如,实现IResourceProvider.GetObject()
)。您可以在web.config中配置它:
<system.web>
<globalization resourceProviderFactoryType="CustomResourceProviderFactory" uiCulture="fr" culture="en-GB"/>
</system.web>
请参阅:http://msdn.microsoft.com/en-us/library/fw69ke6f(v=vs.80).aspx