Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/kl1mm/localize
https://github.com/kl1mm/localize
json localization nuget
Last synced: about 1 month ago
JSON representation
- Host: GitHub
- URL: https://github.com/kl1mm/localize
- Owner: kl1mm
- License: mit
- Created: 2020-03-27T10:11:57.000Z (over 4 years ago)
- Default Branch: develop
- Last Pushed: 2024-09-17T13:32:37.000Z (3 months ago)
- Last Synced: 2024-09-18T11:18:59.332Z (3 months ago)
- Topics: json, localization, nuget
- Language: C#
- Homepage:
- Size: 313 KB
- Stars: 30
- Watchers: 3
- Forks: 3
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- RSCG_Examples - kli.Localize
- csharp-source-generators - kli.Localize - ![stars](https://img.shields.io/github/stars/kl1mm/localize?style=flat-square&cacheSeconds=604800) ![last commit](https://img.shields.io/github/last-commit/kl1mm/localize?style=flat-square&cacheSeconds=86400) - localize strings from json files via source code generation (Source Generators / Localization)
README
# Localize
Simple package to localize **strings** from json files via static source code generation.
Implemented via [C# source generators](https://docs.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/source-generators-overview)
[![CI\CD](https://github.com/kl1mm/localize/actions/workflows/dotnet.yml/badge.svg?branch=main)](https://github.com/kl1mm/localize/actions/workflows/dotnet.yml)
## Usage
_Also see [**example project**](https://github.com/kl1mm/localize/tree/develop/example/kli.Localize.Example)_
### Install the nuget package
Add a [Nuget package](https://www.nuget.org/packages/kli.Localize/) reference to the project file in the project you want to localize:
``
### Create \*.json files for your localized texts.
Example:
```json
{
"SampleText": "FooBar",
"Other": "Text42"
}
```Give your default localization a name **without** specifying the culture (e.g. `Locale.json`). All other localizations follow the pattern `_.json` (e.g. `Locale_en-US.json` for American English or `Locale_en.json` for English)
![locale_files image][locale_files]
### Add json files to csproj
In an `ItemGroup` in your csproj file add an `AdditionFiles` element for **each default localization** json file. Set the `Include` attribute to the path of the file.
Example:
```xml
```
This means: if you have a `Locale.json` and a `Locale_en-US.json` you **only** have to add the `Locale.json` as ``. You can add as many files as you want.
### Use it in your code
Now you should be able to locate the generated source code in your project under Dependencies/Analyzers.
_Of course you can also view and debug the generated source code._![generated_1 image][generated_1]
Generated code example
```csharp
//------------------------------------------------------------------------------
//
// This code was generated by kli.Localize.Generator.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
//------------------------------------------------------------------------------
namespace kli.Localize.Example.Localizations
{
using System;
using System.Globalization;
using System.Collections.Generic;
using Translations = System.Collections.Generic.Dictionary;public sealed class Locale
{
private static readonly LocalizationProvider provider = new LocalizationProvider();
public static IDictionary GetAll(CultureInfo cultureInfo = null) => provider.GetValues(cultureInfo ?? CultureInfo.CurrentUICulture);
public static string GetString(string key, CultureInfo cultureInfo = null) => provider.GetValue(key, cultureInfo ?? CultureInfo.CurrentUICulture);
///Similar to: Hallo Welt (German)
public static string MyText => provider.GetValue(nameof(MyText), CultureInfo.CurrentUICulture);
private class LocalizationProvider
{
delegate bool SelectorFunc(Translations translations, out T arg);
internal string GetValue(string key, CultureInfo cultureInfo)
{
bool ValueSelector(Translations translations, out string value)
{
if (translations.TryGetValue(key, out value))
return true;
value = key;
return false;
}return TraverseCultures(cultureInfo, ValueSelector);
}internal IDictionary GetValues(CultureInfo cultureInfo)
{
bool ValueSelector(Translations translations, out Translations value)
{
value = translations;
return true;
}return TraverseCultures(cultureInfo, ValueSelector);
}private T TraverseCultures(CultureInfo cultureInfo, SelectorFunc selectorFunc)
{
if (resources.TryGetValue(cultureInfo, out Translations translations))
{
if (selectorFunc(translations, out T result) || cultureInfo == CultureInfo.InvariantCulture)
return result;
}return TraverseCultures(cultureInfo.Parent, selectorFunc);
}private static readonly Translations invariant = new()
{{"MyText", "Hallo Welt (German)"}, };
private static readonly Translations en = new()
{{"MyText", "Hello World (English)"}, };
private static readonly Dictionary resources = new()
{{CultureInfo.InvariantCulture, invariant}, {new CultureInfo("en"), en}, };
}
}
}
```
Import the namespace where you put your \*.json files and use the generated code to access your localizations.
Access is based on [CultureInfo.CurrentUICulture](https://docs.microsoft.com/en-us/dotnet/api/system.globalization.cultureinfo.currentuiculture)
![useit image][useit]### Namespace generation
The namespace is generated using the following pattern:
`rootnamespace + relative directory structure`
Since v0.8 this behaviour can be overriden [see 'From version 0.8'](#From version 0.8)## Version Changes
### From version 1.0
#### BREAKING - Ignore none JSON-String/Object values
All properties that are not string or object will be ignored.
```json
{
"Number": 4.2,
"Bool": true,
"Null": null,
"Array": [1,2,3]
}
```#### [Add Support for Nested Classes #8](https://github.com/kl1mm/localize/issues/8)
It is now possible to use JSON objects in the localization files.
During generation, the structure is mapped as a nested class for access```json
{
"SomeText": "some text",
"Sub":
{
"FileNotFound": "Not found",
"DivideByZero": "x / zero"
},
"UI":{
"LabelOne": "One",
"LabelTwo": "Two",
"Login": {
"LabelUserName": "User",
"LabelPassword": "Pass"
}
}
}
```
#### Improved Diagnostics
- SGL0001: InvalidJsonFileFormat - ``
- SGL0002: InvalidJsonPropertyName - `Json property key must be a valid C# identifier`
- SGL0003: InvalidJsonTokenType - `Json property value must be an object or a string`All diagnostics came with LinePostion (linenumber & column)
### From version 0.8
It is now possible to override the namespace and the class/file name that will be generated:
```xml
```
From which the following is generated:
```csharp
namespace Namespace.of.your.choice
{
...
public sealed class MyClassName {
...
```## Help! Why is no code generated?
Directly after including the package sometimes the tooling (Visual Studio) gets stuck. If you encounter any problems with source generation try to restart Visual Studio and/or check the build log for warnings/errors.
## Need help? Problems?
Feel free to create an [Issue](https://github.com/kl1mm/localize/issues)
[locale_files]: docs/locale_files.png
[generated_1]: docs/generated_1.png
[useit]: docs/useit.png