Configurar la localización de objetos portátiles en ASP.NET Core

Por Hisham Bin Ateya y Sébastien Ros.

En este artículo se describen los pasos para usar archivos de objeto portátil (PO) en una aplicación ASP.NET Core con el marco de trabajo de Orchard Core.

Nota: Orchard Core no es un producto de Microsoft. Microsoft no ofrece soporte técnico para esta característica.

Vea o descargue el código de ejemplo (cómo descargarlo)

¿Qué es un archivo de objeto portátil?

Los archivos de objeto portátil se distribuyen como archivos de texto que contienen las cadenas traducidas de un idioma determinado. Entre las ventajas de usar archivos de objeto portátil en lugar de archivos .resx se incluyen las siguientes:

  • Los archivos de objeto portátil admiten la pluralización, a diferencia de los archivos .resx.
  • Los archivos de objeto portátil no se compilan como archivos .resx. Por tanto, no se requieren herramientas ni pasos de compilación especializados.
  • Los archivos de objeto portátil funcionan bien con herramientas de colaboración de edición en línea.

Ejemplo

El siguiente archivo de objeto portátil de ejemplo contiene la traducción de dos cadenas en francés, incluida una con su forma en plural:

fr.po

#: Pages/Index.cshtml:13
msgid "Hello world!"
msgstr "Bonjour le monde!"

msgid "There is one item."
msgid_plural "There are {0} items."
msgstr[0] "Il y a un élément."
msgstr[1] "Il y a {0} éléments."

En este ejemplo se usa la sintaxis siguiente:

  • #:: comentario que indica el contexto de la cadena que se va a traducir. La misma cadena se podría traducir de forma diferente según donde se vaya a usar.
  • msgid: la cadena sin traducir.
  • msgstr: la cadena traducida.

A efectos de compatibilidad con la pluralización, se pueden definir más entradas.

  • msgid_plural: la cadena en plural sin traducir.
  • msgstr[0]: la cadena traducida para el caso 0.
  • msgstr[N]: la cadena traducida para el caso N.

Encontrará aquí la especificación del archivo de objeto portátil.

Configuración de la compatibilidad con archivos de objeto portátil en ASP.NET Core

Este ejemplo se basa en una aplicación web ASP.NET Core generada a partir de una plantilla de proyecto de Visual Studio 2022.

Hacer referencia al paquete

Agregue una referencia al paquete NuGet OrchardCore.Localization.Core.

El archivo .csproj ahora contiene una línea similar a la siguiente (el número de versión puede variar):

<PackageReference Include="OrchardCore.Localization.Core" Version="1.5.0" />

Registrar el servicio

Agregue los servicios necesarios a Program.cs:

builder.Services.AddPortableObjectLocalization();

builder.Services
    .Configure<RequestLocalizationOptions>(options => options
        .AddSupportedCultures("fr", "cs")
        .AddSupportedUICultures("fr", "cs"));

builder.Services
    .AddRazorPages()
    .AddViewLocalization();

Agregue el código siguiente a la página de Razor que quiera. Index.cshtml se usa en este ejemplo.

@page
@using Microsoft.AspNetCore.Mvc.Localization
@inject IViewLocalizer Localizer
@{
    ViewData["Title"] = "Home";
}

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

<p>@Localizer["Hello world!"]</p>

Se inserta una instancia de IViewLocalizer que se usa para traducir el texto "Hello world!".

Crear un archivo de objeto portátil

Cree un archivo denominado <código de referencia cultural>.po en la carpeta raíz de la aplicación. En este ejemplo, el nombre del archivo es fr.po porque se usa el idioma francés:

msgid "Hello world!"
msgstr "Bonjour le monde!"

En este archivo se almacenan la cadena que se va a traducir y la cadena traducida al francés. Si es necesario, las traducciones se revierten a su referencia cultural principal. En este ejemplo, el archivo fr.po se usa si la referencia cultural solicitada es fr-FR o fr-CA.

Probar la aplicación

Ejecute la aplicación, se muestra el texto Hello World!

Vaya a la dirección URL /Index?culture=fr-FR. Se muestra el texto Bonjour le monde!.

Pluralización

Los archivos de objeto portátil son compatibles con las formas de pluralización, lo que resulta útil cuando es necesario traducir la misma cadena de forma diferente en función de una cardinalidad. Esta tarea se ve dificultada por el hecho de que cada idioma define reglas personalizadas para seleccionar qué cadena se va a usar en función de la cardinalidad.

El paquete de localización de Orchard proporciona una API para invocar automáticamente estas diferentes formas plurales.

Crear archivos de objeto portátil de pluralización

Agregue el contenido siguiente al archivo fr.po mencionado anteriormente:

msgid "There is one item."
msgid_plural "There are {0} items."
msgstr[0] "Il y a un élément."
msgstr[1] "Il y a {0} éléments."

Vea ¿Qué es un archivo de objeto portátil? para saber qué representa cada entrada de este ejemplo.

Agregar un idioma con formas de pluralización diferentes

En el ejemplo anterior se han usado cadenas en inglés y francés. El idioma inglés y francés solo tienen dos formas de pluralización y comparten las mismas reglas de formato, es decir, se asigna una cardinalidad de uno a la primera forma plural. Todas las demás cardinalidades se asignan a la segunda forma plural.

No todos los idiomas comparten las mismas reglas. Esto se muestra con el idioma checo, que tiene tres formas plurales.

Cree el archivo cs.po como se indica a continuación y observe que la pluralización requiere tres traducciones diferentes:

msgid "Hello world!"
msgstr "Ahoj světe!!"

msgid "There is one item."
msgid_plural "There are {0} items."
msgstr[0] "Existuje jedna položka."
msgstr[1] "Existují {0} položky."
msgstr[2] "Existuje {0} položek."

Para aceptar localizaciones en checo, agregue "cs" a la lista de referencias culturales admitidas en el método Configure:

builder.Services
    .Configure<RequestLocalizationOptions>(options => options
        .AddSupportedCultures("fr", "cs")
        .AddSupportedUICultures("fr", "cs"));

Edite el archivo Pages/Index.cshtml para representar cadenas localizadas en plural para diversas cardinalidades:

<p>@Localizer.Plural(1, "There is one item.", "There are {0} items.")</p>
<p>@Localizer.Plural(2, "There is one item.", "There are {0} items.")</p>
<p>@Localizer.Plural(5, "There is one item.", "There are {0} items.")</p>

Nota: En un escenario real, se usaría una variable para representar el número. En este caso, repetimos el mismo código con tres valores diferentes para exponer un caso específico.

Si cambia las referencias culturales, verá lo siguiente:

Para /Index:

There is one item.
There are 2 items.
There are 5 items.

Para /Index?culture=fr:

Il y a un élément.
Il y a 2 éléments.
Il y a 5 éléments.

Para /Index?culture=cs:

Existuje jedna položka.
Existují 2 položky.
Existuje 5 položek.

Tenga en cuenta que, para la cultura checa, las tres traducciones son diferentes. Las referencias culturales de inglés y francés comparten la misma construcción para las dos últimas cadenas traducidas.

Tareas avanzadas

Contextualización de cadenas

Las aplicaciones a menudo contienen las cadenas que se van a traducir en lugares diferentes. La misma cadena puede tener una traducción diferente en determinadas ubicaciones dentro de una aplicación (vistas de Razor o archivos de clase). Un archivo de objeto portátil admite el concepto de contexto de archivo, que se puede usar para clasificar la cadena que se va a representar. Mediante el uso de un contexto de archivo, una cadena se puede traducir de forma diferente según el contexto de archivo (o según la falta de contexto de archivo).

Los servicios de localización de objetos portátiles usan el nombre de la clase completa o la vista que se usa al traducir una cadena. Esto se logra mediante el establecimiento del valor en la entrada msgctxt.

Considere la posibilidad de realizar una adición mínima al ejemplo fr.po anterior. Una página de Razor ubicada en Pages/Index.cshtml se puede definir como el contexto de archivo estableciendo el valor de la entrada msgctxt reservada:

msgctxt "Views.Home.About"
msgid "Hello world!"
msgstr "Bonjour le monde!"

Después de establecer msgctxt, el texto se traduce cuando se va a /Index?culture=fr-FR. La traducción no se lleva a cabo al ir a /Privacy?culture=fr-FR.

Cuando ninguna entrada específica coincide con un contexto de archivo determinado, el mecanismo de reserva de Orchard Core busca un archivo de objeto portátil adecuado sin contexto. Suponiendo que no haya ningún contexto de archivo específico definido para Pages/Privacy.cshtml, al ir a /Privacy?culture=fr-FR se carga un archivo de objeto portátil como:

msgid "Hello world!"
msgstr "Bonjour le monde!"

Cambiar la ubicación de los archivos de objeto portátil

La ubicación predeterminada de los archivos de objeto portátil se puede cambiar en Programs.cs:

services.AddPortableObjectLocalization(options => options.ResourcesPath = "Localization");

En este ejemplo, los archivos de objeto portátil se cargan desde la carpeta Localization.

Implementar una lógica personalizada para buscar archivos de localización

Cuando se necesita una lógica más compleja para buscar archivos de objeto portátil, es posible implementar y registrar la interfaz OrchardCore.Localization.PortableObject.ILocalizationFileLocationProvider como un servicio. Esto es útil cuando los archivos de objeto portátil se pueden almacenar en ubicaciones diferentes o cuando los archivos deben encontrarse en una jerarquía de carpetas.

Usar un idioma pluralizado predeterminado diferente

El paquete incluye un método de extensión Plural que es específico para dos formas plurales. Para los idiomas que requieren más formas plurales, es necesario crear un método de extensión. Con un método de extensión, no tendrá que proporcionar ningún archivo de localización para el idioma predeterminado, dado que las cadenas originales ya están disponibles directamente en el código.

Puede usar la sobrecarga Plural(int count, string[] pluralForms, params object[] arguments) más genérica, que acepta una matriz de cadenas de traducciones.

De Sébastien Ros, Scott Addie y Hisham Bin Ateya

En este artículo se describen los pasos para usar archivos de objeto portátil (PO) en una aplicación ASP.NET Core con el marco de trabajo de Orchard Core.

Nota: Orchard Core no es un producto de Microsoft. Por tanto, Microsoft no ofrece soporte técnico para esta característica.

Vea o descargue el código de ejemplo (cómo descargarlo)

¿Qué es un archivo de objeto portátil?

Los archivos de objeto portátil se distribuyen como archivos de texto que contienen las cadenas traducidas de un idioma determinado. Entre las ventajas de usar archivos de objeto portátil en lugar de archivos .resx se incluyen las siguientes:

  • Los archivos de objeto portátil admiten la pluralización, a diferencia de los archivos .resx.
  • Los archivos de objeto portátil no se compilan como archivos .resx. Por tanto, no se requieren herramientas ni pasos de compilación especializados.
  • Los archivos de objeto portátil funcionan bien con herramientas de colaboración de edición en línea.

Ejemplo

Este es un archivo de objeto portátil de ejemplo que contiene la traducción de dos cadenas en francés, incluida una con su forma en plural:

fr.po

#: Pages/Index.cshtml:13
msgid "Hello world!"
msgstr "Bonjour le monde!"

msgid "There is one item."
msgid_plural "There are {0} items."
msgstr[0] "Il y a un élément."
msgstr[1] "Il y a {0} éléments."

En este ejemplo se usa la sintaxis siguiente:

  • #:: comentario que indica el contexto de la cadena que se va a traducir. La misma cadena se podría traducir de forma diferente según donde se vaya a usar.
  • msgid: la cadena sin traducir.
  • msgstr: la cadena traducida.

En el caso de compatibilidad con la pluralización, se pueden definir más entradas.

  • msgid_plural: la cadena en plural sin traducir.
  • msgstr[0]: la cadena traducida para el caso 0.
  • msgstr[N]: la cadena traducida para el caso N.

Encontrará aquí la especificación del archivo de objeto portátil.

Configuración de la compatibilidad con archivos de objeto portátil en ASP.NET Core

Este ejemplo se basa en una aplicación ASP.NET Core MVC generada a partir de una plantilla de proyecto de Visual Studio 2019.

Hacer referencia al paquete

Agregue una referencia al paquete NuGet OrchardCore.Localization.Core.

El archivo .csproj ahora contiene una línea similar a la siguiente (el número de versión puede variar):

<PackageReference Include="OrchardCore.Localization.Core" Version="1.2.0" />

Registrar el servicio

Agregue los servicios necesarios al método ConfigureServices de Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages()
        .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix);

    services.AddPortableObjectLocalization();

    services.Configure<RequestLocalizationOptions>(options => options
        .AddSupportedCultures("fr", "cs")
        .AddSupportedUICultures("fr", "cs")
    );
}

Agregue el middleware necesario al método Configure de Startup.cs:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }

    app.UseRouting();
    app.UseStaticFiles();

    app.UseRequestLocalization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
    });
}

Agregue el código siguiente a la página de Razor que quiera. Index.cshtml se usa en este ejemplo.

@page
@using Microsoft.AspNetCore.Mvc.Localization
@inject IViewLocalizer Localizer
@{
    ViewData["Title"] = "Home";
}

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

<p>@Localizer["Hello world!"]</p>

Se inserta una instancia de IViewLocalizer que se usa para traducir el texto "Hello world!".

Crear un archivo de objeto portátil

Cree un archivo denominado <código de referencia cultural>.po en la carpeta raíz de la aplicación. En este ejemplo, el nombre del archivo es fr.po porque se usa el idioma francés:

msgid "Hello world!"
msgstr "Bonjour le monde!"

En este archivo se almacenan la cadena que se va a traducir y la cadena traducida al francés. Si es necesario, las traducciones se revierten a su referencia cultural principal. En este ejemplo, el archivo fr.po se usa si la referencia cultural solicitada es fr-FR o fr-CA.

Probar la aplicación

Ejecute la aplicación y vaya a la URL /Index. Se muestra el texto Hello world!

Vaya a la dirección URL /Index?culture=fr-FR. Se muestra el texto Bonjour le monde!.

Pluralización

Los archivos de objeto portátil son compatibles con las formas de pluralización, lo que resulta útil cuando es necesario traducir la misma cadena de forma diferente en función de una cardinalidad. Esta tarea se ve dificultada por el hecho de que cada idioma define reglas personalizadas para seleccionar qué cadena se va a usar en función de la cardinalidad.

El paquete de localización de Orchard proporciona una API para invocar automáticamente estas diferentes formas plurales.

Crear archivos de objeto portátil de pluralización

Agregue el contenido siguiente al archivo fr.po mencionado anteriormente:

msgid "There is one item."
msgid_plural "There are {0} items."
msgstr[0] "Il y a un élément."
msgstr[1] "Il y a {0} éléments."

Vea ¿Qué es un archivo de objeto portátil? para saber qué representa cada entrada de este ejemplo.

Agregar un idioma con formas de pluralización diferentes

En el ejemplo anterior se han usado cadenas en inglés y francés. El idioma inglés y francés solo tienen dos formas de pluralización y comparten las mismas reglas de formato, es decir, se asigna una cardinalidad de uno a la primera forma plural. Todas las demás cardinalidades se asignan a la segunda forma plural.

No todos los idiomas comparten las mismas reglas. Esto se muestra con el idioma checo, que tiene tres formas plurales.

Cree el archivo cs.po como se indica a continuación y observe que la pluralización requiere tres traducciones diferentes:

msgid "Hello world!"
msgstr "Ahoj světe!!"

msgid "There is one item."
msgid_plural "There are {0} items."
msgstr[0] "Existuje jedna položka."
msgstr[1] "Existují {0} položky."
msgstr[2] "Existuje {0} položek."

Para aceptar localizaciones en checo, agregue "cs" a la lista de referencias culturales admitidas en el método ConfigureServices:

services.Configure<RequestLocalizationOptions>(options => options
                .AddSupportedCultures("fr", "cs")
                .AddSupportedUICultures("fr", "cs")
            );

Edite el archivo Pages/Index.cshtml para representar cadenas localizadas en plural para diversas cardinalidades:

<p>@Localizer.Plural(1, "There is one item.", "There are {0} items.")</p>
<p>@Localizer.Plural(2, "There is one item.", "There are {0} items.")</p>
<p>@Localizer.Plural(5, "There is one item.", "There are {0} items.")</p>

Nota: En un escenario real, se usaría una variable para representar el número. En este caso, repetimos el mismo código con tres valores diferentes para exponer un caso muy específico.

Si cambia las referencias culturales, verá lo siguiente:

Para /Index:

There is one item.
There are 2 items.
There are 5 items.

Para /Index?culture=fr:

Il y a un élément.
Il y a 2 éléments.
Il y a 5 éléments.

Para /Index?culture=cs:

Existuje jedna položka.
Existují 2 položky.
Existuje 5 položek.

Tenga en cuenta que para la referencia cultural de checo, las tres traducciones son diferentes. Las referencias culturales de inglés y francés comparten la misma construcción para las dos últimas cadenas traducidas.

Tareas avanzadas

Contextualización de cadenas

Las aplicaciones a menudo contienen las cadenas que se van a traducir en lugares diferentes. La misma cadena puede tener una traducción diferente en determinadas ubicaciones dentro de una aplicación (vistas de Razor o archivos de clase). Un archivo de objeto portátil admite el concepto de contexto de archivo, que se puede usar para clasificar la cadena que se va a representar. Mediante el uso de un contexto de archivo, una cadena se puede traducir de forma diferente según el contexto de archivo (o según la falta de contexto de archivo).

Los servicios de localización de objetos portátiles usan el nombre de la clase completa o la vista que se usa al traducir una cadena. Esto se logra mediante el establecimiento del valor en la entrada msgctxt.

Considere la posibilidad de realizar una adición mínima al ejemplo fr.po anterior. Una vista de Razor ubicada en Pages/Index.cshtml se puede definir como el contexto de archivo estableciendo el valor de la entrada msgctxt reservada:

msgctxt "Pages.Index"
msgid "Hello world!"
msgstr "Bonjour le monde!"

Después de establecer msgctxt, el texto se traduce cuando se va a /Index?culture=fr-FR. La traducción no se llevará a cabo al ir a /Privacy?culture=fr-FR.

Cuando ninguna entrada específica coincide con un contexto de archivo determinado, el mecanismo de reserva de Orchard Core busca un archivo de objeto portátil adecuado sin contexto. Suponiendo que no haya ningún contexto de archivo específico definido para Pages/Privacy.cshtml, al ir a /Privacy?culture=fr-FR se carga un archivo de objeto portátil como:

msgid "Hello world!"
msgstr "Bonjour le monde!"

Cambiar la ubicación de los archivos de objeto portátil

La ubicación predeterminada de los archivos de objeto portátil se puede cambiar en ConfigureServices:

services.AddPortableObjectLocalization(options => options.ResourcesPath = "Localization");

En este ejemplo, los archivos de objeto portátil se cargan desde la carpeta Localization.

Implementar una lógica personalizada para buscar archivos de localización

Cuando se necesita una lógica más compleja para buscar archivos de objeto portátil, es posible implementar y registrar la interfaz OrchardCore.Localization.PortableObject.ILocalizationFileLocationProvider como un servicio. Esto es útil cuando los archivos de objeto portátil se pueden almacenar en ubicaciones diferentes o cuando los archivos deben encontrarse en una jerarquía de carpetas.

Usar un idioma pluralizado predeterminado diferente

El paquete incluye un método de extensión Plural que es específico para dos formas plurales. Para los idiomas que requieren más formas plurales, es necesario crear un método de extensión. Con un método de extensión, no tendrá que proporcionar ningún archivo de localización para el idioma predeterminado, dado que las cadenas originales ya están disponibles directamente en el código.

Puede usar la sobrecarga Plural(int count, string[] pluralForms, params object[] arguments) más genérica, que acepta una matriz de cadenas de traducciones.

De Sébastien Ros, Scott Addie y Hisham Bin Ateya

En este artículo se describen los pasos para usar archivos de objeto portátil (PO) en una aplicación ASP.NET Core con el marco de trabajo de Orchard Core.

Nota: Orchard Core no es un producto de Microsoft. Por tanto, Microsoft no ofrece soporte técnico para esta característica.

Vea o descargue el código de ejemplo (cómo descargarlo)

¿Qué es un archivo de objeto portátil?

Los archivos de objeto portátil se distribuyen como archivos de texto que contienen las cadenas traducidas de un idioma determinado. Entre las ventajas de usar archivos de objeto portátil en lugar de archivos .resx se incluyen las siguientes:

  • Los archivos de objeto portátil admiten la pluralización, a diferencia de los archivos .resx.
  • Los archivos de objeto portátil no se compilan como archivos .resx. Por tanto, no se requieren herramientas ni pasos de compilación especializados.
  • Los archivos de objeto portátil funcionan bien con herramientas de colaboración de edición en línea.

Ejemplo

Este es un archivo de objeto portátil de ejemplo que contiene la traducción de dos cadenas en francés, incluida una con su forma en plural:

fr.po

#: Services/EmailService.cs:29
msgid "Enter a comma separated list of email addresses."
msgstr "Entrez une liste d'emails séparés par une virgule."

#: Views/Email.cshtml:112
msgid "The email address is \"{0}\"."
msgid_plural "The email addresses are \"{0}\"."
msgstr[0] "L'adresse email est \"{0}\"."
msgstr[1] "Les adresses email sont \"{0}\""

En este ejemplo se usa la sintaxis siguiente:

  • #:: comentario que indica el contexto de la cadena que se va a traducir. La misma cadena se podría traducir de forma diferente según donde se vaya a usar.
  • msgid: la cadena sin traducir.
  • msgstr: la cadena traducida.

En el caso de compatibilidad con la pluralización, se pueden definir más entradas.

  • msgid_plural: la cadena en plural sin traducir.
  • msgstr[0]: la cadena traducida para el caso 0.
  • msgstr[N]: la cadena traducida para el caso N.

Encontrará aquí la especificación del archivo de objeto portátil.

Configuración de la compatibilidad con archivos de objeto portátil en ASP.NET Core

Este ejemplo se basa en una aplicación ASP.NET Core MVC generada a partir de una plantilla de proyecto de Visual Studio 2017.

Hacer referencia al paquete

Agregue una referencia al paquete NuGet OrchardCore.Localization.Core.

El archivo .csproj ahora contiene una línea similar a la siguiente (el número de versión puede variar):

<PackageReference Include="OrchardCore.Localization.Core" Version="1.0.0" />

Registrar el servicio

Agregue los servicios necesarios al método ConfigureServices de Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc()
        .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix);

    services.AddPortableObjectLocalization();

    services.Configure<RequestLocalizationOptions>(options =>
        {
            var supportedCultures = new List<CultureInfo>
            {
                new CultureInfo("en-US"),
                new CultureInfo("en"),
                new CultureInfo("fr-FR"),
                new CultureInfo("fr")
            };

            options.DefaultRequestCulture = new RequestCulture("en-US");
            options.SupportedCultures = supportedCultures;
            options.SupportedUICultures = supportedCultures;
        });
}

Agregue el middleware necesario al método Configure de Startup.cs:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }

    app.UseRouting();
    app.UseStaticFiles();

    app.UseRequestLocalization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
    });
}

Agregue el código siguiente a la vista de Razor que quiera. About.cshtml se usa en este ejemplo.

@using Microsoft.AspNetCore.Mvc.Localization
@inject IViewLocalizer Localizer

<p>@Localizer["Hello world!"]</p>

Se inserta una instancia de IViewLocalizer que se usa para traducir el texto "Hello world!".

Crear un archivo de objeto portátil

Cree un archivo denominado <código de referencia cultural>.po en la carpeta raíz de la aplicación. En este ejemplo, el nombre del archivo es fr.po porque se usa el idioma francés:

msgid "Hello world!"
msgstr "Bonjour le monde!"

En este archivo se almacenan la cadena que se va a traducir y la cadena traducida al francés. Si es necesario, las traducciones se revierten a su referencia cultural principal. En este ejemplo, el archivo fr.po se usa si la referencia cultural solicitada es fr-FR o fr-CA.

Probar la aplicación

Ejecute la aplicación y vaya a la URL /Home/About. Se muestra el texto Hello world!

Vaya a la dirección URL /Home/About?culture=fr-FR. Se muestra el texto Bonjour le monde!.

Pluralización

Los archivos de objeto portátil son compatibles con las formas de pluralización, lo que resulta útil cuando es necesario traducir la misma cadena de forma diferente en función de una cardinalidad. Esta tarea se ve dificultada por el hecho de que cada idioma define reglas personalizadas para seleccionar qué cadena se va a usar en función de la cardinalidad.

El paquete de localización de Orchard proporciona una API para invocar automáticamente estas diferentes formas plurales.

Crear archivos de objeto portátil de pluralización

Agregue el contenido siguiente al archivo fr.po mencionado anteriormente:

msgid "There is one item."
msgid_plural "There are {0} items."
msgstr[0] "Il y a un élément."
msgstr[1] "Il y a {0} éléments."

Vea ¿Qué es un archivo de objeto portátil? para saber qué representa cada entrada de este ejemplo.

Agregar un idioma con formas de pluralización diferentes

En el ejemplo anterior se han usado cadenas en inglés y francés. El idioma inglés y francés solo tienen dos formas de pluralización y comparten las mismas reglas de formato, es decir, se asigna una cardinalidad de uno a la primera forma plural. Todas las demás cardinalidades se asignan a la segunda forma plural.

No todos los idiomas comparten las mismas reglas. Esto se muestra con el idioma checo, que tiene tres formas plurales.

Cree el archivo cs.po como se indica a continuación y observe que la pluralización requiere tres traducciones diferentes:

msgid "Hello world!"
msgstr "Ahoj světe!!"

msgid "There is one item."
msgid_plural "There are {0} items."
msgstr[0] "Existuje jedna položka."
msgstr[1] "Existují {0} položky."
msgstr[2] "Existuje {0} položek."

Para aceptar localizaciones en checo, agregue "cs" a la lista de referencias culturales admitidas en el método ConfigureServices:

var supportedCultures = new List<CultureInfo>
{
    new CultureInfo("en-US"),
    new CultureInfo("en"),
    new CultureInfo("fr-FR"),
    new CultureInfo("fr"),
    new CultureInfo("cs")
};

Edite el archivo Views/Home/About.cshtml para representar cadenas localizadas en plural para diversas cardinalidades:

<p>@Localizer.Plural(1, "There is one item.", "There are {0} items.")</p>
<p>@Localizer.Plural(2, "There is one item.", "There are {0} items.")</p>
<p>@Localizer.Plural(5, "There is one item.", "There are {0} items.")</p>

Nota: En un escenario real, se usaría una variable para representar el número. En este caso, repetimos el mismo código con tres valores diferentes para exponer un caso muy específico.

Si cambia las referencias culturales, verá lo siguiente:

Para /Home/About:

There is one item.
There are 2 items.
There are 5 items.

Para /Home/About?culture=fr:

Il y a un élément.
Il y a 2 éléments.
Il y a 5 éléments.

Para /Home/About?culture=cs:

Existuje jedna položka.
Existují 2 položky.
Existuje 5 položek.

Tenga en cuenta que para la referencia cultural de checo, las tres traducciones son diferentes. Las referencias culturales de inglés y francés comparten la misma construcción para las dos últimas cadenas traducidas.

Tareas avanzadas

Contextualización de cadenas

Las aplicaciones a menudo contienen las cadenas que se van a traducir en lugares diferentes. La misma cadena puede tener una traducción diferente en determinadas ubicaciones dentro de una aplicación (vistas de Razor o archivos de clase). Un archivo de objeto portátil admite el concepto de contexto de archivo, que se puede usar para clasificar la cadena que se va a representar. Mediante el uso de un contexto de archivo, una cadena se puede traducir de forma diferente según el contexto de archivo (o según la falta de contexto de archivo).

Los servicios de localización de objetos portátiles usan el nombre de la clase completa o la vista que se usa al traducir una cadena. Esto se logra mediante el establecimiento del valor en la entrada msgctxt.

Considere la posibilidad de realizar una adición mínima al ejemplo fr.po anterior. Una vista de Razor ubicada en Views/Home/About.cshtml se puede definir como el contexto de archivo estableciendo el valor de la entrada msgctxt reservada:

msgctxt "Views.Home.About"
msgid "Hello world!"
msgstr "Bonjour le monde!"

Después de establecer msgctxt, el texto se traduce cuando se va a /Home/About?culture=fr-FR. La traducción no se llevará a cabo al ir a /Home/Contact?culture=fr-FR.

Cuando ninguna entrada específica coincide con un contexto de archivo determinado, el mecanismo de reserva de Orchard Core busca un archivo de objeto portátil adecuado sin contexto. Suponiendo que no haya ningún contexto de archivo específico definido para Views/Home/Contact.cshtml, al ir a /Home/Contact?culture=fr-FR se carga un archivo de objeto portátil como:

msgid "Hello world!"
msgstr "Bonjour le monde!"

Cambiar la ubicación de los archivos de objeto portátil

La ubicación predeterminada de los archivos de objeto portátil se puede cambiar en ConfigureServices:

services.AddPortableObjectLocalization(options => options.ResourcesPath = "Localization");

En este ejemplo, los archivos de objeto portátil se cargan desde la carpeta Localization.

Implementar una lógica personalizada para buscar archivos de localización

Cuando se necesita una lógica más compleja para buscar archivos de objeto portátil, es posible implementar y registrar la interfaz OrchardCore.Localization.PortableObject.ILocalizationFileLocationProvider como un servicio. Esto es útil cuando los archivos de objeto portátil se pueden almacenar en ubicaciones diferentes o cuando los archivos deben encontrarse en una jerarquía de carpetas.

Usar un idioma pluralizado predeterminado diferente

El paquete incluye un método de extensión Plural que es específico para dos formas plurales. Para los idiomas que requieren más formas plurales, es necesario crear un método de extensión. Con un método de extensión, no tendrá que proporcionar ningún archivo de localización para el idioma predeterminado, dado que las cadenas originales ya están disponibles directamente en el código.

Puede usar la sobrecarga Plural(int count, string[] pluralForms, params object[] arguments) más genérica, que acepta una matriz de cadenas de traducciones.