Translate line items description with external HTTP service API
You might be getting line items with item descriptions in many languages. However, at the end you need to link the products based on the English descriptions to your own product database. This function can enable you to translate descriptions of the items in just a single click.
This code example assumes you have the following field IDs in your extraction schema:
- "item_description" for capturing the description column in line items
- "localize_button" for having a button that user can click on and translate the line items to English
Moreover, the serverless function should be configured to get notifications on "user_update" action and the function should be assigned to some queue.
Copy the example below and paste it to your schema in order to create a button:
{
"category": "datapoint",
"id": "localize_button",
"label": "Localize button",
"type": "button"
}
Afterwards, create a Microsoft Azure account and setup an access to Translator API service.
Copy the authentication key and replace it in the function code below.
// This serverless function example can be used for annotation_content events
// (e.g. user_update action). annotation_content events provide annotation
// content tree as the input.
//
// The function below shows how to use an external HTTP service API to translate
// the description of line item from any language to english.
// Using https module for HTTP requests
const https = require('https');
// --- ROSSUM HOOK REQUEST HANDLER ---
// The rossum_hook_request_handler is an obligatory main function that accepts
// input and produces output of the rossum serverless function hook. Currently,
// the only available programming language is Javascript executed on Node.js 12 environment.
// @param {Object} annotation - see https://api.elis.rossum.ai/docs/#annotation-content-event-data-format
// @returns {Object} - the messages and operations that update the annotation content
exports.rossum_hook_request_handler = async ({
annotation: {
content
},
updated_datapoints
}) => {
try {
// User clicked or updated a specific datapoint (f.e. clicked on a button)
const [updatedDatapoint] = findByDatapointId(
content,
updated_datapoints[0],
);
let messages = [];
let operations = [];
let dataString = '';
if (updatedDatapoint && updatedDatapoint.schema_id == 'localize_button') {
// Get all item_description datapoints
let itemDescriptions = findBySchemaId(content, "item_description");
let textsToTranslate = [];
for (var i = 0; i < itemDescriptions.length; i++) {
// Prepare translation input for the HTTPS request
if (itemDescriptions[i].content.value != null) {
textsToTranslate.push({
"Text": itemDescriptions[i].content.value
});
}
}
// Create header for the HTTP request
const options = {
hostname: 'api.cognitive.microsofttranslator.com',
path: '/translate?api-version=3.0&to=en',
method: 'POST',
headers: {
'Ocp-Apim-Subscription-Key': '...authentication key...',
'Ocp-Apim-Subscription-Region': 'westeurope',
'Content-Type': 'application/json; charset=UTF-8',
},
};
// Define how to process response
const response = await new Promise((resolve, reject) => {
const req = https.request(options, function(res) {
res.on('data', chunk => {
dataString += chunk;
});
res.on('end', () => {
resolve({
statusCode: 200,
body: dataString
});
});
});
req.on('error', (e) => {
reject({
statusCode: 500,
body: 'Something went wrong!'
});
});
// Fill request with payload
req.write(JSON.stringify(textsToTranslate))
// Execute request
req.end()
});
// Parse response
translatedChunks = JSON.parse(dataString);
// Update existing line item descriptions with translations
for (var j = 0; j < translatedChunks.length; j++) {
const translatedChunk = translatedChunks[j]["translations"][0]["text"];
operations.push(createReplaceOperation(itemDescriptions[j], translatedChunk));
}
}
return {
messages,
operations,
};
} catch (e) {
const messages = [createMessage('error', 'Serverless Function: ' + e.message)];
return {
messages
};
}
};
// --- HELPER FUNCTIONS ---
// Return datapoints matching a schema id.
// @param {Object} content - the annotation content tree (see https://api.elis.rossum.ai/docs/#annotation-data)
// @param {string} schemaId - the field's ID as defined in the extraction schema(see https://api.elis.rossum.ai/docs/#document-schema)
// @returns {Array} - the list of datapoints matching the schema ID
const findBySchemaId = (content, schemaId) =>
content.reduce(
(results, dp) =>
dp.schema_id === schemaId ?
[...results, dp] :
dp.children ?
[...results, ...findBySchemaId(dp.children, schemaId)] :
results,
[],
);
// Create a message which will be shown to the user
// @param {number} datapointId - the id of the datapoint where the message will appear (null for "global" messages).
// @param {String} messageType - the type of the message, any of {info|warning|error}. Errors prevent confirmation in the UI.
// @param {String} messageContent - the message shown to the user
// @returns {Object} - the JSON message definition (see https://api.elis.rossum.ai/docs/#annotation-content-event-response-format)
const createMessage = (type, content, datapointId = null) => ({
content: content,
type: type,
id: datapointId,
});
// Replace the value of the datapoint with a new value.
// @param {Object} datapoint - the content of the datapoint
// @param {string} - the new value of the datapoint
// @return {Object} - the JSON replace operation definition (see https://api.elis.rossum.ai/docs/#annotation-content-event-response-format)
const createReplaceOperation = (datapoint, newValue) => ({
op: 'replace',
id: datapoint.id,
value: {
content: {
value: newValue,
},
},
});
// Return a datapoint by its ID.
// @param {Object} content - the annotation content tree (see https://api.elis.rossum.ai/docs/#annotation-data)
// @param {string} datapointId - the datapoints ID. (https://api.elis.rossum.ai/docs/#common-attributes)
// @returns {Array} - datapoints matched by its ID (should return only one datapoint)
const findByDatapointId = (content, datapointId) =>
content.reduce(
(results, dp) =>
dp.id === datapointId ? [...results, dp] :
dp.children ? [...results, ...findByDatapointId(dp.children, datapointId)] :
results,
[],
);
Enabling access to Internet for serverless function
Make sure the internet access was enabled on your functions. Contact us at [email protected] or read about the limitations.
Updated almost 4 years ago