Pelokalan di .NET

Pelokalan adalah proses menerjemahkan sumber daya aplikasi ke dalam versi yang dilokalkan untuk setiap budaya yang akan didukung aplikasi. Anda harus melanjutkan ke langkah pelokalan hanya setelah menyelesaikan langkah tinjauan Localizability untuk memverifikasi bahwa aplikasi globalisasi siap untuk pelokalan.

Aplikasi yang siap untuk pelokalan dipisahkan menjadi dua blok konseptual: blok yang berisi semua elemen antarmuka pengguna dan blok yang berisi kode yang dapat dieksekusi. Blok antarmuka pengguna hanya berisi elemen antarmuka pengguna yang dapat dilokalkan seperti string, pesan kesalahan, kotak dialog, menu, sumber daya objek yang disematkan, dan sebagainya untuk budaya netral. Blok kode hanya berisi kode aplikasi yang akan digunakan oleh semua budaya yang didukung. Runtime bahasa umum mendukung model sumber daya rakitan satelit yang memisahkan kode yang dapat dieksekusi aplikasi dari sumber dayanya. Untuk informasi selengkapnya tentang menerapkan model ini, lihat Sumber Daya di .NET.

Untuk setiap versi aplikasi yang dilokalkan, tambahkan rakitan satelit baru yang berisi blok antarmuka pengguna yang dilokalkan yang diterjemahkan ke dalam bahasa yang sesuai untuk budaya target. Blok kode untuk semua budaya harus tetap sama. Kombinasi versi blok antarmuka pengguna yang dilokalkan dengan blok kode menghasilkan versi aplikasi Anda yang dilokalkan.

Dalam artikel ini, Anda akan mempelajari cara menggunakan IStringLocalizer<T> implementasi dan IStringLocalizerFactory . Semua contoh kode sumber dalam artikel ini bergantung pada Microsoft.Extensions.Localization paket NuGet dan Microsoft.Extensions.Hosting . Untuk informasi selengkapnya tentang hosting, lihat Host Generik .NET.

File sumber daya

Mekanisme utama untuk mengisolasi string yang dapat dilokalkan adalah dengan file sumber daya. File sumber daya adalah file XML dengan ekstensi file .resx . File sumber daya diterjemahkan sebelum eksekusi aplikasi yang menggunakan—dengan kata lain, file tersebut mewakili konten yang diterjemahkan saat tidak aktif. Nama file sumber daya paling umum berisi pengidentifikasi lokal, dan mengambil formulir berikut:

<FullTypeName><.Locale>.resx

Mana:

  • <FullTypeName> mewakili sumber daya yang dapat dilokalkan untuk jenis tertentu.
  • Opsional <.Locale> mewakili lokal konten file sumber daya.

Menentukan lokal

Lokal harus mendefinisikan bahasa, minimal, tetapi juga dapat menentukan budaya (bahasa daerah), dan bahkan negara atau wilayah. Segmen-segmen ini biasanya dibatasi oleh - karakter. Dengan kekhususan budaya yang ditambahkan, aturan "fallback budaya" diterapkan di mana kecocokan terbaik diprioritaskan. Lokal harus memetakan ke tag bahasa terkenal. Untuk informasi selengkapnya, lihat CultureInfo.Name .

Skenario fallback budaya

Bayangkan bahwa aplikasi lokal Anda mendukung berbagai lokal Serbia, dan memiliki file sumber daya berikut untuk :MessageService

File Bahasa regional Kode Negara
MessageService.sr-Cyrl-RS.resx (Sirilik, Serbia) RS
MessageService.sr-Cyrl.resx Sirilik
MessageService.sr-Latn-BA.resx (Latin, Bosnia & Herzegovina) BA
MessageService.sr-Latn-ME.resx (Latin, Montenegro) ME
MessageService.sr-Latn-RS.resx (Latin, Serbia) RS
MessageService.sr-Latn.resx Latin
MessageService.sr.resx † Latin
MessageService.resx

† Bahasa wilayah default untuk bahasa tersebut.

Saat aplikasi Anda berjalan dengan CultureInfo.CurrentCulture diatur ke budaya "sr-Cyrl-RS" pelokalan mencoba menyelesaikan file dalam urutan berikut:

  1. MessageService.sr-Cyrl-RS.resx
  2. MessageService.sr-Cyrl.resx
  3. MessageService.sr.resx
  4. MessageService.resx

Namun, jika aplikasi Anda berjalan dengan CultureInfo.CurrentCulture diatur ke budaya "sr-Latn-BA" pelokalan mencoba menyelesaikan file dalam urutan berikut:

  1. MessageService.sr-Latn-BA.resx
  2. MessageService.sr-Latn.resx
  3. MessageService.sr.resx
  4. MessageService.resx

Aturan "culture fallback" akan mengabaikan lokal ketika tidak ada kecocokan yang sesuai, yang berarti file sumber daya nomor empat dipilih jika tidak dapat menemukan kecocokan. Jika budaya diatur ke "fr-FR", pelokalan akhirnya akan jatuh ke file MessageService.resx yang dapat bermasalah. Untuk informasi selengkapnya, lihat Proses fallback sumber daya.

Pencarian sumber daya

File sumber daya secara otomatis diselesaikan sebagai bagian dari rutinitas pencarian. Jika nama file proyek Anda berbeda dari namespace layanan akar proyek Anda, nama rakitan mungkin berbeda. Ini dapat mencegah pencarian sumber daya berhasil. Untuk mengatasi ketidakcocokan ini, gunakan RootNamespaceAttribute untuk memberikan petunjuk ke layanan pelokalan. Saat disediakan, ini digunakan selama pencarian sumber daya.

Contoh proyek diberi nama example.csproj, yang membuat example.dll dan example.exe—namun, Localization.Example namespace digunakan. assembly Terapkan atribut tingkat untuk memperbaiki ketidakcocokan ini:

[assembly: RootNamespace("Localization.Example")]

Mendaftarkan layanan pelokalan

Untuk mendaftarkan layanan pelokalan, panggil salah AddLocalization satu metode ekstensi selama konfigurasi layanan. Ini akan mengaktifkan injeksi dependensi (DI) dari jenis berikut:

Mengonfigurasi opsi pelokalan

Kelebihan AddLocalization(IServiceCollection, Action<LocalizationOptions>) beban menerima setupAction parameter jenis Action<LocalizationOptions>. Ini memungkinkan Anda untuk mengonfigurasi opsi pelokalan.

HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);

builder.Services.AddLocalization(options =>
{
    options.ResourcesPath = "Resources";
});

// Omitted for brevity.

File sumber daya dapat hidup di mana saja dalam proyek, tetapi ada praktik umum yang terbukti berhasil. Lebih sering daripada tidak, jalur resistensi paling sedikit diikuti. Kode C# sebelumnya:

Ini akan menyebabkan layanan pelokalan terlihat di direktori Sumber Daya untuk file sumber daya.

Gunakan IStringLocalizer<T> dan IStringLocalizerFactory

Setelah mendaftar (dan secara opsional mengonfigurasi) layanan pelokalan, Anda dapat menggunakan jenis berikut dengan DI:

Untuk membuat layanan pesan yang mampu mengembalikan string yang dilokalkan, pertimbangkan hal berikut MessageService:

using System.Diagnostics.CodeAnalysis;
using Microsoft.Extensions.Localization;

namespace Localization.Example;

public sealed class MessageService(IStringLocalizer<MessageService> localizer)
{
    [return: NotNullIfNotNull(nameof(localizer))]
    public string? GetGreetingMessage()
    {
        LocalizedString localizedString = localizer["GreetingMessage"];

        return localizedString;
    }
}

Dalam kode C# sebelumnya:

  • Bidang IStringLocalizer<MessageService> localizer dideklarasikan.
  • Konstruktor utama mendefinisikan IStringLocalizer<MessageService> parameter dan menangkapnya sebagai localizer argumen.
  • Metode GetGreetingMessage memanggil passing IStringLocalizer.Item[String]"GreetingMessage" sebagai argumen.

juga IStringLocalizer mendukung sumber daya string berparameter, pertimbangkan hal berikut ParameterizedMessageService:

using System.Diagnostics.CodeAnalysis;
using Microsoft.Extensions.Localization;

namespace Localization.Example;

public class ParameterizedMessageService(IStringLocalizerFactory factory)
{
    private readonly IStringLocalizer _localizer =
        factory.Create(typeof(ParameterizedMessageService));

    [return: NotNullIfNotNull(nameof(_localizer))]
    public string? GetFormattedMessage(DateTime dateTime, double dinnerPrice)
    {
        LocalizedString localizedString = _localizer["DinnerPriceFormat", dateTime, dinnerPrice];

        return localizedString;
    }
}

Dalam kode C# sebelumnya:

  • Bidang IStringLocalizer _localizer dideklarasikan.
  • Konstruktor utama mengambil IStringLocalizerFactory parameter, yang digunakan untuk membuat IStringLocalizer dari ParameterizedMessageService jenis , dan menetapkannya ke _localizer bidang .
  • Metode IStringLocalizer.Item[String, Object[]]memanggil GetFormattedMessage , meneruskan "DinnerPriceFormat", dateTime objek, dan dinnerPrice sebagai argumen.

Penting

IStringLocalizerFactory Tidak diperlukan. Sebaliknya, lebih disukai untuk menggunakan layanan untuk memerlukan IStringLocalizer<T>.

Kedua IStringLocalizer.Item[] pengindeks mengembalikan LocalizedString, yang memiliki konversi implisit ke string?.

Satukan semuanya

Untuk mencontohkan aplikasi menggunakan layanan pesan, bersama dengan pelokalan dan file sumber daya, pertimbangkan file Program.cs berikut:

using System.Globalization;
using Localization.Example;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using static System.Console;
using static System.Text.Encoding;

[assembly: RootNamespace("Localization.Example")]

OutputEncoding = Unicode;

if (args is [var cultureName])
{
    CultureInfo.CurrentCulture =
        CultureInfo.CurrentUICulture =
            CultureInfo.GetCultureInfo(cultureName);
}

HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);

builder.Services.AddLocalization();
builder.Services.AddTransient<MessageService>();
builder.Services.AddTransient<ParameterizedMessageService>();
builder.Logging.SetMinimumLevel(LogLevel.Warning);

using IHost host = builder.Build();

IServiceProvider services = host.Services;

ILogger logger =
    services.GetRequiredService<ILoggerFactory>()
        .CreateLogger("Localization.Example");

MessageService messageService =
    services.GetRequiredService<MessageService>();
logger.LogWarning(
    "{Msg}",
    messageService.GetGreetingMessage());

ParameterizedMessageService parameterizedMessageService =
    services.GetRequiredService<ParameterizedMessageService>();
logger.LogWarning(
    "{Msg}",
    parameterizedMessageService.GetFormattedMessage(
        DateTime.Today.AddDays(-3), 37.63));

await host.RunAsync();

Dalam kode C# sebelumnya:

*MessageService Masing-masing kelas mendefinisikan satu set file .resx, masing-masing dengan satu entri. Berikut adalah contoh konten untuk MessageService file sumber daya, dimulai dengan MessageService.resx:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <data name="GreetingMessage" xml:space="preserve">
    <value>Hi friends, the ".NET" developer community is excited to see you here!</value>
  </data>
</root>

MessageService.sr-Cyrl-RS.resx:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <data name="GreetingMessage" xml:space="preserve">
    <value>Здраво пријатељи, ".NЕТ" девелопер заједница је узбуђена што вас види овде!</value>
  </data>
</root>

MessageService.sr-Latn.resx:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <data name="GreetingMessage" xml:space="preserve">
    <value>Zdravo prijatelji, ".NET" developer zajednica je uzbuđena što vas vidi ovde!</value>
  </data>
</root>

Berikut adalah contoh konten untuk ParameterizedMessageService file sumber daya, dimulai dengan ParameterizedMessageService.resx:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <data name="DinnerPriceFormat" xml:space="preserve">
    <value>On {0:D} my dinner cost {1:C}.</value>
  </data>
</root>

ParameterizedMessageService.sr-Cyrl-RS.resx:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <data name="DinnerPriceFormat" xml:space="preserve">
    <value>У {0:D} моја вечера је коштала {1:C}.</value>
  </data>
</root>

ParameterizedMessageService.sr-Latn.resx:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <data name="DinnerPriceFormat" xml:space="preserve">
    <value>U {0:D} moja večera je koštala {1:C}.</value>
  </data>
</root>

Tip

Semua komentar, skema, dan <resheader> elemen XML file sumber daya sengaja dihilangkan untuk brevity.

Contoh eksekusi

Contoh eksekusi berikut menunjukkan berbagai output yang dilokalkan, mengingat lokal yang ditargetkan.

Pertimbangkan "sr-Latn":

dotnet run --project .\example\example.csproj sr-Latn

warn: Localization.Example[0]
      Zdravo prijatelji, ".NET" developer zajednica je uzbuđena što vas vidi ovde!
warn: Localization.Example[0]
      U utorak, 03. avgust 2021. moja večera je koštala 37,63 ¤.

Saat menghilangkan argumen ke .NET CLI untuk menjalankan proyek, budaya sistem default digunakan—dalam hal "en-US"ini :

dotnet run --project .\example\example.csproj

warn: Localization.Example[0]
      Hi friends, the ".NET" developer community is excited to see you here!
warn: Localization.Example[0]
      On Tuesday, August 3, 2021 my dinner cost $37.63.

Saat meneruskan "sr-Cryl-RS", file sumber daya yang sesuai yang benar ditemukan dan pelokalan diterapkan:

dotnet run --project .\example\example.csproj sr-Cryl-RS

warn: Localization.Example[0]
      Здраво пријатељи, ".NЕТ" девелопер заједница је узбуђена што вас види овде!
warn: Localization.Example[0]
      У уторак, 03. август 2021. моја вечера је коштала 38 RSD.

Aplikasi sampel tidak menyediakan file sumber daya untuk "fr-CA", tetapi ketika dipanggil dengan budaya tersebut, file sumber daya yang tidak dilokalkan digunakan.

Peringatan

Karena budaya ditemukan tetapi file sumber daya yang benar tidak, ketika pemformatan diterapkan, Anda berakhir dengan pelokalan parsial:

dotnet run --project .\example\example.csproj fr-CA

warn: Localization.Example[0]
     Hi friends, the ".NET" developer community is excited to see you here!
warn: Localization.Example[0]
     On mardi 3 août 2021 my dinner cost 37,63 $.

Lihat juga