Cómo usar la localización en C #

268

Parece que no puedo conseguir que la localización funcione.

Tengo una biblioteca de clase. Ahora quiero crear archivos resx allí y devolver algunos valores basados ​​en la cultura del hilo.

¿Cómo puedo hacer eso?

JL
fuente
PD: asegúrese de haber instalado la extensión gratuita Microsoft MAT (Multilingual App Toolkit) para Visual Studio ;-)
juFo

Respuestas:

571
  • Agregue un archivo de recursos a su proyecto (puede llamarlo "strings.resx") haciendo lo siguiente:
    Haga clic con el botón derecho en Propiedades en el proyecto, seleccione Agregar -> Nuevo elemento ... en el menú contextual, luego en la lista de Los elementos de Visual C # seleccionan "Archivo de recursos" y lo nombran strings.resx.
  • Agregue un recurso de cadena en el archivo resx y asígnele un buen nombre (ejemplo: asígnele el nombre "Hola" y dele el valor "Hola")
  • Guarde el archivo de recursos ( nota: este será el archivo de recursos predeterminado , ya que no tiene un código de idioma de dos letras)
  • Agregue referencias a su programa: System.ThreadingySystem.Globalization

Ejecute este código:

Console.WriteLine(Properties.strings.Hello);

Debería imprimir "Hola".

Ahora, agregue un nuevo archivo de recursos, llamado "strings.fr.resx" (tenga en cuenta la parte "fr"; este contendrá recursos en francés). Agregue un recurso de cadena con el mismo nombre que en strings.resx, pero con el valor en francés (Name = "Hello", Value = "Salut"). Ahora, si ejecuta el siguiente código, debería imprimir Salut:

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

Lo que sucede es que el sistema buscará un recurso para "fr-FR". No encontrará uno (ya que especificamos "fr" en su archivo "). Luego volverá a buscar" fr ", que encuentra (y usa).

El siguiente código imprimirá "Hola":

Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-US");
Console.WriteLine(Properties.strings.Hello);

Esto se debe a que no encuentra ningún recurso "en-US" y tampoco un recurso "en", por lo que volverá al valor predeterminado, que es el que agregamos desde el principio.

Puede crear archivos con recursos más específicos si es necesario (por ejemplo, strings.fr-FR.resx y strings.fr-CA.resx para francés en Francia y Canadá, respectivamente). En cada uno de estos archivos deberá agregar los recursos para aquellas cadenas que difieren del recurso al que recurriría. Entonces, si un texto es el mismo en Francia y Canadá, puede ponerlo en strings.fr.resx, mientras que las cadenas que son diferentes en francés canadiense podrían ir a strings.fr-CA.resx.

Fredrik Mörk
fuente
24
La respuesta podría hacer referencia a la fontanería "detrás de escena" que está haciendo Visual Studio aquí: archivo resx.designer.cs, haciendo que el intellisense funcione; ensamblajes satelitales compilados con la biblioteca de clases, que deben implementarse con el ensamblaje compilado y cualquier proyecto posterior que lo use, etc. No usas Visual Studio.
Tao
13
¡+1 publicación! En lugar de crear archivos manualmente, pruebe el Editor de recursos de Zeta ( zeta-resource-editor.com/index.html ). Es gratis y te ayuda a hacer este tipo de traducciones MUCHO más rápido que solo en VS.
Killnine
44
Access Modifierdebe establecerse Publicpara que se genere la clase de recurso. La clase no está necesariamente en el espacio de nombres de Propiedades, es donde coloca el archivo .resx.
Andrey Moiseev
3
Tenga en cuenta que en VS 2017 resx con localización en winform no funciona debido a un error (al menos hasta la versión 15.4). Un boleto está disponible: developercommunity.visualstudio.com/content/problem/63772/…
muccix
44
A partir de .NET 4.5 también es posible usar System.Globalization.CultureInfo.DefaultThreadCurrentCulture en lugar de Thread.CurrentThread.CurrentUICulture para que cambie la configuración regional de toda la aplicación en lugar de hilo por hilo
GrixM
41

Es bastante simple, en realidad. Cree un nuevo archivo de recursos, por ejemplo Strings.resx. Establecer Access Modifiera Public. Use la plantilla de archivo adecuada, de modo que Visual Studio generará automáticamente una clase de acceso (el nombre será Strings, en este caso). Este es tu idioma predeterminado.

Ahora, cuando desee agregar, digamos, localización alemana, agregue un archivo resx localizado. Esto será típicamente Strings.de.resxen este caso. Si desea agregar localización adicional para, por ejemplo, Austria, también creará un Strings.de-AT.resx.

Ahora ve a crear una cadena, digamos una cadena con el nombre HelloWorld. En su Strings.resx, agregue esta cadena con el valor "¡Hola, mundo!". En Strings.de.resx, agregue "Hola, Welt!". Y en Strings.de-AT.resx, agregue "Servus, Welt!". Eso es todo hasta ahora.

Ahora tiene esta Stringsclase generada , y tiene una propiedad con un captador HelloWorld. Obtener esta propiedad cargará "Servus, Welt!" cuando su configuración regional es de-AT, "¡Hola, Welt! cuando su configuración regional es cualquier otra configuración regional (incluyendo de-DE y de-CH), y" ¡Hola, Mundo! "cuando su configuración regional es cualquier otra cosa. Si una cadena es falta en la versión localizada, el administrador de recursos subirá automáticamente por la cadena, desde el recurso más especializado hasta el invariante.

Puede usar la ResourceManagerclase para tener más control sobre cómo carga exactamente las cosas. La Stringsclase generada también lo usa.

OregonGhost
fuente
¿Cómo establecer la configuración regional?
Matheus Simon
1
@MatheusSimon: No es necesario. De manera predeterminada, se usa la configuración regional actual del usuario. Si desea forzar una determinada configuración regional (por ejemplo, para permitir que los usuarios cambien el idioma manualmente), debe configurar System.Threading.Thread.CurrentCulture y CurrentUICulture en cada hilo , probablemente antes de que se carguen recursos por primera vez. Es más fácil reiniciar una aplicación para esto en lugar de actualizar en tiempo de ejecución.
OregonGhost
15

Además, la gran respuesta de @Fredrik Mörk sobre cadenas, para agregar localización a un formulario, haga lo siguiente:

  • Establezca la propiedad del formulario"Localizable" entrue
  • Cambie la Languagepropiedad del formulario al idioma que desee (de un buen menú desplegable con todos ellos)
  • Traduce los controles de esa forma y muévelos si es necesario (¡aplasta esas oraciones en francés realmente largas!)

Editar: este artículo de MSDN sobre Localización de formularios de Windows no es el original que vinculé ... pero podría arrojar más luz si es necesario. (el viejo ha sido quitado)

noelicus
fuente
El artículo msdn ya no está disponible, ¿algún reemplazo?
fuomag9
No estoy seguro: he vinculado el mejor que pude ver, pero no recuerdo cómo era el artículo hace 7 años;)
noelicus
14

Gran respuesta de F.Mörk. Pero si desea actualizar la traducción o agregar nuevos idiomas una vez que se lanza la aplicación, está atascado, porque siempre tiene que volver a compilarlo para generar resources.dll.

Aquí hay una solución para compilar manualmente un recurso dll. Utiliza las herramientas resgen.exe y al.exe (instaladas con el sdk).

Supongamos que tiene un archivo de recursos Strings.fr.resx, puede compilar un archivo dll de recursos con el siguiente lote:

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

Asegúrese de mantener el espacio de nombres original en los nombres de archivo (aquí "WpfRibbonApplication1")

Eric Bole-Feysot
fuente
2
Gracias por el comentario sobre la preservación del espacio de nombres (y) que, si se omite, no generará ningún error, sino que simplemente volverá al recurso de reserva.
Mosca Pt
11

Una solución y elaboración de la respuesta de @Fredrik Mörk .

  • Agregue un strings.resxarchivo de recursos a su proyecto (o un nombre de archivo diferente)
  • Establecer Access Modifieren Public(en la strings.resxpestaña del archivo abierto )
  • Agregue un recurso de cadena en el archivo resx: (ejemplo: nombre Hello, valor Hello)
  • Guarde el archivo de recursos

Visual Studio genera automáticamente una stringsclase respectiva , que en realidad se coloca en strings.Designer.cs. La clase está en el mismo espacio de nombres en el que esperaría .csque se coloque un archivo recién creado .

Este código siempre se imprime Hello, porque este es el recurso predeterminado y no hay recursos específicos del idioma disponibles:

Console.WriteLine(strings.Hello);

Ahora agregue un nuevo recurso específico del idioma:

  • Agregar strings.fr.resx(para francés)
  • Agregue una cadena con el mismo nombre que antes, pero con un valor diferente: (nombre Hello, valor Salut)

Se imprime el siguiente código Salut:

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

De qué recurso se utiliza depende Thread.CurrentThread.CurrentUICulture. Se establece según la configuración del idioma de la interfaz de usuario de Windows, o se puede configurar manualmente como en este ejemplo. Obtenga más información sobre esto aquí .

Puede agregar recursos específicos de país como strings.fr-FR.resxo strings.fr-CA.resx.

La cadena que se utilizará se determina en este orden de prioridad:

  • De un recurso específico del país como strings.fr-CA.resx
  • Del recurso específico del idioma como strings.fr.resx
  • Por defecto strings.resx

Tenga en cuenta que los recursos específicos del idioma generan conjuntos de satélites .

Aprenda también cómo CurrentCulturedifiere de CurrentUICulture aquí .

Andrey Moiseev
fuente
1

En mi caso

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

en el AssemblyInfo.cs impidió que las cosas funcionen como de costumbre.

Aleksandr
fuente
0

Además de la respuesta @Eric Bole-Feysot :

Gracias a los ensambles satelitales, la localización se puede crear en base a archivos .dll / .exe . De esta manera:

  • el código fuente (proyecto VS) podría separarse del proyecto de lenguaje,
  • agregar un nuevo idioma no requiere volver a compilar el proyecto,
  • la traducción puede ser realizada incluso por el usuario final.

Existe una herramienta poco conocida llamada LSACreator (gratuita para uso no comercial u opción de compra) que le permite crear localización basada en archivos .dll / .exe. De hecho, internamente (en el directorio del proyecto de lenguaje) crea / administra versiones localizadas de archivos resx y compila un ensamblaje de manera similar a como lo describe @Eric Bole-Feysot .

Tomasz Malik
fuente
0

ResourceManager y .resx son un poco desordenados.

Puede usar Lexical.Localization ¹, que permite incrustar valores predeterminados y valores específicos de cultura en el código, y expandirse en archivos de localización externos para otras culturas (como .json o .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) );
    }
}

¹ (Soy el encargado de mantener esa biblioteca)

Etiqueta
fuente
0

En general, coloca sus traducciones en archivos de recursos, por ejemplo resources.resx.

Cada cultura específica tiene un nombre diferente, por ejemplo, resources.nl.resx, resources.fr.resx, resources.de.resx, ...

Ahora la parte más importante de una solución es mantener sus traducciones. En Visual Studio, instale la herramienta MAT de Microsoft: Kit de herramientas de aplicación multilingüe (MAT). Funciona con winforms, wpf, asp.net (core), uwp, ...

En general, por ejemplo, para una solución WPF, en el proyecto WPF

  • Instale la extensión Microsoft MAT para Visual Studio.
  • En el Explorador de soluciones, navegue hasta su Proyecto> Propiedades> AssemblyInfo.cs
  • Agregue en AssemblyInfo.cs su idioma predeterminado y neutral (en mi caso, inglés): [assembly: System.Resources.NeutralResourcesLanguage("en")]
  • Seleccione su proyecto en el Explorador de soluciones y en Visual Studio, en el menú superior, haga clic en "Herramientas"> "Kit de herramientas de aplicación multilingüe"> "Habilitar selección", para habilitar MAT para el proyecto.
    • Ahora haga clic con el botón derecho del mouse en el proyecto en el Explorador de soluciones, seleccione "Kit de herramientas de aplicación multilingüe"> "Agregar idiomas de traducción ..." y seleccione el idioma para el que desea agregar traducciones. Por ejemplo, holandés.

Lo que verá es que se creará una nueva carpeta, llamada "Recursos multilingües" que contiene un ....nl.xlfarchivo.

Lo único que tienes que hacer ahora es:

  1. agregue su traducción a su archivo resources.resx predeterminado (en mi caso, inglés)
  2. Traduzca haciendo clic en el archivo .xlf (NO en el archivo .resx) ya que los archivos .xlf generarán / actualizarán los archivos .resx.

(los archivos .xlf deben abrirse con el "Editor multilingüe"; si este no es el caso, haga clic con el botón derecho en el archivo .xlf, seleccione "Abrir con ..." y seleccione "Editor multilingüe".

¡Que te diviertas! ahora también puede ver lo que no se ha traducido, exportar traducciones en xlf a empresas de traducción externas, importarlas nuevamente, reciclar traducciones de otros proyectos, etc.

Más información:

juFo
fuente