0

私は週末にペット プロジェクトに取り組んで C# についてさらに学びましたが、ローカリゼーションの作業中に奇妙な問題に遭遇しました。具体的には、私が抱えている問題は System.Threading.Thread.CurrentThread.CurrentUICulture にあります。

ユーザーがメニュー項目をクリックしてアプリの言語をすばやく変更できるように、アプリをセットアップしました。メニュー項目は、言語の 2 文字のコード (「en」、「fr」など) を「Language」というユーザー設定に保存し、アプリケーションを再起動します。

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

問題は、これは一貫して機能しないということです。すべてがうまく機能し、アプリケーションが設定ファイルに保存された文字列に基づいて正しい言語をロードする場合があります。そうでない場合もあり、アプリケーションの再起動後も言語は同じままです。

最初は、アプリケーションを再起動する前に言語を保存していないと思っていましたが、そうではありません。正しい言語の読み込みに失敗した場合、アプリケーションを閉じて再度実行すると、正しい言語が正しく表示されます。これは、Language 文字列が保存されていることを意味しますが、フォーム コンストラクターの CurrentUICulture 割り当てが効果を発揮しない場合があります。

何か助けはありますか?C# でスレッド化がどのように機能するかについて、私が見逃しているものはありますか? これはマシン固有の可能性があるため、違いがある場合は、Pentium デュアルコア CPU を使用しています。

アップデート

Vlad から、CurrentThread の CurrentUICulture が何であるかを確認するように依頼されました。そのため、コンストラクターに MessageBox を追加して、CurrentUICulture の 2 文字のコードと、Language ユーザー文字列の値を教えてくれました。

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

間違った言語が読み込まれると、Language 文字列と CurrentUICulture の両方に間違った言語が含まれます。したがって、CurrentUICulture はクリアされていると思いますが、実際には言語設定に問題があります。

したがって、問題は、アプリケーションが最後に保存された言語文字列ではなく、以前に保存された言語文字列をロードすることがあることだと思います。アプリを再起動すると、実際に保存された言語文字列が読み込まれます。

4

5 に答える 5

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()。アプリを閉じて再度開くと、(新しい) 設定が適用されます。

そのため、フォームを再度初期化して新しい言語設定を行う方法を見つける必要があります。

于 2010-08-20T12:00:32.647 に答える
2

スレッドの内容を確認できますCurrentUICultureか?

あなたのような問題を抱えていたことを覚えています。ローカライズする文字列を含むリソース ディクショナリをリロードすることで解決しました。

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

(そして、このアプローチは動的にも機能しました。ここにいくつかの詳細情報があります)。

于 2010-04-28T08:23:05.087 に答える
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;

それが役立つことを願っています!

于 2012-10-24T22:57:37.920 に答える
0

CurrentThread.CurrentUICultureを使用してからフォームを変更することにより、アプリケーションを再起動する必要はありません。ここに私の古い投稿を参照してください

于 2010-10-27T04:36:41.187 に答える
0

開いているフォームを閉じて再作成するだけで、アプリケーションを「リセット」できます。次に、ユーザーが設定を変更したときにカルチャを直接設定できます。

また、設定されている値と、カルチャが実際に期待どおりのものであるかどうかを確認できるように、デバッグ出力を提供してみてください。

編集: 私の推測: データはファイルに書き込まれ、そのファイルから読み込まれる必要があるため、書き込みが完了するには再起動が速すぎる可能性があります。

于 2010-04-28T08:40:49.120 に答える