asp.net core 實現支持多語言


asp.net core 實現支持多語言

Intro#

最近有一個外國友人通過郵件聯系我,想用我的活動室預約,但是還沒支持多語言,基本上都是寫死的中文,所以最近想支持一下更多語言,於是有了多語言方面的一些實踐

國際化/本地化介紹#

國際化(Globalization)和本地化(Localization)是要實現的多語言支持的基礎

Globalization is the process of designing and developing applications that function for multiple cultures.

Localization is the process of customizing your application for a given culture and locale.

國際化是要支持處理多種文化,而本地化是要根據某一個文化和區域的來展示相應的處理。

更多關於國際化與本地化的不同可以參考 Stack Overflow 上的討論 https://stackoverflow.com/questions/2074869/globalization-vs-localization

Localization In Asp.NET Core#

微軟官方的 Localization 的實現是基於資源文件實現的 (*.resx),我們也可以擴展支持更多方式,如 JSON/數據庫 都是可以的,社區已經有實現的示例,只要是可以提供一個文本源的都是可以的,我們先使用默認的基於資源文件的,下一篇再講一個自定義實現一個 Localization Provider。

.NET Core Localization 的 核心是 IStringLocalizer,asp.net core 里擴展定義了 IViewLocalizer 和 IHtmlLocalizerIViewLocalizer 和 IHtmlLocalizer 主要是為了處理包含 html 的資源,他們不會對資源進行 html encode,相當於 @Html.Raw 的效果,而 IStringLocalizer 則會被 html encode,除此之外 IViewLocalizer 還會根據當前視圖的路徑尋找資源文件

來看一個示例:

Razor 頁面

瀏覽器效果:

查看網頁源代碼:

實際案例#

服務注冊#

注冊 Localization 相關服務:

Copy
var supportedCultures = new[] { new CultureInfo("zh"), new CultureInfo("en"), }; services.Configure<RequestLocalizationOptions>(options => { options.DefaultRequestCulture = new RequestCulture("zh"); // Formatting numbers, dates, etc. options.SupportedCultures = supportedCultures; // UI strings that we have localized. options.SupportedUICultures = supportedCultures; }); services.AddLocalization(options => options.ResourcesPath = Configuration.GetAppSetting("ResourcesPath")); 

配置視圖 Localization(根據需要如果是 WebAPI 就不需要了)

Copy
services.AddControllersWithViews()
   .AddNewtonsoftJson(options =>
   {
       options.SerializerSettings.ContractResolver = new DefaultContractResolver(); options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc; // 設置時區為 UTC options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore; options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; }) .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix, opts => { opts.ResourcesPath = Configuration.GetAppSetting("ResourcesPath"); }) .AddDataAnnotationsLocalization() .SetCompatibilityVersion(CompatibilityVersion.Latest);

中間件配置:#

Copy
app.UseRequestLocalization();

邏輯代碼中使用示例:#

IStringLocalizer 和 IHtmlLocalizer /IViewLocalizer 都可以直接從依賴注入服務中獲取,IStringLocalizer 和 IHtmlLocalizer 推薦使用強類型的方式,也就是下面示例的使用方式,使用方式和 ILogger 類似

Copy
public async Task<ActionResult> MakeReservation( [FromBody]ReservationViewModel model, [FromHeader]string captcha, [FromHeader]string captchaType, [FromServices]IStringLocalizer<HomeController> localizer) { var result = new ResultModel<bool>(); var isCodeValid = await HttpContext.RequestServices.GetService<CaptchaVerifyHelper>() .ValidateVerifyCodeAsync(captchaType, captcha); if (!isCodeValid) { result.Status = ResultStatus.RequestError; result.ErrorMsg = localizer["InvalidCaptchaInfo"]; return Json(result); }

在視圖中使用示例:#

localizer["data"] 返回的是一個 LocalizedString,實現了隱式轉換為 string, 有的時候可能需要強制轉一下string, 或者使用 Value 屬性

Copy
@inject IViewLocalizer viewLocalizer viewLocalizer["About"] @Html.ActionLink((string)viewLocalizer["About"], "About", "Home") @Html.ActionLink(viewLocalizer["About"].Value, "About", "Home") 

資源文件配置:#

資源文件的配置和文件的結構類似,下面是一個示例

准備的來說是和類型的 FullName 有關系,一般的項目名稱就是程序集名稱,就是根命名空間,文件名稱就是類型名稱,所以一般情況下資源文件的位置和類型的位置是一致的,但是如果文件和類型名稱不符合,那就要按照類型的 FullName 來找,視圖也是類似的,如果根命名空間不是程序集名稱,也是可以配置的具體的參考文檔

Controllers.HomeController => Controllers/HomeController.zh.resx/Controllers/HomeController.en.resx

Resource name Dot or path naming
Resources/Controllers.HomeController.fr.resx Dot
Resources/Controllers/HomeController.fr.resx Path
  • Resources/Views/Home/About.fr.resx
  • Resources/Views.Home.About.fr.resx

實際項目中的資源文件示例:

實際訪問效果:https://reservation.weihanli.xyz/

默認的中文界面:

英文界面:

只是做了幾個前台的示例,還有很多地方沒改

Docker 部署#

現在的項目是基於 docker + k8s 部署的,所以支持 docker 部署很重要

要支持多語言,需要安裝 ICU 相關的包,(這個可不是 996.icu 的 icu 哈,如果不裝真的有可能導致 996.icu)

Copy
RUN apk add --no-cache icu-libs # 安裝 icu-libs ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT false # 配置 Globalization

完整的 dockerfile 可以參考:
https://github.com/dotnet/dotnet-docker/blob/cb7a9c35dacf6d34fcf7bab7995e60faef55f61f/samples/dotnetapp/Dockerfile.alpine-x64-globalization

More#

.net core 的設計真的是很靈活,很優美,基於資源文件的本地化,感覺不太方便,使用資源文件的化可能就只能使用 VS 編輯了,雖然也是純文本的,基於 xml 但是編輯起來不如界面看着編輯舒服,如果使用 json 之類的,就比較簡單明了,編輯起來也比較方便,所以想把資源文件替換成 JSON 文件

下次分享一篇基於 JSON 的 Localization Provider 的實現

Reference#

作者: WeihanLi

出處:https://www.cnblogs.com/weihanli/p/implement-localization-in-asp-net-core.html

版權:本站使用「CC BY 4.0」創作共享協議,轉載請在文章明顯位置注明作者及出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM