Asp.net core: Multilingual international custom resource files, core resource files

Source: Internet
Author: User

asp.net core multilingual internationalization custom resource file, core resource file

Let's talk about asp.net core's default multilingual and internationalization. Official document

1: Basic usage

First install the package Microsoft.AspNetCore.Mvc.Localization (depending on Microsoft.Extensions.Localization), and then use the resource file to save data corresponding to different languages.

1. Inject IViewLocalizer in the view page, and then use it where needed. such as:

1 @inject IViewLocalizer Localizer

3 <h2> @Localizer ["hello"] </ h2>
 

The characters in the brackets are the names in the resource file. After running, the output is the resource value set under the resource file corresponding to the current language.

So there is a question, how to set the resource file? 1. By default, it will look for the folder corresponding to the set LocalizationOptions.ResourcesPath value. If it is not set, it will look under the root directory.

Set ResourcesPath in Startup.

services.AddLocalization (options => options.ResourcesPath = "Resources");
2. Find the resource file with the same name as the current view file. There are two ways to search by dot. And path by default. Of course, you can also specify one of them. For example, the current view path is views / account / login.cshtml, then the resource files to look up are views / account / login. {CultureName} .resx file and views.account.login. {CultureName} .resx file

services.AddMvc ()
         .AddViewLocalization ()
          //.AddViewLocalization(Microsoft.AspNetCore.Mvc.Razor.LanguageViewLocationExpanderFormat.SubFolder)
          .AddDataAnnotationsLocalization ();
3. If it is a model class, the search path becomes the full namespace of the typeof (model) .FullName namespace corresponding to the model class. Examples are the ViewModels / account / login. {CultureName} .resx file and the ViewModels.account.login. {CultureName} .resx file. Similarly, if it is in the controller, the resource file is Controllers.HomeController. {CultureName} .resx or Controllers / HomeController. {CultureName} .resx


2: Analysis

So how does this work? If I want to use a database or a json file to store these resource files.

The IViewLocalizer interface is injected into the attempt file, and the corresponding implementation is ViewLocalizer. ViewLocalizer implements the definitions of IViewLocalizer and IHtmlLocalizer, and IViewLocalizer inherits from IHtmlLocalizer. ViewLocalizer will inject an IHtmlLocalizerFactory, and then use IHtmlLocalizerFactory to create an instance of IHtmlLocalizer. When creating, two parameters will be brought in, one is the path currently being tried, and one is the current application name.

 

IHtmlLocalizer is defined as follows:

 

So in the instance of IHtmlLocalizer, you can easily get the corresponding value.

Because ViewLocalizer will inject an instance of IHtmlLocalizerFactory. The default instance is HtmlLocalizerFactory. An instance of IStringLocalizerFactory (located in Microsoft.Extensions.Localization.Abstractions) is injected into the constructor of HtmlLocalizerFactory.

Is defined as

 

The definition of IHtmlLocalizerFactory is

 

It can be said that HtmlLocalizerFactory is a wrapper for HtmlLocalizerFactory.

 

Check the code to know that the default implementation of IStringLocalizerFactory is ResourceManagerStringLocalizerFactory, and reading resource files is the operation of this implementation.

 

Back to the question at the beginning, suppose I want to use a json file instead of a resx file. How to achieve it. ? There are 2 ways

1) Just implement the corresponding IStringLocalizerFactory and replace the default ResourceManagerStringLocalizerFactory.


2) Override ResourceManagerStringLocalizerFactory.











1) 1. Define a JsonStringLocalizerFactory and implement IStringLocalizerFactory.

public class JsonStringLocalizerFactory: IStringLocalizerFactory
    {
        private readonly string _applicationName;
        private readonly IHostingEnvironment _hostingEnvironment;
        private readonly LocalizationOptions _options;
        public JsonStringLocalizerFactory (IHostingEnvironment hostingEnvironment, IOptions <LocalizationOptions> localizationOptions)
        {
            if (localizationOptions == null)
            {
                throw new ArgumentNullException (nameof (localizationOptions));
            }
            this._hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException (nameof (hostingEnvironment));
            this._options = localizationOptions.Value;
            this._applicationName = hostingEnvironment.ApplicationName;
        }

        public IStringLocalizer Create (Type resourceSource)
        {
            TypeInfo typeInfo = IntrospectionExtensions.GetTypeInfo (resourceSource);
            // Assembly assembly = typeInfo.Assembly;
            // AssemblyName assemblyName = new AssemblyName (assembly.FullName);

            string baseResourceName = typeInfo.FullName;
            baseResourceName = TrimPrefix (baseResourceName, _applicationName + ".");

            return new JsonStringLocalizer (_hostingEnvironment, _options, baseResourceName, null);
        }

        public IStringLocalizer Create (string baseName, string location)
        {
            location = location ?? _applicationName;

            string baseResourceName = baseName;
            baseResourceName = TrimPrefix (baseName, location + ".");

            return new JsonStringLocalizer (_hostingEnvironment, _options, baseResourceName, null);
        }

        private static string TrimPrefix (string name, string prefix)
        {
            if (name.StartsWith (prefix, StringComparison.Ordinal))
            {
                return name.Substring (prefix.Length);
            }

            return name;
        }
    }
 

2, JsonStringLocalizer

public class JsonStringLocalizer: IStringLocalizer
    {
        private readonly ConcurrentDictionary <string, string> _all;

        private readonly IHostingEnvironment _hostingEnvironment;
        private readonly LocalizationOptions _options;

        private readonly string _baseResourceName;
        private readonly CultureInfo _cultureInfo;

        public LocalizedString this [string name] => Get (name);
        public LocalizedString this [string name, params object [] arguments] => Get (name, arguments);

        public JsonStringLocalizer (IHostingEnvironment hostingEnvironment, LocalizationOptions options, string baseResourceName, CultureInfo culture)

asp.net core multilingual internationalization custom resource file, core resource file

Let's talk about asp.net core's default multilingual and internationalization. Official document

1: Basic usage

First install the package Microsoft.AspNetCore.Mvc.Localization (depending on Microsoft.Extensions.Localization), and then use the resource file to save data corresponding to different languages.

1. Inject IViewLocalizer in the view page, and then use it where needed. such as:

1 @inject IViewLocalizer Localizer

3 <h2> @Localizer ["hello"] </ h2>
 

The characters in the brackets are the names in the resource file. After running, the output is the resource value set under the resource file corresponding to the current language.

So there is a question, how to set the resource file? 1. By default, it will look for the folder corresponding to the set LocalizationOptions.ResourcesPath value. If it is not set, it will look under the root directory.

Set ResourcesPath in Startup.

services.AddLocalization (options => options.ResourcesPath = "Resources");
2. Find the resource file with the same name as the current view file. There are two ways to search by dot. And path by default. Of course, you can also specify one of them. For example, the current view path is views / account / login.cshtml, then the resource files to look up are views / account / login. {CultureName} .resx file and views.account.login. {CultureName} .resx file

services.AddMvc ()
         .AddViewLocalization ()
          //.AddViewLocalization(Microsoft.AspNetCore.Mvc.Razor.LanguageViewLocationExpanderFormat.SubFolder)
          .AddDataAnnotationsLocalization ();
3. If it is a model class, the search path becomes the full namespace of the typeof (model) .FullName namespace corresponding to the model class. Examples are the ViewModels / account / login. {CultureName} .resx file and the ViewModels.account.login. {CultureName} .resx file. Similarly, if it is in the controller, the resource file is Controllers.HomeController. {CultureName} .resx or Controllers / HomeController. {CultureName} .resx


2: Analysis

So how does this work? If I want to use a database or a json file to store these resource files.

The IViewLocalizer interface is injected into the attempt file, and the corresponding implementation is ViewLocalizer. ViewLocalizer implements the definitions of IViewLocalizer and IHtmlLocalizer, and IViewLocalizer inherits from IHtmlLocalizer. ViewLocalizer will inject an IHtmlLocalizerFactory, and then use IHtmlLocalizerFactory to create an instance of IHtmlLocalizer. When creating, two parameters will be brought in, one is the path currently being tried, and one is the current application name.

 

IHtmlLocalizer is defined as follows:

 

So in the instance of IHtmlLocalizer, you can easily get the corresponding value.

Because ViewLocalizer will inject an instance of IHtmlLocalizerFactory. The default instance is HtmlLocalizerFactory. An instance of IStringLocalizerFactory (located in Microsoft.Extensions.Localization.Abstractions) is injected into the constructor of HtmlLocalizerFactory.

Is defined as

 

The definition of IHtmlLocalizerFactory is

 

It can be said that HtmlLocalizerFactory is a wrapper for HtmlLocalizerFactory.

 

Check the code to know that the default implementation of IStringLocalizerFactory is ResourceManagerStringLocalizerFactory, and reading resource files is the operation of this implementation.

 

Back to the question at the beginning, suppose I want to use a json file instead of a resx file. How to achieve it. ? There are 2 ways

1) Just implement the corresponding IStringLocalizerFactory and replace the default ResourceManagerStringLocalizerFactory.


2) Override ResourceManagerStringLocalizerFactory.











1) 1. Define a JsonStringLocalizerFactory and implement IStringLocalizerFactory.

public class JsonStringLocalizerFactory: IStringLocalizerFactory
    {
        private readonly string _applicationName;
        private readonly IHostingEnvironment _hostingEnvironment;
        private readonly LocalizationOptions _options;
        public JsonStringLocalizerFactory (IHostingEnvironment hostingEnvironment, IOptions <LocalizationOptions> localizationOptions)
        {
            if (localizationOptions == null)
            {
                throw new ArgumentNullException (nameof (localizationOptions));
            }
            this._hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException (nameof (hostingEnvironment));
            this._options = localizationOptions.Value;
            this._applicationName = hostingEnvironment.ApplicationName;
        }

        public IStringLocalizer Create (Type resourceSource)
        {
            TypeInfo typeInfo = IntrospectionExtensions.GetTypeInfo (resourceSource);
            // Assembly assembly = typeInfo.Assembly;
            // AssemblyName assemblyName = new AssemblyName (assembly.FullName);

            string baseResourceName = typeInfo.FullName;
            baseResourceName = TrimPrefix (baseResourceName, _applicationName + ".");

            return new JsonStringLocalizer (_hostingEnvironment, _options, baseResourceName, null);
        }

        public IStringLocalizer Create (string baseName, string location)
        {
            location = location ?? _applicationName;

            string baseResourceName = baseName;
            baseResourceName = TrimPrefix (baseName, location + ".");

            return new JsonStringLocalizer (_hostingEnvironment, _options, baseResourceName, null);
        }

        private static string TrimPrefix (string name, string prefix)
        {
            if (name.StartsWith (prefix, StringComparison.Ordinal))
            {
                return name.Substring (prefix.Length);
            }

            return name;
        }
    }
 

2, JsonStringLocalizer

public class JsonStringLocalizer: IStringLocalizer
    {
        private readonly ConcurrentDictionary <string, string> _all;

        private readonly IHostingEnvironment _hostingEnvironment;
        private readonly LocalizationOptions _options;

        private readonly string _baseResourceName;
        private readonly CultureInfo _cultureInfo;

        public LocalizedString this [string name] => Get (name);
        public LocalizedString this [string name, params object [] arguments] => Get (name, arguments);

        public JsonStringLocalizer (IHostingEnvironment hostingEnvironment, LocalizationOptions options, string baseResourceName, CultureInfo culture)
return _all.Select (t => new LocalizedString (t.Key, t.Value, true)). ToArray ();
        }

        public IStringLocalizer WithCulture (CultureInfo culture)
        {
            if (culture == null)
                return this;

            CultureInfo.CurrentUICulture = culture;
            CultureInfo.DefaultThreadCurrentCulture = culture;

            return new JsonStringLocalizer (_hostingEnvironment, _options, _baseResourceName, culture);
        }

        private LocalizedString Get (string name, params object [] arguments)
        {
            if (_all.ContainsKey (name))
            {
                var current = _all [name];
                return new LocalizedString (name, string.Format (_all [name], arguments));
            }
            return new LocalizedString (name, name, true);
        }

        private ConcurrentDictionary <string, string> GetAll ()
        {
            var file = Path.Combine (_hostingEnvironment.ContentRootPath, _baseResourceName + ".json");
            if (! string.IsNullOrEmpty (_options.ResourcesPath))
                file = Path.Combine (_hostingEnvironment.ContentRootPath, _options.ResourcesPath, _baseResourceName + ".json");

            Debug.WriteLineIf (! File.Exists (file), "Path not found!" + File);

            if (! File.Exists (file))
                return new ConcurrentDictionary <string, string> ();

            try
            {
                var txt = File.ReadAllText (file);

                return JsonConvert.DeserializeObject <ConcurrentDictionary <string, string >> (txt);
            }
            catch (Exception)
            {
            }

            return new ConcurrentDictionary <string, string> ();
        }
    }
 

3. Add injection

services.AddSingleton <IStringLocalizerFactory, JsonStringLocalizerFactory> ();
 

4, json file

 

The above code simply implements a json file using dots (.) As a separator as a resource file. (Actually there is a small problem after the above code runs)

 

The code has been placed on Github

 

2). To be realized ~~~

 

Link: http://blog.wuliping.cn/post/aspnet-core-localization-and-custom-resource-service-with-file

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.