JSON Localization Resources
hishamco / my.extensions.localization.json Goto Github PK
View Code? Open in Web Editor NEWJSON Localization Resources
License: MIT License
JSON Localization Resources
License: MIT License
We can:
Add log entry
Throw an exception
Ignore and use the localization key
In this way your package could also be used in WebAssembly Blazor applications.
Any plans to support fallback-functionality? E.g. say I have a TestController and the files testcontroller.es-ES.json, testcontroller.es.json and testcontroller.json. The fallback-functionality would first check the testcontroller.es-ES.json for the key, then the testcontroller.es.json and then testcontroller.json.
Edit: Like explained here
Based on the comment #2 (comment)
I just notice there's a bug when I run the LocalizationSample.Mvc
more specifically in
This seems a regression bug from #49
I'm not sure if it's useful to have a single file that contains all the localization strings for the supported cultures
{
"Hello":
{
"en": "Hello",
"fr": "Bonjour"
}
}
Is it possible to have one resource file for all project without creating Views->Home or controllers,Views.Home.Privacy
Add benchmark project to measure the performance
After adding LocalizationSample.Mvc
few fallbacks don't work as expected:
HomeController
localized messages should come from Controllers.HomeController.fr-FR.json
instead of HomeController.fr-FR.json
Index.cshtml
is not localized because the resources located in Resources/Views/Home/Index.fr-FR.json
That means views in nested folder don't work as expected as well as Controllers namespaces are ignored
Hi,
As mentioned in the title, I'm wondering when the latest version that was just pushed will be available as a NuGet package (https://www.nuget.org/packages/My.Extensions.Localization.Json). It doesn't seem to have been updated for a while.
Please refer to http://hishambinateya.com/localization-and-generics
We need to investigate to use JSON APIs over configurations APIs to read the .json
files
It would be nice if we allow expose an option that allow the developer to set the cache duration for the localization entries
When registering service via services.AddJsonLocalization
, if the path is not an absolute one it will throw the following exception when resolving the files by IStringLocalizer
// this will cause an error when _localizer["Hello"] is called later on
services.AddJsonLocalization(options => options.ResourcesPath = "Resources");
it should be changed to
var directory = Path.Combine(Directory.GetCurrentDirectory(), "Resources");
services.AddJsonLocalization(options => options.ResourcesPath = directory);
the latter will work perfect.
I think that extra line can be moved to the library itself.
System.ArgumentException: The path must be absolute. (Parameter 'root')
at Microsoft.Extensions.FileProviders.PhysicalFileProvider..ctor(String root, ExclusionFilters filters)
at Microsoft.Extensions.FileProviders.PhysicalFileProvider..ctor(String root)
at Microsoft.Extensions.Configuration.FileConfigurationExtensions.SetBasePath(IConfigurationBuilder builder, String basePath)
at My.Extensions.Localization.Json.JsonStringLocalizer.<>c__DisplayClass17_0.<BuildResourcesCache>b__0(String _)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at My.Extensions.Localization.Json.JsonStringLocalizer.BuildResourcesCache(String culture)
at My.Extensions.Localization.Json.JsonStringLocalizer.GetStringSafely(String name)
at My.Extensions.Localization.Json.JsonStringLocalizer.get_Item(String name)
at My.Extensions.Localization.Json.Internal.StringLocalizer.get_Item(String name)
HEADERS
=======
Accept-Language: fr-FR
I have a basic structure like this
/MyProject.csproj
/Resources/Problems.cs
/Resources/Problems.en-GB.json
If I try to use IStringLocalizer<Problems>
with this configuration, my localisation strings don't work.
However, if I change my file structure to this
/MyProject.csproj
/Problems.cs
/Resources/Problems.en-GB.json
Then the strings now work.
It seems that we can only use classes so long as they exist in the root namespace. You can't place the class anywhere else.
Would be preferable if we can put the marker classes in the same folder as the resources.
Align with #33 it would be nice if the underlying caching mechanism is changeable
Here is the code in my xunit test project
App = new WebApplicationFactory<TProgram>().WithWebHostBuilder(builder => {});
Client = App.CreateClient();
when I run a unit test,the web application throw exception of DirectoryNotFoundException.the console output is under below.
I noticed that JsonStringLocalizerFactory.Create Method called PathHelpers.GetApplicationRoot(),the PathHelpers.GetApplicationRoot() Method simply call Assembly.GetExecutingAssembly().Location. that's the problem. Assembly.GetExecutingAssembly().Location Gets the current executing assembly which is my test project assembly. it returned a path of my test project build directory. normally, I want JsonStringLocalizer to locate the resources file in the Resource directory under my web project, but a unit test can't do that.the Microsoft's StringLocalization is working well in my unit test project.I also noticed that they are using WebApplicationFactoryContentRootAttribute to resolve the localization resources directory. check this document How the test infrastructure infers the app content root path
.Please solve this issue.If something I've missed or went wrong,Please tell me.Thank you.
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
An unhandled exception has occurred while executing the request.
System.IO.DirectoryNotFoundException: Could not find a part of the path '/PathToSolution/TestProject/bin/Debug/net6.0/Resources'.
at System.IO.Enumeration.FileSystemEnumerator`1.CreateDirectoryHandle(String path, Boolean ignoreNotFound)
at System.IO.Enumeration.FileSystemEnumerator`1.Init()
at System.IO.Enumeration.FileSystemEnumerator`1..ctor(String directory, Boolean isNormalized, EnumerationOptions options)
at System.IO.Enumeration.FileSystemEnumerable`1..ctor(String directory, FindTransform transform, EnumerationOptions options, Boolean isNormalized)
at System.IO.Enumeration.FileSystemEnumerableFactory.UserFiles(String directory, String expression, EnumerationOptions options)
at System.IO.Directory.InternalEnumeratePaths(String path, String searchPattern, SearchTarget searchTarget, EnumerationOptions options)
at System.IO.Directory.EnumerateFiles(String path, String searchPattern)
at My.Extensions.Localization.Json.Internal.JsonResourceManager.TryLoadResourceSet(CultureInfo culture)
at My.Extensions.Localization.Json.Internal.JsonResourceManager.GetResourceSet(CultureInfo culture, Boolean tryParents)
at My.Extensions.Localization.Json.Internal.JsonResourceManager.GetString(String name)
at My.Extensions.Localization.Json.JsonStringLocalizer.GetStringSafely(String name, CultureInfo culture)
at My.Extensions.Localization.Json.JsonStringLocalizer.get_Item(String name)
at Microsoft.Extensions.Localization.StringLocalizer`1.get_Item(String name)
I trued using the package and it works fine with simpple json like : {
"Hello": "Bonjour"
}
But it did not work with complex json like
{
"Hello": {
"Key": "Hello"
}
}
I tried using localizer["Hello.Key"] to access the value Hello.
Is it possible with this package, if yes how.
Or else can you please add that functionality as well.
I have a project that needs to be localized,so many view model , is there a simpler way to write?
Adding AppVeyor, Travis and AzurePipeline to make sure that a new commit doesn't break anything
I wanted DataAnnotations Like [Required], [Display], [Range] to be localized. I tried some ways as I found over StackOverflow etc but nothing seems right for this Json localizer.
Any idea on how to accomplish the same. Sample code would be really helpfull.
Unable to Create call IStringLocalizer Create(string baseName, string location)
in case of ResourcesType.TypeBased
FileLoadException: The given assembly name or codebase was invalid. (0x80131047)
in StringLocalizer.cs
_localizer = factory.Create(string.Empty, PathHelpers.GetApplicationRoot());
In version 3.0.1 it was possible to use hierarchical keys (:) thanks to the configurations API that is used https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-7.0#configuration-keys-and-values. After this issue #29 and this change ecf7169 that stopped being supported in version 3.1.0.
Would it be possible to bring support for this back, or should an alternate approach be taken?
Seems I forgot this on
Is it possible to use it with DataAnnotation
? Any sample?
Seems it's good practice to make sure that everything is work as expected, so unit tests can help to validate almost if not all the covered cases
It would be nice to be able to override methods in in JsonStringLocalizer
and JsonStringLocalizerFactory
by making them virtual and at least using the protected modifier. E.g. if I'd like to change the functionality on how the cache is build, there is currently no way of overriding just that method (BuildResourcesCache
), I'd have to make a new localizer by copying the content from JsonStringLocalizer
.
Stumbled upon this when wanting to try to implement a temporary workaround to support the #39 functionality for the current release.
If we add expression to IStringLocalizerOfT
members this will allow us to do the following:
public class SharedResource
{
public string Name { get; set; }
}
var localizer = new StringLocalizer<SharedResource>();
Console.WriteLine(localizer[p => p.Name]);
Console.WriteLine(localizer.GetString(p => p.Name));
When I dotnet run
LocalizationSample I get the following errror:
Application startup exception: System.Exception: Could not resolve a service of type 'Microsoft.Extensions.Localization.IStringLocalizer' for the parameter 'localizer1' of method 'Configure' on type 'LocalizationSample.Startup'.
---> System.IO.FileLoadException: The given assembly name or codebase was invalid. (0x80131047)
at System.Reflection.AssemblyName.nInit()
at System.Reflection.AssemblyName..ctor(String assemblyName)
at My.Extensions.Localization.Json.JsonStringLocalizerFactory.<>c__DisplayClass7_0.b__0(String _) in C:\Users\nemke\Documents\GitHub\My.Extensions.Localization.Json\src\My.Extensions.Localization.Json\JsonStringLocalizerFactory.cs:line 81
When I remove IStringLocalizer localizer1
from injecting into ctor of Configure method, the sample runs ok.
In my project i make use of
.AddDataAnnotationsLocalization(options => { options.DataAnnotationLocalizerProvider = (type, factory) => factory.Create(type); });
Sometimes i get an exception where it tries to do a substring.
it fails on the following assembly and typeinfo.
It also occures with typeInfo.FullName = "System.string".
I think it occures when i have a url like /user/guid here/profile
A possible 'fix' would be the following:
var typeName = $"{assemblyName}.{typeInfo.Name}" == typeInfo.FullName ? typeInfo.Name : assemblyName?.Length + 1 > typeInfo.FullName?.Length ? typeInfo.Name : typeInfo.FullName.Substring(assemblyName.Length + 1);
But i don't know your codebase enough to know the consequences.
I included the stacktrace
An unhandled exception has occurred while executing the request. System.ArgumentOutOfRangeException: startIndex cannot be larger than length of string. (Parameter 'startIndex') at System.String.Substring(Int32 startIndex, Int32 length) at System.String.Substring(Int32 startIndex) at My.Extensions.Localization.Json.JsonStringLocalizerFactory.Create(Type resourceSource) in /Users/me/Downloads/My.Extensions.Localization.Json-dev/src/My.Extensions.Localization.Json/JsonStringLocalizerFactory.cs:line 57 at Api.Entreo.Nl.Startup.<>c.<ConfigureServices>b__5_15(Type type, IStringLocalizerFactory factory) in /Users/me/Projects/project/api/Startup.cs:line 110 at Microsoft.AspNetCore.Mvc.DataAnnotations.DataAnnotationsMetadataProvider.CreateDisplayMetadata(DisplayMetadataProviderContext context) at Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.DefaultCompositeMetadataDetailsProvider.CreateDisplayMetadata(DisplayMetadataProviderContext context) at Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.DefaultModelMetadata.get_DisplayMetadata() at Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.DefaultModelMetadata.get_IsEnum() at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.EnumTypeModelBinderProvider.GetBinder(ModelBinderProviderContext context) at Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderFactory.CreateBinderCoreUncached(DefaultModelBinderProviderContext providerContext, Object token) at Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderFactory.CreateBinder(ModelBinderFactoryContext context) at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.GetParameterBindingInfo(IModelBinderFactory modelBinderFactory, IModelMetadataProvider modelMetadataProvider, ControllerActionDescriptor actionDescriptor, MvcOptions mvcOptions)
Parameter type and json file name in LocalizationSample
are inconsistent.
There is
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IStringLocalizer<Model> localizer)
in Startup
class. However the the file name is Startup.fr-FR.json
.
Either the file name should be Model.fr-FR.json
or the parameter should be IStringLocalizer<Startup>
.
I am currently using .NET 8 with Interactive Auto for Blazor and having trouble getting the WASM part working. I was able to get the Server Part working with:
builder.Services.AddJsonLocalization(options => options.ResourcesPath = "wwwroot/Resources");
But that doesn't seem to work on the Wasm part.
The console error I get is:
One or more errors occurred. (Value cannot be null. (Parameter 'path1'))
I am using a general file: "fr-FR.json" similar to one of the samples in the repo.
Let me know if you have an idea on how to get it working.
Check if we can remove the internal constructor of JsonStringLocalizer
without breaking things
Hey, thanks for the short and sweet library. Unfortunately, I doesn't work in a multi-project scenario because the base directory is always the one that is currently executing (probably the web project) and then resources are referenced relative to that.
But what I want to support is for example:
MyCompany.Core
Resources
SomeCoreSpecificResources.de-CH.json
MyCompany.Web
Resources
SomeWebSpecificResources.de-CH.json
So the JSON needs to be found in a different project. My idea is to embed the JSON into the assembly so that path manipulations and such become obsolete. I'll probably fork from your project to give it a try.
I quote from PR #6
In my solution, I have single localization file for each language (i.e. en.json, ar.json etc.).
A limited set of ASP.NET Core's localization scenarios are currently supported:
IStringLocalizer and IStringLocalizer are supported in Blazor apps.
IHtmlLocalizer, IViewLocalizer, and Data Annotations localization are ASP.NET Core MVC scenarios and not supported in Blazor apps.
When I use it, there's a Microsoft.AspNetCore.Mvc.Localization reference, so can this library separate the code so that NET5.0 Blazor WebAssembly works.
Also, can the name of this library be changed to a more formal name? The name gives a less formal feel.
Hi,
I've been using this (great) library for a while but ever since I switched to deploying my applications to Debian I've started running into issues with weird errors where after a while, I hit the inotify instance limit
set by my webserver.
The configured user limit (128) on the number of inotify instances has been reached, or the per-process limit on the number of open file descriptors has been reached.
After some digging, I noticed that this is a problem in core ASP.NET aswell, specifically when adding the AppSettings.json to your app configuration on startup:
dotnet/AspNetCore.Docs#19814
I've managed to track the root cause of this down to this library, specifically the JsonResourceManager. Every time I hit an API endpoint which would return a localized json resource string using this library, a new inotify watch instance
seems to be created. These instances are not disposed until I manually restart my application.
The JsonResourceManager seems to be using the same reloadOnChange
functionality here:
https://github.com/hishamco/My.Extensions.Localization.Json/blob/dev/src/My.Extensions.Localization.Json/Internal/JsonResourceManager.cs#L181
Which in my opinion, should really only be enabled when developing locally - after deployment the resource files should generally not change.
After forking this library and changing reloadOnChange: true
to reloadOnChange: false
, I've confirmed that this fixes the problem with endless inotify instances
being created without being disposed.
Relevant issue in ASP.NET repository:
dotnet/runtime#27272
dotnet/runtime#37664
dotnet/runtime#62869
I want to configure culture in appsettings.json. If exist a way to assign culture in runtime?
I tried in startup.cs put below
const string culture = "fr-FR";
CultureInfo ci = CultureInfo.GetCultureInfo(culture);
Thread.CurrentThread.CurrentCulture = ci;
Thread.CurrentThread.CurrentUICulture = ci;
But it did not help....
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.