Skip to content
This repository was archived by the owner on Jan 5, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 21 additions & 19 deletions libraries/botbuilder-ai/lib/languageTranslator.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 13 additions & 19 deletions libraries/botbuilder-ai/lib/localeConverter.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion libraries/botbuilder-ai/lib/localeConverter.js.map

Large diffs are not rendered by default.

61 changes: 32 additions & 29 deletions libraries/botbuilder-ai/src/languageTranslator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,21 +136,24 @@ export class LanguageTranslator implements Middleware {
this.translator.setPostProcessorTemplate([], this.wordDictionary);
}

return this.translator.translateArrayAsync({
let translateOptions = {
from: sourceLanguage,
to: targetLanguage,
texts: lines,
texts: lines.slice(),
contentType: 'text/plain'
})
};

return this.translator.translateArrayAsync(translateOptions)
.then((translateResult) => {
let postProcessResult:TranslationResult[] = this.translator.postProcessTranslation(translateResult, lines);
text = '';
translateResult.forEach(translatedSentence => {
postProcessResult.forEach(translatedSentence => {
if (text.length > 0)
text += '\n';
text += translatedSentence.translatedText;
});
message.text = text;
return Promise.resolve(translateResult);
return Promise.resolve(postProcessResult);
})
}
}
Expand All @@ -177,7 +180,9 @@ interface TranslationResult {
* @private
*/
interface Translator {
translateArrayAsync(options: TranslateArrayOptions): Promise<TranslationResult[]>;
translateArrayAsync(options: TranslateArrayOptions): Promise<string>;

postProcessTranslation(response: string, texts: string[]): TranslationResult[];

detect(text: string): Promise<string>;

Expand Down Expand Up @@ -239,7 +244,7 @@ class MicrosoftTranslator implements Translator {
.then(lang => Promise.resolve(lang.replace(/<[^>]*>/g, '')))
}

translateArrayAsync(options: TranslateArrayOptions): Promise<TranslationResult[]> {
translateArrayAsync(options: TranslateArrayOptions): Promise<string> {
let from = options.from;
let to = options.to;
let texts = options.texts;
Expand Down Expand Up @@ -278,23 +283,24 @@ class MicrosoftTranslator implements Translator {
'Content-Type': 'text/xml'
},
body: body,

})
})
.then(response => {
let results: TranslationResult[] = [];
let parser = new DOMParser();
let responseObj = parser.parseFromString(response);
let elements = responseObj.getElementsByTagName("TranslateArray2Response");
Array.from(elements).forEach((element, index, array) => {
let translation = element.getElementsByTagName('TranslatedText')[0].textContent as string;
let alignment = element.getElementsByTagName('Alignment')[0].textContent as string;
translation = this.postProcessor.fixTranslation(orgTexts[index], alignment, translation);
let result: TranslationResult = { translatedText: translation };
results.push(result);
});
return Promise.resolve(results);
})
.then(response => Promise.resolve(response))
}

postProcessTranslation(response: string, orgTexts: string[]): TranslationResult[] {
let results: TranslationResult[] = [];
let parser = new DOMParser();
let responseObj = parser.parseFromString(response);
let elements = responseObj.getElementsByTagName("TranslateArray2Response");
Array.from(elements).forEach((element, index, array) => {
let translation = element.getElementsByTagName('TranslatedText')[0].textContent as string;
let alignment = element.getElementsByTagName('Alignment')[0].textContent as string;
translation = this.postProcessor.fixTranslation(orgTexts[index], alignment, translation);
let result: TranslationResult = { translatedText: translation };
results.push(result);
});
return results;
}
}

Expand All @@ -317,7 +323,6 @@ export class PostProcessTranslator {
delete this.wordDictionary[word];
}
});

}

if(noTranslatePatterns) {
Expand Down Expand Up @@ -429,7 +434,7 @@ export class PostProcessTranslator {
public fixTranslation(sourceMessage: string, alignment: string, targetMessage: string): string {
let numericMatches = sourceMessage.match(/[0-9]+/g);
let containsNum = numericMatches != null;

if ((!containsNum && this.noTranslatePatterns.length == 0 && !this.wordDictionary) || alignment.trim() == '') {
return targetMessage;
}
Expand All @@ -453,10 +458,10 @@ export class PostProcessTranslator {
}

let alignments = alignment.trim().split(' ');

let srcWords = this.splitSentence(sourceMessage, alignments);
let trgWords = this.splitSentence(targetMessage, alignments, false);

let alignMap = this.wordAlignmentParse(alignments, srcWords, trgWords);

if (toBeReplaced.length > 0) {
Expand Down Expand Up @@ -488,7 +493,7 @@ export class PostProcessTranslator {
});

let wrdNoTranslate = srcWords.slice(srcIndx, srcIndx + newNoTranslateArrayLength)

wrdNoTranslate.forEach(srcWrds => {
trgWords = this.keepSrcWrdInTranslation(alignMap, srcWords, trgWords, srcIndx);
srcIndx++;
Expand Down Expand Up @@ -531,8 +536,6 @@ export class PostProcessTranslator {
});
}

console.log(toBeReplacedByDictionary);

if (toBeReplacedByDictionary.length > 0) {
toBeReplacedByDictionary.forEach(word => {
let regExp = new RegExp(word, "i");
Expand Down
36 changes: 14 additions & 22 deletions libraries/botbuilder-ai/src/localeConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import { Middleware, TurnContext, ActivityTypes } from 'botbuilder';
import * as DateTimeRecognizers from '@microsoft/recognizers-text-date-time';
import * as moment from 'moment';

/**
* Settings used to configure an instance of `LocaleConverter`.
*/
Expand Down Expand Up @@ -123,25 +122,23 @@ class MicrosoftLocaleConverter implements ILocaleConverter {
}

private initLocales() {
let yearMonthDay = new DateAndTimeLocaleFormat('hh:mm', 'yyyy-MM-dd');
let dayMonthYear = new DateAndTimeLocaleFormat('hh:mm', 'dd/MM/yyyy');
let monthDayYEar = new DateAndTimeLocaleFormat('hh:mm', 'MM/dd/yyyy');

let yearMonthDayLocales = [ "en-za", "en-ie", "en-gb", "en-ca", "fr-ca", "zh-cn", "zh-sg", "zh-hk", "zh-mo", "zh-tw" ];
yearMonthDayLocales.forEach(locale => {
this.mapLocaleToFunction[locale] = yearMonthDay;
});

let dayMonthYearLocales = [ "en-au", "fr-be", "fr-ch", "fr-fr", "fr-lu", "fr-mc", "de-at", "de-ch", "de-de", "de-lu", "de-li" ];
dayMonthYearLocales.forEach(locale => {
this.mapLocaleToFunction[locale] = dayMonthYear;
let supportedLocales:string[] = [
"en-us", "en-za", "en-ie", "en-gb", "en-ca", "en-au",
"fr-fr", "fr-ca", "fr-be", "fr-ch", "fr-lu", "fr-mc",
"zh-cn", "zh-tw", "zh-sg", "zh-hk", "zh-mo",
"de-de", "de-at", "de-ch", "de-lu", "de-li",
"es-es"
];

supportedLocales.forEach( locale => {
var localeData = moment.localeData(locale);
this.mapLocaleToFunction[locale] = new DateAndTimeLocaleFormat(localeData.longDateFormat('LT'), localeData.longDateFormat('L'));
});

this.mapLocaleToFunction["en-us"] = monthDayYEar;
}

isLocaleAvailable(locale: string): boolean {
return !(typeof this.mapLocaleToFunction[locale] === "undefined")
return this.mapLocaleToFunction[locale] != undefined;
}

private extractDates(message: string, fromLocale:string): TextAndDateTime[] {
Expand Down Expand Up @@ -225,16 +222,11 @@ class MicrosoftLocaleConverter implements ILocaleConverter {
}

private formatDate(date: Date, toLocale: string): string {
return this.mapLocaleToFunction[toLocale].dateFormat
.replace('yyyy', (date.getFullYear()).toLocaleString(undefined, {minimumIntegerDigits: 4}).replace(',', ''))
.replace('MM', (date.getMonth() + 1).toLocaleString(undefined, {minimumIntegerDigits: 2}))
.replace('dd', (date.getDate()).toLocaleString(undefined, {minimumIntegerDigits: 2}));
return moment(date).format(this.mapLocaleToFunction[toLocale].dateFormat);
}

private formatTime(date: Date, toLocale: string): string {
return this.mapLocaleToFunction[toLocale].timeFormat
.replace('hh', (date.getHours()).toLocaleString(undefined, {minimumIntegerDigits: 2}))
.replace('mm', (date.getMinutes()).toLocaleString(undefined, {minimumIntegerDigits: 2}));
return moment(date).format(this.mapLocaleToFunction[toLocale].timeFormat);
}

private formatDateAndTime(date: Date, toLocale: string): string {
Expand Down
Loading