.NET Core中多語言支持

在.NET Core項目中也是可使用.resx資源文件,來爲程序提供多語言支持。如下咱們就以一個.NET Core控制檯項目爲例,來說解資源文件的使用。async

 

新建一個.NET Core控制檯項目,而後咱們在其中新建一個.resx資源文件叫DemoResource.resx測試

 

注意.resx資源文件默認是Internal訪問級別的,這會致使其它程序集沒法訪問資源文件類,因此咱們最好將其改成Public訪問級別spa

 

而後咱們在資源文件DemoResource.resx中定義一個字符串叫"Message",值爲"Hello",以下所示:線程

 

因爲資源文件是支持多語言的,其文件名命名格式以下:code

{資源文件名}.{語言文化名稱}.resx中間件

其中{語言文化名稱}就是諸如:zh-CN、en-US、ja-JP等語言字符串,表明了一種特定的語言,例如zh-CN就是簡體中文。blog

 

因此如今咱們就爲資源文件DemoResource.resx再創造兩種語言:ip

DemoResource.zh-CN.resx,簡體中文資源文件:資源

 

DemoResource.ja-JP.resx,日語資源文件:字符串

 

因此咱們如今,就有三個資源文件:

  • DemoResource.resx是默認的資源文件,咱們將其內部的字符串Message定義爲了英文。
  • DemoResource.zh-CN.resx是簡體中文資源文件,咱們將其內部的字符串Message定義爲了簡體中文。
  • DemoResource.ja-JP.resx是日語資源文件,咱們將其內部的字符串Message定義爲了日語。

其實它們表明的都是DemoResource資源文件,只不過是不一樣的語言版本罷了,如今項目結構以下所示:

 

好了,如今定義好了資源文件,咱們就來看看怎麼使用它們。

在.NET Core中.resx資源文件是和線程的語言相關,其主要和當前線程的以下兩個語言屬性相關:

  • Thread.CurrentThread.CurrentCulture
  • Thread.CurrentThread.CurrentUICulture

若是當前線程的這兩個屬性是什麼語言,那麼.resx資源文件就會返回對應語言的內容。

 

首先咱們在.NET Core控制檯項目的Main方法中,設置當前線程的CurrentCulture和CurrentUICulture爲zh-CN:

static void Main(string[] args)
{
    Thread.CurrentThread.CurrentCulture = new CultureInfo("zh-CN");
    Thread.CurrentThread.CurrentUICulture = new CultureInfo("zh-CN");

    Console.WriteLine($"Message爲:{DemoResource.Message}");

    Console.WriteLine("按任意鍵結束...");
    Console.ReadKey();
}

運行結果以下,咱們能夠看到顯示的Message爲中文"你好"

 

如今咱們將當前線程的CurrentCulture和CurrentUICulture設置爲ja-JP:

static void Main(string[] args)
{
    Thread.CurrentThread.CurrentCulture = new CultureInfo("ja-JP");
    Thread.CurrentThread.CurrentUICulture = new CultureInfo("ja-JP");

    Console.WriteLine($"Message爲:{DemoResource.Message}");

    Console.WriteLine("按任意鍵結束...");
    Console.ReadKey();
}

運行結果以下,咱們能夠看到顯示的Message爲日文"こんにちは"

 

而後,咱們將當前線程的CurrentCulture和CurrentUICulture設置爲fr-FR,表明法語:

static void Main(string[] args)
{
    Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");
    Thread.CurrentThread.CurrentUICulture = new CultureInfo("fr-FR");

    Console.WriteLine($"Message爲:{DemoResource.Message}");

    Console.WriteLine("按任意鍵結束...");
    Console.ReadKey();
}

那麼如今結果是什麼呢,以下所示:

可能不少同窗會以爲很奇怪爲何Message顯示的是英語"Hello"。其實道理很簡單,由於咱們沒有定義DemoResource.fr-FR.resx這個法語資源文件啊,因此在當前線程的CurrentCulture和CurrentUICulture爲fr-FR時,調用DemoResource.Message時,.NET Core只好使用DemoResource默認資源文件DemoResource.resx的內容,因此DemoResource.Message輸出的是英文"Hello"。

 

其實資源文件類DemoResource也是能夠經過設置其Culture屬性來指定使用某一種特定的語言,以下代碼所示,雖然咱們設置當前線程的CurrentCulture和CurrentUICulture爲ja-JP,可是因爲咱們設置了DemoResource.Culture爲zh-CN:

static void Main(string[] args)
{
    Thread.CurrentThread.CurrentCulture = new CultureInfo("ja-JP");
    Thread.CurrentThread.CurrentUICulture = new CultureInfo("ja-JP");

    DemoResource.Culture = new CultureInfo("zh-CN");

    Console.WriteLine($"Message爲:{DemoResource.Message}");

    Console.WriteLine("按任意鍵結束...");
    Console.ReadKey();
}

因此最後顯示的Message爲中文"你好"

 

 

Async和Await模式對線程語言的影響

有的同窗可能會想.NET Core中的Async和Await模式,會對Thread.CurrentThread.CurrentCulture和Thread.CurrentThread.CurrentUICulture這兩個線程的語言屬性產生影響嗎。

 

咱們來看看以下代碼:

/// <summary>
/// 測試Async和Await模式,是否會對Thread.CurrentThread.CurrentCulture和Thread.CurrentThread.CurrentUICulture產生影響
/// </summary>
static void AsyncAwaitThreadCulture()
{
    //設置主線程的CurrentCulture和CurrentUICulture爲語言ja-JP
    Thread.CurrentThread.CurrentCulture = new CultureInfo("ja-JP");
    Thread.CurrentThread.CurrentUICulture = new CultureInfo("ja-JP");

    Console.WriteLine($"Thread id:{Thread.CurrentThread.ManagedThreadId.ToString()}=>主線程的CurrentCulture是{Thread.CurrentThread.CurrentCulture.ToString()}, CurrentUICulture是{Thread.CurrentThread.CurrentUICulture.ToString()}");

    //經過Task來啓動第一層線程
    Task.Run(async () =>
    {
        Console.WriteLine($"Thread id:{Thread.CurrentThread.ManagedThreadId.ToString()}=>第一層線程的CurrentCulture是{Thread.CurrentThread.CurrentCulture.ToString()}, CurrentUICulture是{Thread.CurrentThread.CurrentUICulture.ToString()}");

        //經過Task來啓動第二層線程
        Task task = Task.Run(() =>
        {
            Console.WriteLine($"Thread id:{Thread.CurrentThread.ManagedThreadId.ToString()}=>第二層線程的CurrentCulture是{Thread.CurrentThread.CurrentCulture.ToString()}, CurrentUICulture是{Thread.CurrentThread.CurrentUICulture.ToString()}");

            //經過Thread來啓動第三層線程
            Thread th = new Thread(new ThreadStart(() =>
            {

                Thread.Sleep(3000);

                Console.WriteLine($"Thread id:{Thread.CurrentThread.ManagedThreadId.ToString()}=>第三層線程的CurrentCulture是{Thread.CurrentThread.CurrentCulture.ToString()}, CurrentUICulture是{Thread.CurrentThread.CurrentUICulture.ToString()}");
            }));

            th.IsBackground = true;
            th.Start();

            th.Join();//阻塞第二層線程,直到第三層線程th結束
        });

        Thread.Sleep(1000);

        Console.WriteLine($"Thread id:{Thread.CurrentThread.ManagedThreadId.ToString()}=>await以前CurrentCulture是{Thread.CurrentThread.CurrentCulture.ToString()}, CurrentUICulture是{Thread.CurrentThread.CurrentUICulture.ToString()}");

        await task;//await,直到第二層線程結束

        Console.WriteLine($"Thread id:{Thread.CurrentThread.ManagedThreadId.ToString()}=>await以後CurrentCulture是{Thread.CurrentThread.CurrentCulture.ToString()}, CurrentUICulture是{Thread.CurrentThread.CurrentUICulture.ToString()}");

    }).Wait();//阻塞主線程,直到第一層線程執行完畢
}

運行結果以下所示:

咱們在AsyncAwaitThreadCulture方法中,將主線程的CurrentCulture和CurrentUICulture設置爲了ja-JP,結果能夠發現後續啓動的線程其CurrentCulture和CurrentUICulture也都爲ja-JP

 

如今咱們設置主線程的CurrentCulture和CurrentUICulture爲ja-JP,可是將第一層線程的CurrentCulture和CurrentUICulture改成zh-CN

/// <summary>
/// 測試Async和Await模式,是否會對Thread.CurrentThread.CurrentCulture和Thread.CurrentThread.CurrentUICulture產生影響
/// </summary>
static void AsyncAwaitThreadCulture()
{
    //設置主線程的CurrentCulture和CurrentUICulture爲語言ja-JP
    Thread.CurrentThread.CurrentCulture = new CultureInfo("ja-JP");
    Thread.CurrentThread.CurrentUICulture = new CultureInfo("ja-JP");

    Console.WriteLine($"Thread id:{Thread.CurrentThread.ManagedThreadId.ToString()}=>主線程的CurrentCulture是{Thread.CurrentThread.CurrentCulture.ToString()}, CurrentUICulture是{Thread.CurrentThread.CurrentUICulture.ToString()}");

    //經過Task來啓動第一層線程
    Task.Run(async () =>
    {
        //將第一層線程的CurrentCulture和CurrentUICulture改成zh-CN
        Thread.CurrentThread.CurrentCulture = new CultureInfo("zh-CN");         Thread.CurrentThread.CurrentUICulture = new CultureInfo("zh-CN"); 
        Console.WriteLine($"Thread id:{Thread.CurrentThread.ManagedThreadId.ToString()}=>第一層線程的CurrentCulture是{Thread.CurrentThread.CurrentCulture.ToString()}, CurrentUICulture是{Thread.CurrentThread.CurrentUICulture.ToString()}");

        //經過Task來啓動第二層線程
        Task task = Task.Run(() =>
        {
            Console.WriteLine($"Thread id:{Thread.CurrentThread.ManagedThreadId.ToString()}=>第二層線程的CurrentCulture是{Thread.CurrentThread.CurrentCulture.ToString()}, CurrentUICulture是{Thread.CurrentThread.CurrentUICulture.ToString()}");

            //經過Thread來啓動第三層線程
            Thread th = new Thread(new ThreadStart(() =>
            {

                Thread.Sleep(3000);

                Console.WriteLine($"Thread id:{Thread.CurrentThread.ManagedThreadId.ToString()}=>第三層線程的CurrentCulture是{Thread.CurrentThread.CurrentCulture.ToString()}, CurrentUICulture是{Thread.CurrentThread.CurrentUICulture.ToString()}");
            }));

            th.IsBackground = true;
            th.Start();

            th.Join();//阻塞第二層線程,直到第三層線程th結束
        });

        Thread.Sleep(1000);

        Console.WriteLine($"Thread id:{Thread.CurrentThread.ManagedThreadId.ToString()}=>await以前CurrentCulture是{Thread.CurrentThread.CurrentCulture.ToString()}, CurrentUICulture是{Thread.CurrentThread.CurrentUICulture.ToString()}");

        await task;//await,直到第二層線程結束

        Console.WriteLine($"Thread id:{Thread.CurrentThread.ManagedThreadId.ToString()}=>await以後CurrentCulture是{Thread.CurrentThread.CurrentCulture.ToString()}, CurrentUICulture是{Thread.CurrentThread.CurrentUICulture.ToString()}");

    }).Wait();//阻塞主線程,直到第一層線程執行完畢
}

如今運行結果以下:

咱們能夠看到從第一層線程開始,後續啓動線程的CurrentCulture和CurrentUICulture都爲zh-CN了

這說明在.NET Core中,默認狀況下線程的CurrentCulture和CurrentUICulture屬性是由啓動它的線程來決定的,上面的結果很明顯因爲第一層線程的CurrentCulture和CurrentUICulture爲zh-CN,因此由第一層線程啓動的後續線程(第二層和第三層線程)也都爲zh-CN。因此在.NET Core中要設置線程的CurrentCulture和CurrentUICulture屬性,最簡單的辦法就是在根線程(主線程)上設置CurrentCulture和CurrentUICulture的語言便可。

 

最後若是是在ASP.NET Core中,只須要寫一箇中間件(Middleware),來更改主線程的CurrentCulture和CurrentUICulture屬性爲特定語言,便可實現.resx資源文件的全局利用,固然ASP.NET Core中也有一套自帶的資源文件匹配規則,這裏你們以爲怎麼用起來方便怎麼用便可。

 

本文示例源代碼

相關文章
相關標籤/搜索