This is a migrated thread and some comments may be shown as answers.

[Persist state & Translation] Column translation is lost when using setOption

3 Answers 268 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Julien
Top achievements
Rank 1
Julien asked on 27 Oct 2020, 11:05 AM

Hello,

Anyone have any idea how to handle translation when you want to use data persistence?

Here, template helper + template kendo + kendo grid

        @* ===================================== HELPER and Template ===================================== *@
 
        @* =============== Toolbar =============== *@
        @helper ToolbarTemplate()
        {
            <div>
                <a class="k-button k-button-icontext k-grid-excel" href="\#">@Tools.GetStringRessource("AllList_ExportToExcel", "Download To Excel")</a>
            </div>
        }
        <script type="text/x-kendo-template" id="toolbarTemplate">
            @Html.Raw(@ToolbarTemplate().ToHtmlString().Replace("#", "\\#").Replace("</scr", "<\\/scr"))
        </script>
 
 
        @* =============== ColumnAction =============== *@
        @helper ColumnActionTemplate(bool canEdit, bool canDelete)
        {
            @* Voir page CableDrum_Customer pour les différentes recherches *@
 
            @* VERSION 2: Solution bricolé - href généré avec Url.Action (encode les params mais sera décodé dans le js pour retrouver #= #) *@
 
            var hrefEdit = Url.Action("CableDrumEdit_Site", new { idCustomer = @ViewContext.RouteData.Values["idCustomer"], idSite = @ViewContext.RouteData.Values["idSite"], idCableDrum = "#=Id#" });
            var edit = $"<a class=\"btn icon bg-white tooltip-bottom\" href=\"{@hrefEdit}\" title = \"{Tools.GetStringRessource("AllList_EditItem", "Edit")}\" >#=library.getKendoTemplate(data,'IconCreateTemplate')#</a>";
            var resultEdit = Convert.ToBoolean(canEdit) ? edit : "";
 
            var resultDelete = Convert.ToBoolean(canDelete) ? "#=library.getKendoTemplate(data,'DeleteTemplate')#" : "";
 
            <div class="action">
                <span>
                    @Html.Raw(@resultEdit)
                </span>
                <span>
                    @Html.Raw(@resultDelete)
                </span>
            </div>
        }
        <script type="text/x-kendo-template" id="columnActionTemplate">
            @Html.Raw(@ColumnActionTemplate(ViewBag.CanEdit, ViewBag.CanDelete).ToHtmlString())
        </script>
 
 
        @* =============== Header =============== *@
        @helper HeaderTemplate()
        {
        <span class="k-link">
            @Tools.GetStringRessource("AllList_EditBtn", "Action")
        </span>
}
        <script type="text/x-kendo-template" id="headerTemplate">
            @Html.Raw(@HeaderTemplate().ToHtmlString())
        </script>
        @* ===================================== FIN HELPER and Template ===================================== *@
 
 
        @(Html.Kendo().Grid<CableDrumUIDto>()
            .Name("CableDrumGrid")
            .ToolBar(tools =>
            {
                tools.Template(@<text>@ToolbarTemplate()</text>);
            })
            .Excel(excel => excel
                .FileName(Tools.GetStringRessource("ExportToExcel_CableDrums", "siteDrum.xlsx"))
                .Filterable(true)
                .AllPages(true)
            )
            .DataSource(dataSource => dataSource
                .Ajax()
                .PageSize(10)
                .Read(read => read.Action("CableDrumInfo_Read", "CableDrums").Data("CableDrumLib.getAdditionalData").Type(HttpVerbs.Post))
            )
            .Events(e => e
                .DataBound(@<text>function(e){  CableDrumLib.gridDataBound(); library.dataBound(); }</text>)
                .ExcelExport("onExcelExport")
            )
            .Columns(columns =>
            {
                columns.Bound(p => p.ProductName).Title(Tools.GetStringRessource("CableDrum_ProductName", "PRODUCT NAME"));
                columns.Bound(p => p.ProductRef).Title(Tools.GetStringRessource("CableDrum_ProductRef", "REFERENCE"));
                columns.Bound(p => p.ProductRefCustomer).Title(Tools.GetStringRessource("CableDrum_ProductRefClient", "REFERENCE CUSTOMER"));
                columns.Bound(p => p.LabelProductSerialNumber).Title(Tools.GetStringRessource("CableDrum_Identifier", "DRUM"));
                columns.Bound(p => p.Location).Title(Tools.GetStringRessource("CableDrumEdit_DetailsTab_Location", "LOCATION"));
                if (ViewBag.DisplayLengthInFeets.Equals(true))
                {
                    columns.Bound(p => p.CurrentLengthInM).Title(Tools.GetStringRessource("CableDrum_ProductLengthInF", "LENGTH"));
                }
                if (ViewBag.DisplayLengthInMeters.Equals(true))
                {
                    columns.Bound(p => p.CurrentLengthInM).Title(Tools.GetStringRessource("CableDrum_ProductLengthInM", "LENGTH"));
                }
                /**/
                columns.Bound(p => p.CF_CustomerDrumNumber).Title(Tools.GetStringRessource("Generic_CF_CustomerDrumNumber", "Customer Drum Number")).Hidden();
                columns.Bound(p => p.CF_CustomerShipmentDate).ClientTemplate("#= (CF_CustomerShipmentDate !== null) ? kendo.toString(CF_CustomerShipmentDate,'d') : '' #").Title(Tools.GetStringRessource("Generic_CF_CustomerShipmentDate", "Customer Shipment Date")).Hidden();
                columns.Bound(p => p.CF_SaleOrderNumber).Title(Tools.GetStringRessource("Generic_CF_SaleOrderNumber", "Sale Order Number")).Hidden();
                columns.Bound(p => p.CF_LineOrderNumber).Title(Tools.GetStringRessource("Generic_CF_LineOrderNumber", "Line Order Number")).Hidden();
                columns.Bound(p => p.CF_CustomerPurchaseOrderNumber).Title(Tools.GetStringRessource("Generic_CF_CustomerPurchaseOrderNumber", "Customer Purchase Order Number")).Hidden();
                columns.Bound(p => p.CF_CustomerLineOrderNumber).Title(Tools.GetStringRessource("Generic_CF_CustomerLineOrderNumber", "Customer Line Order Number")).Hidden();
                columns.Bound(p => p.CF_ProductionOrderNumber).Title(Tools.GetStringRessource("Generic_CF_ProductionOrderNumber", "Production Order Number")).Hidden();
 
                columns
                    .Template(@<text></text>)
                    .Title(@Tools.GetStringRessource("AllList_EditBtn", "Action"))
                    .HeaderTemplate(HeaderTemplate().ToHtmlString())
                    .Width(90)
                    .ClientTemplate(ColumnActionTemplate(ViewBag.CanEdit, ViewBag.CanDelete).ToHtmlString());
            })
            .NoRecords(Tools.GetStringRessource("Grid_NoRecords", "No Data"))
 
            .ColumnMenu()
            .Sortable(s => s.SortMode(GridSortMode.MultipleColumn))
            .Reorderable(r => r.Columns(true))
            .Resizable(r => r.Columns(true))
            .Scrollable(sc => sc.Height("auto"))
 
            .Pageable(page => page
                .Input(true)
                .Numeric(false)
                .Info(true)
                .PreviousNext(true)
                .Messages(message => message
                    .Display(ViewBag.Title + " {0}-{1}/{2}")
                    .Empty(Tools.GetStringRessource("Grid_NoRecords", "No Data"))
                    .Of("/{0}")
                    .Page(string.Empty)
                )
            )

 

 

Here, i save grid option

window.onbeforeunload = function () {
    var elGrid = $(GRID_CABLEDRUM);
    if (elGrid !== null)
    {
        var grid = elGrid.data("kendoGrid");
        if (grid !== null && grid.element.length > 0)
        {
            var fullOptions = grid.getOptions();
            // Récupération uniquement des informations qui m'intéresse (affichage des colonnes, tri, filtre, taille colonnes)
            var options = {
                columns: fullOptions.columns,
                dataSource: fullOptions.dataSource
            }
            localStorage.setItem(`_kendoGridCookie_${grid.element[0].id}`, kendo.stringify(options));
        }
    }
}

 

Here i add my template toolbar + template header + i manually apply the translations.

var gridElement = $(this);
        var gridId = gridElement[0].id;
        var kendoGrid = $(`#${gridId}`).data("kendoGrid");
         
        // Récupération des préférences utilisateurs de la grille dans le localStorage
        var kendoGridOptions = localStorage.getItem(`_kendoGridCookie_${gridId}`);
        if (kendoGridOptions && kendoGridOptions !== null) {
            var kendoGridOptionsParse = JSON.parse(kendoGridOptions);
 
            var templateToolbar = $("#toolbarTemplate").html();
            if (templateToolbar !== undefined) {
                kendoGridOptionsParse.toolbar = [
                    { template: templateToolbar }
                ];
            }
 
            //Récupération de la colonne Action. J'ai pas beaucoup de moyen pour l'identifier donc je me base sur qu'elle est la propriété template
            var colAction = kendoGridOptionsParse.columns.find(c => c.template !== undefined)
 
            //Template header colonne action
            var templateHeader = $("#headerTemplate").html();
            if (templateHeader !== undefined) {
                colAction.headerTemplate = templateHeader;
            }
 
            // Template colonne action
            var templateAction = $("#columnActionTemplate").html();
            if (templateAction !== undefined) {
                var action = decodeURIComponent(templateAction);
                colAction.template = action;
            }
 
 
            //Récupération des traductions des entêtes des colonnes
            if (kendoGridOptionsParse !== null && kendoGrid !== null && kendoGridOptionsParse.columns !== null && kendoGrid.columns !== null && kendoGridOptionsParse.columns.length === kendoGrid.columns.length) {
                for (let indice = 0; indice < kendoGridOptionsParse.columns.length; indice++) {
                    var kendoGridOptionsColCurrent = kendoGridOptionsParse.columns[indice]
 
                    var listCorrespondanceColonne;
                    var titleCurrent = "";
 
                    // Soit colonne lié à des champs
                    if (kendoGridOptionsColCurrent.field !== undefined) {
                        listCorrespondanceColonne = kendoGrid.columns.filter(c => c.field !== undefined && c.field === kendoGridOptionsColCurrent.field);
 
                    }
                    else {// Soit colonne template
                        listCorrespondanceColonne = kendoGrid.columns.filter(c => c.field === undefined && c.template !== undefined);
                    }
 
                    if (listCorrespondanceColonne.length === 1) {
                        titleCurrent = listCorrespondanceColonne[0].title;
                    }
 
                    kendoGridOptionsColCurrent.title = titleCurrent;
                }
            }
 
            kendoGrid.setOptions(kendoGridOptionsParse);
        }

 

I see that the operation is not solid and I would like to find a more standard solution for the translation of the columns.

 

Thank you for your time.

3 Answers, 1 is accepted

Sort by
0
Georgi Denchev
Telerik team
answered on 29 Oct 2020, 11:19 AM

Hi Julien,

 

Thank you for providing code snippets.

Could you please elaborate what do you mean by Columns Translation is lost? Do you mean the title of the column does not change when you use setOptions? Examining the code, I can see you are using a for-loop to go through each column and change it's title, this is done correctly. Setting the toolbar template is also done correctly.

Can you tell me how do you call the last script you provided? When you save the grid options, you do it by using window.onbeforeunload. What about when you try to load it? Is it by clicking a button, or when the page loads? Here is a small sample on how to do it when the page loads:

// Execute the script when the page loads.
    $(function () {
        // Get a reference to the grid.
        var grid = $("#grid").data("kendoGrid");

            // Load the options
            var kendoOptions = localStorage.getItem("grid_options");

            // Check if the options are null or not.
        if (kendoOptions && kendoOptions !== null) {
                // Parse the options.
                var kendoParseOptions = JSON.parse(kendoOptions);

                // Apply the toolbar template to the options.
                var toolbarTemplate = $("#toolbarTemplate").html();
                kendoParseOptions.toolbar = [{ template: toolbarTemplate }];

                // Change the titles of the columns.
                for (let i = 0; i < kendoParseOptions.columns.length; i++) {
                    var currentColumn = kendoParseOptions.columns[i];

                    currentColumn.title = "Random Title";
                }

                // Set the options.
                grid.setOptions(kendoParseOptions);
            }
        });

I tested the above approach and the titles of the columns successfully update when I call setOptions. Can you make sure that titleCurrent is not empty when you apply it?

You can also have a look at the Localization Documentation:

https://docs.telerik.com/kendo-ui/globalization/localization?&_ga=2.147608885.385776851.1603698354-1107114872.1600159261#setting-the-current-language

Applying a translation would change some of the default messages for the grid, such as filters for example. The translation script in MVC is usually placed inside the _Layout file.

 

Best Regards,
Georgi Denchev
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

0
Kévin
Top achievements
Rank 1
answered on 29 Oct 2020, 03:19 PM

Hi Georgi,

 

I created the request with Julien's account but now i created my own account.

Columns translation is lost

Firstly, my site web have multi language.

Before i use persistance, when i change language,reloading the page and the grid automatically displayed the new language using the project resources

Now, in the persistance, i have column titles in optionGrid in my localstorage and when i use setoption for reload parameters of my grid, these titles override the new ones.

I found a solution using the foreach loop in javascript but i was wondering if there wasn't a cleaner, simpler method of doing this.

 

LocalStorage & option grid:

I save grid option when window is unload

I load grid option when window is load.

 

Example: I have 1 column with the title "Bonjour / Hello"

I go on the list with the French language so my column have a title "Bonjour"

I change my language to English.

==> My code save in localstorage grid option with the title "Bonjour" because my current language is French

==> Window is unload

==> Window is load

==> New grid loading and she have 1 column with the title "Hello"

==> My code collects the grid option. In this grid option from local storage  and the column title is "Bonjour"

==> My code inserts it into the grid that loads and the column title become "Bonjour" but my language is English and not French ...

 

The method I propose can work with simple examples but when you have several columns that have templates, I don't know how I will be able to differentiate them and therefore associate them with the right translation.

 

If you have an example of an asp.net project that uses the translations with the resources in the C # project, that it works with the persistence of the grids and that uses a more correct method for the translation I am interested.

 

I will try in 1 weeks to make a simple project to be able to discuss this subject.

 

Cordialement, Best Regards

Kévin VERNEt

 

0
Georgi Denchev
Telerik team
answered on 30 Oct 2020, 10:47 PM

Hello Kévin,

Thank you for the additional details.

In this case we can utilize the getOptions and setOptions methods to change the language(titles) of the columns without having to refresh the page.

Let's assume that we have our languages stored in some JSON file. We retrieve them in javascript and then we have an object similar to this one:

var languages = {
        fr: {
            ProductName: "ProductName French",
            ProductRef: "ProductRef French",
            ProductRefCustomer: " ProductRefCustomer French"
        },
        it: {
            ProductName: "ProductName Italian",
            ProductRef: "ProductRef Italian",
            ProductRefCustomer: " ProductRefCustomer Italian"
        }
    }

We can then write a function that returns the title based on the selected language and column field.

function changeTitleLanguage(language, field) {
        return languages[language][field];
    }

And then using the grid options we can change the titles based on the selected language. I am not sure how the language is selected in the application, so I am going to give you an example with a button.

$("#button").click(function () {
        var grid = $("#grid").data("kendoGrid");
        var options = grid.getOptions();
        
        for (var i = 0; i < options.columns.length; i++) {
            var column = options.columns[i];
            column.title = changeTitleLanguage("fr", column.field);
        }

        grid.setOptions(options);
    });

The language is hard coded in my example, but this can easily be changed. The column.field will always be the same as the property in the Model, it doesn't matter if you apply templates to the columns.

Now we don't need to change the titles once again during the loading of the page, because they will be saved in the correct language when we leave.

Let me know if this solution works for you, if not I will assist you further.

 

Best Regards,
Georgi Denchev
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

Tags
Grid
Asked by
Julien
Top achievements
Rank 1
Answers by
Georgi Denchev
Telerik team
Kévin
Top achievements
Rank 1
Share this question
or