I would try to inject the ICultureDictionaryFactory interface in your constructor.
Then you can call the CreateDictionary() method on that.
I think you will need to do that each that time you changed the culture on variation context.
The Umbraco Helper is constructed at the beginning of your request and holds a internal dictionary created with the culture of the request. So changing culture using on the variation context does not affect the internal dictionary in the umbracohelper instance.
Yeah, they really leave you hanging if you need to access dictionary values via an API controller, a traditional MVC controller or service that lives outside of the Umbraco pipeline. There seems to be quite a few ways of accessing dictionary items, but nothing in the docs. If you use the localization service then I think you are hitting the database so that is bad for performance - looking under the hood deeper Umbraco helper uses that service but I think that it then caches the results...
We ended up creating a translation service that is basically a service that is based on the GetDictionaryValue() of UmbracoHelper without all the other UmbracoHelper methods. Then in the methods that call that service you need to explicitly set the current culture or ui culture with a new new CultureInfo(lang); before triggering the method call. Or we added a menthod where you can pass in a cultureinfo into your translation service.
using System.Globalization;
using Umbraco.Cms.Core.Dictionary;
namespace Attwood.Core.Services
{
public class TranslationService
{
private readonly ICultureDictionaryFactory _cultureDictionaryFactory;
private ICultureDictionary? _cultureDictionary;
public TranslationService(ICultureDictionaryFactory cultureDictionaryFactory)
{
_cultureDictionaryFactory = cultureDictionaryFactory;
}
public string? GetDictionaryValue(string key) => CultureDictionary[key];
/// <summary>
/// Returns the dictionary value for the key specified, and if empty returns the specified default fall back value
/// </summary>
/// <param name="key">Key of dictionary item</param>
/// <param name="altText">Fallback text if dictionary item is empty - Name altText to match Umbraco.Field</param>
/// <returns></returns>
public string GetDictionaryValue(string key, string altText)
{
var dictionaryValue = GetDictionaryValue(key);
if (string.IsNullOrWhiteSpace(dictionaryValue))
{
dictionaryValue = altText;
}
return dictionaryValue;
}
/// <summary>
/// Returns the dictionary value for the key specified and culture specified, and if empty returns the specified default fall back value
/// </summary>
/// <param name="key">Key of dictionary item</param>
/// <param name="cultureInfo">Set culture info. Example: new CultureInfo("en-US")</param>
/// <returns></returns>
public string GetDictionaryValue(string key, CultureInfo cultureInfo)
{
Thread.CurrentThread.CurrentUICulture = cultureInfo;
var dictionaryValue = GetDictionaryValue(key);
if (string.IsNullOrWhiteSpace(dictionaryValue))
{
dictionaryValue = string.Empty;
}
return dictionaryValue;
}
public ICultureDictionary CultureDictionary => _cultureDictionary ??= _cultureDictionaryFactory.CreateDictionary();
}
}
This service would need to be registered in the DI container:
builder.Services.AddScoped<TranslationService>();
and then injected into your controller/service, etc. that lives outside of the Umbraco pipeline. You could then call it like this:
_translationService.GetDictionaryValue("your-dictionary-key", new CultureInfo("fr-CA"));
UmbracoHelper.GetDictionaryValue invariant to VariationContext Culture
Both calls to .GetDictionaryValue returns the english translation.
Expected behaviour would be the english translation first and then the danish.
Am i doing something wrong or is there another way to get culture specific translations inside an API controller?
Hi Kare
I would try to inject the ICultureDictionaryFactory interface in your constructor.
Then you can call the CreateDictionary() method on that.
I think you will need to do that each that time you changed the culture on variation context.
The Umbraco Helper is constructed at the beginning of your request and holds a internal dictionary created with the culture of the request. So changing culture using on the variation context does not affect the internal dictionary in the umbracohelper instance.
Dave
Hey Kare and Dave
I'm having the exact same issue, but I'm using IUmbracoHelperAccessor interface to get UmbracoHelper.
I've tried
and
(setting the dictionary before and after getting UmbracoHelper)
The outcome is always the same: lang is ignored and all dictionary values come in english..
I'm using Umbraco v11.1.0
I was able to get it working by setting the
System.Threading.Thread.CurrentThread.CurrentUICulture = new CultureInfo(lang);
I'm not really sure if this is the best or only solution.. If anyone could "validate" this, it would be awesome :D
Yeah, they really leave you hanging if you need to access dictionary values via an API controller, a traditional MVC controller or service that lives outside of the Umbraco pipeline. There seems to be quite a few ways of accessing dictionary items, but nothing in the docs. If you use the localization service then I think you are hitting the database so that is bad for performance - looking under the hood deeper Umbraco helper uses that service but I think that it then caches the results...
We ended up creating a translation service that is basically a service that is based on the GetDictionaryValue() of UmbracoHelper without all the other UmbracoHelper methods. Then in the methods that call that service you need to explicitly set the current culture or ui culture with a new new CultureInfo(lang); before triggering the method call. Or we added a menthod where you can pass in a cultureinfo into your translation service.
I have no idea how performant that is.
Here is a feature request just created: https://github.com/umbraco/Umbraco-CMS/discussions/14425
Here's my code if you are interested....
This service would need to be registered in the DI container:
and then injected into your controller/service, etc. that lives outside of the Umbraco pipeline. You could then call it like this:
is working on a reply...