Unified Service Desk (USD) for Dynamics 365 has two actions which until now I hadn’t used. Translate and DetectLanguage. What are these and what do they do?
In this post, I will explain these actions and show you a working example.
The Translate action provides on demand translation of text data using Azure Translation Services. Meaning we can translate a data parameter from any language to any language. Additionally, the DetectLanguage parameter provides the capability to determine the language of any block of text.
Below you will find a video that shows how I have used these actions within my USD solution to translate the body of any from English into another language. Or from English into any language.
Before I explain how this functionality was created, let me explain a little detail about these actions. These details will be based on the information you can find on Microsoft’s site, here. But I will add additional snippets of information that I’ve discovered. (With a little help from my friends!)
Translate Action
Enables you to perform language translations using Microsoft Translator.
The Translate and DetectLanguage actions are UII Actions of Global Manager.
Parameter | Description |
Value | This is the text to translate. This value may be escaped for multi-line support.
Some valid examples: value=$Escaped(“my string<br>new line\\\”my text\\\””) value=[[myapp.myparam]^] value=$Escaped([[myapp.myparam]$]) value=$Multiline([[myapp.myparam]$]) You may find it useful to review how replacement parameters work, see details here or here. |
fromlanguage | Name of the language to translate from.
If this is blank, the system will attempt to detect the language of the specified value to be translated before translating. For a list of valid language values, see Translator Language Codes. |
tolanguage | Name of the language to translate to.
For a list of valid language values, see Translator Language Codes. |
clientId | A client ID obtained from Microsoft Azure for translation services.
If this option is blank that USD will look for an option called Azure_ClientId For information about registering with Azure, https://datamarket.azure.com/developer/applications/ Note: |
clientSecret | A client secret obtained from Microsoft Azure for translation services.
If this option is blank that USD will look for an option called Azure_ClientSecret For information about registering with Azure, https://datamarket.azure.com/developer/applications/ |
The translated value is displayed under the $Return replacement parameter.
DetactLanguage Action
Enables you to return the language of a block of text using Microsoft Translator.
Parameter | Description |
Value | This is the text to inspect. This value may be escaped for multi-line support.
Some valid examples: value=$Escaped(“my string<br>new line\\\”my text\\\””) value=[[myapp.myparam]^] value=$Escaped([[myapp.myparam]$]) value=$Multiline([[myapp.myparam]$]) You may find it useful to review how replacement parameters work, see details here or here. |
clientId | A client ID obtained from Microsoft Azure for translation services.
If this option is blank that USD will look for an option called Azure_ClientId For information about registering with Azure, https://datamarket.azure.com/developer/applications/ Note: |
clientSecret | A client secret obtained from Microsoft Azure for translation services.
If this option is blank that USD will look for an option called Azure_ClientSecret For information about registering with Azure, https://datamarket.azure.com/developer/applications/ |
The language value is displayed under the $Return replacement parameter.
Setup
Before you can use these actions some setup will be required.
Firstly, you will need to obtain a client ID and client secret for Microsoft Azure translation services. Using this link …. https://datamarket.azure.com/developer/applications/
Warning:
You can obtain an Azure trial that will “work” for development purposes. But it will have a limitation that you can only complete one translation every 10 minutes. I have been told that this restriction is removed with a fully paid Azure subscription. I haven’t tested that! It would be great if the first person who tries these actions with a paid subscription could comment on this post to confirm this is correct.
Next you will need to make an alteration to one of USDs configuration files. UnifiedServiceDesk.exe.config
You will find this in the program directory of our Unified Service Desk client. Typically, this will be “Program Files/Microsoft Dynamics CRM USD/USD”
To edit this XML configuration file, you may need to copy to your desktop and open using any editor. (NotePad will do!)
You will need to insert a service binding to connect with Microsoft Translation Service. The code for this is below;
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_LanguageService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
<message clientCredentialType="UserName" algorithmSuite="Default"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://api.microsofttranslator.com/V2/soap.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_LanguageService" contract="MicrosoftTranslationService.LanguageService" name="BasicHttpBinding_LanguageService"/>
</client>
</system.serviceModel>
Below you can see that I have added this code into my config file.
Example Solution
In the following notes I will describe the steps I took to create the solution shown in my video.
I am going to assume that you can already open a CRM entity in a session and you have some functionality to open an email.
The steps involved are;
- Create options
- Create Translate action
- Create DetectLanguage action
- Create “RunXRMCommand” action
- Create “Copy To Context” actions
- Create a toolbar and add actions
Step One – Create options
You should have a Client ID and Client Secret for the Azure translation service, now you could enter these on each of your Translate or DetectLanguage actions. However, I felt creating them as options was a more elegant approach. So in Unified Service Desk settings I opened the “Options” option and create two new ones.
I’ve shown my options below. You’ll need to create “Azure_ClientId” and “Azure_ClientSecret”. And enter appropriate values.
Step Two – Create Translate action
Next we need an action that will actually do our translation.
Some things to note ….
Field | Details |
Name | CRM Global Manager – Translate (Email Description) |
Order | 10
This will be significant when we add this action into the toolbar! |
Hosted Control | CRM Global Manager |
Action | Translate |
Data | value=$Escaped([[email.description]$])
fromlanguage=[[$Context.TranslateFromLanguage]] tolanguage=[[$Context.TranslateToLanguage]] In particular, notice the approach I have taken to value, I found this method of using $Escaped coped with any formatting I added into the email. Including the formatting used on my email signature. You will also notice that I have used a couple of values from my context for the from and to languages. We will see how these get set in a second! |
Step Three – Create DetectLanguage action
The next action I needed was a DetectLanguage action. In my example I use this when converting an email from any “unknown” language into English. I am essentially automatically detecting the from language.
To be honest I have used this action just for demonstration purposes! As it is valid to omit from fromlanguage value from your Translate action.
Field | Details |
Name | CRM Global Manager – Detect Language |
Order | 1
This will be significant when we add this action into the toolbar! |
Hosted Control | CRM Global Manager |
Action | DetectLanguage |
Data | value=$Multiline([[email.description]v])
Notice that I have used different syntax for my value field. Again I have simply done this to show a variation on how to set the value to be examined / translated. Notice that I have no other parameters! I don’t need to set a clientID or clientSecret. |
Step Four – Create “RunXrmCommand” action
Next we have a RunXrmCommand! Why?
Well I use this command to take the translated test and update the body of the email. So I am injecting a single line of JavaScript into the email form to set a value.
Field | Details |
Name | Email – RunXrmCommand (Set Email Description) |
Order | 20
This will be significant when we add this action into the toolbar! |
Hosted Control | Email
The name of the CRM Page hosted control that holds my email activity. |
Action | RunXrmCommand
This action simply injects JavaScript into your CRM form at runtime. |
Data | Xrm.Page.getAttribute(“description”).setValue(“[[$Return.CRM Global Manager – Translate (Email Description)]$]”);
This is a simple Xrm.Page command to set a value. But notice the $Return replacement parameter. This will be taking the results from our translate action and inserting them into the JavaScript. Pay attention to the “]$]” in my replacement parameter. I found the $ was needed and the translation didn’t correctly apply if missed! |
Step Five – Create “Copy To Context” actions
Next I created several actions to copy “from” AND “to” languages into my context. Essentially I always need two values in the context. One if “TranslateFromLanguage” and “TranslateToLanguage”.
Field | Details |
Name | CRM Global Manager – Copy To Context (From English)
And CRM Global Manager – Copy To Context (To French) CRM Global Manager – Copy To Context (To German) CRM Global Manager – Copy To Context (To English) |
Order | 5
This will be significant when we add this action into the toolbar! |
Hosted Control | CRM Global Manager |
Action | CopyToContext |
Data | TranslateFromLanguage=en
And TranslateToLanguage=fr TranslateToLanguage=de TranslateToLanguage=en |
Next I created one final Copy To Context action, this one was for my detected from language.
Field | Details |
Name | CRM Global Manager – Copy To Context (Detected Language) |
Order | 5
This will be significant when we add this action into the toolbar! |
Hosted Control | CRM Global Manager |
Action | CopyToContext |
Data | TranslateFromLanguage=[[$Return.CRM Global Manager – Detect Language]]
So this time I am copying the results in $Return from my DetectLanguage action. |
Step Six – Create a toolbar and add actions
Ok, so now we have all the building blocks for this solution. They come together on a toolbar.
I’d already got a navigation toolbar on my email tab, so I simply added my translate button. My button looked like this.
Field | Details |
Name | Email – Translate |
Image | I found in image in the Dynamics 365 SDK which I uploaded as the icon on my toolbar. You can find it if you search the SDK for ico_16_4216 |
Button Text | Blank, if you don’t use an image then you could simply set this text field to TRANSLATE |
Order | 5
In my example this simply made the button the last one. |
Tooltip | Optional! |
Enabled condition and visible condition | “[[email.description]]”!=””
This condition will hide the button until the email has been saved, as the email description will not be in the context until the email is saved. FYI: A refinement to my approach would be to get the contents of the email description using a RunXrmCommand. As then you could skip having to save the email. |
Next I used the toolbar buttons option available in the navigation.
My buttons were as follows;
Let’s look at the Email – Translate Other first. The button is simple enough, as shown below.
Now I created two more toolbar buttons. (Again, using the toolbar button in navigation.) One button was for translating into French and one for German.
They were almost identical, so let’s just look at the French one. As you can see below I simply gave the toolbar button a name and then added the actions we created earlier. For this button I added
- CRM Global Manager – Copy To Context (To French) …. Copies “fr” into the context as the to language.
- CRM Global Manager – Copy To Context (From English) …. Copies “en” into the context as the from language.
- CRM Global Manager – Translate (Email Description) …. Translates from “en” to “fr”.
- Email – RunXrmCommand (Set Email Description) …. Updates the email description with the translated text.
Obviously from German button was about the same except I used the “CRM Global Manager – Copy To Context (To German)” action instead.
Finally, I created my button to translate an email from any language into English. Again it was simple. I just gave it a button text of “To English” and added some actions.
- CRM Global Manager – Detect Language …. This runs my DetectLanguage action to work out the language.
- CRM Global Manager – Copy To Context (Detected Language) … now we copy the detected language to the context as my from language.
- CRM Global Manager – Copy To Context (To English) …. Copies “en” into the context as the to language.
- CRM Global Manager – Translate (Email Description) …. Translates from “detected language” to “en”.
-
Email – RunXrmCommand (Set Email Description) …. Updates the email description with the translated text.
I hope this post has been useful, I think this is really cook feature. I look forward to hearing how people get on with this and keen to hear from someone who tries this with a paid Azure subscription. (Unlike me!)
J
Pingback: USD – The Book | Microsoft Dynamics CRM and Unified Service Desk