Search code examples
c#asp.netjsonasp.net-corelocalization

Asp.net Core localization with json files


I'm trying to find a good tutorial about asp.net localization. In the official documentation, the explanation are about .resx files and I want to use json files.

If someone have a good tutorial on how to write the middleware to do that.

Thanks


Solution

  • Nuget Package

    https://www.nuget.org/packages/Askmethat.Aspnet.JsonLocalizer/

    Solution

    After some investigations, I finally find an example in Asp/Localization GitHub.

    I provide here for people that want to use a flat JSON without breaking default culture provider.

    Data :

    The flat JSON:

    [
      {
        "Key": "Hello",
        "LocalizedValue" : {
          "fr-FR": "Bonjour",
          "en-US": "Hello"
        }
      }
    ]
    

    The C# model:

    class JsonLocalization
    {
        public string Key { get; set; }
        public Dictionary<string, string> LocalizedValue = new Dictionary<string, string>();
    }
    

    The Middleware

    The Factory

    This is just to have access to the CultureInfo is the StringLocalizer.

     public class JsonStringLocalizerFactory : IStringLocalizerFactory
     {
        public IStringLocalizer Create(Type resourceSource)
        {
            return new JsonStringLocalizer();
        }
    
        public IStringLocalizer Create(string baseName, string location)
        {
            return new JsonStringLocalizer();
        }
     }
    

    The Localizer

    The logic to get the data from the JSON file

    public class JsonStringLocalizer : IStringLocalizer
    {
        List<JsonLocalization> localization = new List<JsonLocalization>();
    
        public JsonStringLocalizer()
        {
            //read all json file
            JsonSerializer serializer = new JsonSerializer();
            localization = JsonConvert.DeserializeObject<List<JsonLocalization>>(File.ReadAllText(@"localization.json"));
        }
    
        public LocalizedString this[string name]
        {
            get
            {
                var value = GetString(name);
                return new LocalizedString(name, value ?? name, resourceNotFound: value == null);
            }
        }
    
        public LocalizedString this[string name, params object[] arguments]
        {
            get
            {
                var format = GetString(name);
                var value = string.Format(format ?? name, arguments);
                return new LocalizedString(name, value, resourceNotFound: format == null);
            }
        }
    
        public IEnumerable<LocalizedString> GetAllStrings(bool includeParentCultures)
        {
            return localization.Where(l => l.LocalizedValue.Keys.Any(lv => lv == CultureInfo.CurrentCulture.Name)).Select(l => new LocalizedString(l.Key, l.LocalizedValue[CultureInfo.CurrentCulture.Name], true));
        }
    
        public IStringLocalizer WithCulture(CultureInfo culture)
        {
            return new JsonStringLocalizer();
        }
    
        private string GetString(string name)
        {
            var query = localization.Where(l => l.LocalizedValue.Keys.Any(lv => lv == CultureInfo.CurrentCulture.Name));
            var value = query.FirstOrDefault(l => l.Key == name);
            return value.LocalizedValue[CultureInfo.CurrentCulture.Name];
        }
    }
    

    With this solution you are able to use the basic IStringLocalizer in your Views and Controllers.

    Of course if you have a big json file, you can use IMemoryCache or IDistributedMemoryCache to improve performance.

    EDIT :

    In the application Startup add this lines to use your own implementation :

    services.AddSingleton<IStringLocalizerFactory, JsonStringLocalizerFactory>();
    services.AddSingleton<IStringLocalizer, JsonStringLocalizer>();
    services.AddLocalization(options => options.ResourcesPath = "Resources");
    

    After that you can configure as you want your globalization preferences.