JsonLanguageLocalizerNet is an alternative to Microsoft's ResourceManager.
JsonLanguageLocalizerNet manage language localizations by using a json file instead of *.resx file.
- String notation
- Strong data types
- Json nested structures
- Reloading when file changes (Disk load only)
- Loading from
- Disk
- Network
- Change culture and/or translations with or without reloading
- Integrations
- AspNetCore (Manually, Auto Integration With Supported Cultures Soon)
- Xamarin (Manually, Auto Integration With Supported Cultures Soon)
- Blazor Wasm & Server (Auto Integrated With Supported Cultures)
- Everywhere .net is able to run
Install-Package JsonLanguageLocalizerNet -Version 1.0.5
//For blazor
Install-Package JsonLanguageLocalizerNet.Blazor -Version 1.0.5
services.AddJsonLanguageLocalizer();
services.AddJsonLanguageLocalizer(sonLanguageLocalizerService jsonLanguageLocalizerService);
services.AddJsonLanguageLocalizer(Func<IServiceProvider, JsonLanguageLocalizerService> provider);
services.AddJsonLanguageLocalizer(ConfigurationBuilder configurationBuilder);
services.AddJsonLanguageLocalizer(IConfiguration configuration);
services.AddJsonLanguageLocalizer(IConfigurationRoot configurationRoot);
services.AddJsonLanguageLocalizer(Stream stream);
services.AddJsonLanguageLocalizer(string path);
services.AddJsonLanguageLocalizer(Action<JsonConfigurationSource> configureSource);
services.AddJsonLanguageLocalizer(string path, bool optional);
services.AddJsonLanguageLocalizer(string path, bool optional, bool reloadOnChange);
Take note that the default constructor register the instance without any data loaded.
Data should be provided when registering the service but it can be loaded/overrided at any time since it's a singleton service.
services.AddJsonLanguageLocalizerSupportedCultures();
services.AddJsonLanguageLocalizerSupportedCultures(JsonLanguageLocalizerSupportedCulturesService jsonLanguageLocalizerSupportedCulturesService);
services.AddJsonLanguageLocalizerSupportedCultures(Func<IServiceProvider, JsonLanguageLocalizerSupportedCulturesService> provider);
services.AddJsonLanguageLocalizerSupportedCultures(ConfigurationBuilder configurationBuilder);
services.AddJsonLanguageLocalizerSupportedCultures(IConfiguration configuration);
services.AddJsonLanguageLocalizerSupportedCultures(IConfigurationRoot configurationRoot);
services.AddJsonLanguageLocalizerSupportedCultures(Stream stream);
services.AddJsonLanguageLocalizerSupportedCultures(string path);
services.AddJsonLanguageLocalizerSupportedCultures(Action<JsonConfigurationSource> configureSource);
services.AddJsonLanguageLocalizerSupportedCultures(string path, bool optional);
services.AddJsonLanguageLocalizerSupportedCultures(string path, bool optional, bool reloadOnChange);
Take note that the default constructor register the instance without any data loaded.
Data should be provided when registering the service but it can be loaded/overrided at any time since it's a singleton service.
IJsonLanguageLocalizerService JsonLanguageLocalizerService { get; set; }
IJsonLanguageLocalizerSupportedCulturesService JsonLanguageLocalizerSupportedCulturesService { get; set; }
void ChangeLanguageLocalizer(JsonLanguageLocalizerService jsonLanguageLocalizerService);
void ChangeLanguageLocalizer(JsonLanguageLocalizerService jsonLanguageLocalizerService);
public JsonLanguageLocalizerService();
public JsonLanguageLocalizerService(ConfigurationBuilder configurationBuilder);
public JsonLanguageLocalizerService(Stream stream);
public JsonLanguageLocalizerService(string path);
public JsonLanguageLocalizerService(Action<JsonConfigurationSource> configureSource);
public JsonLanguageLocalizerService(string path, bool optional);
public JsonLanguageLocalizerService(string path, bool optional, bool reloadOnChange);
public JsonLanguageLocalizerService(IConfiguration configuration);
public JsonLanguageLocalizerService(IConfigurationRoot configurationRoot);
void ChangeLanguageLocalizerSupportedCultures(JsonLanguageLocalizerSupportedCulturesService jsonLanguageLocalizerSupportedCulturesService);
LanguageLocalizerSupportedCultures GetLanguageLocalizerSupportedCultures();
Take note that GetLanguageLocalizerSupportedCultures()
specs that the json structure is an object of type of LanguageLocalizerSupportedCultures
.
{
"supportedCultures": [
{
"name": "en",
"localSource": "/locales/en.json",
"remoteSource": "https://www.myawesomedomain.com/cultures/en.json"
},
{
"name": "es",
"localSource": "/locales/es.json",
"remoteSource": "https://www.myawesomedomain.com/cultures/es.json"
}
],
"fallbackCulture": "en",
"httpMethod": "GET",
"useRemoteSourceAlwaysWhenAvailable": true,
"useLocalSourceWhenRemoteSourceFails": true,
"localSourceStrategy": 0, //0 - FileSystem, 1 - HttpClient
"remoteRetryTimes": 3
}
If you want to name this something else then you manage this on your own.
I still invite you to use the built-in supported structure.
void ChangeLanguageLocalizerSupportedCultures(JsonLanguageLocalizerSupportedCulturesService jsonLanguageLocalizerSupportedCulturesService);
LanguageLocalizerSupportedCultures GetLanguageLocalizerSupportedCultures();
public JsonLanguageLocalizerSupportedCulturesService();
public JsonLanguageLocalizerSupportedCulturesService(ConfigurationBuilder configurationBuilder);
public JsonLanguageLocalizerSupportedCulturesService(Stream stream);
public JsonLanguageLocalizerSupportedCulturesService(string path);
public JsonLanguageLocalizerSupportedCulturesService(Action<JsonConfigurationSource> configureSource);
public JsonLanguageLocalizerSupportedCulturesService(string path, bool optional);
public JsonLanguageLocalizerSupportedCulturesService(string path, bool optional, bool reloadOnChange);
public JsonLanguageLocalizerSupportedCulturesService(IConfiguration configuration);
public JsonLanguageLocalizerSupportedCulturesService(IConfigurationRoot configurationRoot);
using JsonLanguageLocalizerNet;
using JsonLanguageLocalizerNet.Blazor.Helpers;
..//Omitted for brevity
WebAssemblyHostBuilder builder = WebAssemblyHostBuilder.CreateDefault(args);
var httpClient = new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) };
builder.Services.AddTransient(sp => httpClient);
var LanguageLocalizerSupportedCultures = await httpClient.GetJsonAsync<LanguageLocalizerSupportedCultures>("cultures/supported.json");
builder.Services
.AddJsonLanguageLocalizerSupportedCultures(new MemoryStream(Encoding.ASCII.GetBytes(Newtonsoft.Json.JsonConvert.SerializeObject(LanguageLocalizerSupportedCultures))));
builder.Services.AddJsonLanguageLocalizer();
... //Continue others service registrations
WebAssemblyHost host = builder.Build();
string applicationLocale;
//We try to lookup the locale in the browser storage
var jsRuntime = host.Services.GetRequiredService<IJSRuntime>();
applicationLocale = await jsRuntime.InvokeAsync<string>("window.localStorage.getItem", "ApplicationLocale");
if (string.IsNullOrWhiteSpace(applicationLocale))
{
//We try use the browser navigator language
var navigatorLanguage = await jsRuntime.InvokeAsync<string>("eval", "navigator.language");
//If is empty we use the fallback culture
if (string.IsNullOrWhiteSpace(navigatorLanguage))
{
//The navigator language is not supported then we use the fallback culture
applicationLocale = LanguageLocalizerSupportedCultures.FallbackCulture;
}
}
//Set the application locale with the current or fallback
await jsRuntime.InvokeAsync<string>("window.localStorage.setItem", "ApplicationLocale", applicationLocale);
//Set's the default thread current culture
var cultureInfo = new CultureInfo(applicationLocale);
CultureInfo.DefaultThreadCurrentCulture = cultureInfo;
CultureInfo.DefaultThreadCurrentUICulture = cultureInfo;
//Loads the jsonLanguageLocalizer service
var jsonLanguageLocalizer = host.Services.GetRequiredService<IJsonLanguageLocalizerService>();
//Loads the service with the source by the specified application locale
var jsonLanguageLocalizerService = await host.GetJsonLanguageLocalizerServiceFromSupportedCulturesAsync(httpClient, LanguageLocalizerSupportedCultures, applicationLocale);
//Initializes the jsonLanguageLocalizer service
jsonLanguageLocalizer.ChangeLanguageLocalizer(jsonLanguageLocalizerService);
await host.RunAsync();
This example works with Blazor WASM.
For Blazor Server/MVC/Web Api this may work as well but you should use the overloads which reads from the web server path instead of the http client, since it's more faster and efficient.
I will provide Blazor Server/MVC/Web Api examples later.
The benefits are:
- No need of compiling
- Lightweight structure over the wire compared to .resx (.xml)
- Supports compression algorithms
- Human Readable
- Shareable
- Extendable
- Portable to other platforms
- Remotely accessible or Embeddable (embedding is not recommended)
You may use JsonLanguageLocalizerNet over Resource Manager if:
- Wording may or could be changed over time.
- Translations can be remotely accessed.
- Application needs to be as lightweight as possible.
- New languages are added frequently over time.
Take note that including *.resx for every in language in your application will make your application build output bigger over time.
Take note that adding support to a new language remotely doesn't never need compiling and deploying, were .resx needs all this extra work since it's need to be compiled.
MIT