Giter Club home page Giter Club logo

winui3localizer's Introduction

🌏WinUI3Localizer

WinUI3Localizer is a NuGet package that helps you localize your WinUI 3 app.

  • Switch languages without app restarting
  • You/users can edit localized strings even after deployment
  • You/users can add new languages even after deployment
  • Use standard Resources.resw (see Microsoft docs)

🙌 Quick Start

Note: This is a quick start guide. Check the sample app for details.

Install WinUI3Localizer

Install WinUI3Localizer from the NuGet Package Manager.

Create localized strings

Create a "Strings" folder in your app project and populate it with your string resources files for each language you need. For example, this is a basic structure for English (en-US), es-ES (Spanish) and Japanese (ja) resources files.

  • Strings
    • en-US
      • Resources.resw
    • es-ES
      • Resources.resw
    • ja
      • Resources.resw

Add this ItemGroup in the project file (*.csproj) of your app.

<!-- Copy all "Resources.resw" files in the "Strings" folder to the output folder. -->
<ItemGroup>
  <Content Include="Strings\**\*.resw">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </Content>
</ItemGroup>

Note: The "Strings" folder can be anywhere as long the app can access it. Usually, aside the app executable for non-packaged apps, or in the "LocalFolder" for packaged-apps.

Build WinUI3Localizer

  • Non-packaged apps:

    In App.xaml.cs, build WinUI3Localizer like this:

    private async Task InitializeLocalizer()
    {
        // Initialize a "Strings" folder in the executables folder.
        StringsFolderPath StringsFolderPath = Path.Combine(AppContext.BaseDirectory, "Strings");
        StorageFolder stringsFolder = await StorageFolder.GetFolderFromPathAsync(StringsFolderPath);
    
        ILocalizer localizer = await new LocalizerBuilder()
            .AddStringResourcesFolderForLanguageDictionaries(StringsFolderPath)
            .SetOptions(options =>
            {
                options.DefaultLanguage = "en-US";
            })
            .Build();
    }
  • Packaged apps:

    In App.xaml.cs, build WinUI3Localizer like this:

    private async Task InitializeLocalizer()
    {
    
        // Initialize a "Strings" folder in the "LocalFolder" for the packaged app.
        StorageFolder localFolder = ApplicationData.Current.LocalFolder;
        StorageFolder stringsFolder = await localFolder.CreateFolderAsync(
          "Strings",
           CreationCollisionOption.OpenIfExists);
    
        // Create string resources file from app resources if doesn't exists.
        string resourceFileName = "Resources.resw";
        await CreateStringResourceFileIfNotExists(stringsFolder, "en-US", resourceFileName);
        await CreateStringResourceFileIfNotExists(stringsFolder, "es-ES", resourceFileName);
        await CreateStringResourceFileIfNotExists(stringsFolder, "ja", resourceFileName);
    
        ILocalizer localizer = await new LocalizerBuilder()
            .AddStringResourcesFolderForLanguageDictionaries(stringsFolder.Path)
            .SetOptions(options =>
            {
                options.DefaultLanguage = "en-US";
            })
            .Build();
    }
    
    private static async Task CreateStringResourceFileIfNotExists(StorageFolder stringsFolder, string language, string resourceFileName)
    {
        StorageFolder languageFolder = await stringsFolder.CreateFolderAsync(
            language,
            CreationCollisionOption.OpenIfExists);
    
        if (await languageFolder.TryGetItemAsync(resourceFileName) is null)
        {
            string resourceFilePath = Path.Combine(stringsFolder.Name, language, resourceFileName);
            StorageFile resourceFile = await LoadStringResourcesFileFromAppResource(resourceFilePath);
            _ = await resourceFile.CopyAsync(languageFolder);
        }
    }
    
    private static async Task<StorageFile> LoadStringResourcesFileFromAppResource(string filePath)
    {
        Uri resourcesFileUri = new($"ms-appx:///{filePath}");
        return await StorageFile.GetFileFromApplicationUriAsync(resourcesFileUri);
    }

Localizing controls

This is an example of how to localize the Content of a Button.

First asign an Uid to the Button, then in each language resources file, add an item that corresponds to the Uid.

You can also have multiple string resources files. For example, besides the default Resources.resw file, you can have a Messages.resw for your messages file. To just need to include /<resources-file-name>/ before the string resource identifier.

<Page
    x:Class="WinUI3Localizer.SampleApp.TestPage"
    ...
    xmlns:l="using:WinUI3Localizer">
    <StackPanel>
        <Button l:Uids.Uid="TestPage_Button">
            <Button.Flyout>
                <Flyout>
                    <TextBlock l:Uids.Uid="/Messages/ButtonFlyoutMessage" />
                </Flyout>
            </Button.Flyout>
        </Button>
    </StackPanel>
</Page>
  • en-US

    • Resources.resw

      Name Value
      TestPageButton.Content Awesome!
    • Messages.resw

      Name Value
      ButtonFlyoutMessage.Text This is an awesome message!
  • es-ES:

    • Resources.resw

      Name Value
      TestPageButton.Content ¡Increíble!
    • Messages.resw

      Name Value
      ButtonFlyoutMessage.Text ¡Esto es un mensaje increíble!
  • ja:

    • Resources.resw

      Name Value
      TestPageButton.Content 素晴らしい!
    • Messages.resw

      Name Value
      ButtonFlyoutMessage.Text これは素晴らしいメッセージです!

Getting localized strings

If we need to localize strings in code-behind or in ViewModels, we can use the GetLocalizedString() method.

List<string> colors = new()
{
    "Red",
    "Green",
    "Blue",
};

ILocalizer localizer = Localizer.Get();
List<string> localizedColors = colors
    .Select(x => localizer.GetLocalizedString(x))
    .ToList();

In this case, we just use the Uid as Name.

  • en-US

    • Resources.resw

      Name Value
      Red Red
      Green Green
      Blue Blue
  • es-ES:

    • Resources.resw

      Name Value
      Red Rojo
      Green Verde
      Blue Azul
  • ja:

    • Resources.resw

      Name Value
      Red
      Green
      Blue

Minimal example

Refer to TemplateStudioWinUI3LocalizerSampleApp

winui3localizer's People

Contributors

andrewkeepcoding avatar cnbluefire avatar liaosunny123 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

winui3localizer's Issues

Can't change language

Hi,

I want to use this plugin for my unpackaged app, but I found out that I can't change the language.

When I initialize localizer with different default language it throws me this error:
obrazek

When I initialize it with the same language (for example "en-US") the SetLanguage(localization); method doesn't change the language at all when ran outside of VS.

Initialization:
obrazek
Settings language (it really get the correct localization string, but doesn't change it when ran outside of VS):
obrazek

Am I doing it wrong? I would appreciate any help :)

multiple resources

how to use for multiple resources?
for x:Uid we can use

<TextBlock x:Uid="/ErrorMessages/PasswordTooWeak"/>

Unpackaged sample in README is not correct

CurrentDirectory may not be where the assembly locates.

// Initialize a "Strings" folder in the executables folder.
- StringsFolderPath StringsFolderPath = Path.Combine(Directory.GetCurrentDirectory(), "Strings");
+ StringsFolderPath StringsFolderPath = Path.Combine(AppContext.BaseDirectory, "Strings");

PublishTrimmed/TrimMode support?

Hey,

I am trying to use the library, which works fine untrimmed. Unfortunately we are having issues with TrimmedMode with .NET7/8, in which the app crashes at launch.

I have managed to resolve this by using TrimMode partial as suggested here microsoft/WindowsAppSDK#2478 (comment) which has the app running but none of the strings are being loaded in. Its tricky to debug as its occuring after a publish.

Does WinUI3Localizer support trimmed apps / partially trimmed apps with .NET 7/8?

MVVM sample project in NuGet Gallery crash with V2

I'm implementing the WinUI3 Localizer in my MVVM project duplicating the sample project available with the NuGet package. Unfortunately, SettingsViewModel.cs throws and exception when its constructor reaches the last statement because _localizationService.GetCurrentLanguage() returns an empty string;

    public SettingsViewModel(IThemeSelectorService themeSelectorService, ILocalizationService localizationService)
    {
        _themeSelectorService = themeSelectorService;
        _elementTheme = _themeSelectorService.Theme;
        _versionDescription = GetVersionDescription();

        SwitchThemeCommand = new RelayCommand<ElementTheme>(
            async (param) =>
            {
                if (ElementTheme != param)
                {
                    ElementTheme = param;
                    await _themeSelectorService.SetThemeAsync(param);
                }
            });

        _localizationService = localizationService;
        AvailableLanguages = _localizationService.GetAvailableLanguages()
            .Select(x => new LanguageItem(Language: x, UidKey: $"{"Settings_Language"}_{x}"))
            .ToList();

       // next line throws an exception because  _localizationService.GetCurrentLanguage() returns an empty string "";
        _selectedLanguage = AvailableLanguages.First(x => x.Language == _localizationService.GetCurrentLanguage());
    }

the second problem I encountered is that the It fails to return the default language in a machine where the app runs for a first time (ie no "AppLocalizationLanguage" setting yet). This was solved by preventing that to changing the initalization logic in LocalizationService.cs from this:

    public async Task InitializeAsync()
    {
        await InitializeLocalizer();
        if (await LoadLanguageFromSettingsAsync() is string language)
        {
            await Localizer.SetLanguage(language);
        }
    }

To this:

    public async Task InitializeAsync()
    {
        await InitializeLocalizer();
        if (await LoadLanguageFromSettingsAsync() is string language)
        {
            await Localizer.SetLanguage(language);
        }
        else
        {
            SetLanguageAsync("us-en");
        }
    }

Edit:
Whit this change I hopped to be able to get back the localized strings with the default language, but I did not, and _localizationService.GetCurrentLanguage() still returns an empty string.

Maybe I missed to copy a piece of code somewhere?

Implementing the WinUI3Localizer is a great addition to the UX but it is not trivial. Hopefully it gets added to the CommunityToolkit.Mvvm, or, at least a detailed step by step instructions are published with the package for that framework.

How to change language without restart the app?

I want to change the app's language without restart the app. Then I notice this library. I have already saw the sample app. But because I'm new in WinUI, so I didn't find the way to change the language in that sample app. Could any one please tell me the way to change the language? You can offer a document or give me a functhion. Any help are appreciated.

Example for Language Change

I implemented everything correctly and the text changes according to the initial value of the language. Now I should make the app change the language in runtime on clicking a MenuFlyoutItem, could I have an example? the app is packaged and not built with TemplateStudio

Make building process easier

We should be able to make the building process easier and make the WinUI3Localizer easier to use.

For instance, we can make the Build method synchronous by removing the SemaphoreSlim in DependencyObjectWeakReferences class.

Localizing DLLs

Hi,

is there any way how can I localize WinUI 3 library's page?

I'm using my WinUI 3 library in my project that has a page with your localizer but it doesn't translate it when showed in my project.
obrazek
obrazek
obrazek

Navigating to the page from my library:
obrazek

FlowDirection not working

if we have a resource
somekey.FlowDirection | RightToLeft

and we set in Grid or any Element:

<Grid x:Localizer.Uid="somekey"

flow direction is not working but if we use x:Uid flow direction working fine.

Dynamically Loading a String Dictionary at Runtime

Hello everyone,

I'm facing a challenge where I need to dynamically load a dictionary of strings during the runtime of my application. I want to update localized strings in the app without having to reload or recompile the entire application. How can I implement the loading and updating of string resources "on the fly"? Are there any methods or practices that would allow me to efficiently manage strings, especially in the context of multilingual support?

I would appreciate any ideas or suggestions on how to implement or integrate such functionality.

Thank you!

Minimal, simple example usage.

Hello There,
Is it possible to provide a minimal, beginner-friendly example usage. I have carefully examined the code samples available in the repository, but as a beginner, I still find it challenging to comprehend the implementation details.

Thank you for the efforts

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.