Compartir a través de


Recuperación de recursos en aplicaciones .NET

Al trabajar con recursos localizados en aplicaciones .NET, lo ideal es empaquetar los recursos para la referencia cultural predeterminada o neutral con el ensamblado principal y crear un ensamblado satélite independiente para cada idioma o referencia cultural que admita la aplicación. A continuación, puede usar la ResourceManager clase como se describe en la sección siguiente para acceder a los recursos con nombre. Si decide no insertar los recursos en el ensamblado principal y los ensamblados satélite, también puede acceder directamente a los archivos .resources binarios, como se describe en la sección Recuperación de recursos de archivos .resources más adelante en este artículo.

Recuperación de recursos de ensamblados

La ResourceManager clase proporciona acceso a los recursos en tiempo de ejecución. Use el ResourceManager.GetString método para recuperar recursos de cadena y el ResourceManager.GetObject método o ResourceManager.GetStream para recuperar recursos que no son de cadena. Cada método tiene dos sobrecargas:

El Administrador de recursos usa el proceso de reserva de recursos para controlar la forma en que la aplicación recupera los recursos específicos de referencia cultural. Para obtener más información, consulte la sección "Proceso de reserva de recursos" en Empaquetar e implementar recursos. Para obtener información sobre cómo crear instancias de un ResourceManager objeto, vea la sección "Creación de instancias de un objeto ResourceManager" en el tema de la ResourceManager clase.

Ejemplo de recuperación de datos de cadena

En el ejemplo siguiente se llama al método GetString(String) para recuperar los recursos de cadena de la referencia cultural de interfaz de usuario actual. Incluye un recurso de cadena neutral para la cultura inglesa (Estados Unidos) y recursos localizados para las culturas francesa (Francia) y rusa (Rusia). El siguiente recurso inglés (Estados Unidos) está en un archivo denominado Strings.txt:

TimeHeader=The current time is

El recurso francés (Francia) está en un archivo denominado Strings.fr-FR.txt:

TimeHeader=L'heure actuelle est

El recurso ruso (Rusia) está en un archivo denominado Strings.ru-RU.txt:

TimeHeader=Текущее время —

El código fuente de este ejemplo, que se encuentra en un archivo denominado GetString.cs para la versión de C# del código y GetString.vb para la versión de Visual Basic, define una matriz de cadenas que contiene el nombre de cuatro referencias culturales: las tres referencias culturales para las que están disponibles los recursos y la referencia cultural española (España). Un bucle que se ejecuta cinco veces selecciona aleatoriamente una de estas referencias culturales y la asigna a las propiedades Thread.CurrentCulture y CultureInfo.CurrentUICulture. A continuación, llama al GetString(String) método para recuperar la cadena localizada, que se muestra junto con la hora del día.

using System;
using System.Globalization;
using System.Resources;
using System.Threading;

[assembly: NeutralResourcesLanguageAttribute("en-US")]

public class Example
{
   public static void Main()
   {
      string[] cultureNames = { "en-US", "fr-FR", "ru-RU", "es-ES" };
      Random rnd = new Random();
      ResourceManager rm = new ResourceManager("Strings",
                               typeof(Example).Assembly);

      for (int ctr = 0; ctr <= cultureNames.Length; ctr++) {
         string cultureName = cultureNames[rnd.Next(0, cultureNames.Length)];
         CultureInfo culture = CultureInfo.CreateSpecificCulture(cultureName);
         Thread.CurrentThread.CurrentCulture = culture;
         Thread.CurrentThread.CurrentUICulture = culture;

         Console.WriteLine($"Current culture: {culture.NativeName}");
         string timeString = rm.GetString("TimeHeader");
         Console.WriteLine($"{timeString} {DateTime.Now:T}\n");
      }
   }
}
// The example displays output like the following:
//    Current culture: English (United States)
//    The current time is 9:34:18 AM
//
//    Current culture: Español (España, alfabetización internacional)
//    The current time is 9:34:18
//
//    Current culture: русский (Россия)
//    Текущее время — 9:34:18
//
//    Current culture: français (France)
//    L'heure actuelle est 09:34:18
//
//    Current culture: русский (Россия)
//    Текущее время — 9:34:18
Imports System.Globalization
Imports System.Resources
Imports System.Threading

<Assembly: NeutralResourcesLanguageAttribute("en-US")>

Module Example
    Public Sub Main()
        Dim cultureNames() As String = {"en-US", "fr-FR", "ru-RU", "es-ES"}
        Dim rnd As New Random()
        Dim rm As New ResourceManager("Strings", GetType(Example).Assembly)

        For ctr As Integer = 0 To cultureNames.Length
            Dim cultureName As String = cultureNames(rnd.Next(0, cultureNames.Length))
            Dim culture As CultureInfo = CultureInfo.CreateSpecificCulture(cultureName)
            Thread.CurrentThread.CurrentCulture = culture
            Thread.CurrentThread.CurrentUICulture = culture

            Console.WriteLine("Current culture: {0}", culture.NativeName)
            Dim timeString As String = rm.GetString("TimeHeader")
            Console.WriteLine("{0} {1:T}", timeString, Date.Now)
            Console.WriteLine()
        Next
    End Sub
End Module
' The example displays output similar to the following:
'    Current culture: English (United States)
'    The current time is 9:34:18 AM
'    
'    Current culture: Español (España, alfabetización internacional)
'    The current time is 9:34:18
'    
'    Current culture: русский (Россия)
'    Текущее время — 9:34:18
'    
'    Current culture: français (France)
'    L'heure actuelle est 09:34:18
'    
'    Current culture: русский (Россия)
'    Текущее время — 9:34:18

El siguiente archivo por lotes (.bat) compila el ejemplo y genera ensamblados satélite en los directorios adecuados. Los comandos se proporcionan para el compilador y el lenguaje C#. Para Visual Basic, cambie csc a vbc, y cambie GetString.cs a GetString.vb.

resgen strings.txt
csc GetString.cs -resource:strings.resources

resgen strings.fr-FR.txt
md fr-FR
al -embed:strings.fr-FR.resources -culture:fr-FR -out:fr-FR\GetString.resources.dll

resgen strings.ru-RU.txt
md ru-RU
al -embed:strings.ru-RU.resources -culture:ru-RU -out:ru-RU\GetString.resources.dll

Cuando la referencia cultural actual de la interfaz de usuario es español (España), tenga en cuenta que en el ejemplo se muestran los recursos de idioma inglés, ya que los recursos de idioma español no están disponibles y el inglés es la referencia cultural predeterminada del ejemplo.

Recuperar ejemplos de datos de objetos

Puede usar los GetObject métodos y GetStream para recuperar datos de objeto. Esto incluye tipos de datos primitivos, objetos serializables y objetos que se almacenan en formato binario (como imágenes).

En el ejemplo siguiente se usa el GetStream(String) método para recuperar un mapa de bits que se usa en la ventana de presentación de apertura de una aplicación. El siguiente código fuente de un archivo denominado CreateResources.cs (para C#) o CreateResources.vb (para Visual Basic) genera un archivo .resx que contiene la imagen serializada. En este caso, la imagen se carga desde un archivo denominado SplashScreen.jpg; Puede modificar el nombre de archivo para sustituir su propia imagen.

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Resources;

public class Example
{
   public static void Main()
   {
      Bitmap bmp = new Bitmap(@".\SplashScreen.jpg");
      MemoryStream imageStream = new MemoryStream();
      bmp.Save(imageStream, ImageFormat.Jpeg);

      ResXResourceWriter writer = new ResXResourceWriter("AppResources.resx");
      writer.AddResource("SplashScreen", imageStream);
      writer.Generate();
      writer.Close();
   }
}
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.IO
Imports System.Resources

Module Example
    Public Sub Main()
        Dim bmp As New Bitmap(".\SplashScreen.jpg")
        Dim imageStream As New MemoryStream()
        bmp.Save(imageStream, ImageFormat.Jpeg)

        Dim writer As New ResXResourceWriter("AppResources.resx")
        writer.AddResource("SplashScreen", imageStream)
        writer.Generate()
        writer.Close()
    End Sub
End Module

El código siguiente recupera el recurso y muestra la imagen en un PictureBox control .

using System;
using System.Drawing;
using System.IO;
using System.Resources;
using System.Windows.Forms;

public class Example
{
   public static void Main()
   {
      ResourceManager rm = new ResourceManager("AppResources", typeof(Example).Assembly);
      Bitmap screen = (Bitmap) Image.FromStream(rm.GetStream("SplashScreen"));

      Form frm = new Form();
      frm.Size = new Size(300, 300);

      PictureBox pic = new PictureBox();
      pic.Bounds = frm.RestoreBounds;
      pic.BorderStyle = BorderStyle.Fixed3D;
      pic.Image = screen;
      pic.SizeMode = PictureBoxSizeMode.StretchImage;

      frm.Controls.Add(pic);
      pic.Anchor = AnchorStyles.Top | AnchorStyles.Bottom |
                   AnchorStyles.Left | AnchorStyles.Right;

      frm.ShowDialog();
   }
}
Imports System.Drawing
Imports System.IO
Imports System.Resources
Imports System.Windows.Forms

Module Example
    Public Sub Main()
        Dim rm As New ResourceManager("AppResources", GetType(Example).Assembly)
        Dim screen As Bitmap = CType(Image.FromStream(rm.GetStream("SplashScreen")), Bitmap)

        Dim frm As New Form()
        frm.Size = new Size(300, 300)

        Dim pic As New PictureBox()
        pic.Bounds = frm.RestoreBounds
        pic.BorderStyle = BorderStyle.Fixed3D
        pic.Image = screen
        pic.SizeMode = PictureBoxSizeMode.StretchImage

        frm.Controls.Add(pic)
        pic.Anchor = AnchorStyles.Top Or AnchorStyles.Bottom Or
                     AnchorStyles.Left Or AnchorStyles.Right

        frm.ShowDialog()
    End Sub
End Module

Puede usar el siguiente archivo por lotes para compilar el ejemplo de C#. Para Visual Basic, cambie csc a vbc, y cambie la extensión del archivo de código fuente de .cs a .vb.

csc CreateResources.cs
CreateResources

resgen AppResources.resx

csc GetStream.cs -resource:AppResources.resources

En el ejemplo siguiente se usa el ResourceManager.GetObject(String) método para deserializar un objeto personalizado. En el ejemplo se incluye un archivo de código fuente denominado UIElements.cs (UIElements.vb para Visual Basic) que define la siguiente estructura denominada PersonTable. Esta estructura está pensada para ser utilizada por una rutina de visualización de tabla general que muestra los nombres localizados de las columnas de tabla. Tenga en cuenta que la PersonTable estructura está marcada con el SerializableAttribute atributo .

using System;

[Serializable] public struct PersonTable
{
   public readonly int nColumns;
   public readonly string column1;
   public readonly string column2;
   public readonly string column3;
   public readonly int width1;
   public readonly int width2;
   public readonly int width3;

   public PersonTable(string column1, string column2, string column3,
                  int width1, int width2, int width3)
   {
      this.column1 = column1;
      this.column2 = column2;
      this.column3 = column3;
      this.width1 = width1;
      this.width2 = width2;
      this.width3 = width3;
      this.nColumns = typeof(PersonTable).GetFields().Length / 2;
   }
}
<Serializable> Public Structure PersonTable
    Public ReadOnly nColumns As Integer
    Public Readonly column1 As String
    Public ReadOnly column2 As String
    Public ReadOnly column3 As String
    Public ReadOnly width1 As Integer
    Public ReadOnly width2 As Integer
    Public ReadOnly width3 As Integer

    Public Sub New(column1 As String, column2 As String, column3 As String,
                   width1 As Integer, width2 As Integer, width3 As Integer)
        Me.column1 = column1
        Me.column2 = column2
        Me.column3 = column3
        Me.width1 = width1
        Me.width2 = width2
        Me.width3 = width3
        Me.nColumns = Me.GetType().GetFields().Count \ 2
    End Sub
End Structure

El código siguiente de un archivo denominado CreateResources.cs (CreateResources.vb para Visual Basic) crea un archivo de recursos XML denominado UIResources.resx que almacena un título de tabla y un PersonTable objeto que contiene información para una aplicación localizada para el idioma inglés.

using System;
using System.Resources;

public class CreateResource
{
   public static void Main()
   {
      PersonTable table = new PersonTable("Name", "Employee Number",
                                          "Age", 30, 18, 5);
      ResXResourceWriter rr = new ResXResourceWriter(@".\UIResources.resx");
      rr.AddResource("TableName", "Employees of Acme Corporation");
      rr.AddResource("Employees", table);
      rr.Generate();
      rr.Close();
   }
}
Imports System.Resources

Module CreateResource
    Public Sub Main()
        Dim table As New PersonTable("Name", "Employee Number", "Age", 30, 18, 5)
        Dim rr As New ResXResourceWriter(".\UIResources.resx")
        rr.AddResource("TableName", "Employees of Acme Corporation")
        rr.AddResource("Employees", table)
        rr.Generate()
        rr.Close()
    End Sub
End Module

El código siguiente de un archivo de código fuente denominado GetObject.cs (GetObject.vb) recupera los recursos y los muestra en la consola.

using System;
using System.Resources;

[assembly: NeutralResourcesLanguageAttribute("en")]

public class Example
{
   public static void Main()
   {
      string fmtString = String.Empty;
      ResourceManager rm = new ResourceManager("UIResources", typeof(Example).Assembly);
      string title = rm.GetString("TableName");
      PersonTable tableInfo = (PersonTable) rm.GetObject("Employees");

      if (! String.IsNullOrEmpty(title)) {
         fmtString = "{0," + ((Console.WindowWidth + title.Length) / 2).ToString() + "}";
         Console.WriteLine(fmtString, title);
         Console.WriteLine();
      }

      for (int ctr = 1; ctr <= tableInfo.nColumns; ctr++) {
         string columnName = "column"  + ctr.ToString();
         string widthName = "width" + ctr.ToString();
         string value = tableInfo.GetType().GetField(columnName).GetValue(tableInfo).ToString();
         int width = (int) tableInfo.GetType().GetField(widthName).GetValue(tableInfo);
         fmtString = "{0,-" + width.ToString() + "}";
         Console.Write(fmtString, value);
      }
      Console.WriteLine();
   }
}
Imports System.Resources

<Assembly: NeutralResourcesLanguageAttribute("en")>

Module Example
    Public Sub Main()
        Dim fmtString As String = String.Empty
        Dim rm As New ResourceManager("UIResources", GetType(Example).Assembly)
        Dim title As String = rm.GetString("TableName")
        Dim tableInfo As PersonTable = DirectCast(rm.GetObject("Employees"), PersonTable)

        If Not String.IsNullOrEmpty(title) Then
            fmtString = "{0," + ((Console.WindowWidth + title.Length) \ 2).ToString() + "}"
            Console.WriteLine(fmtString, title)
            Console.WriteLine()
        End If

        For ctr As Integer = 1 To tableInfo.nColumns
            Dim columnName As String = "column" + ctr.ToString()
            Dim widthName As String = "width" + ctr.ToString()
            Dim value As String = CStr(tableInfo.GetType().GetField(columnName).GetValue(tableInfo))
            Dim width As Integer = CInt(tableInfo.GetType().GetField(widthName).GetValue(tableInfo))
            fmtString = "{0,-" + width.ToString() + "}"
            Console.Write(fmtString, value)
        Next
        Console.WriteLine()
    End Sub
End Module

Puede compilar el archivo de recursos y los ensamblados necesarios y ejecutar la aplicación ejecutando el siguiente archivo por lotes. Debe usar la /r opción para proporcionar Resgen.exe con una referencia a UIElements.dll para que pueda acceder a información sobre la PersonTable estructura. Si usa C#, reemplace el nombre del vbc compilador por cscy reemplace la .vb extensión por .cs.

vbc -t:library UIElements.vb
vbc CreateResources.vb -r:UIElements.dll
CreateResources

resgen UIResources.resx  -r:UIElements.dll
vbc GetObject.vb -r:UIElements.dll -resource:UIResources.resources

GetObject.exe

Compatibilidad de versiones de los ensamblados satélite

De forma predeterminada, cuando el ResourceManager objeto recupera los recursos solicitados, busca ensamblados satélite que tienen números de versión que coinciden con el número de versión del ensamblado principal. Después de implementar una aplicación, es posible que quiera actualizar el ensamblaje principal o los ensamblajes satélite de recursos específicos. .NET Framework proporciona compatibilidad con el control de versiones del ensamblado principal y los ensamblados satélite.

El SatelliteContractVersionAttribute atributo proporciona compatibilidad de control de versiones para un ensamblado principal. Especificar este atributo en el ensamblado principal de una aplicación permite actualizar y volver a implementar un ensamblado principal sin actualizar sus ensamblados satélite. Después de actualizar el ensamblado principal, incremente el número de versión del ensamblado principal, pero deje sin cambios el número de versión del contrato satélite. Cuando el administrador de recursos recupera los recursos solicitados, carga la versión del ensamblado satélite especificada por este atributo.

Los ensamblados de directiva de edición ofrecen compatibilidad de las versiones de los ensamblados satélite. Puede actualizar y volver a implementar un ensamblado satélite sin actualizar el ensamblado principal. Después de actualizar un ensamblado satélite, incremente su número de versión y distribúyalo con un ensamblado de directiva de edición. En el ensamblado de directiva de edición, especifique que el nuevo ensamblado satélite es compatible con su versión anterior. El administrador de recursos usará el atributo SatelliteContractVersionAttribute para determinar la versión del ensamblaje satélite, pero el cargador de ensamblajes se enlazará a la versión del ensamblaje satélite especificada por la política del editor. Para obtener más información sobre los ensamblados de directiva de edición, consulte Creación de un archivo de directiva de edición.

Para habilitar la compatibilidad completa de versiones de ensamblados, se recomienda implementar ensamblados con nombres seguros en la caché global de ensamblados e implementar los ensamblados que no tengan nombres seguros en el directorio de la aplicación. Si quiere implementar ensamblados con nombres seguros en el directorio de la aplicación, no podrá aumentar el número de versión de un ensamblado satélite al actualizar el ensamblado. En su lugar, debe realizar una actualización local donde reemplace el código existente por el código actualizado y mantenga el mismo número de versión. Por ejemplo, si desea actualizar la versión 1.0.0.0 de un ensamblado satélite con el nombre de ensamblado completamente especificado "myApp.resources, Version=1.0.0.0, Culture=de, PublicKeyToken=b03f5f11d50a3a", sobrescribirlo con el myApp.resources.dll actualizado que se ha compilado con el mismo nombre de ensamblado totalmente especificado "myApp.resources, Version=1.0.0.0, Culture=de, PublicKeyToken=b03f5f11d50a3a". Tenga en cuenta que el uso de actualizaciones en contexto en archivos de ensamblado satélite dificulta que una aplicación determine con precisión la versión de un ensamblado satélite.

Para obtener más información sobre el versionado de ensamblado, consulte Versionado de ensamblados y Cómo el runtime localiza ensamblados.

Recuperar recursos de archivos .resources

Si decide no desplegar recursos en ensamblados satélite, puede seguir usando un objeto ResourceManager para acceder a los recursos de los archivos .resources directamente. Para ello, debe implementar los archivos .resources correctamente. A continuación, use el ResourceManager.CreateFileBasedResourceManager método para crear una instancia de un ResourceManager objeto y especifique el directorio que contiene los archivos .resources independientes.

Despliegue de archivos .resources

Al insertar archivos .resources en un ensamblado de aplicación y ensamblados satélite, cada ensamblado satélite tiene el mismo nombre de archivo, pero se coloca en un subdirectorio que refleja la referencia cultural del ensamblado satélite. En cambio, cuando se accede directamente a los recursos desde archivos .resources, puede colocar todos los archivos .resources en un único directorio, normalmente un subdirectorio del directorio de la aplicación. El nombre del archivo .resources predeterminado de la aplicación consta solo de un nombre raíz, sin indicación de su referencia cultural (por ejemplo, strings.resources). Los recursos de cada referencia cultural localizada se almacenan en un archivo cuyo nombre consta del nombre raíz seguido de la referencia cultural (por ejemplo, strings.ja.resources o cadenas.de-DE.resources).

En la ilustración siguiente se muestra dónde deben encontrarse los archivos de recursos en la estructura de directorios. También proporciona las convenciones de nomenclatura para los archivos .resource.

Ilustración que muestra el directorio principal de la aplicación.

Uso del administrador de recursos

Después de crear los recursos y colocarlos en el directorio adecuado, cree un ResourceManager objeto para usar los recursos llamando al CreateFileBasedResourceManager(String, String, Type) método . El primer parámetro especifica el nombre raíz del archivo .resources predeterminado de la aplicación (esto sería "cadenas" para el ejemplo de la sección anterior). El segundo parámetro especifica la ubicación de los recursos ("Resources" para el ejemplo anterior). El tercer parámetro especifica la ResourceSet implementación que se va a usar. Si el tercer parámetro es null, se usa el entorno de ejecución ResourceSet predeterminado.

Nota:

No implemente ASP.NET aplicaciones con archivos .resources independientes. Esto puede provocar problemas de bloqueo y interrumpir la implementación de XCOPY. Se recomienda que implemente los recursos de ASP.NET en ensamblados satélite. Para obtener más información, consulte ASP.NET Información general sobre los recursos de página web.

Después de crear una instancia del ResourceManager objeto, use los GetStringmétodos , GetObjecty GetStream como se explicó anteriormente para recuperar los recursos. Sin embargo, la recuperación de recursos directamente desde archivos .resources difiere de la recuperación de recursos incrustados desde los ensamblados. Al recuperar recursos de archivos .resources, los métodos GetString(String), GetObject(String) y GetStream(String) siempre recuperan los recursos de la cultura predeterminada independientemente de la cultura actual. Para recuperar los recursos de la cultura actual de la aplicación o de una cultura específica, debe llamar al método GetString(String, CultureInfo), GetObject(String, CultureInfo) o GetStream(String, CultureInfo), y especificar la cultura cuyos recursos se van a recuperar. Para recuperar los recursos de la referencia cultural actual, especifique el valor de la propiedad CultureInfo.CurrentCulture como argumento culture . Si el administrador de recursos no puede recuperar los recursos de culture, usa las reglas de reserva de recursos estándar para recuperar los recursos adecuados.

Un ejemplo

En el ejemplo siguiente se muestra cómo el administrador de recursos recupera los recursos directamente de los archivos .resources. El ejemplo consta de tres archivos de recursos basados en texto para las culturas inglesa (Estados Unidos), francesa (Francia) y rusa (Rusia). Inglés (Estados Unidos) es la referencia cultural predeterminada del ejemplo. Sus recursos se almacenan en el siguiente archivo denominado Strings.txt:

Greeting=Hello
Prompt=What is your name?

Los recursos para la cultura francesa (Francia) se almacenan en el siguiente archivo, que se denomina Strings.fr-FR.txt:

Greeting=Bon jour
Prompt=Comment vous appelez-vous?

Los recursos para la cultura rusa (Rusia) se almacenan en el siguiente archivo, que se denomina Strings.ru-RU.txt:

Greeting=Здравствуйте
Prompt=Как вас зовут?

A continuación se muestra el código fuente del ejemplo. En el ejemplo se crea una instancia de objetos CultureInfo para las referencias culturales de inglés (Estados Unidos), inglés (Canadá), francés (Francia) y ruso (Rusia); además, las convierte a todas en la referencia cultural actual. Luego, el método ResourceManager.GetString(String, CultureInfo) proporciona el valor de la propiedad CultureInfo.CurrentCulture como argumento culture para recuperar los recursos específicos de la referencia cultural adecuados.

using System;
using System.Globalization;
using System.Resources;
using System.Threading;

[assembly: NeutralResourcesLanguage("en-US")]

public class Example
{
   public static void Main()
   {
      string[] cultureNames = { "en-US", "en-CA", "ru-RU", "fr-FR" };
      ResourceManager rm = ResourceManager.CreateFileBasedResourceManager("Strings", "Resources", null);

      foreach (var cultureName in cultureNames) {
         Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName);
         string greeting = rm.GetString("Greeting", CultureInfo.CurrentCulture);
         Console.WriteLine($"\n{greeting}!");
         Console.Write(rm.GetString("Prompt", CultureInfo.CurrentCulture));
         string name = Console.ReadLine();
         if (! String.IsNullOrEmpty(name))
            Console.WriteLine("{0}, {1}!", greeting, name);
      }
      Console.WriteLine();
   }
}
// The example displays output like the following:
//       Hello!
//       What is your name? Dakota
//       Hello, Dakota!
//
//       Hello!
//       What is your name? Koani
//       Hello, Koani!
//
//       Здравствуйте!
//       Как вас зовут?Samuel
//       Здравствуйте, Samuel!
//
//       Bon jour!
//       Comment vous appelez-vous?Yiska
//       Bon jour, Yiska!
Imports System.Globalization
Imports System.Resources
Imports System.Threading

<Assembly: NeutralResourcesLanguageAttribute("en-US")>

Module Example
    Public Sub Main()
        Dim cultureNames() As String = {"en-US", "en-CA", "ru-RU", "fr-FR"}
        Dim rm As ResourceManager = ResourceManager.CreateFileBasedResourceManager("Strings", "Resources", Nothing)

        For Each cultureName In cultureNames
            Console.WriteLine()
            Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName)
            Dim greeting As String = rm.GetString("Greeting", CultureInfo.CurrentCulture)
            Console.WriteLine("{0}!", greeting)
            Console.Write(rm.GetString("Prompt", CultureInfo.CurrentCulture))
            Dim name As String = Console.ReadLine()
            If Not String.IsNullOrEmpty(name) Then
                Console.WriteLine("{0}, {1}!", greeting, name)
            End If
        Next
        Console.WriteLine()
    End Sub
End Module
' The example displays output like the following:
'       Hello!
'       What is your name? Dakota
'       Hello, Dakota!
'       
'       Hello!
'       What is your name? Koani
'       Hello, Koani!
'       
'       Здравствуйте!
'       Как вас зовут?Samuel
'       Здравствуйте, Samuel!
'       
'       Bon jour!
'       Comment vous appelez-vous?Yiska
'       Bon jour, Yiska!

Puede compilar la versión de C# del ejemplo ejecutando el siguiente archivo por lotes. Si está usando Visual Basic, reemplace csc por vbc, y reemplace la extensión .cs por .vb.

md Resources
resgen Strings.txt Resources\Strings.resources
resgen Strings.fr-FR.txt Resources\Strings.fr-FR.resources
resgen Strings.ru-RU.txt Resources\Strings.ru-RU.resources

csc Example.cs

Consulte también