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:
- MessageService.sr-Cyrl-RS.resx
- MessageService.sr-Cyrl.resx
- MessageService.sr.resx
- MessageService.resx
Namun, jika aplikasi Anda berjalan dengan CultureInfo.CurrentCulture diatur ke budaya "sr-Latn-BA"
pelokalan mencoba menyelesaikan file dalam urutan berikut:
- MessageService.sr-Latn-BA.resx
- MessageService.sr-Latn.resx
- MessageService.sr.resx
- 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:
- Microsoft.Extensions.Localization.IStringLocalizer<T>
- Microsoft.Extensions.Localization.IStringLocalizerFactory
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:
- Membuat pembuat aplikasi host default.
AddLocalization
Panggilan pada koleksi layanan, menentukan LocalizationOptions.ResourcesPath sebagai"Resources"
.
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 sebagailocalizer
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 membuatIStringLocalizer
dariParameterizedMessageService
jenis , dan menetapkannya ke_localizer
bidang . - Metode IStringLocalizer.Item[String, Object[]]memanggil
GetFormattedMessage
, meneruskan"DinnerPriceFormat"
,dateTime
objek, dandinnerPrice
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:
- Set RootNamespaceAttribute
"Localization.Example"
sebagai namespace layanan akar. - Console.OutputEncoding ditetapkan ke Encoding.Unicode.
- Ketika argumen tunggal diteruskan ke
args
, CultureInfo.CurrentCulture dan CultureInfo.CurrentUICulture diberi hasil dari CultureInfo.GetCultureInfo(String) diberikanarg[0]
. - Host dibuat dengan default.
- Layanan pelokalan,
MessageService
, danParameterizedMessageService
didaftarkan keIServiceCollection
untuk DI. - Untuk menghapus kebisingan, pengelogan dikonfigurasi untuk mengabaikan tingkat log apa pun yang lebih rendah dari peringatan.
MessageService
diselesaikan dariIServiceProvider
instans dan pesan yang dihasilkan dicatat.ParameterizedMessageService
diselesaikan dariIServiceProvider
instans dan pesan berformat yang dihasilkan dicatat.
*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 $.