- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
2 hours ago
So, I was in a call with a customer the other day who are going live with NowAssist in Virtual Agent in a bunch of languages and so they had an ask of "how can we translate some of that static strings that aren't coming from the LLM's?".
As usual it got me thinking - let's make another LF artifact 🙂
Here goes - as usual we need 3 key parts (all made in the global scope). Also, please remember this is a prototype so I can't guarantee it will work for all scenarios or pick up all strings. It will depend on how you've made your various topics, so you may need to adjust the query of the processor script if necessary for your specific use-case.
The UI action:
We need to define it on the [sys_cs_context_profile] table
^ remember to pay attention to the "internal name" of the artifact that is called in the condition of the UI action. We will be calling this one "proto_gen_ai_skill" in this example.
The Artifact configuration:
The processor script (remember to set it for all application scopes):
var LF_gen_ai_skill = Class.create();
LF_gen_ai_skill.prototype = Object.extendsObject(global.LFArtifactProcessorSNC, {
category: 'localization_framework', // DO NOT REMOVE THIS LINE!
/**********
* Extracts the translatable content for the artifact record
*
* @Param params.tableName The table name of the artifact record
* @Param params.sysId The sys_id of the artifact record
* @Param params.language Language into which the artifact has to be translated (Target language)
* @return LFDocumentContent object
**********/
getTranslatableContent: function(params) {
/**********
* Use LFDocumentContentBuilder to build the LFDocumentContent object
* Use the build() to return the LFDocumentContent object
**********/
var tableName = params.tableName;
var sysId = params.sysId;
var language = params.language;
var groupName = "";
var lfDocumentContentBuilder = new global.LFDocumentContentBuilder("v1", language, sysId, tableName);
// what context profile are we looking at
var contextProfile = new GlideRecord('sys_cs_context_profile');
contextProfile.addQuery('sys_id', sysId);
contextProfile.query();
if (contextProfile.next()) {
lfDocumentContentBuilder.processTranslatableFieldsForSingleRecord(contextProfile, "ContextProfile", "Name");
// from the profile we need to find the topics
var getTopics = new GlideRecord('sys_cs_context_profile_topic');
getTopics.addQuery('context_profile', contextProfile.sys_id);
getTopics.query();
while (getTopics.next()) {
// we need to process the topics and the ai-skills
// topics first
var getCSTopic = new GlideRecord('sys_cs_topic');
getCSTopic.addQuery('sys_id', getTopics.topic.sys_id);
getCSTopic.query();
if (getCSTopic.next()){
lfDocumentContentBuilder.processTranslatableFieldsForSingleRecord(getCSTopic, "Topic", "Name");
// now we need to get it's corresponding AI Skill
var getAISkill = new GlideRecord('sys_gen_ai_skill');
getAISkill.addQuery('skill_document', getCSTopic.sys_id);
getAISkill.query();
if (getAISkill.next()){
lfDocumentContentBuilder.processTranslatableFieldsForSingleRecord(getAISkill, "Skill", "Name");
}
}
}
// we need to process a bunch of static entries from NowAssist
var defMsgs = [
"Here's what you can do next:",
"Search for more results",
"Need more help?",
"Sources",
"Show sources",
"Hide sources",
"Ask Now Assist for help or search",
"Hi {0}, how can I help you",
"Hi {0}, how can I help you? I'm an AI powered Virtual Assistant that can handle work-related questions and requests.",
"Generating responses",
"{0} minute ago",
"{0} minutes ago",
"{0} seconds ago",
"Just now",
"Helpful",
"Not helpful",
"Go to search results",
"Go to request",
"New chat",
"Reply…",
"Reply to Now Assist…",
"Copy message",
"Now Assist",
"Chats",
"Support and settings",
"Some answers generated by AI. Be sure to check for accuracy",
"upload up to {0} files (max {1} mb each) to ask questions about their contents",
"Send",
"Settings",
"Audio Notifications",
"Support",
"No live agents currently available",
"Active",
"No chatter at the moment",
"Updates",
"a notification has arrived. you can continue the conversation after viewing the notification.",
"Important updates and reminders",
"Ongoing chats you can interact with",
"View AI Steps",
"Let me look up information related to {0}. for you.",
];
for (var i = 0; i < defMsgs.length; i++) {
lfDocumentContentBuilder.processString(defMsgs[i].toString(), "Default Messages", "Name");
}
// now we need to get some default system messages
var sysDef = new GlideRecord('sys_properties');
sysDef.addEncodedQuery('name=com.glide.cs.conversation.interrupt_redirect.message^ORname=com.glide.cs.idle_chat_reminder_message^ORname=com.glide.cs.agent_transfer_msg^ORname=com.glide.cs.autopilot.client_initiated_header^ORname=com.glide.cs.sensitive.data.agent_error^ORname=com.glide.cs.sensitive.data.requester_message^ORname=com.glide.cs.sensitive.data.agent_message^ORname=com.glide.cs.idle_chat_reminder_message_for_agent^ORname=com.glide.cs.autopilot.agent_finished_msg^ORname=com.glide.cs.general.retry_question_message^ORname=com.glide.cs.autopilot.agent_initiated_msg^ORname=com.glide.cs.autopilot.agent_error_msg^ORname=com.glide.cs.autopilot.client_finished_message^ORname=com.glide.cs.autopilot.client_initiated_message^ORname=com.glide.cs.transfer_to_queue_msg^ORname=com.glide.cs.end_chat_msg^ORname=com.glide.cs.conversation_ended_msg^ORname=com.glide.cs.topic_picker_msg^ORname=com.glide.cs.link_account_msg^ORname=com.glide.cs.available_topics_msg^ORname=com.glide.cs.want_something_else_option^ORname=com.glide.cs.wrong_topic_message^ORname=com.glide.cs.general.retry_filtered_list_message^ORname=com.glide.cs.general.waiting_for_live_agent_message^ORname=com.glide.cs.general.retry_max_char_limit_exceeded_message^ORname=com.glide.cs.no_topic_sorry_message^ORname=com.glide.cs.no_topic_found_message^ORname=com.glide.cs.general.live_agent_handoff_message^ORname=com.glide.cs.topic_choice_list_message^ORname=com.glide.cs.topic_confirmation_message^ORname=com.glide.cs.general.live_agent_handoff_error_message^ORname=com.glide.cs.conversation_faulted_reason^ORname=com.glide.cs.chat_conversation_translating_message^ORname=com.glide.cs.linking_account.message^ORname=com.glide.cs.conversation.start_over_message^ORname=com.glide.cs.unlinking_account.message^ORname=com.glide.cs.unlink_account.confirmation_message^ORname=com.glide.cs.resume_conversation.message^ORname=com.glide.cs.general.closing_message^ORname=com.glide.cs.general.chat_survey_verification_message^ORname=com.glide.cs.general.error_message');
sysDef.query();
while (sysDef.next()) {
if (sysDef.value != '') {
// it's best to be defensive here
lfDocumentContentBuilder.processString(sysDef.value.toString(), "System Messages", "Name");
}
}
// CS profile messages
var getMsgs = new GlideRecord('sys_cs_context_profile_message');
getMsgs.addQuery('context_profile', contextProfile.sys_id);
getMsgs.addEncodedQuery('context_profile.active=true^context_profile.model_type=llm'); // to narrow down the results
getMsgs.query();
while (getMsgs.next()) {
lfDocumentContentBuilder.processString(getMsgs.message.toString(), "Context Message", getMsgs.context_profile.getDisplayValue()); // it needs to be both MSG
lfDocumentContentBuilder.processTranslatableFieldsForSingleRecord(getMsgs, "Context Message", getMsgs.context_profile.getDisplayValue()); // whilst the message field is a TRT field, we might need the translation to also be a TRT
}
}
return lfDocumentContentBuilder.build();
},
/**********
* Uncomment the saveTranslatedContent function to override the default behavior of saving translations
*
* @Param documentContent LFDocumentContent object
* @return
**********/
/**********
saveTranslatedContent: function(documentContent) {},
**********/
type: 'LF_gen_ai_skill'
});
The logic of this query is to follow the assistant you've made, then to find all the messages associated to that assistant, then to find all the default messages which are mostly coming from some system properties. If you are finding some strings are still not translated, you may also need to run the specific "topic" artifact to translate the corresponding VA topics you've made.
When you have it set up and working, you should see an output like this in the LFTask:
NOTE: if you want to use this with the Localization Workspace, as usual you will need to define some RCA's and create some Cross Scope privileges for the "execute API" call (to the Script include) and "read" action to the table [sys_cs_context_profile].
As usual, because this is a prototype, no support or warranties are offered on this artifact, this is just being shared for the benefit of the community to help you progress faster.
So, again we've seen that we can keep expanding the translation capability with more artifacts to help simplify how we translate more areas of the platform.
If you found this helpful / useful, please like, share and subscribe for more as it always helps.
