How to run PCF Control in Multilanguage using .resx (resource) files

By | February 17, 2020

Introduction

In this blog, we will see how to run PCF Control in multiple languages. Let’s consider a scenario where we have one PCF field control, which contains some user interface part which we currently display in only one language i.e English. Now, we want to display PCF control UI part in more than one language such as French and English which is also supported by Dynamics 365 CRM, so that the PFC control will load as per logged in user language.

Solution

Step 1: For this scenario, we are using .resx (resource) files, wherein we maintain XML entries for all languages as shown below. For each language, we have created individual resource files. Please find below sample code of resource file:

1. English:

<data name=“agelbl” xml:space=“preserve”>

                 <value>Age</value>

</data>

<data name=“agetbplaceholder” xml:space=“preserve”>

                <value>Enter the age here</value>

</data>

2. French:

<data name=“agelbl” xml:space=“preserve”>

 <value>Âge</value>

</data>

<data name=“agetbplaceholder” xml:space=“preserve”>

 <value>Entrez l’âge ici</value>

</data>

Note : All resource files name should be have in following format : [PCF_ControlName].[Language_Code].resx where Language_Code is dynamic 365 logged language code for example ([].1036.resx).

Step 2: Add all languages files into PCF control project and add resources reference of each .resx in ControlMainfest.Input.xml file as shown in below code:

  <resources>

                <code  path=“index.ts” order=“1”/>

                <resx  path=“/[PCF_ControlName].1033.resx” version=“1.0.0” />

                <resx  path=” /[PCF_ControlName].1036.resx” version=“1.0.0” />

    </resources>

Step 3: Access languages data of rescouce files using PCF control context as shown in below code:

public init(context: ComponentFramework.Context, notifyOutputChanged: () => void, state: ComponentFramework.Dictionary, container: HTMLDivElement) {
        let functionName: string = "init";
        this._contextObj = context;
        this._container = container;
        let labelText: string = "";
       let labelPlaceholder: string = "";
        try {
            //Create div
            this._mainContainer = document.createElement('div');
            //label input
            this._label = document.createElement("label");

           //read label text from language resource files
//check the value returned by getstring – if it does not find a resource file for the logged-in users language or the base language of the organization – it returns the same value as the key requested.
            if(context.resources.getString("agelbl")!="agelbl"){
	//found a matching key in the resource file
               labelText = context.resources.getString("agelbl");
            }else{
	//resource file not found for the logged-in user’s language or the base language.
	labelText = “Age”;
            }
            this._label.innerText = labelText;
            this._label.setAttribute("id", "ageTB");

            //text input
            this._input = document.createElement("input");

            //read placeholder text from language resource files
//check the value returned by getstring – if it does not find a resource file for the logged-in users language or the base language of the organization – it returns the same value as the key requested.
            if(context.resources.getString("agetbplaceholder")!="agetbplaceholder"){
               //found a matching key in the resource file
               labelPlaceholder = context.resources.getString("agetbplaceholder");
            }else{
//resource file not found for the logged-in user’s language or the base language.
	labelPlaceholder = “Enter the age here”;
            }
            this._input.placeholder = labelPlaceholder;
            this._input.setAttribute("type", "text");
            this._input.setAttribute("id", "ageTB");
            this._input.setAttribute("class", "form-control");

            //add all html components in dic container
            this._mainContainer.appendChild(this._label);           
            this._mainContainer.appendChild(this._input);
            


            //append div to PCF container
            this._container.appendChild(this._mainContainer);
        } catch (error) {
                    let alertStrings = { text: error.message };
                    let alertOptions = { height: 100, width: 200 };
                    this._ contextObj.navigation.openAlertDialog(alertStrings, alertOptions);
        }
    }

In the above code, we find one of the default functions of PCF control and in that function we try to append some HTML elements to default HTMLDivElement of PCF control i.e container. HTML part contains one label and input type Html element and we can see label text and place holder of input element we retrieve from context.resources.getString() function. With the help of this function, we can read the language data from .resx (resource) files. We need to pass XML_Tag_Name which will retrieve text from resource files with respect to their XML tag name. Also, language data always read on the basis of current logged in user of selected language code (for eg. 1033, 1036)of Dynamic 365 CRM.

In our example we use context.resources.getString(“agelbl”) & context.resources.getString(“agetbplaceholder”) , it will retrieve the result as follows:

1. If logged in user have English language as selected then result will be retrieved language data from [PCF_ControlName].1033.resx and further it will be filtered by XML tag name i.e “agelbl” and “agetbplaceholder”.

PCF Control in multiple languages

2. If logged in user have Frech language as selected then result will be retrieved language data from [PCF_ControlName].1036.resx and further it will be filtered by XML tag name i.e “agelbl” and “agetbplaceholder”.

PCF Control in multiple languages

Conclusion

In this way, if you want to run our PCF control in more than one language then we can use resources file and access language data from that file using ComponentFramework.Context.getString([XML_Tag_Name]). We just need to create a language tag for the text which we want to display in different languages and add into resource files.