Because the IStringLocalizer
is implemented on ResourceManagerStringLocalizer
setting CultureInfo.CurrentUICulture
is the only way to change the culture on the fly.
IStringLocalizer Localizer = ServiceHelper.GetService<IStringLocalizer<AppStrings>>();
CultureInfo.CurrentUICulture = new CultureInfo("en-US");
var HelloEN = Localizer["Hello"];
CultureInfo.CurrentUICulture = new CultureInfo("fr-FR");
var HelloFR = Localizer["Hello"];
However, the automatically generated ResX file has ResourceManager
which it access with either CultureInfo.CurrentUICulture
or its local Culture
static member. Here's a demonstration of both:
CultureInfo.CurrentUICulture = new CultureInfo("en-US");
var HelloEN = AppStrings.Hello;
CultureInfo.CurrentUICulture = new CultureInfo("fr-FR");
var HelloFR = AppStrings.Hello;
AppString.Culture = new CultureInfo("es-ES");
var HelloES = AppStrings.Hello;
The current ResourceManagerStringLocalizer
is unaware of the AppStrings.Culture
property, so, you cannot use it with ResrouceManagerStringLocalizer
.
A solution is to build your own using reflection to retrieve the Culture
and ResourceManager
from the ResX:
public class ResourceStringLocalizer<TStringResource> : IStringLocalizer
{
private Type _stringResource;
private PropertyInfo _cultureProperty;
private PropertyInfo _resourceManagerProperty;
private ResourceManager _resourceManager;
private CultureInfo Culture
=> _cultureProperty?.GetValue(null) as CultureInfo;
public IEnumerable<LocalizedString> GetAllStrings(bool includeParentCultures)
{
throw new NotImplementedException();
}
public LocalizedString this[string name]
{
get
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
var value = _resourceManager?.GetString(name, Culture);
return new LocalizedString(name, value ?? name, resourceNotFound: value == null);
}
}
public LocalizedString this[string name, params object[] arguments]
{
get
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
var format = _resourceManager?.GetString(name, Culture);
var value = string.Format(format ?? name, arguments);
return new LocalizedString(name, value ?? name, resourceNotFound: value == null);
}
}
public ResourceStringLocalizer()
{
_stringResource = typeof(TStringResource);
_cultureProperty = _stringResource?.GetProperty("Culture", BindingFlags.Static | BindingFlags.NonPublic);
_resourceManagerProperty = _stringResource?.GetProperty("ResourceManager", BindingFlags.Static | BindingFlags.NonPublic);
_resourceManager = _resourceManagerProperty?.GetValue(null) as ResourceManager;
}
}
Here's a demo of the above class:
IStringLocalizer Localizer = new ResourceStringLocalizer<AppStrings>();
CultureInfo.CurrentUICulture = new CultureInfo("en-US");
var HelloEN = Localizer["Hello"];
CultureInfo.CurrentUICulture = new CultureInfo("fr-FR");
var HelloFR = Localizer["Hello"];
AppStrings.Culture = new CultureInfo("es-ES");
var HelloES = Localizer["Hello"];
IStringLocalizer
, it is very well hidden. Moreover, the example is for ASP applications, which is not my case. – Ironwork