views:

129

answers:

3

Im creating a C# Application based on WinForms / KryptonForms, and as the application is halfway in development i thought to myself I best sort the localization out.

As a born and bread PHP Programmer (and I know C# is a whole new level), I would create a class to detect the language and auto assign the language pack to the application. and then use the language objects to access the values.

Im wondering if I can get some examples on the easiest / Best methods of doing this.

I personally would like something along the lines of the Application Settings

Where usually I would do MyApplication.Properties.Settings.Default.SomeKey I was hopeing of a MyApplication.Languages.Current.ApplicationTitle and MyApplication.Languages.en.ApplicationTitle for example.

Also by only loading a single resource per language file to improve speed would be benificial aswell.

So the language loads in English, Spanish user is promoted that this application is in english, would he like to change it to the Spanish language, he clicks YES, the settings get updated and application restarts and loads the single Spanish language pack.

What's your thoughts on this.


Edit:

The application is based on the XMPP Protocols and uses agsXMPP Libraries. From my understanding each user that sends me their presence should also send the language their system is on.

So basically if there's any way to "grasp" the fact of storing a single word and using the __("some string") in my application would be possible, but for the mean time I'm just looking at the GUI text.

+4  A: 

The way we do localization is:

  • Set the "Localizable"-Property of a WinForm to true (which will generate a new resource file for that Form, holding e.g. the text of labels, buttons, but also z-order etc)
  • Create a FormName.de.resx file ("de" because we're german) and then store the strings that will need to be localized in there (access to this resource-file works via the ResourceManager-class)
  • As for non-WinForms code that needs to be localized, we simply create separate resource files

Upon compiling your app, a AppName.resources.dll is created. This dll holds all the resources of your application and can then be used with tools such as Visual Localize to translate the strings into another language like english or spanish etc.

Christian
OK, but I do not want to load all language resources if possible, just a single language needs to be imported so, so can I have `lang.en.dll` and `lang.de.dll` on witch will be loaded from the language in settings name space? or by doing this way not make any difference on the applications speed ?
RobertPitt
Only one resources dll will be loaded. On my german machine, the AppName.de.dll will be loaded, on an english machine, the AppName.en.dll.
Christian
Looks interesting, In this case ill see what i can do with it. Thanks for your help.
RobertPitt
+1  A: 

We use Resources.MyResources.SomeString which gets automatically translated in the right language. Resource files are named MyResources.de-DE.resx, MyResources.nl-BE.resx etc. Same method as the Project Properties basically.

Sample translation code:

public void TranslateForm()
{
        menuItem11.Text = Resources.MyResources.Nieuw;
        menuItem12.Text = Resources.MyResources.Verwijderen;
        menuItem13.Text = Resources.MyResources.Kopieren;
}

Or you could do it manually like:

menuItem11.Text = Translator.GetString("New", "de-DE" );

...

    public static string GetString( string varname )
    {
        string resourceName = typeof(Vertaling).Namespace + ".Resources.MyResources";
        ResourceManager rm = new ResourceManager(resourceName, Assembly.GetExecutingAssembly());
        return rm.GetString(varname);
    }

    public static string GetString( string varname, string taalCode )
    {
        string resourceName = typeof(Vertaling).Namespace + ".Resources.MyResources";
        ResourceManager rm = new ResourceManager(resourceName, Assembly.GetExecutingAssembly());
        return rm.GetString(varname, new CultureInfo(taalCode) );
    }
Run CMD
see this to me is not efficiant if i have lots of elements that need to be translated, basically i want in my designer code `this.LoginLabel.Text = Language.Current.LoginLabel;` so i do not have to worry about things as the system will load the needed language ?
RobertPitt
I don't understand. What's the difference between this.LoginLabel.Text = Language.Current.LoginLabel; and menuItem11.Text = Resources.MyResources.Nieuw; ??We don't do translations in the designer anymore since that gives lots of (dreaded) designer errors.
Run CMD
well, the problem is not with the way the code is, i just want the text labels to be loaded with the text from the language pack and not for me to create a new method and individually assign all elements new text values.
RobertPitt
+1  A: 

You should use resources.

You can change language dynamically:

1) in console app:

Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
double a = 100.12;
Console.WriteLine("{0} - {1}", Thread.CurrentThread.CurrentCulture, a);

Thread.CurrentThread.CurrentCulture = new CultureInfo("ru-RU");
Console.WriteLine("{0} - {1}", Thread.CurrentThread.CurrentCulture, a);
Console.ReadLine();

2) in winforms app we can reopen form to apply localization resources (use Localizable and Language properties in the form designer to auto generate resources for every language):

if (Thread.CurrentThread.CurrentCulture.Name == "en-US")
{
    Thread.CurrentThread.CurrentCulture = new CultureInfo("ru-RU");
    Thread.CurrentThread.CurrentUICulture = new CultureInfo("ru-RU");
}
else
{
    Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
    Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
}

double a = 100.12;
textBox1.Text = a.ToString(Thread.CurrentThread.CurrentCulture);

Form1 f = new Form1();
f.ShowDialog();

3) using many threads with own localization

private void button1_Click(object sender, EventArgs e)
{
    // for example main thread language is en-US        

    Thread t = new Thread(StartForm);
    t.CurrentUICulture = new CultureInfo("ru-RU");
    t.Start();
    //t.Join();
}

public static void StartForm()
{
    Form1 f = new Form1();
    f.ShowDialog();
}
igor
How do you auto detect the the users Locale, and can i use language resources from windows itself ?
RobertPitt
When your application starts the Thread.CurrentThread.CurrentCulture has value according to your windows settings (My operation system has Ukrainian uk-UA), but I can change Thread.CurrentThread.CurrentCulture value and then, for example, I can save this value to some application setting to use in the next session.
igor
3) using many threads with own localization (see my updated answer)
igor