26
loading...
This website collects cookies to deliver better user experience
json
file:using System.Collections.Generic;
namespace I18N
{
internal class JsonLocalization
{
public string Key { get; set; }
public Dictionary<string, string> LocalizedValues { get; set; }
}
}
Key
is an unique identifier for the localization and LocalizedValues
is a dictionary, which its key is the language and the value the text that must be displayed.Exception
, to easily pinpoint what went wrong with the application.using System;
namespace I18N
{
public class I18NException : Exception
{
public I18NException(string message) : base(message)
{
}
public I18NException(string message, Exception innerException) : base(message, innerException)
{
}
public I18NException()
{
}
}
}
JsonLocalizer
class will read our json resources files
, store them in memory and make them available to our application.useBase
and additionalPaths
.useBase
is set to true, the localizer will load *.json
files that are in the Resources
folder.additionalPaths
uses a type as a key, the localizer will use this type to find the assembly path and read the *.json
files in the Resources
folder.using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using Newtonsoft.Json;
namespace I18N
{
public class JsonLocalizer
{
private readonly Dictionary<string, JsonLocalization[]> _localization
= new Dictionary<string, JsonLocalization[]>();
public JsonLocalizer(bool useBase = true, Dictionary<Type, string> additionalPaths = null)
{
if (useBase)
PopulateLocalization("Resources");
if (additionalPaths == null) return;
foreach (var additional in additionalPaths)
{
var codeBase = additional.Key.Assembly.CodeBase;
var uri = new UriBuilder(codeBase);
var data = Uri.UnescapeDataString(uri.Path);
var path = Path.GetDirectoryName(data);
var fullPath = Path.Combine(path, additional.Value);
PopulateLocalization(fullPath);
}
}
/// <summary>
/// resource:key:culture
/// resource is the resource name
/// key is the key you're looking for
/// culture is optional
/// </summary>
/// <param name="key"></param>
public string this[string key] => GetString(key);
private void PopulateLocalization(string path)
{
foreach (var resource in Directory.GetFiles(path, "*.json", SearchOption.AllDirectories))
{
try
{
var fileInfo = new FileInfo(resource);
var fileName = fileInfo.Name.Substring(0, fileInfo.Name.IndexOf('.'));
var loc = JsonConvert.DeserializeObject<JsonLocalization[]>(File.ReadAllText(resource));
_localization.Add(fileName, loc);
}
catch (ArgumentException e)
{
throw new I18NException($"Resource {resource} was already added, check your files.", e);
}
catch (Exception ex)
{
throw new I18NException("Something wrong is not right, check inner exception", ex);
}
}
}
private string GetString(string query)
{
try
{
string culture = null;
var split = query.Split(':');
var resource = split[0];
var key = split[1];
if (split.Length > 2)
culture = split[2];
culture = culture ?? CultureInfo.CurrentCulture.Name;
return _localization
.Single(l => l.Key == resource)
.Value.Single(x => x.Key == key)
.LocalizedValues[culture];
}
catch (Exception ex)
{
throw new I18NException($"Couldn't find key: {query}", ex);
}
}
}
}
dotnet core
applications, you can add the JsonLocalizer
using the IServiceCollection
in the ConfigureServices
method.// use it in DI as a singleton
public void ConfigureServices(IServiceCollection services)
{
// Other configurations ...
services.AddSingleton<JsonLocalizer>();
}
additionalPaths
var additional = new Dictionary<Type, string>
{
{ typeof(MyClass), "My Resource Folder" },
{ typeof(MyAnotherClass), "My Resource Folder/Even Handles sub folders" }
};
var withExternalSources = new JsonLocalizer(additionalPaths: additional);
private readonly JsonLocalizer _localizer;
public class MySampleClass(JsonLocalizer localizer)
{
_localizer = localizer;
}
public string GetLocalizedMessage()
{
return _localizer["MyAppResource:MyKey"];
}
FileName:Key:Language
File Name | Resource Name |
---|---|
MyResource.json | MyResource |
MyApp.Resource.json | MyApp |
MyApp-Errors.Resource.json | MyApp-Errors |
MyApp.Errors.Resource.json | MyApp |
Key
is the key inside the resource file, and the Language
is the culture, if not informed, will use the CultureInfo.CurrentCulture
value.json
resource file should follow this format:[
{
"Key":"Name",
"LocalizedValues":{
"en-US":"Name",
"pt-BR":"Nome"
}
},
{
"Key":"Age",
"LocalizedValues":{
"en-US":"Age",
"pt-BR":"Idade"
}
}
]