Skip to content

Instantly share code, notes, and snippets.

@isaacpalomero
Last active June 25, 2019 22:18
Show Gist options
  • Save isaacpalomero/39a4765cbb81551ec5fa05b06f83d2bf to your computer and use it in GitHub Desktop.
Save isaacpalomero/39a4765cbb81551ec5fa05b06f83d2bf to your computer and use it in GitHub Desktop.
i18next Localization Helpers generator
// - With this script you can generate the Localization helpers
//
// es-ES.json example for i18next
// ---------
// {
// "SkillName": "S.M. Educamos",
// "UnAuth": {
// "WelcomeSpeech": {
// "OnMorning": [
// "Good Morning! How can I help you?"
// ]
// },
// "WelcomeReprompt": "How can I help you?"
// },
// "Help": {
// "Reprompt": "What can I do for you?",
// "PreAccountLinking": {
// "RegisterMessages": [
// {
// "speech": "You have to register first longer text",
// "apl": "You have to register first shorter text"
// },
// {
// "speech": "You're not registered longer text",
// "apl": "You're not registered shorter text"
// }
// ]
// }
// }
// }
//
// How to use it:
// change the 3 "const" with yours, and follow these steps:
// [any-path]$ npm install -g "fs"
// [any-path]$ npm install -g "json-ts"
// [root-project-path]$ ts-node scripts/generate-localization-interfaces.ts
// TODO: change this by your locale reference path
const i18nLocaleFile = "es-ES.json";
const fromLocalePath = "src/localization/";
const toLocalePath = "src/localization/";
///
// tslint:disable: no-var-requires no-implicit-dependencies
import * as fs from "fs";
const jsonObjectFile = "localization.ts";
const structureFile = "localizationStructure.d.ts";
const localizationResource = JSON.parse(fs.readFileSync(fromLocalePath + i18nLocaleFile, "utf8"));
function updateObject(object: { [key: string]: any }, parentKeys: string[]) {
Object.keys(object).forEach((key: string) => {
// tslint:disable-next-line: no-empty
if (Array.isArray(object[key])) {
if (object[key].length > 0 && typeof object[key][0] === "object") {
updateObject(object[key], parentKeys.concat([key]));
} else {
object[key] = parentKeys.length === 0 ? key : `${parentKeys.join(".")}.${key}`;
}
} else if (Array.isArray(object[key]) || typeof object[key] !== "object") {
object[key] = parentKeys.length === 0 ? key : `${parentKeys.join(".")}.${key}`;
} else {
updateObject(object[key], parentKeys.concat([key]));
}
});
}
updateObject(localizationResource, []);
const { json2ts } = require("json-ts");
const json = JSON.stringify(localizationResource);
const literalInterfaces = json2ts(json, { rootName: "Locale", prefix: "" });
const jsonObject = `import { Locale } from "../localization/localizationStructure"; \nexport const LOCALE: Locale = ${json};`;
try {
fs.writeFileSync(`${toLocalePath}${jsonObjectFile}`, jsonObject);
fs.writeFileSync(`${toLocalePath}${structureFile}`, `export ${literalInterfaces}`);
console.log(`Success saving Localization Interfaces and Localization.ts`);
} catch (e) {
console.log(`Success saving Localization Interfaces and Localization.ts: ${toLocalePath}${structureFile}`);
throw e;
}
// tslint:disable-next-line: no-var-requires
const i18next = require("i18next");
import * as sprintf from "i18next-sprintf-postprocessor";
type TranslationFunction = (...args: any[]) => string;
export async function generateLocalization(locale: string, localePath: string = "./") {
const resource: any = {};
resource[locale] = {
translation: require(`${localePath}${locale}.json`),
};
const t = await i18next.use(sprintf).init({
lng: locale,
overloadTranslationOptionHandler: sprintf.overloadTranslationOptionHandler,
// tslint:disable-next-line: no-implicit-dependencies
resources: resource,
});
// tslint:disable-next-line: no-shadowed-variable
const customTranslator = {
/**
* Example One single String (w/o sprintf )
* {
* 'WELCOME_MESSAGE' : 'Hello',
* 'GOODBYE_MESSAGE' : 'Bye %s', // using sprintf
* }
*
* attributes.t('WELCOME_MESSAGE');
* attributes.t('GOODBYE_MESSAGE', 'sir');
*/
t: (...args: any[]) => {
return (t as TranslationFunction)(...args);
},
/**
* Example Random String (w/o sprintf )
* {
* 'MULTIPLE_WELCOME': ['Hello', 'Hi', 'How are you', 'Whats up'],
* 'MULTIPLE_GOODBYE': ['Bye %s', 'Goodbye %s'] // using sprintf
* }
*
* attributes.tr('MULTIPLE_WELCOME', 'sir');
*/
tr: (...args: any[]) => {
const values = [];
for (let i = 1; i < args.length; i++) {
values.push(args[i]);
}
const result: string | string[] = t(args[0], {
returnObjects: true,
postProcess: "sprintf",
sprintf: values,
});
if (Array.isArray(result)) {
return result[Math.floor(Math.random() * result.length)];
} else {
return result;
}
},
};
return customTranslator;
}
import { RequestInterceptor, HandlerInput } from "ask-sdk-core";
import { generateLocalization } from "./generateTranslator";
/**
* Adds translation functions to the RequestAttributes.
*/
export class LocalizationInterceptor implements RequestInterceptor {
public async process(handlerInput: HandlerInput): Promise<void> {
const locale: string =
handlerInput.requestEnvelope.request.locale || "es-ES";
const attributes = handlerInput.attributesManager.getRequestAttributes();
const customTranslator = await generateLocalization(locale, "../localization/");
attributes.t = customTranslator.t;
attributes.tr = customTranslator.tr;
}
}
import { HandlerInput, RequestHandler } from "ask-sdk-core";
import { Response, IntentRequest } from "ask-sdk-model";
import { LOCALE } from "../../localization/localization";
export class YesIntentHandler implements RequestHandler {
public canHandle(handlerInput: HandlerInput): boolean {
const request = handlerInput.requestEnvelope.request;
if (request.type === "IntentRequest" && request.intent.name === "AMAZON.HelpIntent") {
return true;
}
return false;
}
public handle(handlerInput: HandlerInput): Response {
const sessionAttributes = handlerInput.attributesManager.getRequestAttributes();
/**
* Examples:
* - Random message from array
*/
const randomNotImplementedYetMessage = attributes.tr(LOCALE.Errors.NotImplementedYet);
/**
* - Get collection of objects
*/
const messages: [{ speech: string, apl: string }] = attributes.t(LOCALE.Help.PreAccountLinking.RegisterMessages, { returnObjects: true });
return handlerInput.responseBuilder
.speak(sessionAttributes.t(LOCALE.Help.PreAccountLinking.GenericMessages))
.reprompt(sessionAttributes.t(LOCALE.Help.Reprompt))
.withShouldEndSession(false)
.getResponse();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment