Skip to content

Instantly share code, notes, and snippets.

@KayLerch

KayLerch/en-US.js

Last active Mar 29, 2020
Embed
What would you like to do?
Optimized i18n request interceptor for Alexa custom skills in Node. Loads only required language assets from external files and provides some convenient functions to read them. Will also let you store localized settings represented as JSON objects in your language files.
module.exports = Object.freeze({
translation: {
welcome: 'Howdy',
images: [
{
background: 'https://image/en-US.png'
},
{
background: 'https://image/en-US2.png'
},
{
background: 'https://image/en-US3.png'
}
]
}
});
module.exports = Object.freeze({
translation: {
welcome: 'Hello',
greet: 'Hello %s',
random: {
welcome: [ 'Hello', 'Hi' ],
greet: [ 'Hello %s', 'Hi %s' ],
}
}
});
const Alexa = require('ask-sdk-core');
const LaunchRequestHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'LaunchRequest';
},
handle(handlerInput) {
console.log(handlerInput.t('welcome'));
console.log(handlerInput.t2('welcome'));
console.log(handlerInput.t('random.welcome'));
console.log(handlerInput.t2('random.welcome')[1]);
console.log(handlerInput.t('greet', 'Michael'));
console.log(handlerInput.t2('greet', 'Michael'));
console.log(handlerInput.t('random.greet', 'Michael'));
console.log(handlerInput.t2('random.greet', 'Michael')[1]);
console.log(handlerInput.o('images').background);
console.log(handlerInput.o2('images')[1].background);
return handlerInput.responseBuilder.speak('Test').getResponse();
},
};
const skillBuilder = Alexa.SkillBuilders.custom();
exports.handler = skillBuilder
.addRequestHandlers(LaunchRequestHandler)
.addRequestInterceptors(require("./intercept_i18n"))
.lambda();
const i18n = require('i18next');
const sprintf = require('i18next-sprintf-postprocessor');
const merge_json = require("merge-json");
/*
1) SETUP:
required are language file (e.g. en.js or de.js) and locale file (e.g. en-US.js) both in format of:
/*
module.exports = Object.freeze({
translation: {
sayhello: [ 'hello', 'hi' ],
greet: 'Welcome %s',
saybye: 'Good bye',
images: {
logo: 'https://localized/images/us.png'
},
nice_places: [
{
name: 'Golden Gate Bridge',
city: 'San Francisco'
}, ...
],
...
}
});
2) INTEGRATE:
Alexa.SkillBuilders.custom().addRequestInterceptors(require("./path/to/this/file.js"));
3) USE:
handlerInput.t('welcome');
handlerInput.t('greet', 'Scott');
handlerInput.o('images').logo;
handlerInput.o2('nice_places')[0].name;
*/
module.exports = Object.freeze({
process(handlerInput) {
const locale = handlerInput.requestEnvelope.request.locale;
const localizationClient = i18n.use(sprintf).init({
resources: {
/* merge language and locale file where locale file is dominant and overwrites generic language assets.
e.g. you can set generic English welcome string 'hello' and specifc en-US welcome 'Howdy'. 'Howdy' will be taken */
[locale]: merge_json.merge(
require(`./strings/${locale.split("-")[0]}.js`), // e.g. en.js
require(`./strings/${locale}.js`) // e.g. en-US.js
)}, lng: locale });
localizationClient.localize = function(format, randomize, ...args) {
const settings = Object.assign({ returnObjects: true }, format ? { postProcess: 'sprintf', sprintf: args.slice(1) } : {});
const value = i18n.t(args[0], settings);
return randomize && Array.isArray(value) ? value[Math.floor(Math.random() * value.length)] : value;
};
handlerInput.t = handlerInput.attributesManager.getRequestAttributes().t = function(...args) {
return localizationClient.localize(true, true, ...args);
};
// t2 skips returning randomized string from an array of strings for a given asset. instead returns array as is
handlerInput.t2 = handlerInput.attributesManager.getRequestAttributes().t2 = function(...args) {
return localizationClient.localize(true, false, ...args);
};
// o skips string post processing and returns plain JSON object (useful if you store localized settings in your language files)
// will still pick random item if requested asset is an array
handlerInput.o = handlerInput.attributesManager.getRequestAttributes().o = function(...args) {
return localizationClient.localize(false, true, ...args);
};
// o2 skips string post processing and returns JSON object (useful if you store localized settings in your language files)
// also skips picking random item if requested asset is an array
handlerInput.o2 = handlerInput.attributesManager.getRequestAttributes().o2 = function(...args) {
return localizationClient.localize(false, false, ...args);
};
}
});
{
"name": "i18n-interceptor-sample",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Kay Lerch",
"license": "ISC",
"dependencies": {
"ask-sdk-core": "^2.0.0",
"ask-sdk-model": "^1.0.0",
"i18next": "^11.8.0",
"i18next-sprintf-postprocessor": "^0.2.2",
"merge-json": "0.1.0-b.3"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.