asp.net core 實現支持多語言

来源:https://www.cnblogs.com/weihanli/archive/2020/01/08/implement-localization-in-asp-net-core.html
-Advertisement-
Play Games

asp.net core 實現支持多語言 Intro 最近有一個外國友人通過郵件聯繫我,想用我的活動室預約,但是還沒支持多語言,基本上都是寫死的中文,所以最近想支持一下更多語言,於是有了多語言方面的一些實踐 國際化/本地化介紹 國際化(Globalization)和本地化(Localization) ...


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 里擴展定義了 IViewLocalizerIHtmlLocalizerIViewLocalizerIHtmlLocalizer 主要是為了處理包含 html 的資源,他們不會對資源進行 html encode,相當於 @Html.Raw 的效果,而 IStringLocalizer 則會被 html encode,除此之外 IViewLocalizer 還會根據當前視圖的路徑尋找資源文件

來看一個示例:

Razor 頁面

瀏覽器效果:

查看網頁源代碼:

實際案例

服務註冊

註冊 Localization 相關服務:

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 就不需要了)

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);

中間件配置:

app.UseRequestLocalization();

邏輯代碼中使用示例:

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

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 屬性

@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)

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


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 方法一:psutil模塊 psutil 方法二:、proc proc 方法三:subprocess pipe,poen top+Popen ...
  • 譯者:Jiong 鏈接: https://robots.thoughtbot.com/how-to-manage-your-python-projects-with-pipenv 在thoughtbot,我們用Ruby和Rails工作,但通常我們總是嘗試使用最合適的語言或者框架來解決問題。 我最近一 ...
  • 攔截器介紹 mybatis提供了 @Intercepts 註解允許開發者對mybatis的執行器Executor進行攔截。 Executor介面方法主要有update、query、commit、rollback等等。 主要思路為: 1. 進入攔截器方法中 2. 獲取攔截器方法參數 3. 獲取解析參數 ...
  • 1. Java中有幾種方法可以實現一個線程?用什麼關鍵字修飾同步方法?stop()和suspend()方法為何不推薦使用? 三種實現方法 1.繼承 Thread 類 擴展性差 無返回值 2, 實現 Runnable 介面 可擴展 無返回值 3. 實現 Callable 介面 有返回值 用synchr ...
  • 這篇文章主要是介紹生成器和IO多路復用機制, 算是學習asyncio需要的預備知識. 這個系列還有另外兩篇文章: 從零開始學asyncio(中) 從零開始學asyncio(下) 一. 簡單爬蟲實例 首先創建一個crawler.py文件, 寫入以下代碼: import socket req = 'GE ...
  • 目的:修改VS Code的註釋文本顏色 S1:假設VS Code的安裝路徑是 %MVSC% S2:文件資源管理器進入目錄 %MVSC%\resources\app\extensions\ S3:該目錄底下由若幹以“theme-”開頭的目錄,例如: theme-abyss theme-defaults ...
  • 控制台錯誤提示: 2020-01-08 18:34:40,292 [http-nio-8080-exec-3] [org.apache.struts2.dispatcher.Dispatcher]-[WARN] Could not find action or result: /views/dire ...
  • 背景 程式在發佈部署時候,設置環境 不生效,也沒在代碼里使用 ,啟動一直是 .最後測試發現只有在 中配置 才生效,網上找了半天資料也沒看到有什麼問題。 最終翻看源代碼,發現是在 中的 替換了全局 導致。 平時開發大體知道程式啟動時候埠啟用順序是 環境變數 預設,具體是怎麼確定使用哪個配置的,沒找到 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...