How to use localization in C#

后端 未结 9 2474
栀梦
栀梦 2020-11-22 02:59

I just can\'t seem to get localization to work.

I have a class library. Now I want to create resx files in there, and return some values based on the threa

相关标签:
9条回答
  • 2020-11-22 03:07

    Great answer by F.Mörk. But if you want to update translation, or add new languages once the application is released, you're stuck, because you always have to recompile it to generate the resources.dll.

    Here is a solution to manually compile a resource dll. It uses the resgen.exe and al.exe tools (installed with the sdk).

    Say you have a Strings.fr.resx resource file, you can compile a resources dll with the following batch:

    resgen.exe /compile Strings.fr.resx,WpfRibbonApplication1.Strings.fr.resources 
    Al.exe /t:lib /embed:WpfRibbonApplication1.Strings.fr.resources /culture:"fr" /out:"WpfRibbonApplication1.resources.dll"
    del WpfRibbonApplication1.Strings.fr.resources
    pause
    

    Be sure to keep the original namespace in the file names (here "WpfRibbonApplication1")

    0 讨论(0)
  • 2020-11-22 03:07

    A fix and elaboration of @Fredrik Mörk answer.

    • Add a strings.resx Resource file to your project (or a different filename)
    • Set Access Modifier to Public (in the opened strings.resx file tab)
    • Add a string resouce in the resx file: (example: name Hello, value Hello)
    • Save the resource file

    Visual Studio auto-generates a respective strings class, which is actually placed in strings.Designer.cs. The class is in the same namespace that you would expect a newly created .cs file to be placed in.

    This code always prints Hello, because this is the default resource and no language-specific resources are available:

    Console.WriteLine(strings.Hello);
    

    Now add a new language-specific resource:

    • Add strings.fr.resx (for French)
    • Add a string with the same name as previously, but different value: (name Hello, value Salut)

    The following code prints Salut:

    Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("fr-FR");
    Console.WriteLine(strings.Hello);
    

    What resource is used depends on Thread.CurrentThread.CurrentUICulture. It is set depending on Windows UI language setting, or can be set manually like in this example. Learn more about this here.

    You can add country-specific resources like strings.fr-FR.resx or strings.fr-CA.resx.

    The string to be used is determined in this priority order:

    • From country-specific resource like strings.fr-CA.resx
    • From language-specific resource like strings.fr.resx
    • From default strings.resx

    Note that language-specific resources generate satellite assemblies.

    Also learn how CurrentCulture differs from CurrentUICulture here.

    0 讨论(0)
  • 2020-11-22 03:12

    ResourceManager and .resx are bit messy.

    You could use Lexical.Localization¹ which allows embedding default value and culture specific values into the code, and be expanded in external localization files for futher cultures (like .json or .resx).

    public class MyClass
    {
        /// <summary>
        /// Localization root for this class.
        /// </summary>
        static ILine localization = LineRoot.Global.Type<MyClass>();
    
        /// <summary>
        /// Localization key "Ok" with a default string, and couple of inlined strings for two cultures.
        /// </summary>
        static ILine ok = localization.Key("Success")
                .Text("Success")
                .fi("Onnistui")
                .sv("Det funkar");
    
        /// <summary>
        /// Localization key "Error" with a default string, and couple of inlined ones for two cultures.
        /// </summary>
        static ILine error = localization.Key("Error")
                .Format("Error (Code=0x{0:X8})")
                .fi("Virhe (Koodi=0x{0:X8})")
                .sv("Sönder (Kod=0x{0:X8})");
    
        public void DoOk()
        {
            Console.WriteLine( ok );
        }
    
        public void DoError()
        {
            Console.WriteLine( error.Value(0x100) );
        }
    }
    

    ¹ (I'm maintainer of that library)

    0 讨论(0)
  • 2020-11-22 03:16

    In my case

    [assembly: System.Resources.NeutralResourcesLanguage("ru-RU")]
    

    in the AssemblyInfo.cs prevented things to work as usual.

    0 讨论(0)
  • 2020-11-22 03:19

    In addition @Fredrik Mörk's great answer on strings, to add localization to a form do the following:

    • Set the form's property "Localizable" to true
    • Change the form's Language property to the language you want (from a nice drop-down with them all in)
    • Translate the controls in that form and move them about if need be (squash those really long full French sentences in!)

    Edit: This MSDN article on Localizing Windows Forms is not the original one I linked ... but might shed more light if needed. (the old one has been taken away)

    0 讨论(0)
  • 2020-11-22 03:22

    In addition to @Eric Bole-Feysot answer:

    Thanks to satellite assemblies, localization can be created based on .dll/.exe files. This way:

    • source code (VS project) could be separated from language project,
    • adding a new language does not require recompiling the project,
    • translation could be made even by the end-user.

    There is a little known tool called LSACreator (free for non-commercial use or buy option) which allows you to create localization based on .dll/.exe files. In fact, internally (in language project's directory) it creates/manages localized versions of resx files and compiles an assembly in similar way as @Eric Bole-Feysot described.

    0 讨论(0)
提交回复
热议问题