C# – Multi Language (đa ngôn ngữ) trong Windows Forms

Để tạo một ứng dụng đa ngôn ngữ, cách điển hình là tạo các string table để lưu trữ các văn bản, chuỗi cho mỗi ngôn ngữ. Trong .NET, bạn có thể dùng các Resource để tạo ra các string table này và dùng lớp ResourceManager để quản lý và lấy ra các chuỗi cụ thể dựa vào một đối tượng CultureInfo.

Download sourcecode (38 KB)

Trước hết tôi tạo một ứng dụng WinFoms với tên WinFormsMultilingual, tạo thêm một thư mục tên là “Lang”. Sau đó thêm một Resources File với tên MyResource.resx vào thư mục này.

Tạo thêm hai Resource vào thư mục Lang tương ứng cho hai ngôn ngữ là English và Vietnamese. Các Resource này phải có tên theo dạng < default resource name >.<culture>.resx với <default resource name > chính là MyResource mà tôi đặt ở bước trên.

Solution Explorer sẽ có dạng:

Thêm dữ liệu vào các file MyResource.en-US.resx và  MyResource.vi-VN.resx. Mỗi dòng bao gồm hai cột cần có dữ liệu là Name và Value. Cột Name là định danh giúp lấy ra Value của bảng khi bạn dùng ResourceManager để làm việc:

Viết phương thức SetLanguage() để thay đổi ngôn ngữ cho giao diện. Các giá trị của tham số cultureName bạn có thể tham khảo ở cuối bài viết:

private void SetLanguage(string cultureName)
{
    culture = CultureInfo.CreateSpecificCulture(cultureName);
    ResourceManager rm = new
        ResourceManager("WinFormsMultiLingual.Lang.MyResource", typeof(Form1).Assembly);

    btnHello.Text = rm.GetString("hello", culture);
    radEnglish.Text = rm.GetString("english", culture);
    radVietnamese.Text = rm.GetString("vietnamese", culture);
    helloWorldString = rm.GetString("helloworld", culture);
}

Mã nguồn code-behind hoàn chỉnh của Form1.cs:

using System;
using System.Windows.Forms;
using System.Resources;
using System.Globalization;

namespace WinFormsMultiLingual
{
    public partial class Form1 : Form
    {
        CultureInfo culture;
        string helloWorldString = "Hello World!";

        public Form1()
        {
            InitializeComponent();

            culture = CultureInfo.CurrentCulture;

        }

        private void btnHello_Click(object sender, EventArgs e)
        {
            MessageBox.Show(helloWorldString);
        }

        private void LanguageRadioButtons_CheckedChanged(object sender, EventArgs e)
        {
            if (radEnglish.Checked)
                SetLanguage("en-US");
            else if (radVietnamese.Checked)
                SetLanguage("vi-VN");
            //else
            //    ...

        }

        private void SetLanguage(string cultureName)
        {
            culture = CultureInfo.CreateSpecificCulture(cultureName);
            ResourceManager rm = new
                ResourceManager("WinFormsMultiLingual.Lang.MyResource", typeof(Form1).Assembly);

            btnHello.Text = rm.GetString("hello", culture);
            radEnglish.Text = rm.GetString("english", culture);
            radVietnamese.Text = rm.GetString("vietnamese", culture);
            helloWorldString = rm.GetString("helloworld", culture);
        }
    }
}

Khi biên dịch, mỗi một tập tin Resource sẽ được tạo ra trong một thư mục mới với tên tương ứng là en-US và vi-VN. Mỗi thư mục này sẽ chứa một tập tin có tên WinFormsMultiLingual.resources.dll.

Kết quả:

Tham khảo:

National Language Support (NLS) API Reference

https://yinyangit.wordpress.com

19 bình luận về “C# – Multi Language (đa ngôn ngữ) trong Windows Forms

  1. Cảm ơn bạn nhiều .
    Nhưng vấn đề là mình cần áp dùng demo này vào bài tập lớn làm trên nhiều form khác nhau ?
    Mình cũng có gủi email cho bạn rồi?
    Mình không hiểu cách nào để chỉ cần chọn ngôn ngữ và tất cả các form khác liên quan trong bài đều thay đổi ngôn ngữ theo?
    Bạn có thể giúp mình 1 demo 2 đa form về multi language đc không bạn?

    • Vấn đề của bạn gặp phải có lẽ là làm sao để tất cả form đang mở tự động thay đổi ngôn ngữ (giao diện) khi bạn thao tác với một Form điều khiển. Bạn có thể giải quyết như sau:

      1. Giả sử trong mỗi Form của bạn có một phương thức là UpdateLanguage() để tự động thay đổi giao diện theo ngôn ngữ nào đó. Việc xác định culture bạn nên đặt trong một lớp riêng biệt để các Form mới mở sẽ dựa vào đó để chọn ngôn ngữ hiển thị.

      2. Trong Form điều khiển, bạn có thể dùng Application.OpenForms để duyệt qua tất cả Form đang mở, sau đó kiểm tra Form đó có phương thức UpdateLanguage() không bằng cách dùng reflection. Sau đó gọi phương thức đó để các Form tự động cập nhật giao diện mới.

      foreach(Form frm in Application.OpenForms)
      {
      MethodInfo method=frm.GetType().GetMethod(“UpdateLanguage”);
      if(method!=null)
      method.Invoke(frm,null);
      }

      Mình và bạn DuyBK có thể giúp đỡ nếu bạn vẫn còn vướng mắc.

  2. Bạn có thể cho mình biết mục đích của file MyResource.resx trong thư mục Lang trong ví dụ của bạn được không? Mình exclude nó ra khỏi project và khi chạy vẫn bình thường, ko có lỗi.

  3. Trong trường hợp để đảm bảo tính năng multi language cho chương trình, file đó được dùng để chứa ngôn ngữ mặc định. Chẳng hạn như bạn có thể thiết lập sang một ngôn ngữ mới như Fench, và chương trình ko thể tìm thấy file MyResource.fr-FR.resx tương ứng, khi đó tập tin MyResource.resx trên sẽ được sử dụng.

  4. mình vô tình vào Blog này thấy các bạn hướng dẫn và thảo luận rất hay.
    Mình có một vấn đề nho nhỏ mà vẫn chưa tìm được cách để giải quyết vấn đề
    – Minh co 2 form. Form đầu tiên là formMain là form cha còn form thứ 2 là formchil
    => trong formMain có một processbar dùng để hiển thị tiến trình.
    ===> vấn đề là ở chỗ. khi formMain chạy, sau đó gọi formchil lên. trong formchil co một nút LoadData mình muốn cho nó hiển thị tiến trình load bằng processbar của formMain. vậy mình phải làm sao đây các bạn. Mình đã sử dụng delegate va event rồi.

  5. truyền tham số không phải là vấn đề chính. Cái khó ở đây là nó không chạy khi chúng ta gọi nó tại formChil. Còn formMain thì chạy bình thường không có vấn đề

    • Cơ chế này chủ yếu là bạn giao việc lấy các text (để hiện thị) cho 1 đối tượng ResourceManager. Rồi tùy theo ngôn ngữ bạn chọn, ResourceManager sẽ trả ra text tương ứng. Cũng tương tự như bạn viết một hàm vậy:

      btnCancel.Text = GetCancelText(string language);

Đã đóng bình luận.