IncaTechnologies.LocalizationFramework 1.0.10

Prefix Reserved
dotnet add package IncaTechnologies.LocalizationFramework --version 1.0.10                
NuGet\Install-Package IncaTechnologies.LocalizationFramework -Version 1.0.10                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="IncaTechnologies.LocalizationFramework" Version="1.0.10" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add IncaTechnologies.LocalizationFramework --version 1.0.10                
#r "nuget: IncaTechnologies.LocalizationFramework, 1.0.10"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install IncaTechnologies.LocalizationFramework as a Cake Addin
#addin nuget:?package=IncaTechnologies.LocalizationFramework&version=1.0.10

// Install IncaTechnologies.LocalizationFramework as a Cake Tool
#tool nuget:?package=IncaTechnologies.LocalizationFramework&version=1.0.10                

IncaTechnologies.LocalizationFramework

What does it do?

I created this piece of software to manage localization more easily then using resource file. The general idea is to have xml files (*.incaloc) that contains the localized text and a C# class that retrieve the text when needed.

How to use it?

The main two classes of the framework are IncaLocReader and IncLocGenerator. The first one is used to retrieve the localized text, the second one to generate .incaloc files that will contain the localized text.

How to use IncaReader?

IncaLocReader is a concrete implementation of IIncaLocReader. It can be customized by overriding its methods and properties if needed. To use this implementation your project must embed .incaloc files as a resource that reflects the properties that shall be localized. This file must be an xml file whose name match the pattern [NameSpace].[Class].incaloc, the content of the file instead must match the following pattern:

<?xml version="1.0" encoding="utf-8"?>
<IncaTehcnologies NameSpace="MyNameSpace" Class="MyClass">
  <Localize Property="FirstProperty">
    <en-EN>Text</en-EN>
    <fr-FR>Texte</fr-FR>
    <es-ES>Texto</es-ES>
  </Localize>
  <Localize Property="SecondProperty">
    <en-EN>...</en-EN>
    <fr-FR>...</fr-FR>
    <es-ES>...</es-ES>
  </Localize>
</IncaTehcnologies>

Thus, the root element must be IncaTchnologies and it shall have two attributes NameSpace and Class. Inside this root element shall be contained as many Localize elements as are needed. Every Localize element shall have a Property attribute that points to the property that shall be localized. It contains elements named after the culture codes for which the localization is avaliable. In the snippet are included codes for English, Spanish and French but any culture code can be included.

IncaLocReader.GetText(IncaLocParameters parameters) can be used to retrive the translated text. For example, the following code can be used in a ViewModel:

public abstract class ViewModelBase
{
    protected virtual string GetText([CallerMemberName] string? propertyName = null)
    {
        return IncaLocReader.Default.GetText(new IncaLocParameters(
            nameSpace: this.GetType().Namespace,
            classIdentifier: this.GetType().Name,
            propertyIdentifier: propertyName));
    }
}

public class MyViewModel : ViewModelBase
{
    public string FirstProperty => GetText();

    public string SecondProperty => GetText();
}

The interface IIncaLocReader comes with some handy extension methods that can be used to retrieve the localized text in a more concise way. For example, the previous code can be rewritten as:

public class MyClass
{
    public string FirstProperty => this.GetText();

    public string SecondProperty => this.GetText();
}

The GetText() method in the first example will look for an .incaloc file embedded in the project/library that called the method. In the second example the assembly containing the object passed as parameter is used. Then the most relevant translation is retrived from the file. The most relevant translation is the one that matches the IIncaLocReader.CurrentCulture property. If no match is fonud the IIncaLocReader.DefaultCulture is used. If no match is found again, the first translation found is used. If no translation is found at all, the method returns an empty string.

How to use IncaLocGenerator?

So far it looks like that use IncaLocReader requires quite a work since .incaloc files must be generated end embedded to the project. Here is where IncaLocGenerator comes into place. As for the reader, it can be customized and personalized. It has a method that generates .incaloc files but its direct usage is not particularly useful since the method must know all the properties (including namespaces and classes) for the files to be generated.

This object is ment to be used mainly in a tool combined with the IncaLocalizeAttribute. The tool has already been created and it is installed (locally) automatically when this framework is installed via Nuget package. If for some reason the installation fails, it is possible to install the tool directly from dotnet client. Once installed, it is possible to call the tool from the dotnet client (by default is installed locally in the directory of the solution and it can be invoked only from that directory or subdirectories):

dotnet inca-loc [-Diagnostic] [-Input <String>] [-Output <String>] [-Generator <String>] [-Cultures <String>]

Otherwise, if Visual Studio is used for development, it can be invoked inside the Package Manager Console via:

Invoke-Localization [-Diagnostic] [-Input <String>] [-Output <String>] [-Generator <String>] [-Cultures <String>] [<CommonParameters>]

In both cases the tool will look inside all the .cs files in a project folder and automatically generates the .incaloc file for every property that is decorated with IncaLocalizeAttribute. It also automatically embeds the file to the project as a resource.

Example:

public class MyClass
{
    [IncaLocalize]
    public string FirstProperty => this.GetText();

    [IncaLocalize]
    public string SecondProperty => this.GetText();
}

Call Invoke-Localization and the followiong file will be created in the folder .\MyProject\Localization .

<?xml version="1.0" encoding="utf-8"?>
<IncaTehcnologies NameSpace="MyNameSpace" Class="MyClass">
  <Localize Property="FirstProperty">
    <en-EN></en-EN>
  </Localize>
  <Localize Property="SecondProperty">
    <en-EN></en-EN>
  </Localize>
</IncaTehcnologies>

If cultures where specified by invoking, for example:

Invoke-Localization -Cultures "en-US, it-IT"

The .incaloc file would be:

<?xml version="1.0" encoding="utf-8"?>
<IncaTehcnologies NameSpace="MyNameSpace" Class="MyClass">
  <Localize Property="FirstProperty">
    <en-US></en-US>
    <it-IT></it-IT>
  </Localize>
  <Localize Property="SecondProperty">
    <en-US></en-US>
    <it-IT></it-IT>
  </Localize>
</IncaTehcnologies>

The same results can be achieved invoking the tool form the dotnet client as:

PS: C:\MyCoolProject\MyProject> dotnet inca-loc -Cultures "en-US, it-IT"

Author Remarks

This project is tailor made on my needings but I thought that maybe someone else might be interested in a similar solution for the localization, or better for the support of multiple languages in their own projects. I also used this project to study more in depth how dotnet tools works, how Nuget packages works, how to write commandlet, how to write analyzers and how code generation works. My ultimate goal was not only to create a framework that I needed but I was also interested in finding out if I was able to create a similar experience to the one provided by the Microsoft.EntityFrameworkCore.Tools and CommunityToolkit.Mvvm.

In the next update (if ever there will be one), I would like to use code generators in order to create programmatically the properties that has to be localized. This is the result I would like to get:

public partial class MyViewModel : ViewModelBase
{
    [IncaAutoLocalize]
    string FirstProperty;

    [IncaAutoLocalize]
    string SecondProperty;
}

//Generated
partial class MyViewModel
{
    public string FirstProperty => this.GetText();

    public string SecondProperty => this.GetText();

}

Or something like this at least.

I actually explored a lot of possible solution to get around this project and I ended up with different approaches than the ones used in the framework that inspired me the most. Nonetheless I am pretty happy with the results I got.

If anyone wants to contribute, give advise or point out a better strategy to achieve what this framework does, you are very welcome sir. You can do it through GitHub at any time.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.1

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.10 105 7/12/2024
1.0.9 105 5/29/2024
1.0.8 128 2/21/2024
1.0.7 272 10/18/2023
1.0.6 152 10/14/2023
1.0.2 263 3/2/2023
1.0.1 245 3/1/2023
1.0.0 274 3/1/2023 1.0.0 is deprecated because it has critical bugs.

1.0.0 - Release
1.0.1 - Bug fix
1.0.2 - Included documentation
1.0.3 - Improved stability
1.0.4 - Removed the source generator that was never implemented
1.0.5 - Fixed a bug in init.ps
1.0.6 - Fixed a bug when add new cultures to .incaloc
1.0.7 - Fixed persistent bug on init.ps1
1.0.8 - Added helpers to translate text
1.0.9 - Added more helpers to translate text
1.0.10 - Reduced the exceptions thrown when .incaloc files are not yet created