2012-07-29 30 views
18

Cách thích hợp để thay đổi ngôn ngữ Biểu mẫu khi chạy là gì?Cách thích hợp để thay đổi ngôn ngữ tại thời gian chạy

  1. Thiết tất cả các điều khiển bằng tay sử dụng đệ quy như this
  2. Lưu lựa chọn ngôn ngữ để nộp> Khởi động lại ứng dụng> Load languge lựa chọn trước khi InitializeComponent();
  3. Sử dụng constructor Form để thay thế thể hiện của hoạt động từ (nếu điều này thậm chí có thể)
  4. Cái gì khác

Có quá nhiều chủ đề bằng văn bản về điều này nhưng không có gì cung cấp s câu trả lời thực sự về cách thích hợp để làm điều này là gì?

UPDATE:
Để làm rõ câu hỏi của tôi:

Làm một cái gì đó như thế này:

public Form1() 
{ 
    Thread.CurrentThread.CurrentUICulture = new CultureInfo("de"); 
    this.InitializeComponent(); 
} 

hoạt động tốt và tất cả các điều khiển của tôi và mọi thứ khác trong nguồn được dịch một cách chính xác. Và làm một cái gì đó như:

private void button1_Click(object sender, EventArgs e) 
{ 
    Thread.CurrentThread.CurrentUICulture = new CultureInfo("en"); 
} 

không có gì, Mẫu nằm trong ngôn ngữ tôi thiết lập trước khi InitializeComponent();

+0

bản sao có thể có của [Làm cách nào để thay đổi văn hóa của ứng dụng WinForms khi chạy] (http://stackoverflow.com/questions/7556367/how-do-i-change-the-culture-of-a- winforms-application-at-runtime) –

+2

@Hans Đây không phải là một bản sao, câu hỏi của tôi là: cách thích hợp để làm điều đó là gì, câu hỏi bạn liên kết với chỉ cung cấp sửa chữa nhanh và không phải là câu trả lời thực sự. – formatc

+1

Điều gì trên trái đất sai với "sửa lỗi nhanh"? Hầu hết các lập trình viên ủng hộ họ trên một thiết kế lại hoàn chỉnh của khuôn khổ. Tôi đoán bạn cho rằng đây phải là một tính năng tích hợp cho Winforms. Không phải vậy. Chỉ có khả năng áp dụng "sửa lỗi nhanh" là tính năng thiết kế. –

Trả lời

20

Tôi tin rằng giải pháp thể hiện trong bình luận Hans passant của có thể là duy nhất (nói chung) giải pháp.

Cá nhân, tôi sử dụng lớp cơ sở này cho tất cả các hình thức mà cần phải được bản địa hoá:

public class LocalizedForm : Form 
{ 
    /// <summary> 
    /// Occurs when current UI culture is changed 
    /// </summary> 
    [Browsable(true)] 
    [Description("Occurs when current UI culture is changed")] 
    [EditorBrowsable(EditorBrowsableState.Advanced)] 
    [Category("Property Changed")] 
    public event EventHandler CultureChanged; 

    protected CultureInfo culture; 
    protected ComponentResourceManager resManager; 

    /// <summary> 
    /// Current culture of this form 
    /// </summary> 
    [Browsable(false)] 
    [Description("Current culture of this form")] 
    [EditorBrowsable(EditorBrowsableState.Never)] 
    public CultureInfo Culture 
    { 
     get { return this.culture; } 
     set 
     { 
      if (this.culture != value) 
      { 
       this.ApplyResources(this, value); 

       this.culture = value; 
       this.OnCultureChanged(); 
      } 
     } 
    } 

    public LocalizedForm() 
    { 
     this.resManager = new ComponentResourceManager(this.GetType()); 
     this.culture = CultureInfo.CurrentUICulture; 
    } 

    private void ApplyResources(Control parent, CultureInfo culture) 
    { 
     this.resManager.ApplyResources(parent, parent.Name, culture); 

     foreach (Control ctl in parent.Controls) 
     { 
      this.ApplyResources(ctl, culture); 
     } 
    } 

    protected void OnCultureChanged() 
    { 
     var temp = this.CultureChanged; 
     if (temp != null) 
      temp(this, EventArgs.Empty); 
    } 
} 

Sau đó, thay vì thay đổi trực tiếp Thread.CurrentThread.CurrentUICulture, tôi sử dụng tài sản trong lớp quản lý tĩnh này để thay đổi Văn bản giao diện người dùng:

public static CultureInfo GlobalUICulture 
{ 
    get { return Thread.CurrentThread.CurrentUICulture; } 
    set 
    { 
     if (GlobalUICulture.Equals(value) == false) 
     { 
      foreach (var form in Application.OpenForms.OfType<LocalizedForm>()) 
      { 
       form.Culture = value; 
      } 

      Thread.CurrentThread.CurrentUICulture = value; 
     } 
    } 
} 
+0

@mnm Cảm ơn, có vẻ đẹp! – formatc

+11

Lưu ý rằng bạn không hoàn thành việc duyệt qua cây điều khiển nếu bạn chỉ lặp lại "parent.Controls". Một TabControl ví dụ giữ các tabPages của nó trong "parent.TabPages". MenuStrip có các mục trong "parent.Items". Và cứ thế. – Chrigl

0

Tham chiếu đến lỗi ColumnHeader .NET framework của bạn, tôi cũng phát hiện ra lỗi này gần đây và đăng câu hỏi về nó (mà tôi chưa nhận được bất kỳ phản hồi nào). Tôi đã có thể khắc phục vấn đề bằng cách mã hóa cứng những thay đổi cho các ColumnHeaders. Ví dụ:

resources.ApplyResources(_myHeader, "_myHeader", culture); 

Về cơ bản, bạn chỉ cần thay thế cuộc gọi thành .Name bằng chuỗi ký tự bằng chữ. Tôi đã thử nghiệm này và nó hoạt động. Thật không may điều này có nghĩa là nó sẽ không phù hợp như một phần của mã bạn sử dụng để thay đổi tất cả các điều khiển. Bạn sẽ phải thêm một dòng cho mỗi đối tượng ColumnHeader mà bạn cần phải thay đổi. Nếu bạn có một listview với một số lượng biến cột, có thể có được khó khăn. Một tùy chọn khác là tạo các tệp tài nguyên được bản địa hóa. Tôi cho rằng bạn có thể đã có chúng cho những thứ như văn bản hộp thư và các chuỗi khác. Sau đó, bạn có thể thêm mục nhập trong tệp tài nguyên của mình như "columnHeader_myHeader" và đặt văn bản ngôn ngữ phù hợp cho từng ngôn ngữ. Cuối cùng, bạn có thể thay đổi văn bản thành tiêu đề cột theo cách thủ công bằng cách sử dụng:

_myHeader.Text = myResourceFileName.columnHeader_myHeader; 

Điều này sẽ chọn ngôn ngữ phù hợp dựa trên văn bản chuỗi hiện tại. Hans đã chính xác trong đó có vẻ không phải là một cách "phù hợp" để thực hiện nội địa hóa.NET, mặc dù có nhiều công cụ bạn có thể sử dụng. Đối với một cái gì đó giống như một ứng dụng công việc, mặc dù có thể đã quá muộn cho lời khuyên này, đề nghị của tôi là học nhiều phương pháp khác nhau để bạn có thể địa phương hóa, tìm hiểu ưu và khuyết điểm, và sau đó chỉ cần chọn một hệ thống và có thể để tranh luận lý do tại sao bạn tin rằng đó là lựa chọn "đúng". Họ có lẽ quan tâm hơn đến logic của bạn và lý luận và trình diễn kinh nghiệm trước đây hơn là với phương pháp thực tế.

1

Tôi đã phát hiện ra loại phương pháp này cách đây vài phút. Chỉ cần khởi động lại nhanh chóng và đơn giản của biểu mẫu chính. Meybe nó sẽ giúp cho ai đó. Sự kiện được tạo bên trong biểu mẫu của riêng tôi, được gọi khi người dùng chọn ngôn ngữ từ trình đơn nhưng sau khi tên của nền văn hóa đã chọn được lưu vào cài đặt. Tên văn hóa sau đó được tải từ các cài đặt đó. Hoạt động chính xác như tôi cần và trông giống như giải pháp thích hợp.

static class Program 
{ 
    private static bool doNotExit = true; 
    private static FormMain fm; 
    /// <summary> 
    /// The main entry point for the application. 
    /// </summary> 
    [STAThread] 
    static void Main() 
    { 


     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false); 

     while(doNotExit) 
     { 
      System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo(Properties.Settings.Default.language);// 
      System.Threading.Thread.CurrentThread.CurrentUICulture = new CultureInfo(Properties.Settings.Default.language);// 

      doNotExit = false; 
      fm = new FormMain(); 
      fm.lanugageChangedEvent += new EventHandler(main_LanugageChangedEvent); 
      Application.Run(fm); 
     } 
    } 



    static void main_LanugageChangedEvent(object sender, EventArgs e) 
    { 
     doNotExit = true; 
     fm.Close(); 
    } 
} 
3

Tôi đã tìm thấy một cách khác:

Move mẫu mã khởi tạo trong tole tin như dưới đây

private void FormInitialize() {/*Your code here*/} 

Ở dạng constructor sử dụng nó như thế này

public Form1() 
{ 
    InitializeComponent(); 
    FormInitialize(); 
} 

Và từ Button, menuItem hoặc methode gọi khác như thế này

private void ChangeCultureToFrench_Click(object sender, EventArgs e) 
{ 
    Thread.CurrentThread.CurrentUICulture = new CultureInfo("fr"); 
    this.Controls.Clear(); 
    this.InitializeComponent(); 
    FormInitialize(); 
} 

Tôi hy vọng điều này sẽ giúp ;-)

0

Hy vọng điều này sẽ giúp bất cứ ai, tôi thấy nó tốt nhất cho tôi gây ra tôi cần phải thay đổi các nút vị trí theo các lang (duyệt trên bên phải hoặc bên trái của hộp tìm kiếm và nhãn bên cạnh trường văn bản).

  1. lưu một var công khai trên chính sẽ tổ chức lang.
  2. tạo ra một lớp mà xử lý phần hình ảnh
  3. tạo file xml mà sẽ giữ bất kỳ dữ liệu ngôn ngữ và nhiều hơn nữa (trong thẻ xml name = tên đối tượng của tôi).
  4. gửi constructor của lớp rằng hình thức (để tiết kiệm và làm việc với)
  5. kết nối đến tập tin xml hiện

Từ cuộc gọi hình thức chính bất cứ khi nào bạn muốn initialView (một phần của lớp view) và thay đổi lang (và nhiều hơn nữa) bất cứ lúc nào (chỉ cần kết nối đến tập tin xml phải):

public void initialView() 
{ 
    //Set rightToLeft values 
    initialIndent(mainForm); 

    //set visual text values 
    initialTxt(); 
} 

private void initialTxt() 
{ 
    // Are there any more controls under mainObj (Form1)? 
    Boolean endOfElemsUnderPnl = false; 

    // The current Control im working on 
    Object curObj = mainForm; 

    do 
    { 
     // MenuStrip needs to be handled separately 
     if (typeof(MenuStrip).ToString().Equals(curObj.GetType().ToString())) 
     { 
      foreach (ToolStripMenuItem miBase in ((MenuStrip)(curObj)).Items) 
      { 
       miBase.Text = mainForm.dbCon.getData(miBase.Name.ToString()); 
       foreach (ToolStripMenuItem miInnerNode in miBase.DropDownItems) 
       { 
        miInnerNode.Text = mainForm.dbCon.getData(miInnerNode.Name.ToString()); 
       } 
      } 
     } 

     // Any other Control i have on the form 
     else 
     { 
      ((Control)(curObj)).Text = mainForm.dbCon.getData(((Control)(curObj)).Name.ToString()); 
     } 

     curObj = mainForm.GetNextControl(((Control)(curObj)), true); 

     // Are there any more controls under mainObj? 
     if (null == curObj) 
     { 
      endOfElemsUnderPnl = true; 
     } 

    } while (!endOfElemsUnderPnl); 
} 

private void initialIndent(frmMyFileManager parent) 
{ 
    if (parent.Language.Equals("Hebrew")) 
    { 
     parent.RightToLeft = RightToLeft.Yes; 
    } 
    else if (parent.Language.Equals("English")) 
    { 
     parent.RightToLeft = RightToLeft.No; 
    } 
    else 
    { 
     parent.RightToLeft = RightToLeft.No; 
    } 
} 

và đây là một ví dụ về cách dễ dàng là cho tôi trong thời gian chạy:

private void selectLanguageToolStripMenuItem_Click(object sender, EventArgs e) 
{ 
    DialogResult res = MessageBox.Show(this, "click yes for english and no for hebrew", "Select language", MessageBoxButtons.YesNoCancel); 

    if (DialogResult.Yes == res) 
    { 
     Language = "English"; 
    } 
    else if (DialogResult.No == res) 
    { 
     Language = "Hebrew"; 
    } 
    dbCon = new CDBConnector("****\\lang" + Language + ".xml"); 
    view.initialView(); 
} 
Các vấn đề liên quan