Привет. Сегодня рассмотри процесс локализации FormFlow в Microsoft Bot Framework(BotBuilder SDK). А именно научим чат-бот работать с несколькими языками. Делая отступление, скажу, что будет сделан упор именно на FormFlow из-за того, что остальные компоненты BotBuilder SDK в плане локализации ничем особенным не выделяются.
Для начала создадим класс, необходимый для заполнения
public enum SexOptions
{
Male,
Female
};
public enum LangOptions
{
Russian,
English,
Spanish,
Italian,
German,
Chinese,
Other
};
public enum MessengerOptions
{
Skype,
Telegram,
Viber,
WhatsApp,
Bleep,
FacebookMessenger,
Icq
};
[Serializable]
public class InterviewInfo
{
public string Name;
public SexOptions? Sex;
public LangOptions? Language;
[Numeric(18, 100)]
public int Age = 18;
public List Messenger;
public static IForm BuildForm()
{
var form = new FormBuilder<InterviewInfo>().Build();
return form;
}
};
Данный класс можно заполнять автоматически, используя возможности FowmFlow, используя подобный вызов:
await context.Forward(MakeInterviewDialog(), ResumeAfterNewDialog, activity, CancellationToken.None);
Вместо нового диалога, можно создать форму для заполнения.
internal static IDialog MakeInterviewDialog()
{
return Chain.From(() => FormDialog.FromForm(InterviewInfo.BuildForm));
}
Выглядеть это будет следующем образом:
Если переключиться на русский язык
Как можно заметить, локализация для полей для класса InterviewInfo не меняется. Но элементы «интерфейсов» FormFlow самого BotBuilder SDK уже переведены на множество языков, в том числе на русский.
Мы можем получить файл ресурсов, сгенерированный из нашей модели, это можно сделать, вызвав IFormBuilder.SaveResources
Например, мы можем сохранить сгенерированный файл ресурсов:
var form = new FormBuilder<InterviewInfo>().Build();
var resourceWriter = new System.Resources.ResXResourceWriter(@"C:\temp\resGen.resx");
form.SaveResources(resourceWriter);
resourceWriter.Close();
Он будет иметь следующий вид:
<data name="Name_description;VALUE" xml:space="preserve">
<value>Name</value>
</data>
<data name="Sex_description;VALUE" xml:space="preserve">
<value>Sex</value>
</data>
<data name="SexOptions.Male;VALUE" xml:space="preserve">
<value>Male</value>
</data>
<data name="SexOptions.Female;VALUE" xml:space="preserve">
<value>Female</value>
</data>
<data name="Language_description;VALUE" xml:space="preserve">
<value>Language</value>
</data>
<data name="LangOptions.Russian;VALUE" xml:space="preserve">
<value>Russian</value>
</data>
<data name="LangOptions.English;VALUE" xml:space="preserve">
<value>English</value>
</data>
<data name="LangOptions.Spanish;VALUE" xml:space="preserve">
<value>Spanish</value>
</data>
Я здесь привожу пример не всех параметров, так как их генерирует много, смысл, думаю, понятен.
Также, для генерации файла ресурсов можно воспользоваться утилитой RView, которая входит в состав BotBuilder SDK
Здесь можно увидеть её исходный код и разобраться, как именно идёт генерация: https://github.com/Microsoft/BotBuilder/blob/master/CSharp/Tools/RView/Program.cs
Вызов для генерации будет примерно следующий:
rview -g TestBot.dll TestBot.Models.BuildForm
Когда файл ресурсов сгенерирован и добавлен в проект, можно сделать его локализацию на другие языки. Это можно сделать как автоматически, так и вручную.
Сперва следует установить язык проекта. Для этого в настройках проекта, выберем «Assembly Information». Я установил русский язык, именно он будет языком по умолчанию в проекте.
В BuildForm можно указать какую сборку и файл ресурсов нужно использовать:
var form = new FormBuilder<InterviewInfo>().Build(Assembly.GetAssembly(typeof(AutoResources)), "AutoResources");
После этого параметры, которые были переведены, отображаются на целевом языке:
Использовать сгенерированные файлы ресурсов не обязательно. Можно использовать атрибуты. Например, атрибут Describe позволяет задать имя для требуемой переменной.
[Describe("наименование")]
public string Name;
Для того чтобы использовать файлы ресурсов в подобных атрибутах, можно использовать собственные атрибуты, которые наследуются от тех, что вам необходимы. Например, для показанного Describe можно сделать следующее:
public class LocalizableDescribeAttribute: DescribeAttribute
{
private readonly PropertyInfo _nameOfProperty;
public LocalizableDescribeAttribute(string descriptionKey, Type resourceType, string description = null, string image = null, string message = null, string title = null, string subTitle = null)
: base(description, image,message, title, subTitle)
{
if (resourceType != null)
{
_nameOfProperty = resourceType.GetProperty(descriptionKey,
BindingFlags.Static | BindingFlags.Public);
}
if (_nameOfProperty != null)
{
Description = (string)_nameOfProperty.GetValue(_nameOfProperty.DeclaringType, null);
}
}
}
Подобный подход позволяет получать информацию из файлов ресурсов. Нужно лишь задать название требуемого параметра и требуемый файл ресурсов.
[LocalizableDescribe("Name", typeof(Resources.Resources))]
public string Name;
Для атрибута Prompt можно сделать что-то следующее:
public class LocalizablePromptAttribute : PromptAttribute
{
private readonly PropertyInfo _nameOfProperty;
public LocalizablePromptAttribute(string descriptionKey, Type resourceType, string[] patterns = null)
: base(patterns)
{
if (resourceType != null)
{
_nameOfProperty = resourceType.GetProperty(descriptionKey,
BindingFlags.Static | BindingFlags.Public);
}
if (_nameOfProperty != null)
{
Patterns = new[] { (string)_nameOfProperty.GetValue(_nameOfProperty.DeclaringType, null) };
}
}
}
BotBuilder SDK обладает всеми необходимыми возможностями для локализации. Есть возможность автоматической генерации файла ресурсов для FormFlow, также можно задавать необходимые параметры файлов ресурсов вручную, а также переопределять имеющиеся атрибуты.
Приятного программирования.