- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
on 12-09-2021 01:20 AM
In the Tokyo release a new Capability has been added (via the Localization Framework) to drastically simplify how you
can implement multi-lingual email notifications.
Check it out here in the Tokyo release notes. It is now possible to translate the Notification template, or Dynamically
Translate an email on-the-fly.
I've been seeing quite a few posts recently about how to create / define emails in other languages. Naturally (as with most things in the platform) there's a few ways to achieve this which partly comes down to requirements, it also comes down to how complex you need it to be. So let's delve into the options, discuss them and go through the pros and cons of each approach.
These emails need to go out in multiple languages - the technically easy option
Ok, so just like I go through in the 2nd module of the "Localization Journey" training here, the simplest option is to essentially create a notification per language of that notification concept, specifically checking for the language of the singular recipient.
This is because most processes (and it's not just IT processes) only really need a few types of notifications:
The Originator (e.g. the Caller, the Requester etc) would need:
- X Created
- X Updated
- X Resolved
- X Closed
The Fulfiller (the person doing the actions) might need:
- X Assigned
- X Updated by Originator
- X re-opened by Originator
X is the process type, e.g. an Incident, a Request or a Case etc.
- I suppose you could also add SLA emails in to that mix as well if necessary.
So the concept in this example is that in the trigger conditions we're specifically checking for the singular recipients preferred language as that's a known data-point we can check on their respective user profile, which is a data point we can correlate on the notification definition as there will be a reference field to the [sys_user] table as the recipient of the notification in question.
The Pros
On a technical level, this is pretty simple. One "Created" email
per language, one "updated" email per language etc, and either
the email contents or a template it leverages contains the
translated structure.
The Cons
This will not process group members, because this is processed
on an individual level, so not ideal for "Assigned" emails to a
group as they will receive the same language.
If you need to factor in a watch_list, you may also need to factor
this in your trigger condition with this approach.
These emails need to go out in multiple languages - the technically more nuanced option
There is another option if you need it, but it is more technical in nature. It also opens the door to other possibilities, however it also comes with it's own challenges and restrictions to weigh up.
Since Orlando there has been another getMessage method available called "getMessageLang", where this method can be used to retrieve content on-behalf of someone else. It's typical structure is like this:
gs.getMessageLang([key],[langID],[param1],[param2])
So where "gs.getMessage" is for being run as you the user of that content in question, "gs.getMessageLang" can technically be used to retrieve in a manner that is on-behalf of someone else.
Cool fact - we use it for VA responses.
Example of how it works
So let's start small to explain how it works before I show how it works with an email notification. Imagine I use trusty "Abel" my no.1 demo user - (check his twitter if you haven't already, he's famous), and let's set his language to Japanese for the purpose of this demo:
Let's make some translations of a message record, in this case we'll use the key "1 {0} associated successfully." like this:
If I run an experimental background script to prove the concept out, this is what I could do:
msgLangTest();
function msgLangTest(){
try {
// lets find our example non-English user example
var getUser = new GlideRecord('sys_user');
getUser.addQuery('user_name', 'abel.tuter');
getUser.query();
if(getUser.next()){
gs.debug('User is - '+getUser.user_name+', Language - '+getUser.preferred_language);
// this user has a non English language
if(getUser.preferred_language != ''){
gs.debug(gs.getMessageLang("1 {0} associated successfully.", getUser.preferred_language, getUser.user_name));
}
}
} catch (err) {
gs.debug('Error in msgLangTest - '+err.name+ ' - '+err.message);
}
}
Which would give me the following output:
*** Script: [DEBUG] User is - abel.tuter, Language - ja
*** Script: [DEBUG] 1 個の abel.tuter が正常に関連付けられました。
Example recap
So we can clearly see that it's quite possible to easily retrieve a message in another language without any super complex scripting. Let's make a notification taking what we've just learned.
Email Notification Example
For the sake of demonstration, I'm just going to make a very simple notification on the incident table to trigger when a new Incident is created (active=true) and it's going to call a template and send to the caller:
^ Our template in this example is called "PoC Inc Open", which in-turn is going to call a "mail script" like this:
This means that all of the content of the notification will have to be handled via the "mail script" which in this example is called "incident_script_1" (you can call it what-ever you would like).
Cool fact - when you write <mail_script>// do something</mail_script> in your notification, you will get a prompt for it to auto-create the mail script record on your behalf and adjust your code to call it accordingly, I would suggest you accept the prompt.
It's also important to note that if necessary you can have more than one mail script in a given notification, what I'm showing here is just an example of how it works.
So our "mail script" actually looks like this:
(function runMailScript( /* GlideRecord */ current, /* TemplatePrinter */ template,
/* Optional EmailOutbound */
email, /* Optional GlideRecord */ email_action,
/* Optional GlideRecord */
event) {
// let's get the language of the recipient
var getUserLang = new GlideRecord('sys_user');
getUserLang.addQuery('sys_id', current.caller_id.sys_id);
getUserLang.query();
if (getUserLang.next()) {
email.setSubject(gs.getMessageLang("Incident Created", getUserLang.preferred_language));
template.print(gs.getMessageLang("Dear - {0}", getUserLang.preferred_language, getUserLang.name));
template.print('<br>');
template.print(gs.getMessageLang("Thank you for raising your incident", getUserLang.preferred_language));
}
})(current, template, email, email_action, event);
What it's doing is checking the caller's details (as that's the recipient we defined in our notification) because we need their preferred language in order to know what message record we want to call. It's then defining the subject of the email and some of the body of the email.
So, we need 3 [sys_ui_message] records in English and Japanese for this example to work;
Now we just need to test it by creating 2 incidents, one for an English speaking user and one for a Japanese speaking user;
Joe Employee (English)
Abel Tuter (Japanese example)
The Pros
It's the same email notification being sent to 2 different recipients,
with the contents being called in a manner that can
check for the recipients languages.
The Cons
This method is great if it's for a singular recipient that is defined in
a field associated to that process record. Whilst being a bit more
technical in nature compared to the first option, it does open up
many other possibilities.
What if we need to send an email to a watchlist and one member is an English speaker and the other is a Japanese speaker?
As I like a good challenge (within a few minutes of this post originally going up, I got asked about "what about watchlists?") - good question.
What I'm about to go through is by no means perfect, however it's just a very quick example to show what is possible. And for sure this would need refining to meet the needs you may have, so take this purely as a proof of concept that needs to be refined.
With that out of the way, what could we do if we wanted this to work for a watchlist scenario? Let's go through the challenge, if we just added "watch_list" as a field to our existing notification, then only 1 email is actually being generated as all those recipients are added to the "cc" of the email, so we should probably duplicate our notification to give us a bit more options.
In my example I have our same notification for the "caller_id" and the same notification duplicated for the "watch_list" calling the same notification template referring to an updated version of the original mail_script:
Our original mail script has now been updated to be like this:
(function runMailScript( /* GlideRecord */ current, /* TemplatePrinter */ template,
/* Optional EmailOutbound */
email, /* Optional GlideRecord */ email_action,
/* Optional GlideRecord */
event) {
var fieldsToCheck = email_action.recipient_fields.toString().split(',');
var multiUsers = [];
multiUsers.push(current[fieldsToCheck]);
multiUsers = multiUsers.toString().split(',');
for (var i = 0; i < multiUsers.length; i++) {
var emailMsg = '';
// let's get the language of the recipient
var getUserLang = new GlideRecord('sys_user');
getUserLang.addQuery('sys_id', multiUsers[i]);
getUserLang.query();
if (getUserLang.next()) {
emailMsg += gs.getMessageLang("Dear - {0}", getUserLang.preferred_language, getUserLang.name);
emailMsg += '<br>';
emailMsg += gs.getMessageLang("Thank you for raising your incident", getUserLang.preferred_language);
if (i == 0) {
email.setBody(emailMsg);
email.setSubject(gs.getMessageLang("Incident Created", getUserLang.preferred_language));
} else {
var newEmail = new GlideRecord('sys_email');
newEmail.initialize();
newEmail.recipients = getUserLang.email.toString();
newEmail.subject = gs.getMessageLang("Incident Created", getUserLang.preferred_language);
newEmail.body = emailMsg;
newEmail.type = 'send-ready';
// base fields
newEmail.target_table = current.getTableName();
newEmail.instance = current.sys_id;
newEmail.outbox = current.outbox;
newEmail.content_type = 'text/html';
newEmail.headers = current.headers;//
newEmail.notification_type = 'SMTP';
newEmail.insert();
}
}
}
})(current, template, email, email_action, event);
And when I raise an incident where we have an English speaking Caller, and two members in the watch_list where one is English speaking and one is Japanese speaking, we should see the following notifications generated:
It for sure needs refinement, because Abel would have received both an English and Japanese notification, but the takeaway here is that it is doable and possible to split out the notifications per language.
For Groups, you could follow the same logic and loop through the [sys_user_grmember] table to determine the language of those group members leading to the same multi-lingual output as necessary.
Summary
So, we've learned that it is very possible to generate emails to be sent in other languages. The options available to us vary based on our requirements, and the platform gives us these building blocks so that we (Solution Architects / Designers / Platform Owners) can leverage what suits us best.
Naturally what I've discussed here can be expanded upon massively (including even calling the Dynamic Translation api (getTranslations), which all depends on how you want to mature it for your needs, ultimately however there are multiple options to help with your specific needs.
If you found this helpful, please like, share and subscribe for more as it always helps
- 3,839 Views

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi Alex,
Nice write up. Question though... what if the email is sent to multiple recipients. And those recipients having different languages 🙂
Kind regards,
Mark
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Good question - I've updated the article with the answer