Skip to content

Instantly share code, notes, and snippets.

@germanviscuso
Forked from KayLerch/en-US.js
Created August 13, 2019 10:33
Show Gist options
  • Save germanviscuso/fd5a9f132e4f4faf5e12360634a5af9e to your computer and use it in GitHub Desktop.
Save germanviscuso/fd5a9f132e4f4faf5e12360634a5af9e to your computer and use it in GitHub Desktop.
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