我的项目背景故事
我正在尝试添加多种语言到我的网站。为此,我在URL的路径中使用区域设置来区分各种语言。默认网站(英语)位于http://localhost:5000/
,而德语页面位于http://localhost:5000/de-de/
。我已经可以设置存储在会话中的区域设置。
用户可以通过表单在网站上更改其区域设置。如果用户已将其语言设置为德语,并且尝试访问http://localhost:5000/
,则会重定向到位于http://localhost:5000/de-de
的德语页面。这对于将用户重定向到正确的路径非常有效。没什么不对的。
例如,如果用户将其区域设置为德语,并且他们尝试进入页面,则此方法也有效:http://localhost:5000/Pictures
会将它们重定向到http://localhost:5000/de-de/Pictures
。没有任何问题。
目前,我还没有为特定的区域设置创建任何页面。我所做的基本上只是将其设置为重定向到起始页作为回退。由于/de-de/
实际上并不存在于网站中,因此它只会使用以下命令加载起始页:Program.cs
文件中的app.UseStatusCodePagesWithReExecute("/");
。
我的问题
由于我只是将用户重定向到一个回退页面的时刻(由于事实上,没有de-de
文件夹在我的Pages
文件夹),它只加载了英文开始页的内容。因此,如果我访问http://localhost:5000/de-de/Pictures
,我实际上看到的是http://localhost:5000/
的内容。这可不好。
假设我的Pages
文件夹中有两个页面。它们分别称为Index.cshtml
和Pictures.cshtml
。我可以使用默认区域设置(英语)在以下URL访问它们:http://localhost:5000/
和http://localhost:5000/Pictures
。
**但是,我如何设置它,使它将加载相应的页面,排除在URL中的地区?**换句话说,如果用户将其区域设置为德语并访问http://localhost:5000/de-de/Pictures
,如何使其从http://localhost:5000/Pictures
加载HTML?
我还需要它为我以后创建的任何页面工作,例如。/Videos
或/About
等等。它必须是动态的。
不要担心它是英语内容。我可以稍后再解决。我只想实现的是,无需在Pages\de-de
处创建子目录,它应该自动加载页面的内容,而无需在URL中设置区域设置。
在未来,我想添加20+语言的网站。我不想有20多个文件夹,每个都包含相同的HTML文件。例如,文件夹和文件结构如下所示:
Pages
Index.cshtml
Pictures.cshtml
/de-de/
Index.cshtml
Pictures.cshtml
/es-es/
Index.cshtml
Pictures.cshtml
/fr-fr/
Index.cshtml
Pictures.cshtml
字符串
上面的文件夹结构示例很难维护。我只想在Pages
目录中有两个文件(Index.cshtml
和Pictures.cshtml
)。并路由所有其他区域设置以加载这些文件。因此,如果我对Pictures.cshtml
文件进行更改,它将更新所有区域设置。
我的中间件
我已经设置了一个名为LocaleMiddleware
的中间件,它检查名为"locale"
的会话变量,并相应地重定向用户。我不确定是否有什么可以在中间件内部完成。中间件所做的就是将用户重定向到正确的URL。
我需要解决的问题是,让URL从路径中加载页面内容(HTML),而不需要在其中设置区域。
public class LocaleMiddleware
{
private readonly RequestDelegate _next;
public LocaleMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
// Exclude redirects for "/api" and "/auth" paths
if (context.Request.Path.StartsWithSegments("/api") || context.Request.Path.StartsWithSegments("/auth"))
{
await _next(context);
}
else
{
// Regex pattern for URL ([xx-yy])
string pattern = @"\/([a-z]{2})-([a-z]{2})";
// Get locale from session
string? locale = context.Session.GetString("locale");
// If no locale, or if locale is default "en-us"
// Remove any potential locales from URL and redirect them to "root" path
// E.g. /de-de/Pictures will be reset to /Pictures
if (String.IsNullOrEmpty(locale) || locale == "en-us")
{
if (Regex.IsMatch(context.Request.Path, pattern))
{
// Redirect to page without locale in URL
string newPath = Regex.Replace(context.Request.Path, pattern, "");
if (String.IsNullOrEmpty(newPath)) newPath = "/";
context.Response.Redirect($"{newPath}");
return;
}
}
// If locale is set and is not default "en-us" and locale is not currently in the URL
// Then it should redirect them to the correct locale URL path
// E.g. if the user has set locale to "de-de" and loads /Pictures it will redirect to /de-de/Pictures
if (!String.IsNullOrEmpty(locale) && locale != "en-us" && !context.Request.Path.ToString().Contains(locale))
{
// Redirect to locale path
string oldPath = Regex.Replace(context.Request.Path, pattern, "");
context.Response.Redirect($"/{locale}{oldPath}");
return;
}
await _next(context);
}
}
}
public static class RequestLocaleMiddlewareExtensions
{
public static IApplicationBuilder UseLocaleMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<LocaleMiddleware>();
}
}
型
Tl/dr:
基本上,如果用户将其区域设置为de-de
,我希望URL为http://localhost:5000/de-de/Pictures
,但从http://localhost:5000/Pictures
加载HTML内容。以及所有未来的路径,例如/Videos
、/Contact
的数据。
换句话说,逻辑是:
1. Check if the URL path matches Regex pattern for locales [xx-yy]
2. If it does, setup a router to load HTML from the path EXCLUDING the locale
型
我在哪里以及如何做到这一点?在哪些文件中设置路由?它需要是动态的。
1条答案
按热度按时间jtjikinw1#
在asp.net核心中有对本地化的内置支持,您可以检查document相关
根据医生和迈克·布林德的文章
这里有一个最小的例子:
字符串
在Program.cs中:
型
....
型
页面型号:
型
页面:
@Model.Hi;
资源文件:x1c 0d1x的数据
我的项目:
的
测试结果:
的
修改资源文件:
的