Skip to content
Permalink
Browse files

Merge pull request #38 from webcomputing/feature/default-ts-translations

Feature/default ts translations
  • Loading branch information...
antoniusostermann committed May 7, 2019
2 parents 38e8c91 + 27b1921 commit c35dc2b6b508f8864b74094734fab3c641a93f7f
@@ -4,6 +4,7 @@ version 0.5.0
- adds option to UniferConfiguration that allows to change the way how request extractors are found.
- adds option to pass component's defaultConfiguration a function that returns a new configuration object
- passes list of components to except from autobind to inversify-components
- Loads all TypeScript, JavaScript and JSON files from locales directory, if i18next backend is not configured. `.ts` files shadow `.js` files, `.js` files shadow `.json` files. The folder/file structure is resembled in the final locales object, while the filenames are camelcased, i.e. a folder `main-state` will be a key `mainState`, which will contain all content from that folder. If LocalesLoader finds an ES6 default export or an export the same name as the camelcased file name, only this is taken from the file. In any other case, everything is exported. Files and folders of the same name are merged. An example can be found [here](https://gist.github.com/baflo/b88e636948b6b57c3f07af2672088961).

version 0.4.1
- fixes typing of StayInContextCallback and ClearContextCallback

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.
@@ -47,6 +47,7 @@
"lodash": "^4.17.11",
"redis": "2.8.0",
"reflect-metadata": "^0.1.12",
"require-directory": "^2.1.1",
"resolve": "^1.8.1",
"rxjs": "^5.5.11"
},
@@ -17,10 +17,12 @@ const configuration: AssistantJSConfiguration = {
"core:i18n": {
// This is basically the i18next configuration. Check out https://www.i18next.com/ for more information!
i18nextAdditionalConfiguration: {
// This entry is needed and tells i18next where to find your language files.
backend: {
loadPath: process.cwd() + "/config/locales/{{lng}}/{{ns}}.json",
},
// Translation resources are automatically loaded from path given in `UnifierConfiguration#utterancePath`, but may be overridden here.
// resources: {}
// Alternatively you can give a path to a folder with JSON files that can be loaded by i18next
// backend: {
// loadPath: process.cwd() + "/config/locales/{{lng}}/{{ns}}.json",
// },
lngs: ["en"],
fallbackLng: "en",
// If you encouter problems with i18next, change this to true
@@ -1,8 +1,11 @@
import * as path from "path";

import { TEMPORARY_INTERPOLATION_END, TEMPORARY_INTERPOLATION_START } from "../../../src/components/i18n/interpolation-resolver";
import { arraySplitter } from "../../../src/components/i18n/plugins/array-returns-sample.plugin";
import { I18nextWrapper } from "../../../src/components/i18n/wrapper";
import { injectionNames } from "../../../src/injection-names";
import { configureI18nLocale } from "../../support/util/i18n-configuration";
import { configureUnifier } from "../../support/util/unifier-configuration";
import { ThisContext } from "../../this-context";

interface CurrentThisContext extends ThisContext {
@@ -56,3 +59,41 @@ describe("I18nWrapper", function() {
});
});
});

describe("I18nWrapper loading Typescript files", function(this: CurrentThisContext) {
const expectedTranslations = ["hello my name", "hi my name", "welcome my name"];

beforeEach(function(this: CurrentThisContext) {
this.specHelper.prepareSpec(this.defaultSpecOptions);
// Remove emitting of warnings
this.specHelper.bindSpecLogger("error");

configureI18nLocale(this.assistantJs.container, false);
configureUnifier(this.assistantJs.container, path.join(__dirname, "../../support/mocks/i18n-ts/locale/"));
this.wrapper = this.inversify.get("core:i18n:wrapper");
});

describe("translation function", function() {
it("returns one of many options", function(this: CurrentThisContext) {
expect(expectedTranslations).toContain(this.wrapper.instance.t("templateSyntaxSmall", { name: "my name" }));
});
});

describe("loading behaviour", function() {
it("load from file that has the same name as a directory", function() {
expect(this.wrapper.instance.store.data.de.translation.mySpecificKeys.keyOne).toBe("keyOneResult");
});

it("loads default only if exists", function() {
expect(this.wrapper.instance.store.data.de.translation.defaultExport.test).toBe("default");
});

it("loads export with camelcase filename if no default exists", function() {
expect(this.wrapper.instance.store.data.de.translation.templateSyntaxSmall[0]).toBe("{hello|hi} {{name}}");
});

it("loads all exports if neither default nor one equal to camelcase filename exists", function() {
expect(this.wrapper.instance.store.data.de.translation.mainState.testIntent.embedded.test).toBe("very-specific-without-extractor");
});
});
});
@@ -2,14 +2,13 @@ import * as fs from "fs";
import { Component, getMetaInjectionName } from "inversify-components";
import { resolve } from "path";
import { LocalesLoader, UnifierConfiguration } from "../../../src/assistant-source";
import { Configuration } from "../../../src/components/unifier/private-interfaces";
import { injectionNames } from "../../../src/injection-names";
import { ThisContext } from "../../this-context";

// tslint:disable no-var-requires
const deUtterances = require("../../support/mocks/i18n/locale/de/utterances.json");
const enUtterances = require("../../support/mocks/i18n/locale/en/utterances.js");
const deEntities = require("../../support/mocks/i18n/locale/de/entities.json");
const enUtterances = require("../../support/mocks/i18n/locale/en/utterances.ts");
const { default: deEntities } = require("../../support/mocks/i18n/locale/de/entities.ts");
const enEntities = require("../../support/mocks/i18n/locale/en/entities.js");
// tslint:enable no-var-requires

@@ -102,7 +101,7 @@ describe("LocalesLoader", function() {
});
});

it("prioritizes JS files over JSON files", function(this: CurrentThisContext) {
it("prioritizes JS files over JSON and TS over JS and JSON files", function(this: CurrentThisContext) {
const entities = this.localesLoader.getCustomEntities();
const utterances = this.localesLoader.getUtteranceTemplates();

@@ -121,7 +120,7 @@ describe("LocalesLoader", function() {
});
});

describe("getUtteranceTemplates", function() {
describe("#getUtteranceTemplates", function() {
it("loads all utterance templates of all languages from file system", function(this: CurrentThisContext) {
const utterances = this.localesLoader.getUtteranceTemplates();

@@ -133,7 +132,7 @@ describe("LocalesLoader", function() {
});
});

describe("getCustomEntities", function() {
describe("#getCustomEntities", function() {
it("loads all custom entities of all languages from file system", function(this: CurrentThisContext) {
const entities = this.localesLoader.getCustomEntities();

@@ -0,0 +1,56 @@
export default {
mySpecificKeys: {
keyOne: "keyOneResult",
},
multiple: ["a", "b"],
var: "a{{var}}",
multipleVars: "a{{firstVar}}b{{secondVar}}c{{thirdVar}}",
deviceDependentState: {
ExtractorComponent: {
device1: "state-platform-device-specific",
},
},
root: {
testIntent: {
embedded: {
platformDependent: {
ExtractorComponent: "platform-specific-embedded",
},
platformIndependent: "platform-independent-root-embedded",
},
withoutExtractor: "root-without-extractor",
deviceDependent: {
ExtractorComponent: {
device1: "root-intent-platform-device-specific",
},
},
},
secondPlatformSpecificIntent: {
ExtractorComponent: "root-platform-specific-intent",
},
yesGenericIntent: "root-yes",
rootKey: {
ExtractorComponent: "platform-specific-root-only",
},
ExtractorComponent: "root-only-platform-given",
},
noIntentState: "stateOnly",
templateSyntax: ["{Can|May} I help you, {{var}}?", "Would you like me to help you?"],
filter: {
stateA: {
intentA: "FilterAState - filterTestAIntent",
intentB: "FilterAState - filterTestBIntent",
intentC: "FilterAState - filterTestCIntent",
intentD: "FilterAState - filterTestDIntent",
},
stateB: {
intentA: "FilterBState - filterTestAIntent",
intentB: "FilterBState - filterTestBIntent",
},
stateC: {
intentA: "FilterCState - filterTestAIntent",
intentB: "FilterCState - filterTestBIntent",
},
},
noInterpolation: "no interpolation",
};
@@ -0,0 +1,2 @@
export const someState = { some: "state" };
export default { test: "default" };
@@ -0,0 +1,32 @@
export const testIntent = {
embedded: {
test: "very-specific-without-extractor",
platformDependent: {
ExtractorComponent: "platform-specific-sub-key",
},
},
};

export const deviceDependentIntent = {
embeddedKeyOuter: {
embeddedKeyInner: {
ExtractorComponent: {
device1: "device-specific-sub-key",
},
},
},
};

export const yesGenericIntent = "yes";

export const platformDependent = {
ExtractorComponent: "platform-specific-embedded-state-only",
};

export const platformIndependent = "platform-independent-main-state";

export const ExtractorComponent = "platform-specific-main-state-only";

export const platformSpecificIntent = {
ExtractorComponent: "platform-specific-intent",
};
@@ -0,0 +1 @@
export const templateSyntaxSmall = ["{hello|hi} {{name}}", "welcome {{name}}"];
@@ -1,16 +1,3 @@
{
"color": [
{
"value": "grün",
"synonyms": ["waldgrün", "salbei", "oliv", "limone", "jade", "minz"]
},
{
"value": "rot",
"synonyms": ["scharlach", "lachs", "karmin", "ziegel", "rubin", "blut"]
},
{
"value": "gelb",
"synonyms": ["kanariengelb", "flachs", "mais", "honig", "bernstein", "blond"]
}
]
}
"this should be shadowed by entities.ts": true
}
@@ -0,0 +1,16 @@
export default {
color: [
{
value: "grün",
synonyms: ["waldgrün", "salbei", "oliv", "limone", "jade", "minz"],
},
{
value: "rot",
synonyms: ["scharlach", "lachs", "karmin", "ziegel", "rubin", "blut"],
},
{
value: "gelb",
synonyms: ["kanariengelb", "flachs", "mais", "honig", "bernstein", "blond"],
},
],
};
@@ -1,3 +1,3 @@
module.exports = {
testIntent: ["This is a test", "A second test utterances"],
};
"this should be shadowed by utterances.ts": true
}
@@ -1,3 +1,3 @@
{
"this should be shadowed by utterances.ts": true
}
"this should be shadowed by utterances.js": true
}
@@ -0,0 +1,3 @@
module.exports = {
testIntent: ["This is a test", "A second test utterances"],
};
@@ -27,4 +27,12 @@ export class LocalesLoaderMock implements LocalesLoader {
},
};
}

public getTranslations() {
return {};
}

public getLocales() {
return undefined;
}
}
@@ -0,0 +1,11 @@
import * as i18next from "i18next";
import { Container } from "inversify-components";
import { UnifierConfiguration } from "../../../src/assistant-source";

export function configureUnifier(container: Container, utterancePath: string) {
const config: UnifierConfiguration = {
utterancePath,
};

container.componentRegistry.lookup("core:unifier").addConfiguration(config);
}
Oops, something went wrong.

0 comments on commit c35dc2b

Please sign in to comment.
You can’t perform that action at this time.