SirJohnK / LocalizationResourceManager.Maui

Enhanced .NET MAUI version of the XCT LocalizationResourceManager.
MIT License
140 stars 9 forks source link
dotnet dotnetmaui localization

LocalizationResourceManager.Maui Buy Me A Coffee

Enhanced .NET MAUI version of the Xamarin Community Toolkit LocalizationResourceManager.

NuGet

Name Info
LocalizationResourceManager.Maui NuGet

Background

I have been a fan of the Localization helpers and extensions in the Xamarin Community Toolkit and have been using this in my Xamarin projects. Since moving to .NET MAUI, I hoped for this to be part of the MAUI Community Toolkit. For good reasons the team has decided not to include this in MCT and a proposal is issued in the .NET Community Toolkit. But the XCT solution have dependencies to the Xamarin IMarkupExtension interface and the XCT WeakEventManager helper class, which makes it tricky to port to a non MAUI library. So until we have a official solution, or anyway is added to MCT, I have created this library for .NET MAUI.

Big shoutout to the original authors, Charlin Agramonte, Brandon Minnick, Maksym Koshovyi and the entire Xamarin Community Toolkit Team!

What's included?

Compared to the original solution we have some enhanced and added features:

For localized texts used in XAML and/or code behind, we still have:

Setup

Use the UseLocalizationResourceManagerbuilder pattern extension method for library configuration.

var builder = MauiApp.CreateBuilder();
builder
    .UseMauiApp<App>()
    .ConfigureFonts(fonts =>
    {
        fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
        fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
    })
    .UseLocalizationResourceManager(settings =>
    {
        settings.AddResource(AppResources.ResourceManager);
        settings.RestoreLatestCulture(true);
    });

Settings contains 6 methods for configuration:

Use in XAML

When used for localized texts in XAML pages, use the TranslateExtension:

Plural support in XAML

<Button
    x:Name="CounterBtn"
    Clicked="OnCounterClicked"
    HorizontalOptions="Center"
    SemanticProperties.Hint="{localization:Translate CounterBtnHint}"
    Text="{localization:TranslateBinding Count, TranslateFormat=ClickedManyTimes, TranslateOne=ClickedOneTime, TranslateZero=ClickMe}" />

The way it works is:

TranslateFormat : (optional) similar to StringFormat, but the format comes from a string resource, e.g. "Clicked {0} times"
TranslateOne : (optional) similar to StringFormat, but used for when the binding value is one (1), e.g. "Clicked {0} time"
TranslateZero : (optional) similar to StringFormat, but used for when the binding value is zero (0), e.g. "Click Me"

Date/Time in XAML

public DateTime CurrentDateTime { get; set; } = DateTime.Now;
<!-- DateIs string resource: "Date is: {0}" -->
<Label Text="{localization:TranslateBinding CurrentDateTime, TranslateFormat=DateIs}/"/>

<! -- TimeIs string resource: "Time is: {0:HH}:{0:mm}:{0:ss}" -->
<Label Text="{localization:TranslateBinding CurrentDateTime, TranslateFormat=TimeIs}/" />

Currency in XAML

public decimal Price { get; set; } = 123.45;
<!-- TotalPrice string resource: "Total Price is: {0:C}" -->
<Label Text="{localization:TranslateBinding Price, TranslateFormat=TotalPrice}" />

Translate collections in XAML

TranslateValue : (optional) Apply localization changes to a view model, e.g.

public IList<string> Fruits { get; set; } = new List<string> { "LBL_APPLES", "LBL_ORANGES" };
<CollectionView ItemsSource="{Binding Fruits}">
    <CollectionView.ItemTemplate>
        <DataTemplate>
            <Label Text="{localization:TranslateBinding . , TranslateValue=True}"/>
        <DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

Translate true/false states in XAML

TranslateTrue : (optional) string resource used for when the binding value is true, e.g. "Yes", "On", "Activated"
TranslateFalse : (optional) string resource used for when the binding value is false, e.g. "No", "Off", "Deactivated"

public bool OrderSent { get; set; } = false;
<!-- Yes/No string resources: "Yes" / "No" -->
<Label Text="{localization:TranslateBinding OrderSent, TranslateTrue=Yes, TranslateFalse=No}" />

Use in Code

When used to handle localized texts in code behind or ViewModel, use the LocalizedString class:

public MainPage(ILocalizationResourceManager resourceManager) { HelloWorld = new(() => $"{resourceManager["Hello"]}, {resourceManager["World"]}!");

```csharp
<Label
    FontSize="32"
    HorizontalOptions="Center"
    SemanticProperties.HeadingLevel="Level1"
    Text="{Binding HelloWorld.Localized}" />

Set and Get Culture

To handle and access the Current or Default Culture, we inject the ILocalizationResourceManager interface into our code behind or ViewModel to access the LocalizationResourceManager instance:

public MainPage(ILocalizationResourceManager resourceManager) { CurrentCulture = new(() => resourceManager.CurrentCulture.NativeName);

One line to change Current Culture and Refresh ALL localized texts!
```csharp
resourceManager.CurrentCulture = new CultureInfo("en");

Sample

Look at the Sample project for a example of how to use this library in an .NET MAUI application.

Sample Application