Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Kåre Mai 29 posts 207 karma points
    Dec 15, 2022 @ 12:37
    Kåre Mai
    0

    UmbracoHelper.GetDictionaryValue invariant to VariationContext Culture

    public ExperiencesController(UmbracoHelper umbracoHelper, IVariationContextAccessor variationContextAccessor)
        {
            _variationContextAccessor = variationContextAccessor;
            _umbracoHelper = umbracoHelper;
    
            _variationContextAccessor.VariationContext = new VariationContext("en-US");
            var testEn = _umbracoHelper.GetDictionaryValue("ReadMore");
    
            _variationContextAccessor.VariationContext = new VariationContext("da");
            var testDa = _umbracoHelper.GetDictionaryValue("ReadMore");
        }
    

    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?

  • Dave Woestenborghs 3504 posts 12133 karma points MVP 8x admin c-trib
    Dec 16, 2022 @ 09:43
    Dave Woestenborghs
    100

    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

  • Pedro Mendes 53 posts 258 karma points
    Mar 09, 2023 @ 18:00
    Pedro Mendes
    0

    Hey Kare and Dave

    I'm having the exact same issue, but I'm using IUmbracoHelperAccessor interface to get UmbracoHelper.

    I've tried

    _variationContextAccessor.VariationContext = new VariationContext(lang);
    _cultureDictionaryFactory.CreateDictionary();
    if (!_umbracoHelperAccessor.TryGetUmbracoHelper(out UmbracoHelper? umbracoHelper)) return null;
    (...)
    

    and

    .VariationContext = new VariationContext(lang);
    if (!_umbracoHelperAccessor.TryGetUmbracoHelper(out UmbracoHelper? umbracoHelper)) return null;
    _cultureDictionaryFactory.CreateDictionary();
    (...)
    

    (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

  • Pedro Mendes 53 posts 258 karma points
    Mar 09, 2023 @ 19:00
    Pedro Mendes
    1

    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

  • Jamie Attwood 201 posts 493 karma points c-trib
    Jun 20, 2023 @ 18:27
    Jamie Attwood
    1

    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....

    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"));
    
Please Sign in or register to post replies

Write your reply to:

Draft