.NET'te yerelleştirme
Yerelleştirme, bir uygulamanın kaynaklarını uygulamanın destekleyene her kültür için yerelleştirilmiş sürümlere çeviri işlemidir. Yerelleştirme adımına devam etmek için Yerelleştirme gözden geçirme adımını tamamlayarak genelleştirilmiş uygulamanın yerelleştirme için hazır olduğunu doğrulamanız gerekir.
Yerelleştirme için hazır bir uygulama iki kavramsal bloka ayrılır: tüm kullanıcı arabirimi öğelerini içeren bir blok ve yürütülebilir kod içeren bir blok. Kullanıcı arabirimi bloğu yalnızca bağımsız kültür için dizeler, hata iletileri, iletişim kutuları, menüler, katıştırılmış nesne kaynakları gibi yerelleştirilebilir kullanıcı arabirimi öğelerini içerir. Kod bloğu yalnızca desteklenen tüm kültürler tarafından kullanılacak uygulama kodunu içerir. Ortak dil çalışma zamanı, bir uygulamanın yürütülebilir kodunu kaynaklarından ayıran bir uydu derleme kaynak modelini destekler. Bu modeli uygulama hakkında daha fazla bilgi için bkz. .NET'te Kaynaklar.
Uygulamanın her yerelleştirilmiş sürümü için, hedef kültür için uygun dile çevrilmiş yerelleştirilmiş kullanıcı arabirimi bloğu içeren yeni bir uydu derlemesi ekleyin. Tüm kültürler için kod bloğu aynı kalarak devam gerekir. Kullanıcı arabirimi bloğunun yerelleştirilmiş bir sürümünün kod bloğuyla birleşimi, uygulamanın yerelleştirilmiş bir sürümünü üretir.
Bu makalede ve uygulamalarını kullanmayı IStringLocalizer<T> IStringLocalizerFactory öğrenirsiniz. Bu makaledeki tüm örnek kaynak kodu, ve kaynak Microsoft.Extensions.Localization NuGet Microsoft.Extensions.Hosting kullanılır. Barındırma hakkında daha fazla bilgi için bkz. .NET Genel Ana Bilgisayarı.
Kaynak dosyalar
Yerelleştirilebilir dizeleri yalıtma için birincil mekanizma, kaynak dosyalarıyla birlikte kullanılır. Kaynak dosyası, .resx dosya uzantısına sahip bir XML dosyasıdır. Kaynak dosyaları, tüketen uygulamanın yürütülmesi öncesinde başka bir deyişle, rest'te — çevrilmiş içeriği temsil edecek şekilde çevrilir. Bir kaynak dosyası adı en yaygın olarak bir yerel kimlik içerir ve aşağıdaki formu alır:
<FullTypeName><.Locale>.resx
Konum:
- ,
<FullTypeName>belirli bir tür için yerelleştirilebilir kaynakları temsil eder. - İsteğe
<.Locale>bağlı, kaynak dosyası içeriklerinin yerel olarak temsil eder.
Yerel seçenekleri belirtme
Yerel seçim en azından dili tanımlamalı, ancak kültürü (diyalekti) ve hatta ülkeyi de tanımlayabilir. Bu segmentler genellikle karakteriyle - ayrılmıştır. Bir kültürün özelliği eklendiklerinden, en iyi eşleşmelerin öncelik sırasına sahip olduğu yerde "kültür geri dönüş" kuralları uygulanır. Yerel değer, iyi bilinen bir dil etiketiyle eşlemektedir. Daha fazla bilgi için bkz. CultureInfo.Name.
Kültür geri dönüş senaryoları
Imagine yerelleştirilmiş uygulamanın çeşitli Sırpça yerel seçimleri desteklediğini ve için aşağıdaki kaynak dosyalarına sahip olduğunu MessageService gösterir:
| Dosya | Lehçesi | Ülke Kodu |
|---|---|---|
| MessageService.sr-Cyrl-RS.resx | (Kiril, Sırpça) | RS |
| MessageService.sr-Cyrl.resx | Kiril | |
| MessageService.sr-Latn-BA.resx | (Latin, Boşnakça & İleri) | BA |
| MessageService.sr-Latn-ME.resx | (Latin, Türkiye) | ME |
| MessageService.sr-Latn-RS.resx | (Latin, Sırbistan) | RS |
| MessageService.sr-Latn.resx | Latin | |
| MessageService.sr.resx | † Latin | |
| MessageService.resx |
† Dil için varsayılan diyalekti.
Uygulamanız bir yerelleştirme CultureInfo.CurrentCulture kültürüne ayarlanmış şekilde "sr-Cyrl-RS" çalıştır olduğunda dosyaları aşağıdaki sırayla çözümlemeye çalışır:
- MessageService.sr-Cyrl-RS.resx
- MessageService.sr-Cyrl.resx
- MessageService.sr.resx
- MessageService.resx
Ancak, uygulamanız yerelleştirme CultureInfo.CurrentCulture kültürüne ayarlanmış şekilde "sr-Latn-BA" çalışıyorsa dosyaları aşağıdaki sırayla çözümlemeye çalışır:
- MessageService.sr-Latn-BA.resx
- MessageService.sr-Latn.resx
- MessageService.sr.resx
- MessageService.resx
"Kültür geri dönüş" kuralı, karşılık gelen eşleşme yoksa yerelleri yoksayır, yani eşleşme bulamazsa dört numaralı kaynak dosyası seçilir. Kültür olarak "fr-FR" ayarlanmışsa, yerelleştirme messageService.resx dosyasına düşer ve bu da sorunlu olabilir. Daha fazla bilgi için bkz. Kaynak geri dönüş işlemi.
Kaynak arama
Kaynak dosyaları, arama yordamının bir parçası olarak otomatik olarak çözümlenir. Proje dosya adınız projenizin kök ad alanıyla farklı ise derleme adı farklı olabilir. Bu, kaynak aramanın başka bir şekilde başarılı olmalarını önleyebilirsiniz. Bu eşleşmezliği ele için, RootNamespaceAttribute yerelleştirme hizmetleri için bir ipucu sağlamak üzere kullanın. Sağlanıyorsa, kaynak araması sırasında kullanılır.
Örnek projenin adı example.csproj'tır. Bu,example.dllve example.exe — oluşturur, ancak ad alanı Localization.Example kullanılır. Bu assembly eşleşmeyen sorunu düzeltmek için bir düzey özniteliği uygulama:
[assembly: RootNamespace("Localization.Example")]
Yerelleştirme hizmetlerini kaydetme
Yerelleştirme hizmetlerini kaydetmek için, hizmetlerin yapılandırması AddLocalization sırasında uzantı yöntemlerinden birini çağırabilirsiniz. Bu, aşağıdaki türlerde bağımlılık eklemeye (DI) olanak sağlar:
- Microsoft.Extensions.Localization.IStringLocalizer<T>
- Microsoft.Extensions.Localization.IStringLocalizerFactory
Yerelleştirme seçeneklerini yapılandırma
Aşırı AddLocalization(IServiceCollection, Action<LocalizationOptions>) yükleme türünde bir parametre kabul setupAction Action<LocalizationOptions> eder. Bu, yerelleştirme seçeneklerini yapılandırmaya olanak sağlar.
using IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddLocalization(options =>
{
options.ResourcesPath = "Resources";
});
});
// Omitted for brevity.
Kaynak dosyaları projenin herhangi bir yerinde yer alıyor olabilir, ancak başarılı olduğu kanıtlanmış yaygın uygulamalar vardır. Çoğu zaman en az direnç yolu izlenmektedir. Yukarıdaki C# kodu:
- Varsayılan konak oluşturucusu oluşturur.
- Aşırı HostBuilder.ConfigureServices yüke sahip
IServiceCollectionçağrılar. - olarak
AddLocalizationbelirterek hizmet koleksiyonuna LocalizationOptions.ResourcesPath"Resources"çağrılar.
Bu, yerelleştirme hizmetlerinin kaynak dosyaları için Kaynaklar dizinine baktırmalarına neden olur.
ve IStringLocalizer<T> kullanma IStringLocalizerFactory
Yerelleştirme hizmetlerini kaydettikten (ve isteğe bağlı olarakyapılandırdıktan) sonra, DI ile aşağıdaki türleri kullanabilirsiniz:
Yerelleştirilmiş dizeleri döndürebilecek bir ileti hizmeti oluşturmak için, aşağıdakilere dikkat etmek MessageService gerekir:
using System.Diagnostics.CodeAnalysis;
using Microsoft.Extensions.Localization;
namespace Localization.Example;
public class MessageService
{
private readonly IStringLocalizer<MessageService> _localizer = null!;
public MessageService(IStringLocalizer<MessageService> localizer) =>
_localizer = localizer;
[return: NotNullIfNotNull("_localizer")]
public string? GetGreetingMessage()
{
LocalizedString localizedString = _localizer["GreetingMessage"];
return localizedString;
}
}
Yukarıdaki C# kodunda:
IStringLocalizer<MessageService> _localizerBir alan bildirildi.- Oluşturucu bir
IStringLocalizer<MessageService>parametre alır ve bunu alana_localizeratar. - yöntemi,
GetGreetingMessagegeçirmeyi IStringLocalizer.Item[String] bağımsız değişken olarak"GreetingMessage"çağırır.
parametresi, IStringLocalizer parametreli dize kaynaklarını da destekler, şunları göz önünde önünde önünden ParameterizedMessageService yapın:
using System.Diagnostics.CodeAnalysis;
using Microsoft.Extensions.Localization;
namespace Localization.Example;
public class ParameterizedMessageService
{
private readonly IStringLocalizer _localizer = null!;
public ParameterizedMessageService(IStringLocalizerFactory factory) =>
_localizer = factory.Create(typeof(ParameterizedMessageService));
[return: NotNullIfNotNull("_localizer")]
public string? GetFormattedMessage(DateTime dateTime, double dinnerPrice)
{
LocalizedString localizedString = _localizer["DinnerPriceFormat", dateTime, dinnerPrice];
return localizedString;
}
}
Yukarıdaki C# kodunda:
IStringLocalizer _localizerBir alan bildirildi.- Oluşturucu, türünden bir oluşturmak için kullanılan bir parametre
IStringLocalizerFactoryalır ve bunu alanaIStringLocalizerParameterizedMessageService_localizeratar. - yöntemi
GetFormattedMessageIStringLocalizer.Item[String, Object[]] çağrılır,"DinnerPriceFormat", bir nesnesi ve bağımsız değişken olarakdateTimedinnerPriceiletir.
Önemli
IStringLocalizerFactorygerekli değildir. Bunun yerine, gerektiren hizmetleri tüketmek için tercih IStringLocalizer<T> edilir.
Her IStringLocalizer.Item[] iki dizin LocalizedString de, 'ye örtülü dönüştürmeleri olan bir dönüştür. string?
Hepsini bir araya getirin
Yerelleştirme ve kaynak dosyalarıyla birlikte bir uygulamayı her iki ileti hizmeti kullanarak örnek olarak kullanmak için aşağıdaki Program.cs dosyasını göz önünde bulundurabilirsiniz:
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 { Length: 1 })
{
CultureInfo.CurrentCulture =
CultureInfo.CurrentUICulture =
CultureInfo.GetCultureInfo(args[0]);
}
using IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddLocalization();
services.AddTransient<MessageService>();
services.AddTransient<ParameterizedMessageService>();
})
.ConfigureLogging(options => options.SetMinimumLevel(LogLevel.Warning))
.Build();
IServiceProvider services = host.Services;
ILogger logger =
services.GetRequiredService<ILoggerFactory>()
.CreateLogger("Localization.Example");
MessageService messageService =
services.GetRequiredService<MessageService>();
logger.LogWarning(
messageService.GetGreetingMessage());
ParameterizedMessageService parameterizedMessageService =
services.GetRequiredService<ParameterizedMessageService>();
logger.LogWarning(
parameterizedMessageService.GetFormattedMessage(
DateTime.Today.AddDays(-3), 37.63));
await host.RunAsync();
Yukarıdaki C# kodunda:
- Kök RootNamespaceAttribute ad alanı olarak
"Localization.Example"kümeleri. - Console.OutputEncoding, 'a Encoding.Unicode atanır.
- 'ye tek bir bağımsız değişken
argsgeçir CultureInfo.CurrentCulture olduğunda ve CultureInfo.CurrentUICulture değerine verilen sonucu CultureInfo.GetCultureInfo(String)arg[0]atanır. - Hostvarsayılan değerleriyle oluşturulur.
- ve yerelleştirme
MessageServiceParameterizedMessageServicehizmetleri, DI içinIServiceCollection'ye kaydedilir. - Gürültüyü kaldırmak için günlük kaydı, bir uyarıdan daha düşük herhangi bir günlük düzeyini yoksaymak üzere yapılandırılır.
MessageService, örneğindenIServiceProviderçözümlenir ve sonuçta elde edilen iletisi günlüğe kaydedilir.ParameterizedMessageService, örneğindenIServiceProviderçözümlenir ve sonuçta elde edilen biçimlendirilmiş iletisi günlüğe kaydedilir.
Sınıfların her *MessageService biri, her biri tek bir girişe sahip bir dizi .resx dosyası tanımlar. MessageService MessageService.resx ile başlayarak kaynak dosyaları için örnek içerik şu şekildedir:
<?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>
ParameterizedMessageService ParameterizedMessageService.resx ile başlayarak kaynak dosyaları için örnek içerik şu şekildedir:
<?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>
İpucu
Kaynak dosyası XML açıklamalarının, şemasının ve öğelerinin hepsi kasıtlı olarak <resheader> atlanır.
Örnek çalıştırmalar
Aşağıdaki örnek çalıştırmalar, hedeflenen yerel olarak verilen çeşitli yerelleştirilmiş çıkışları gösterir.
Göz önünde: "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 ¤.
Projeyi çalıştırmak için .NET CLI'ya bir bağımsız değişken kullanılırken, bu durumda varsayılan — sistem kültürü "en-US" kullanılır:
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.
"sr-Cryl-RS"iletirken, doğru karşılık gelen kaynak dosyaları bulunur ve yerelleştirme uygulanır:
dotnet run --project .\example\example.csproj sr-Cryl-RS
warn: Localization.Example[0]
Здраво пријатељи, ".NЕТ" девелопер заједница је узбуђена што вас види овде!
warn: Localization.Example[0]
У уторак, 03. август 2021. моја вечера је коштала 38 RSD.
Örnek uygulama için kaynak dosyaları "fr-CA" sağlamaz, ancak bu kültürle çağrıldıklarda, yerelleştirilmiş olmayan kaynak dosyaları kullanılır.
Uyarı
Kültür bulunsa da doğru kaynak dosyaları bulunamaysa da biçimlendirme uygulandığında kısmi yerelleştirmeyle karşınız olur:
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 $.