2010-04-28 159 views
0

我一直在週末的一個寵物項目上工作,以瞭解更多關於C#的知識,並且在使用本地化時遇到了一個奇怪的問題。更具體地說,我遇到的問題是System.Threading.Thread.CurrentThread.CurrentUICulture。Thread.CurrentThread.CurrentUICulture工作不一致

我已經設置了我的應用程序,以便用戶可以通過單擊菜單項快速更改應用程序的語言。該菜單項依次將用於該語言的雙字母代碼(例如「en」,「fr」等)保存在名爲「語言」的用戶設置中,然後重新啓動該應用程序。

Properties.Settings.Default.Language = "en"; 
Properties.Settings.Default.Save(); 
Application.Restart(); 

當應用程序啓動時,在窗體的構造函數的第一行代碼(的InitializeComponent()甚至之前)獲取的設置語言字符串,並設置的CurrentUICulture像這樣:

public Form1() 
{ 
    Thread.CurrentThread.CurrentUICulture = new CultureInfo(Properties.Settings.Default.Language); 
    InitializeComponent(); 
} 

事情是,這不一致。有時候,一切正常,應用程序會根據保存在設置文件中的字符串加載正確的語言。其他時候,它沒有,並且應用程序重新啓動後語言保持不變。

起初我以爲我沒有在重新啓動應用程序之前保存語言,但事實絕非如此。當正確的語言加載失敗時,如果我要關閉應用程序並再次運行,正確的語言將正確顯示。所以這意味着語言字符串已經被保存了,但是我的表單構造函數中的CurrentUICulture賦值有時並不起作用。

任何幫助?有什麼我缺少線程在C#中的工作原理嗎?這可能是機器特定的,所以如果它有什麼區別,我使用奔騰雙核CPU。

UPDATE

弗拉德問我檢查CurrentThread的CurrentUICulture是什麼。因此,我在構造函數中添加了一個MessageBox,告訴我CurrentUICulture的兩個字母代碼以及我的Language用戶字符串的值。

MessageBox.Show(string.Format("Current Language: {0}\nCurrent UI Culture: {1}", Properties.Settings.Default.Language, Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName)); 

當錯誤的語言被加載,無論是語言字符串的CurrentUICulture有錯誤的語言。所以我想CurrentUICulture已經被清除了,我的問題實際上是在語言設置中。

所以我想問題是,我的應用有時加載以前保存的語言字符串,而不是上次保存的語言字符串。如果應用程序重新啓動,它將加載實際保存的語言字符串。

+1

當您更改CurrentUICulture時是否真的有必要重新啓動應用程序? – 2010-04-28 08:12:09

+0

@第七元素 顯然如此。當您僅更改CurrentUICulture時,顯示的語言不會更改。我一直在搜索如何在運行時更改表單的語言,但它有點麻煩(循環遍歷表單上的每個控件並應用該資源文件中找到的所有控件的屬性,但無法獲取該想法工作)。 重新啓動應用程序似乎是完成工作的更簡單的方法。 – xTRUMANx 2010-04-28 08:30:37

回答

3

我得到了同樣的問題。我發現Application.Restart()並不真正重啓,請參閱MSDN

因此,Application.Restart()不像InitializeComponent()那樣調用窗體構造函數 中的初始化事物,更多的是「應用程序在它們最初運行的環境中重新啓動」。

所以,你的代碼是正確的

Properties.Settings.Default.Language = "en"; 
Properties.Settings.Default.Save(); 

public Form1() 
{ 
    Thread.CurrentThread.CurrentUICulture = new CultureInfo(Properties.Settings.Default.Language); 
    //... 
    InitializeComponent(); 
} 

,但它不與Application.Restart()以這種方式工作。如果關閉應用程序並再次打開,則會進行(新)設置。

所以我們必須找到一種方法來再次初始化表單,以使新的語言設置發生。

+0

我沒太多用,所以我才找到你的答案。 這幾乎是我解決的解決方案。應用程序不會自動重新啓動,而是會通知用戶重新啓動應用程序以使新語言生效。 不是最好的解決方案,但我想我可以忍受它。猜猜我會標記你爲答案。 – xTRUMANx 2010-11-23 06:53:19

1

你能檢查你的線程是什麼CurrentUICulture

我記得有一個像你這樣的問題;它解決了重裝包含字符串進行本地化資源字典:

Thread.CurrentThread.CurrentUICulture = <new culture>; 
ResourceDictionary newDict = new ResourceDictionary(); 
newDict.Source = localizedStrings.Source; 
localizedStrings = newDict; 

(而這種做法的工作動態,以及; here是一些更多的信息)。

+0

好問題,看來我錯了,說CurrentThread存在問題。我更新了我的帖子,但顯然問題在於調用Properties.Settings.Default.Language。它似乎在加載舊語言,而不是上次保存的語言。第二次重新啓動後,實際加載了上次保存的語言。 P.S.試圖upvote你,但唉,沒有足夠的代表。 – xTRUMANx 2010-04-28 08:55:45

0

您可以簡單地通過關閉打開的表單並重新創建它們來「重置」您的應用程序。然後,您可以在用戶更改設置時直接設置文化。

此外,請嘗試給出一些調試輸出,以便您看到正在設置的值以及文化是否實際上是您所期望的。

編輯:我的猜測:由於數據必須寫入文件,然後從該文件加載,您可能會重新啓動太快,寫入已完成。

+0

我已經更新了我的文章,因爲我發現實際問題不在CurrentThread.CurrentUICulture任務中,而是在調用我的語言設置。 但是,我不太確定我瞭解您的「重置」建議。當用戶更改語言時,可能會打開許多​​不同類型的表單。重新創建它們並不容易,因爲我不知道哪些表單是開放的,它們的構造函數需要什麼參數等。 – xTRUMANx 2010-04-28 09:13:29

+0

通過重置,我的意思是找到所有打開的窗口,關閉它們,然後打開主窗體。但是,我個人更希望如果您將顯示一條消息,沿着「重新啓動應用程序之前,語言更改不會生效」。這樣,用戶不會失去任何開放性工作。 – 2010-04-28 09:56:58

0

通過使用CurrentThread.CurrentUICulture,然後更改窗體,您不需要重新啓動應用程序。參考我以前的帖子here

1

你可以手動更改與此類似當前的語言形式:

CultureInfo cInfo = new CultureInfo("en-US"); 
ResourceManager rm = new ResourceManager(GetType()); 

// For each control on the form, perform the translation manually (probably better in a loop) 
control1.Text = rm.GetString(control1.Name + ".Text", cInfo); 

// Now set the culture for all other dialogs 
Thread.CurrentThread.CurrentUICulture = cInfo; 

希望幫助!

+0

2年前問過這個問題.. – evandentremont 2012-10-24 23:18:12