将 Razor 页面传送为 /example.com/en/ 格式



我的网站上有三种语言。我正在尝试让我的剃须刀片页面路由到文化/本地化,如下所示:

https://localhost:44396/en/
https://localhost:44396/ru/

在这一点上,我使用过去两天一直在谷歌搜索的方法注释了数百行代码,但似乎没有什么能完成这项工作。 该网站大部分是静态的,所以现在除了文化之外,没有其他需要路由的东西。

这里有一种方法可以做到这一点,不需要你在所有页面上放置中间件属性。这在全球范围内有效。

在"启动.cs"的ConfigureServices方法中,添加以下内容:

services.AddMvc().AddRazorPagesOptions(options => {
options.Conventions.AddFolderRouteModelConvention("/", model => {
foreach (var selector in model.Selectors) {
selector.AttributeRouteModel.Template = AttributeRouteModel.CombineTemplates("{lang=en}", selector.AttributeRouteModel.Template);
}
});
});
services.Configure<RequestLocalizationOptions>(options => {
var defaultCulture = new CultureInfo("en");
var supportedCultures = new CultureInfo[] {
defaultCulture,
new CultureInfo("fr")
};
options.DefaultRequestCulture = new RequestCulture(defaultCulture);
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
options.RequestCultureProviders.Insert(0, new RouteDataRequestCultureProvider() {
RouteDataStringKey = "lang",
UIRouteDataStringKey = "lang",
Options = options
});
});

这将设置全局路由、支持的区域性,并将主要区域性提供程序设置为来自路由。(这仍会保留其他提供程序,因此如果无法通过路由值,它仍然可以基于查询字符串、Cookie 或语言标头设置区域性。

现在,在Configure方法(仍在 Startup.cs 中(中添加以下内容:

var routeBuilder = new RouteBuilder(app) {
DefaultHandler = app.ApplicationServices.GetRequiredService<MvcRouteHandler>(),
};
routeBuilder.Routes.Insert(0, AttributeRouting.CreateAttributeMegaRoute(app.ApplicationServices));
var router = routeBuilder.Build();
app.Use(async (context, next) => {
var routeContext = new RouteContext(context);
await router.RouteAsync(routeContext);
context.Features[typeof(IRoutingFeature)] = new RoutingFeature() {
RouteData = routeContext.RouteData
};
await next();
});
var options = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();
app.UseRequestLocalization(options.Value);
app.UseMvc();

这里有一些诡计。首先,我们必须在调用app.UseMvc之前调用app.UseRequestLocalization,否则我们的程序将在我们改变当前文化之前运行。但问题是,app.UseMvc()是设置路由数据的人。因此,在调用它之前,路由值都是空白的。因此,当RouteDataRequestCultureProvider尝试观察 {lang} 是什么时,它会返回空,因此始终默认为en。捕获 22。

因此,我们只需在自己的自定义中间件中手动填充 RouteData。这样,RouteDataRequestCultureProvider 可以看到它,并且一切都会很好地工作。

(我承认这不是最有效的,因为您只是在复制app.UseMvc()本身也会做的路由工作,但我会采取这种不明显的延迟来确保我的所有页面都已本地化。

我会告诉你我做什么有效。唯一的区别是我使用 5 个字符的语言代码,但我想这并不难改变。

确保已安装以下 nuget 库

Microsoft.AspNetCore.Localization.Routing

在 Startup 的 ConfigureServices 方法中.cs我们在服务下键入以下代码。AddMvc((;

services.AddMvc()
.AddRazorPagesOptions(options =>
{
options.Conventions.AuthorizeFolder("/Account/Manage");
options.Conventions.AuthorizePage("/Account/Logout");
options.Conventions.AddFolderRouteModelConvention("/", model =>
{
foreach (var selector in model.Selectors)
{
var attributeRouteModel = selector.AttributeRouteModel;
attributeRouteModel.Template = AttributeRouteModel.CombineTemplates("{lang=el-GR}", attributeRouteModel.Template);
}
});
});
IList<CultureInfo> supportedCultures = new List<CultureInfo>
{
new CultureInfo("en-US"),
new CultureInfo("fr-FR"),
new CultureInfo("el-GR"),
};
var MyOptions = new RequestLocalizationOptions()
{
DefaultRequestCulture = new RequestCulture(culture: "en-US", uiCulture: "en-US"),
SupportedCultures = supportedCultures,
SupportedUICultures = supportedCultures
};
MyOptions.RequestCultureProviders = new[]
{
new RouteDataRequestCultureProvider() { RouteDataStringKey = "lang", Options = MyOptions }        // requires nuget package Microsoft.AspNetCore.Localization.Routing
};
services.AddSingleton(MyOptions);

我们添加以下类

using Microsoft.AspNetCore.Builder;
public class LocalizationPipeline
{
public void Configure(IApplicationBuilder app, RequestLocalizationOptions options)
{
app.UseRequestLocalization(options);
}
}

现在,您必须在PageModel类上添加以下行:

[MiddlewareFilter(typeof(LocalizationPipeline))]
public class ContactModel : PageModel
{
public void OnGet()
{
}
}

我希望它有所帮助。

相关内容

最新更新