前情提要: MVC-多國語系設定方法

(簡單描述開發環境)
使用環境: ASP.Net Core 2.X
開發工具: VSCode
範例網址: 多語範例Github 已經進行本次的更新了

本篇會說明以上方設定的方法後,後續會遇到的問題。

1. Cshtml中使用Asp屬性自動生成URL

修改在Home/About頁面
若需要以REST-like的方式取資料的話,加入語系的時候會出現問題

1
2
3
4
5
6
7
[HttpGet("[controller]/[action]/{year?}/{month?}")]
public IActionResult About(int? year, int? month)
{
ViewData["param"] = year + "/" + month;

return View();
}

若在Cshtml中使用Asp屬性跳轉頁面的話會有以下情況:

1
2
<li><a asp-route-culture="zh">zh</a></li>
<li><a asp-route-culture="en">en</a></li>

會以莫名的方式自動生成這樣的URL,到前端后會有這種情況:

1
2
<li><a href="/Home/About?culture=zh">zh</a></li>
<li><a href="/Home/About?culture=en">en</a></li>

**需要多了解一下Asp的taghelper的生成原理,以及Route的邏輯

個人推測為是因為 [HttpGet("[controller]/[action]/{year?}/{month?}")] 這邊修改了Route的邏輯,所以會出現生成不一樣的URL邏輯

目前稍微研究出使用startup.cs檔案中的maproute部分去做對照。
這方法是目前想到的方法,但是又覺得有點不合適。。。
(經過測試,自動生成URL時偶爾會生產錯誤的url,所以目前就先不理會了。。。)

1
2
3
4
routes.MapRoute(
name: "About",
template: "About/{action=Index}/{year?}/{month?}",
defaults: new {controller="About", culture = "zh" });

2. URL中語系欄位沒有進行限制

多語範例Github中,設定了由url決定語系。
但是若在url的語系的部分中胡亂輸入,僅僅會自動fallback到預設的語系,但是正常來說應該進行限制的。
例如進入/fake-culture/Home/About,則會以zh為語系顯示。

解決方法:(在startup.cs中)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}",
defaults: new { culture = "zh" });//這部分不需要加入contraints,因為已經寫死是zh了
routes.MapMiddlewareRoute("{culture=zh}/{*mvcRoute}", subApp =>
{
subApp.UseRequestLocalization(localizationOptions.Value);

subApp.UseMvc(mvcRoutes =>
{
mvcRoutes.MapRoute(
name: "default",
template: "{culture}/{controller}/{action}/{id?}",
defaults: new { culture = "zh", Controller = "home", action = "index" },
constraints: new { Culture = @"(zh)|(en)" }); //加入這行即可
//正規表達式可以match的話則會正常進入相關頁面,若沒有match的話,則會變為404
});
});
});

3. 程式Namespace與Assembly的問題(非語系問題)

這部分是在做範例程式時遇到的陷阱,會導致多語套件設定錯誤的namaspace。
這部分牽涉的範圍較廣,並非只有語系套件會出現問題。

由於專案命名為core-localization,因為” - “是程式碼的運算子,所以在程式中會自動將namespace改編為:core_localization
結果就發現多語無論如何都抓不到對的語系檔,因此讓我鬱悶了一段時間。
在某次機緣之下,發現了下面的東西:(VSCode Debugger)

因為專案預設的namespace是core-localization與程式碼內的namespace core_localization不一致,所以自動尋找資源檔時會找尋到這個namespace core-localization.Resources.core_localization.X.X.X
所以必須在csproj裡面設定預設的namespace以及assembly的名字:
***其實這個解決方法在StackOverflow上已經看到過多次了,因為不知道是DefaultNamespace的問題,所以一直都沒有採用這個解決方法

在設定好後就可以抓到對的namespace: core_localization.Resources.X.X.X

後記

表示一開始只是工作上需要設定多語,然後再來設定URL語系,發現這個設定方法對於Google的SEO是有幫助的。
然後在寫的途中找到了限制URL語系的方法,這又能反饋回原本的專案。
再來在寫部落格時無法達成多語功能(詳情在第三部分),因此了解到了namespace的問題,學習到了多一個知識。
寫blog的好處就這樣漸漸凸顯出來了!!

知識鏈接

微軟官方路徑約束文檔
ASP.NET Core Localization Deep Dive
John Wu-多國語言教學