找到你要的答案

Q:Localize dataannotation error messages as per culture

Q:定位dataannotation错误消息按文化

In my WPF appliation, I have property defined as following

[Required(AllowEmptyStrings =false, ErrorMessageResourceName ="Msg1", ErrorMessageResourceType =typeof(*<AssemblyName>*.Resources.*<ResourceFileName>*))]
public string Name
{
    get
    {
        return _name;
    }

    set
    {
        if (_name == value)
        {
            return;
        }
        _name = value;
    }
}

I have my error messages defined in separate assembly which has resource file for different cultures e.g. Resources.resx, Resources.en-GB.Resx, Resources.fr-FR.Resx, Resources.en-US.Resx, etc.

With above code in place, I'm able to retrieve the error message from default resource file in my satellite assembly but I don't see any provision to find the string resource from culture specific resource file. What I mean is if my CurrentUICluture is set as english(United Kingdom) then I want to retrieve the resource value from the file "Resources.en-GB.Resx" instead of the default file (i.e. Resources.Resx).

I don't see any way to pass the culture info in the Required attribute definition. Also, I have tested that it is not inherently look into the culture specific resource file based on the current culture set.

What I want is some way to make the resource retrieval mechanism culture aware.

Thanks,

在我的WPF应用,我有财产的定义如下

[Required(AllowEmptyStrings =false, ErrorMessageResourceName ="Msg1", ErrorMessageResourceType =typeof(*<AssemblyName>*.Resources.*<ResourceFileName>*))]
public string Name
{
    get
    {
        return _name;
    }

    set
    {
        if (_name == value)
        {
            return;
        }
        _name = value;
    }
}

我有我的错误信息在单独的组件具有不同的文化,如resources.resx,资源文件中定义的resources.en-gb.resx,resources.fr-fr.resx,resources.en-us.resx,等。

有了上述代码,我能够从我的卫星程序集中的默认资源文件中检索错误消息,但我看不出从特定的资源文件中查找字符串资源的任何条款。我的意思是,如果我的CurrentUICluture设置为英语(英国)然后我想从文件“资源检索资源价值。en GB .resx”而不是默认的文件(即资源.resx)。

我看不出在所需的属性定义中传递文化信息的任何方法。而且,我已经测试了它并不是根据当前的文化设置来查看特定于文化的资源文件。

我想要的是使资源检索机制文化意识。

谢谢,

answer1: 回答1:

If you'd like to make your website culture aware, you'll need to modify the globalization attribute in the web.config under the system.web element:

<globalization fileEncoding="utf-8" requestEncoding="utf-8" culture="auto" uiCulture="auto" enableClientBasedCulture="true" />

Then it will look for resources based on the browser's preferred language settings.

Alternatively, you can specify it explicitly:

<globalization fileEncoding="utf-8" requestEncoding="utf-8" responseEncoding="" culture="en-US" uiCulture="en-US" />

如果你想让你的网站的文化意识,你需要修改全球化属性在Web.config的system.web元下:

<globalization fileEncoding="utf-8" requestEncoding="utf-8" culture="auto" uiCulture="auto" enableClientBasedCulture="true" />

然后它会根据浏览器的首选语言设置查找资源。

或者,可以显式指定它:

<globalization fileEncoding="utf-8" requestEncoding="utf-8" responseEncoding="" culture="en-US" uiCulture="en-US" />
answer2: 回答2:

Finally I got the fix for my problem from this link

In my app, I was setting the culture at the time of starting the application by putting following code in app.xaml.cs file.

    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        InitializeCultures();
    }

    private static void InitializeCultures()
    {
        var culture = ConfigurationManager.AppSettings.Get("Culture");
        if (!String.IsNullOrEmpty(culture))
        {
            Thread.CurrentThread.CurrentCulture =  new CultureInfo(culture);
        }

        var UICulture = ConfigurationManager.AppSettings.Get("UICulture");
        if (!String.IsNullOrEmpty(UICulture))
        {
            Thread.CurrentThread.CurrentUICulture = new CultureInfo(UICulture);
        }
    }

However problem is even if I set the Culture initially, not all threads will use the same culture set by me initially. So the thread which was reading the resource value for me was still using the default culture and this resulted in reading of resource string always from default culture resource file rather then the culture specific resource file.

So the trick was to set all the threads in my app to use the same culture which I set initially. There are two properties for this

  1. CultureInfo.DefaultThreadCurrentCulture
  2. CultureInfo.DefaultThreadCurrentUICulture

Setting required culture value to these two properties initially will ensure that all the subsequent threads used in the application will have the same culture as set by user. These two properties sets the culture on all the threads in current app domain.

Once culture is set properly, reading of resource values inherently becomes culture aware and reads resource values from culture specific resource files.

So following is the updated version of InitializeCulture method :

    private static void InitializeCultures()
    {
        var culture = ConfigurationManager.AppSettings.Get("Culture");
        if (!String.IsNullOrEmpty(culture))
        {
            Thread.CurrentThread.CurrentCulture = CultureInfo.DefaultThreadCurrentCulture =  new CultureInfo(culture);
        }

        var UICulture = ConfigurationManager.AppSettings.Get("UICulture");
        if (!String.IsNullOrEmpty(UICulture))
        {
            Thread.CurrentThread.CurrentUICulture = CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo(UICulture);
        }
    }

P.S. There is a word of caution of using this fix in web application. Pls read about it on original link.

Hope this helps...

最后,我得到了解决我的问题,从这个链接

在我的应用程序,我在开始把以下代码中的app.xaml.cs文件的应用程序的时间设定的文化。

    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        InitializeCultures();
    }

    private static void InitializeCultures()
    {
        var culture = ConfigurationManager.AppSettings.Get("Culture");
        if (!String.IsNullOrEmpty(culture))
        {
            Thread.CurrentThread.CurrentCulture =  new CultureInfo(culture);
        }

        var UICulture = ConfigurationManager.AppSettings.Get("UICulture");
        if (!String.IsNullOrEmpty(UICulture))
        {
            Thread.CurrentThread.CurrentUICulture = new CultureInfo(UICulture);
        }
    }

然而问题是,即使我最初设置了这个文化,也不是所有的线程都会使用我最初设置的相同的文化。因此,为我读取资源值的线程仍然使用默认的文化,这导致读取资源字符串总是从默认的文化资源文件而不是特定于文化的资源文件。

所以诀窍是设置所有线程在我的应用程序使用相同的文化,我最初设置。有两个属性

  1. CultureInfo.DefaultThreadCurrentCulture
  2. CultureInfo.DefaultThreadCurrentUICulture

首先将所需的文化值设置为这两个属性将确保应用程序中使用的所有后续线程具有与用户设置的相同的文化。这两个属性设置当前应用程序域上所有线程的。

一旦适当地设置了文化,资源值的读取就变成了文化感知,并从特定于文化的资源文件中读取资源值。

所以,以下是initializeculture方法的更新版本:

    private static void InitializeCultures()
    {
        var culture = ConfigurationManager.AppSettings.Get("Culture");
        if (!String.IsNullOrEmpty(culture))
        {
            Thread.CurrentThread.CurrentCulture = CultureInfo.DefaultThreadCurrentCulture =  new CultureInfo(culture);
        }

        var UICulture = ConfigurationManager.AppSettings.Get("UICulture");
        if (!String.IsNullOrEmpty(UICulture))
        {
            Thread.CurrentThread.CurrentUICulture = CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo(UICulture);
        }
    }

另外有一个词的使用这个解决Web应用中的注意。请阅读关于它的原始链接。

希望这有助于…

c#  .net  wpf  localization  cultureinfo