Skip to content

Commit 9db6ae3

Browse files
authored
Create translationUtil.js
his SI is a translationUtil to for dynamic language translation for example english to French This script include for language translation will invoke flow designer action and sublfow to do the dynamic language transaltion
1 parent 01bb3d8 commit 9db6ae3

File tree

1 file changed

+359
-0
lines changed

1 file changed

+359
-0
lines changed
Lines changed: 359 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,359 @@
1+
/*
2+
This SI is a translationUtil to for dynamic language translation for example english to French
3+
4+
This script include for language translation will invoke flow designer action and sublfow to complete the real time language transaltion
5+
6+
The properties referred in this translation util is DUMMY name that needs to be replaced with actual property name
7+
8+
Identify the right AI translator for language and Update
9+
*/
10+
var TranslationUtils = Class.create();
11+
TranslationUtils.prototype = {
12+
initialize: function() {},
13+
14+
getLimits: function() {
15+
16+
var charLimit = parseInt(gs.getProperty('mycompany.dynamic.translation.char.limit', 30720));//51200=50KB 30720 = 30KB
17+
var requestBufferSize = parseInt(gs.getProperty('mycompany.dynamic.translation.request.buffer', 100));
18+
charLimit = (charLimit >= requestBufferSize) ? (charLimit - requestBufferSize) : charLimit;
19+
return {
20+
'charLimit': charLimit,
21+
'arrayLimit': parseInt(gs.getProperty('mycompany.dynamic.translation.array.limit', 10)),
22+
'textBufferSize': parseInt(gs.getProperty('mycompany.dynamic.translation.text.buffer', 4))
23+
};
24+
},
25+
26+
27+
getSubscriptionKey: function() {
28+
29+
/* try {
30+
31+
var result = sn_fd.FlowAPI.getRunner().action('<call FD action to get subscription key>').inForeground().run();
32+
var get_key_outputs = result.getOutputs();
33+
var subscription_key = get_key_outputs.subscription_key;
34+
35+
return subscription_key;
36+
37+
} catch (ex) {
38+
var message = ex.getMessage();
39+
gs.error(message);
40+
41+
}*/
42+
try {
43+
44+
var alias = gs.getProperty('mycompany.alias.ia.translation.id');
45+
var subscription_key = '';
46+
47+
var gr_connection = new GlideRecord('http_connection');
48+
gr_connection.addEncodedQuery('active=true^connection_alias=' + alias);
49+
gr_connection.query();
50+
51+
if (gr_connection.next()) {
52+
var gr_api_key = new GlideRecord('api_key_credentials');
53+
gr_api_key.get(gr_connection.getValue('credential'));
54+
subscription_key = gr_api_key.api_key.getDecryptedValue();
55+
}
56+
57+
return subscription_key;
58+
59+
} catch (ex) {
60+
var message = ex.getMessage();
61+
gs.error(message);
62+
}
63+
64+
},
65+
66+
67+
getKBSize: function(text, limits) {
68+
var bytes = text.length;
69+
for (var i = text.length - 1; i >= 0; i--) {
70+
var code = text.charCodeAt(i);
71+
if (code > 0x7f && code <= 0x7ff)
72+
bytes++;
73+
else if (code > 0x7ff && code <= 0xffff)
74+
bytes += 2;
75+
if (code >= 0xDC00 && code <= 0xDFFF)
76+
i--;
77+
}
78+
var textBufferSize = limits.textBufferSize;
79+
return bytes + textBufferSize;
80+
},
81+
82+
getBytesData: function(texts, limits) {
83+
var bytesData = {};
84+
for (var i = 0; i < texts.length; i++) {
85+
var kbSize = this.getKBSize(texts[i], limits);
86+
bytesData[texts[i]] = kbSize;
87+
}
88+
return bytesData;
89+
},
90+
91+
classifyBulkTexts: function(texts, charLimit, bytesData) {
92+
var count = 0;
93+
var classifiedData = {};
94+
classifiedData["smallTexts"] = [];
95+
classifiedData["largeTexts"] = [];
96+
classifiedData["isBatchingRequired"] = false;
97+
for (var i = 0; i < texts.length; i++) {
98+
if (bytesData[texts[i]] > charLimit) {
99+
classifiedData["largeTexts"].push(texts[i]);
100+
} else {
101+
classifiedData["smallTexts"].push(texts[i]);
102+
count = count + bytesData[texts[i]];
103+
if (count > charLimit) {
104+
classifiedData["isBatchingRequired"] = true;
105+
}
106+
}
107+
}
108+
return classifiedData;
109+
},
110+
111+
splitLargeTexts: function(texts, charLimit) {
112+
113+
var text_obj = {}; //text_obj = texts[0];
114+
var text_transl = []; //text_transl = text_obj["texts_to_translate"];
115+
var text_splited = [];
116+
//gs.log("charLimit : " + charLimit +'\n\ntext_transl : ' + JSON.stringify(text_transl), "BELLTR");
117+
//var text_array = texts[0].texts_to_translate;
118+
//for (var i = 0; i < text_transl.length; i++) {
119+
//var txt = text_transl[i];
120+
var txt = texts
121+
var kbSize = this.getKBSize(txt, limits);
122+
gs.log('kbSize : ' + kbSize +'\n\ntxt : ' + JSON.stringify(txt), "TELCOTR");
123+
if (kbSize > charLimit) {
124+
var text = txt
125+
var size = 0;
126+
var stop = 0
127+
gs.log('text : ' + text, "TELCOTR");
128+
while (size > charLimit && stop < 4) {
129+
text = txt.subString(0, charLimit);
130+
txt = txt.subString(charLimit);
131+
text_splited.push(text);
132+
gs.log('text_splited : ' + text_splited, "TELCOTR");
133+
size = this.getKBSize(txt, limits)
134+
stop++;
135+
}
136+
text_splited.push(txt)
137+
}
138+
139+
140+
return text_splited;
141+
},
142+
143+
144+
addLargeTextsToArray: function(result, largeTexts, targetLanguages) {
145+
146+
for (var large = 0; large < largeTexts.length; large++) {
147+
this.transformBatchTextsResponse([largeTexts[large]], targetLanguages, result);
148+
}
149+
},
150+
151+
getSortedBytesMap: function(texts, bytesData) {
152+
var bytesList = [];
153+
for (var i = 0; i < texts.length; i++) {
154+
var kbSize = bytesData[texts[i]];
155+
if (kbSize) {
156+
bytesList.push([kbSize, texts[i]]);
157+
}
158+
}
159+
return bytesList.sort();
160+
},
161+
162+
getBatchTexts: function(texts, bytesData, limits) {
163+
var bytesList = this.getSortedBytesMap(texts, bytesData);
164+
var weight = limits.charLimit;
165+
var splitTexts = [];
166+
var startIdx = 0;
167+
var arrayLength = bytesList.length;
168+
var endIdx = arrayLength - 1;
169+
var textsProcessed = 0;
170+
while (textsProcessed < arrayLength) {
171+
var singleSplit = [];
172+
var tempWeight = 0;
173+
while (singleSplit.length != limits.arrayLimit &&
174+
endIdx >= 0 &&
175+
startIdx <= endIdx &&
176+
weight >= (tempWeight + bytesList[endIdx][0])) {
177+
tempWeight += bytesList[endIdx][0];
178+
singleSplit.push(bytesList[endIdx][1]);
179+
endIdx -= 1;
180+
textsProcessed += 1;
181+
}
182+
while (singleSplit.length != limits.arrayLimit &&
183+
startIdx < arrayLength &&
184+
startIdx <= endIdx &&
185+
weight >= (tempWeight + bytesList[startIdx][0])) {
186+
tempWeight += bytesList[startIdx][0];
187+
singleSplit.push(bytesList[startIdx][1]);
188+
startIdx += 1;
189+
textsProcessed += 1;
190+
}
191+
splitTexts.push(singleSplit);
192+
}
193+
return splitTexts;
194+
},
195+
196+
197+
transformBatchTextsResponse: function(texts, targetLanguages, result) {
198+
for (var i = 0; i < targetLanguages.length; i++) {
199+
result.push({
200+
"texts_to_translate": texts,
201+
"target_language": targetLanguages[i]
202+
});
203+
}
204+
},
205+
206+
addSmallTextsToArray: function(smallTexts, result, limits, targetLanguages) {
207+
var tempSmallTexts = [];
208+
for (var i = 0; i < smallTexts.length; i++) {
209+
tempSmallTexts.push(smallTexts[i]);
210+
if (tempSmallTexts.length == limits.arrayLimit) {
211+
this.transformBatchTextsResponse(tempSmallTexts, targetLanguages, result);
212+
tempSmallTexts = [];
213+
}
214+
}
215+
if (tempSmallTexts.length > 0) {
216+
this.transformBatchTextsResponse(tempSmallTexts, targetLanguages, result);
217+
}
218+
219+
},
220+
221+
splitInputTextsIntoBatches: function(texts, limits, targetLanguages) {
222+
var result = [];
223+
var bytesData = this.getBytesData(texts, limits);
224+
var classifiedData = this.classifyBulkTexts(texts, limits.charLimit, bytesData);
225+
if (classifiedData["isBatchingRequired"]) {
226+
var splitTexts = this.getBatchTexts(classifiedData.smallTexts, bytesData, limits);
227+
228+
for (var idx = 0; idx < splitTexts.length; idx++) {
229+
var selectedTexts = splitTexts[idx];
230+
this.transformBatchTextsResponse(selectedTexts, targetLanguages, result);
231+
}
232+
} else {
233+
this.addSmallTextsToArray(classifiedData.smallTexts, result, limits, targetLanguages);
234+
}
235+
this.addLargeTextsToArray(result, classifiedData.largeTexts, targetLanguages);
236+
return result;
237+
},
238+
239+
240+
batchBulkTexts: function(texts, targetLanguages) {
241+
var limits = this.getLimits();
242+
//var test = this.splitLargeTexts(texts, limits.charLimit)
243+
//gs.log('test: ' + JSON.stringify(test), "TELCOTR")
244+
return this.splitInputTextsIntoBatches(texts, limits, targetLanguages);
245+
},
246+
247+
_getProcessedTextResult: function(textResult) {
248+
var processedTextResult = {};
249+
var textResultKeys = Object.keys(textResult);
250+
for (var keyIdx = 0; keyIdx < textResultKeys.length; keyIdx++) {
251+
var key = textResultKeys[keyIdx];
252+
if (key == 'text_translations') {
253+
var textTranslations = [];
254+
var languages = Object.keys(textResult.text_translations);
255+
for (var idx = 0; idx < languages.length; idx++) {
256+
var language = languages[idx];
257+
var textTranslation = {
258+
'translated_text': textResult.text_translations[language],
259+
'target_language': language
260+
};
261+
textTranslations.push(textTranslation);
262+
}
263+
processedTextResult.text_translations = textTranslations;
264+
} else {
265+
processedTextResult[key] = textResult[key];
266+
}
267+
}
268+
return processedTextResult;
269+
},
270+
271+
rearrangeJSONResult: function(texts, result, isTranslation) {
272+
var response = {
273+
'status': 'Success'
274+
};
275+
var rearrangedResponse = [];
276+
for (var i = 0; i < texts.length; i++) {
277+
var eachTextResult = result[texts[i]];
278+
if ('Error' === eachTextResult.status) {
279+
response['status'] = 'Error';
280+
}
281+
var processedTextResult = this._getProcessedTextResult(eachTextResult);
282+
rearrangedResponse.push(processedTextResult);
283+
}
284+
if (isTranslation)
285+
response['translations'] = rearrangedResponse;
286+
else
287+
response['detections'] = rearrangedResponse;
288+
return response;
289+
},
290+
291+
292+
detectLanguage: function(texts) {
293+
294+
try {
295+
var inputs = {};
296+
inputs['texts'] = texts; // Array.String
297+
298+
// Start Asynchronously: Uncomment to run in background. Code snippet will not have access to outputs.
299+
// sn_fd.FlowAPI.getRunner().subflow('<detect langugage FD Action>').inBackground().withInputs(inputs).run();
300+
301+
// Execute Synchronously: Run in foreground. Code snippet has access to outputs.
302+
var result = sn_fd.FlowAPI.getRunner().subflow('<detect langugage FD Action>').inForeground().withInputs(inputs).run();
303+
var outputs = result.getOutputs();
304+
305+
// Get Outputs:
306+
// Note: outputs can only be retrieved when executing synchronously.
307+
var detections = outputs['detections']; // Array.Object
308+
var status = outputs['status']; // Choice
309+
var rest_calls = outputs['rest_calls']; // Integer
310+
311+
return detections;
312+
313+
} catch (ex) {
314+
var message = ex.getMessage();
315+
gs.log(message, "AI Translator - detectLanguage");
316+
}
317+
318+
return '';
319+
320+
},
321+
322+
translateFields: function(texts, source_language, target_languages, additional_parameters) {
323+
324+
try {
325+
326+
var inputs = {};
327+
inputs['texts'] = texts; // Array.String
328+
inputs['source_language'] = source_language; // String
329+
inputs['target_languages'] = target_languages; // Array.String
330+
inputs['additional_parameters'] = additional_parameters; // Array.Object
331+
332+
// Start Asynchronously: Uncomment to run in background. Code snippet will not have access to outputs.
333+
// sn_fd.FlowAPI.getRunner().subflow('<FD ACTION for Text Translation>').inBackground().withInputs(inputs).run();
334+
335+
// Execute Synchronously: Run in foreground. Code snippet has access to outputs.
336+
var result = sn_fd.FlowAPI.getRunner().subflow('global.<FD ACTION for Text Translation>').inForeground().withInputs(inputs).run();
337+
var outputs = result.getOutputs();
338+
339+
// Get Outputs:
340+
// Note: outputs can only be retrieved when executing synchronously.
341+
var translations = outputs['translations']; // Array.Object
342+
var status = outputs['status']; // Choice
343+
var rest_calls = outputs['rest_calls']; // Integer
344+
345+
return translations;
346+
347+
} catch (ex) {
348+
var message = ex.getMessage();
349+
gs.log(message, "
350+
AI Translator - translateFields");
351+
}
352+
353+
return '';
354+
355+
},
356+
357+
358+
type: 'TranslationUtils'
359+
};

0 commit comments

Comments
 (0)