UNPKG

type2docfx

Version:

A tool to convert json format output from TypeDoc to universal reference model for DocFx to consume.

282 lines (241 loc) 12.1 kB
/** * @module botbuilder-ai */ /** * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. */ import { Middleware, TurnContext, ActivityTypes } from 'botbuilder'; import * as DateTimeRecognizers from '@microsoft/recognizers-text-date-time'; import * as moment from 'moment'; export interface LocaleConverterSettings { toLocale: string, fromLocale?: string, getUserLocale?: (context: TurnContext) => string, setUserLocale?: (context: TurnContext) => Promise<boolean> } /** * The LocaleConverter converts all locales in a message to a given locale. */ export class LocaleConverter implements Middleware { private localeConverter: ILocaleConverter; private fromLocale: string | undefined; private toLocale: string; private getUserLocale: ((context: TurnContext) => string) | undefined; private setUserLocale: ((context: TurnContext) => Promise<boolean>) | undefined; public constructor(settings: LocaleConverterSettings) { this.localeConverter = new MicrosoftLocaleConverter(); this.toLocale = settings.toLocale; this.fromLocale = settings.fromLocale; this.getUserLocale = settings.getUserLocale; this.setUserLocale = settings.setUserLocale; } /// Incoming activity public async onTurn(context: TurnContext, next: () => Promise<void>): Promise<void> { if (context.activity.type != ActivityTypes.Message) { return next(); } if (this.setUserLocale != undefined) { let changedLocale = await this.setUserLocale(context); if (changedLocale) { return Promise.resolve(); } } return this.convertLocalesAsync(context) .then(() => next()); } private async convertLocalesAsync(context: TurnContext): Promise<void> { let message = context.activity; let fromLocale: string; if (this.fromLocale != undefined) { fromLocale = this.fromLocale; } else if (this.getUserLocale != undefined) { fromLocale = this.getUserLocale(context); } else { fromLocale = 'en-us'; } return this.localeConverter.convert(message.text, fromLocale, this.toLocale) .then(result => { message.text = result; return Promise.resolve(); }); } public getAvailableLocales(): Promise<string[]> { return this.localeConverter.getAvailableLocales() .then(result => Promise.resolve(result)); } } interface ILocaleConverter { isLocaleAvailable(locale: string): boolean; convert(message: string, fromLocale: string, toLocale: string): Promise<string>; getAvailableLocales(): Promise<string[]>; } class MicrosoftLocaleConverter implements ILocaleConverter { mapLocaleToFunction: { [id: string] : DateAndTimeLocaleFormat } = {}; constructor() { this.initLocales(); } 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; }); this.mapLocaleToFunction["en-us"] = monthDayYEar; } isLocaleAvailable(locale: string): boolean { return !(typeof this.mapLocaleToFunction[locale] === "undefined") } private extractDates(message: string, fromLocale:string): TextAndDateTime[] { let fndDates: string[]; let culture = DateTimeRecognizers.Culture.English; if (fromLocale.startsWith("fr")) { culture = DateTimeRecognizers.Culture.French; } else if (fromLocale.startsWith("pt")) { culture = DateTimeRecognizers.Culture.Portuguese; } else if (fromLocale.startsWith("zh")) { culture = DateTimeRecognizers.Culture.Chinese; } else if (fromLocale.startsWith("es")) { culture = DateTimeRecognizers.Culture.Spanish; } else if(!fromLocale.startsWith("en")) { throw new Error("Unsupported from locale"); } let model = new DateTimeRecognizers.DateTimeRecognizer(culture).getDateTimeModel(); let results = model.parse(message); let foundDates: TextAndDateTime[] = []; results.forEach(result => { let curDateTimeText: TextAndDateTime; let momentTime: Date; let momentTimeEnd: Date; let foundType: string; let resolutionValues = result.resolution["values"][0]; let type = result.typeName.replace('datetimeV2.', ''); if (type.includes('range')) { if (type.includes('date') && type.includes('time')) { momentTime = moment(resolutionValues["start"]).toDate(); momentTimeEnd = moment(resolutionValues["end"]).toDate(); foundType = 'datetime'; } else if (type.includes('date')) { momentTime = moment(resolutionValues["start"]).toDate(); momentTimeEnd = moment(resolutionValues["end"]).toDate(); foundType = 'date'; } else { // Must be a time-only result with no date momentTime = new Date(); momentTime.setHours(parseInt(String(resolutionValues['start']).substr(0, 2))); momentTime.setMinutes(parseInt(String(resolutionValues['start']).substr(3, 2))); momentTimeEnd = new Date(); momentTimeEnd.setHours(parseInt(String(resolutionValues['end']).substr(0, 2))); momentTimeEnd.setMinutes(parseInt(String(resolutionValues['end']).substr(3, 2))); foundType = 'time'; } curDateTimeText = { text: new RegExp(`\\b${result.text}\\b`, "gi"), dateTimeObj: momentTime, endDateTimeObj: momentTimeEnd, type: foundType, range: true } } else { if (type.includes('date') && type.includes('time')) { momentTime = moment(resolutionValues["value"]).toDate(); foundType = 'datetime'; } else if (type.includes('date')) { momentTime = moment(resolutionValues["value"]).toDate(); foundType = 'date'; } else { // Must be a time-only result with no date momentTime = new Date(); momentTime.setHours(parseInt(String(resolutionValues['value']).substr(0, 2))); momentTime.setMinutes(parseInt(String(resolutionValues['value']).substr(3, 2))); foundType = 'time'; } curDateTimeText = { text: new RegExp(`\\b${result.text}\\b`, "gi"), dateTimeObj: momentTime, type: foundType, range: false } } foundDates.push(curDateTimeText); }); return foundDates; } 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})); } 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})); } private formatDateAndTime(date: Date, toLocale: string): string { return `${this.formatDate(date, toLocale)} ${this.formatTime(date, toLocale)}` } convert(message: string, fromLocale: string, toLocale: string): Promise<string> { if (!this.isLocaleAvailable(toLocale)) { return Promise.reject(`Unsupported to locale ${toLocale}`); } try { let dates: TextAndDateTime[] = this.extractDates(message, fromLocale); let processedMessage = message; dates.forEach(date => { if (date.range) { if (date.type == 'time') { let convertedStartDate = this.formatTime(date.dateTimeObj, toLocale); let convertedEndDate = this.formatTime(date.endDateTimeObj, toLocale); processedMessage = processedMessage.replace(date.text, `${convertedStartDate} - ${convertedEndDate}`); } else if (date.type == 'date') { let convertedStartDate = this.formatDate(date.dateTimeObj, toLocale); let convertedEndDate = this.formatDate(date.endDateTimeObj, toLocale); processedMessage = processedMessage.replace(date.text, `${convertedStartDate} - ${convertedEndDate}`); } else { let convertedStartDate = this.formatDateAndTime(date.dateTimeObj, toLocale); let convertedEndDate = this.formatDateAndTime(date.endDateTimeObj, toLocale); processedMessage = processedMessage.replace(date.text, `${convertedStartDate} - ${convertedEndDate}`); } } else { if (date.type == 'time') { let convertedDate = this.formatTime(date.dateTimeObj, toLocale); processedMessage = processedMessage.replace(date.text, convertedDate); } else if (date.type == 'date') { let convertedDate = this.formatDate(date.dateTimeObj, toLocale); processedMessage = processedMessage.replace(date.text, convertedDate); } else { let convertedDateTime = this.formatDateAndTime(date.dateTimeObj, toLocale); processedMessage = processedMessage.replace(date.text, convertedDateTime); } } }); return Promise.resolve(processedMessage); } catch(e) { return Promise.reject(e); } } getAvailableLocales(): Promise<string[]> { return Promise.resolve(Object.keys(this.mapLocaleToFunction)); } } class DateAndTimeLocaleFormat { public timeFormat: string; public dateFormat: string; constructor(timeFormat: string, dateFormat: string) { this.timeFormat = timeFormat; this.dateFormat = dateFormat; } } class TextAndDateTime { public text: RegExp; public dateTimeObj: Date; public type: string; public endDateTimeObj?: Date; public range: boolean }