Copied to clipboard

Flag this post as spam?

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


  • Valentin 11 posts 110 karma points
    Apr 02, 2018 @ 07:25
    Valentin
    0

    Hello everybody! I have some requirements on my Frontend, and I try made UI on ReactJs Frontend. Another detail, I made it on https://reactjs.net/ for server rendering, and now I can't imagine how can I use on JS side Umbraco API services or as minimum, how in JSX I can got Dictionary Items for multilanguage needs in Razor View I can as ex. @Umbraco.GetDictionaryValue("SomeKey") has the analogy on JSX ?

    thank you

  • Alex Skrypnyk 6132 posts 23951 karma points MVP 7x admin c-trib
    Apr 02, 2018 @ 07:51
    Alex Skrypnyk
    0

    Hi Valentin

    Try to use Surface Controllers + Partial view combination

    return filled view with controllers to the page, in views use JSX instead of Razor

    Thanks,

    Alex

  • Valentin 11 posts 110 karma points
    Apr 02, 2018 @ 08:03
    Valentin
    0

    I'm not imagine how I can draw HTML on Razor into JSX can you explain more details?

  • Alex Skrypnyk 6132 posts 23951 karma points MVP 7x admin c-trib
    Apr 02, 2018 @ 08:15
    Alex Skrypnyk
    0

    Valentin

    How are you handling requests to the website? Is it Umbraco page?

  • Valentin 11 posts 110 karma points
    Apr 02, 2018 @ 08:30
    Valentin
    0

    it is ASP.NET page than render something like @Html.React("ReactComponent", new { data = Model })

  • Valentin 11 posts 110 karma points
    Apr 02, 2018 @ 09:29
    Valentin
    0

    As solution, but very ugly, I can render al dictionary keys and values to window dictionary, and on client side use them, but is bad because increase traffic (page size); another way, make any http handler with cache to get dictionary as some js file, that shall generated on fly from Umbraco data

  • Alex Skrypnyk 6132 posts 23951 karma points MVP 7x admin c-trib
    Apr 02, 2018 @ 09:34
    Alex Skrypnyk
    0

    So you are using html views instead of Razor?

    You can render html with SurfaceController, the issue is that you haven't access to UmbracoHelper inside html code, right?

  • Valentin 11 posts 110 karma points
    Apr 02, 2018 @ 09:36
    Valentin
    0

    right, I have jsx file (like js) with html embeded into it I can not use razor helpers

  • Alex Skrypnyk 6132 posts 23951 karma points MVP 7x admin c-trib
    Apr 02, 2018 @ 12:24
    Alex Skrypnyk
    0

    Can you avoid of using @Html.React("ReactComponent", new { data = Model }) helper?

    You can use render Partial or render view razor helper and use Umbraco context inside this view

  • Valentin 11 posts 110 karma points
    Apr 02, 2018 @ 14:52
    Valentin
    0

    unfortunately no, because react & JSX inseparable

  • Valentin 11 posts 110 karma points
    Apr 02, 2018 @ 16:56
    Valentin
    0

    I think best solution be use umbraco event, and when dictionary items changed, re-generate js file, with content initializer via JSON like: module.exports = [ {key:.., value ...}, .. ] and after that, I can include that JS file to my webpack chain to use and on server rendering side and client (browser) side

  • Alex Skrypnyk 6132 posts 23951 karma points MVP 7x admin c-trib
    Apr 02, 2018 @ 17:41
    Alex Skrypnyk
    0

    Valentin, you can download all dictionary to csv with this package - https://www.diplo.co.uk/blog/web-development/diplo-dictionary-editor-for-umbraco/

  • Alex Skrypnyk 6132 posts 23951 karma points MVP 7x admin c-trib
    Apr 05, 2018 @ 16:21
    Alex Skrypnyk
    0

    Hi Valentin

    Did you solve the issue? Can you share with the community?

    Thanks,

    Alex

  • Dave Woestenborghs 3504 posts 12133 karma points MVP 8x admin c-trib
    Apr 05, 2018 @ 17:57
    Dave Woestenborghs
    0

    Hi Valentin,

    We solved this by passing in the dictionary items as well to the react component.

    Then you get something like this :

        @Html.React("ReactComponent", 
        new { data = Model, 
        labels = new {
                        firstname = Umbraco.GetDictionaryValue("firstname"),
                        lastname = Umbraco.GetDictionaryValue("lastname")
    }
    })
    

    And then in your react component you can access all the values throught the labels prop.

    Dave

  • Valentin 11 posts 110 karma points
    Apr 05, 2018 @ 18:11
    Valentin
    100

    I made Observer singleton class that subscribe to appropriate events and auto generate JSON object

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Web;
    using Umbraco.Core;
    using Umbraco.Core.Services;
    using Umbraco.Web;
    
    namespace WinePortal.Core
    {
        public class LocalizationServiceObserver
        {
            public static string ScriptPath { get; private set; }
    
            public static void Subscribe(string scriptPath)
            {
                ScriptPath = scriptPath;
    
                LocalizationService.SavedLanguage += UpdateDictionaryScript;
                LocalizationService.DeletedLanguage += UpdateDictionaryScript;
                LocalizationService.DeletedDictionaryItem += UpdateDictionaryScript;
                LocalizationService.SavedDictionaryItem += UpdateDictionaryScript;
            }
    
            private static void UpdateDictionaryScript(ILocalizationService sender, object e)
            {
                StringBuilder scriptBuilder = new StringBuilder("var UmbDictionary = {\r\n");
                foreach (var language in sender.GetAllLanguages())
                {
                    var culture = language.CultureInfo.Name;
                    scriptBuilder.AppendLine($"\"{culture}\": [");
    
                    var items = GetDictionaryItems(culture);
                    foreach (var dictionaryItem in items)
                    {
                        var key = HttpUtility.JavaScriptStringEncode(dictionaryItem.Key);
                        var value = HttpUtility.JavaScriptStringEncode(dictionaryItem.Value);
                        scriptBuilder.AppendLine($"{{ \"Key\": \"{key}\", \"Value\": \"{value}\" }},");
                    }
    
                    scriptBuilder.AppendLine("],");
                }
                scriptBuilder.AppendLine("};");
                System.IO.File.WriteAllText(ScriptPath, scriptBuilder.ToString());
            }
    
            public static IEnumerable<DictionaryItem> GetDictionaryItems(string culture)
            {
                //For now, we're only going to get the English items
    
                var dictionary = new List<DictionaryItem>();
    
                var root = ApplicationContext.Current.Services.LocalizationService.GetRootDictionaryItems();
    
                if (!root.Any())
                {
                    return Enumerable.Empty<DictionaryItem>();
                }
    
                foreach (var item in root)
                {
                    dictionary.Add(new DictionaryItem
                    {
                        Key = item.ItemKey,
                        Value = item.Translations.Where(x => x.Language.CultureInfo.Name == culture).Select(x => x.Value).FirstOrDefault()
                    });
    
                    dictionary.AddRange(LoopThroughDictionaryChildren(item.Key, culture));
                }
    
                return dictionary;
            }
    
            private static IEnumerable<DictionaryItem> LoopThroughDictionaryChildren(Guid key, string culture)
            {
                var dictionary = new List<DictionaryItem>();
                var items = ApplicationContext.Current.Services.LocalizationService.GetDictionaryItemChildren(key);
    
                if (!items.Any())
                {
                    return Enumerable.Empty<DictionaryItem>();
                }
    
                foreach (var subItem in items)
                {
                    dictionary.Add(new DictionaryItem
                    {
                        Key = subItem.ItemKey,
                        Value = subItem.Translations.Where(x => x.Language.CultureInfo.Name == culture).Select(x => x.Value).FirstOrDefault()
                    });
    
                    dictionary.AddRange(LoopThroughDictionaryChildren(subItem.Key, culture));
                }
    
                return dictionary;
            }
        }
    
    
    
        public class DictionaryItem
        {
            public string Key { get; set; }
    
            public string Value { get; set; }
        }
    }
    

    usage example

    protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
            {
                var scriptPath = UmbracoContext.Current.HttpContext.Server.MapPath("~/scripts/UmbDictionary.generated.js");
                LocalizationServiceObserver.Subscribe(scriptPath);
            }
    

    this is more universal approach

Please Sign in or register to post replies

Write your reply to:

Draft