Skip to content
This repository was archived by the owner on Jan 15, 2025. It is now read-only.

Commit e0fc804

Browse files
authored
Merge branch 'master' into axsuarez/luis-gen
2 parents d4d7149 + a104eca commit e0fc804

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+819
-292
lines changed

packages/chatdown/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ OPTIONS
2727
2828
-h, --help Chatdown command help
2929
30-
-o, --out=out Path to the directory where the output of the multiple chat file processing (-f) will be
30+
-o, --out=out Path to the directory where the output of the multiple chat file processing (-o) will be
3131
placed.
3232
3333
-p, --prefix Prefix stdout with package name.

packages/chatdown/src/commands/chatdown.ts

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,11 @@ export default class Chatdown extends Command {
3737
})
3838
}
3939

40+
let outputDir = flags.out ? path.resolve(flags.out) : null
41+
4042
if (inputIsDirectory) {
4143
let inputDir = flags.in ? flags.in.trim() : ''
42-
let outputDir = (flags.out) ? flags.out.trim() : './'
43-
if (outputDir.substr(0, 2) === './') {
44-
outputDir = path.resolve(process.cwd(), outputDir.substr(2))
45-
}
44+
4645
const len = await this.processFiles(inputDir, outputDir)
4746
if (len === 0) {
4847
throw new CLIError('No chat files found at: ' + flags.in)
@@ -51,9 +50,10 @@ export default class Chatdown extends Command {
5150
return
5251
} else {
5352
const fileContents = await this.getInput(flags.in)
53+
const fileName = flags.in ? this.getFileName(flags.in) : ''
5454
if (fileContents) {
5555
const activities = await chatdown(fileContents, flags)
56-
const writeConfirmation = await this.writeOut(activities)
56+
const writeConfirmation = await this.writeOut(activities, fileName, outputDir)
5757
/* tslint:disable:strict-type-predicates */
5858
if (typeof writeConfirmation === 'string') {
5959
process.stdout.write(`${chalk.green('Successfully wrote file:')} ${writeConfirmation}\n`)
@@ -91,21 +91,20 @@ export default class Chatdown extends Command {
9191
}
9292
}
9393

94+
private getFileName(file: any) {
95+
let fileName = path.basename(file, path.extname(file))
96+
return fileName
97+
}
98+
9499
private async processFiles(inputDir: any, outputDir: any) {
95100
return new Promise(async (resolve, reject) => {
96101
let files = glob.sync(inputDir, {ignore: ['**/node_modules/**']})
97102
/* tslint:disable:prefer-for-of */
98103
for (let i = 0; i < files.length; i++) {
99104
try {
100-
let fileName = files[i]
101-
if (files[i].lastIndexOf('/') !== -1) {
102-
fileName = files[i].substr(files[i].lastIndexOf('/'))
103-
}
104-
fileName = fileName.split('.')[0]
105+
const fileName = this.getFileName(files[i])
105106
let activities = await chatdown(await utils.readTextFile(files[i]))
106-
let writeFile = `${outputDir}/${fileName}.transcript`
107-
await fs.ensureFile(writeFile)
108-
await fs.writeJson(writeFile, activities, {spaces: 2})
107+
await this.writeOut(activities, fileName, outputDir)
109108
} catch (e) {
110109
if (e.message.match(/no such file or directory/)) {
111110
reject(new CLIError(e.message))
@@ -119,7 +118,13 @@ export default class Chatdown extends Command {
119118
})
120119
}
121120

122-
private async writeOut(activities: any) {
121+
private async writeOut(activities: any, fileName: string, outputDir: any) {
122+
if (fileName && outputDir) {
123+
let writeFile = path.join(outputDir, `${fileName}.transcript`)
124+
await fs.ensureFile(writeFile)
125+
await fs.writeJson(writeFile, activities, {spaces: 2})
126+
return writeFile
127+
}
123128
const output = JSON.stringify(activities, null, 2)
124129
await new Promise(done => process.stdout.write(output, 'utf-8', () => done()))
125130
return true

packages/chatdown/test/commands/chatdown.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ describe('chatdown', () => {
4444
});
4545

4646
it('should read from file when chat file is passed as an argument', done => {
47-
cp.exec(`node ./bin/run chatdown --in ${path.join(__dirname, '../utils/cli.sample.chat')}`, (error, stdout) => {
47+
cp.exec(`node ./bin/run chatdown --in ./test/utils/cli.sample.chat`, (error, stdout) => {
4848
assert.doesNotThrow(() => JSON.parse(stdout));
4949
done();
5050
});

packages/cli/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"dependencies": {
1010
"@microsoft/bf-chatdown": "1.0.0",
1111
"@microsoft/bf-cli-config": "1.0.0",
12-
"@microsoft/bf-luis": "1.0.0",
12+
"@microsoft/bf-lu": "1.0.0",
1313
"@microsoft/bf-qnamaker": "1.0.0",
1414
"@oclif/command": "~1.5.13",
1515
"@oclif/config": "~1.13.0",
@@ -64,7 +64,7 @@
6464
"@microsoft/bf-chatdown",
6565
"@microsoft/bf-cli-config",
6666
"@microsoft/bf-qnamaker",
67-
"@microsoft/bf-luis"
67+
"@microsoft/bf-lu"
6868
],
6969
"hooks": {
7070
"init": "./lib/hooks/init/inithook"

packages/luis/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
{
2-
"name": "@microsoft/bf-luis",
2+
"name": "@microsoft/bf-lu",
33
"version": "1.0.0",
44
"author": "Microsoft",
55
"bugs": "https://github.com/microsoft/botframework-cli/issues",
6-
"main": "src/parser/index.js",
6+
"main": "lib/parser/index.js",
77
"dependencies": {
88
"@microsoft/bf-cli-command": "1.0.0",
99
"@oclif/config": "~1.13.3",

packages/luis/src/commands/luis/translate.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ export default class LuisTranslate extends Command {
1818
srclang: flags.string({description: 'Source lang code. Auto detect if missing.'}),
1919
tgtlang: flags.string({description: 'Comma separated list of target languages.', required: true}),
2020
translatekey: flags.string({description: 'Machine translation endpoint key.', required: true}),
21-
translate_comments: flags.string({description: 'When set, machine translate comments found in .lu file'}),
22-
translate_link_text: flags.string({description: 'When set, machine translate link description in .lu file'}),
21+
translate_comments: flags.boolean({description: 'When set, machine translate comments found in .lu file'}),
22+
translate_link_text: flags.boolean({description: 'When set, machine translate link description in .lu file'}),
2323
}
2424

2525
/* tslint:disable:forin no-for-in*/

packages/luis/src/parser/converters/lumerger.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ const buildLuJsonObject = async function(luObjArray, log, luis_culture, luSearch
3535
filesToParse.splice(0,1)
3636
continue
3737
}
38-
parsedContent = await parseLuFile(luOb.content, log, luis_culture)
38+
let parsedContent = await parseLuFile(luOb.content, log, luis_culture)
3939
parsedFiles.push(luOb.id)
4040

4141
if (haveLUISContent(parsedContent.LUISJsonStructure)

packages/luis/src/parser/converters/lutoluisconverter.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,9 @@ const mergeResults_closedlists = function (blob, finalCollection, type) {
258258
const checkAndUpdateVersion = function(finalLUISJSON) {
259259
// Detect if there is content specific to 5.0.0 schema
260260
// any entity with children
261+
if (!finalLUISJSON) {
262+
return
263+
}
261264
let v5DefFound = false;
262265
v5DefFound = (finalLUISJSON.entities || []).find(i => i.children || i.features) ||
263266
(finalLUISJSON.intents || []).find(i => i.features) ||

packages/luis/src/parser/lufile/translate-helpers.js

Lines changed: 28 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ const translateHelpers = {
4949
continue;
5050
}
5151
if(translate_comments) {
52-
addSegment(linesToTranslate, currentLine, true);
52+
addSegment(linesToTranslate, currentLine.charAt(0), false);
53+
addSegment(linesToTranslate, currentLine.substring(1), true);
5354
} else {
5455
addSegment(linesToTranslate, currentLine, false);
5556
}
@@ -92,77 +93,34 @@ const translateHelpers = {
9293
let listSeparator = '';
9394
let content = '';
9495
switch (currentSectionType) {
95-
case PARSERCONSTS.INTENT: {
96-
// strip line of the list separator
97-
listSeparator = currentLine.charAt(0);
98-
addSegment(linesToTranslate, listSeparator + ' ', false);
99-
content = currentLine.slice(1).trim();
100-
let entitiesList = [];
101-
// strip line off labelled entity values,mark pattern any entities as not to localize
102-
if (content.includes('{')) {
103-
const entityRegex = new RegExp(/\{(.*?)\}/g);
104-
let entitiesFound = content.match(entityRegex);
105-
let eStartIndex = -1;
106-
let eEndIndex = -1;
107-
let entity;
108-
for (var entityIdx in entitiesFound) {
109-
entity = entitiesFound[entityIdx];
110-
let lEntity = entity.replace('{', '').replace('}', '');
111-
let labelledValue = '';
112-
let updatedUtteranceLeft = content.substring(0, content.indexOf(entity));
113-
let updatedUtteranceRight = content.substring(content.indexOf(entity) + entity.length);
114-
// is this a labelled value?
115-
if (lEntity.includes('=')) {
116-
let entitySplit = lEntity.split('=');
117-
if (entitySplit.length > 2) {
118-
throw (new exception(retCode.errorCode.INVALID_INPUT, '[ERROR]: Nested entity references are not supported in utterance: ' + content));
119-
}
120-
lEntity = entitySplit[0].trim();
121-
labelledValue = entitySplit[1].trim();
122-
eStartIndex = content.indexOf(entity);
123-
eEndIndex = eStartIndex + labelledValue.length - 1;
124-
content = updatedUtteranceLeft + labelledValue + updatedUtteranceRight;
125-
entitiesList.push(new helperClasses.entity(lEntity, labelledValue, eStartIndex, eEndIndex));
126-
} else {
127-
// This is a pattern entity without a labelled value. Do not localize this.
128-
eStartIndex = content.indexOf(lEntity) - 1;
129-
eEndIndex = eStartIndex + lEntity.length - 1;
130-
content = updatedUtteranceLeft + lEntity + updatedUtteranceRight;
131-
entitiesList.push(new helperClasses.entity(lEntity, null, eStartIndex, eEndIndex));
132-
}
96+
case PARSERCONSTS.INTENT:
97+
listSeparator = currentLine.charAt(0);
98+
addSegment(linesToTranslate, listSeparator + ' ', false);
99+
content = currentLine.slice(1).trim();
100+
let skipChars = ['{', '}', '(', ')', '[', ']', '|', '=']
101+
for (let i = 0; i < content.length; i++) {
102+
let processedText = ''
103+
let tslt = false
104+
if (!skipChars.includes(content.charAt(i))) {
105+
for (let j = i; j < content.length && !skipChars.includes(content.charAt(j)); j++) {
106+
processedText += content.charAt(j)
107+
}
108+
tslt = true
109+
} else if (content.charAt(i) == '{') {
110+
for (let j = i; j < content.length && (content.charAt(j) !== '=' && content.charAt(j) !== '}'); j++) {
111+
processedText += content.charAt(j)
133112
}
113+
} else {
114+
processedText += content.charAt(i)
134115
}
135-
let offset = 0;
136-
let candidateText = '';
137-
// Tokenize the input utterance.
138-
for (var idx in entitiesList) {
139-
let entity = entitiesList[idx];
140-
if (entity.start < 0) entity.start = 0;
141-
if (entity.start !== offset) {
142-
candidateText = content.substring(offset, entity.start);
143-
if (candidateText.trim() !== '') {
144-
addSegment(linesToTranslate, candidateText, true);
145-
} else {
146-
addSegment(linesToTranslate, candidateText, false);
147-
}
148-
}
149-
if (entity.value !== '') {
150-
addSegment(linesToTranslate, ' {' + entity.entity + '=', false);
151-
addSegment(linesToTranslate, content.substring(entity.start, entity.end + 1).trim(), true);
152-
addSegment(linesToTranslate, '} ', false);
153-
} else {
154-
addSegment(linesToTranslate, ' {' + entity.entity + '} ', false);
155-
}
156-
offset = entity.end + 1;
157-
}
158-
if (offset !== content.length) {
159-
candidateText = content.substring(offset);
160-
if (candidateText.trim() !== '') {
161-
addSegment(linesToTranslate, candidateText.trim(), true);
162-
} else {
163-
addSegment(linesToTranslate, candidateText, false);
164-
}
116+
117+
if (processedText.charAt(0) === ' ') {
118+
addSegment(linesToTranslate, ' ', false)
165119
}
120+
121+
addSegment(linesToTranslate, processedText, tslt)
122+
content = content.slice(processedText.length)
123+
i--
166124
}
167125
break;
168126
case PARSERCONSTS.NEWENTITY:
@@ -204,7 +162,6 @@ const translateHelpers = {
204162
addSegment(linesToTranslate, '$', false);
205163
addSegment(linesToTranslate, entityName.trim(), true);
206164
addSegment(linesToTranslate, ' : ' + PARSERCONSTS.QNAALTERATIONS + ' = ', false);
207-
c
208165
} else {
209166
// we would not localize entity line but remember we are under entity section for list entities
210167
// FIX for BF CLI # 121
@@ -219,7 +176,7 @@ const translateHelpers = {
219176
}
220177
} else if(currentLine.indexOf(PARSERCONSTS.ANSWER) === 0) {
221178
if (inAnswer) {
222-
answerData = '';
179+
let answerData = '';
223180
}
224181
addSegment(linesToTranslate, currentLine, false);
225182
inAnswer = !inAnswer;

packages/luis/src/parser/translator/lutranslate.js

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -30,36 +30,14 @@ module.exports = {
3030
}
3131
}
3232

33-
/**
34-
* Helper function to parse, translate and write out localized lu files
35-
* @param {string} file file name
36-
* @param {string} translate_key translate text API key
37-
* @param {string} to_lang language code to translate content to
38-
* @param {string} src_lang language code for source content
39-
* @param {boolean} translate_comments translate comments in .lu files if this is set to true
40-
* @param {boolean} translate_link_text translate URL or LU reference link text in .lu files if this is set to true
41-
* @returns {void} nothing
42-
* @throws {exception} Throws on errors. exception object includes errCode and text.
43-
*/
44-
async function parseFile(file) {
45-
if(!fs.existsSync(path.resolve(file))) {
46-
throw(new exception(retCode.errorCode.FILE_OPEN_ERROR, 'Sorry unable to open [' + file + ']'));
47-
}
48-
let fileContent = txtfile.readSync(file);
49-
if (!fileContent) {
50-
throw(new exception(retCode.errorCode.FILE_OPEN_ERROR, 'Sorry, error reading file:' + file));
51-
}
52-
return fileContent
53-
}
54-
5533
async function translateLuObject(luObject, translate_key, to_lang, src_lang, translate_comments, translate_link_text) {
5634
let parsedLocContent = ''
5735
let result = {}
5836
// Support multi-language specification for targets.
5937
// Accepted formats are space or comma separated list of target language codes.
6038
// Tokenize to_lang
6139
let toLang = to_lang.split(/[, ]/g)
62-
for (idx in toLang) {
40+
for (let idx in toLang) {
6341
let tgt_lang = toLang[idx].trim();
6442
if (tgt_lang === '') continue;
6543
try {

0 commit comments

Comments
 (0)