您现在访问的是微软AZURE全球版技术文档网站,若需要访问由世纪互联运营的MICROSOFT AZURE中国区技术文档网站,请访问 https://docs.azure.cn.

本地化处理表单内容Localize form content

备注

本主题适用于 SDK v3 版本。This topic applies to SDK v3 release. 可以在此处找到最新版 SDK (v4) 的文档。You can find the documentation for the latest version of the SDK v4 here.

表单的本地化语言由当前线程的 CurrentUICultureCurrentCulture 决定。A form's localization language is determined by the current thread's CurrentUICulture and CurrentCulture. 默认情况下,区域性派生自当前消息的 Locale 字段,但用户可替代该默认行为 。By default, the culture derives from the Locale field of the current message, but you can override that default behavior. 根据机器人的构造方式,本地化信息可能来自三个不同的源:Depending on how your bot is constructed, localized information may come from up to three different sources:

  • PromptDialog 和 FormFlow 的内置本地化 the built-in localization for PromptDialog and FormFlow
  • 为表单中的静态字符串生成的资源文件a resource file that you generate for the static strings in your form
  • 使用字符串为动态计算的字段、消息或确认创建的资源文件a resource file that you create with strings for dynamically-computed fields, messages or confirmations

为表单中的静态字符串生成资源文件Generate a resource file for the static strings in your form

表单中的静态字符串包括表单根据 C# 类中的信息生成的字符串,以及指定为提示、模板、消息或确认的字符串。Static strings in a form include the strings that the form generates from the information in your C# class and the strings that you specify as prompts, templates, messages or confirmations. 基于内置模板生成的字符串已本地化处理,因此不被视为静态字符串。Strings that are generated from built-in templates are not considered static strings, since those strings are already localized. 由于表单中的许多字符串会自动生成,因此不可直接使用常规的 C# 资源字符串。Since many of the strings in a form are automatically generated, it is not feasible to use normal C# resource strings directly. 相反,可通过调用 IFormBuilder.SaveResources 或使用 BotBuilder SDK for .NET 附带的 RView 工具为表单中的静态字符串生成资源文件 。Instead, you can generate a resource file for the static strings in your form either by calling IFormBuilder.SaveResources or by using the RView tool that is included with the BotBuilder SDK for .NET.

使用 IFormBuilder.SaveResourcesUse IFormBuilder.SaveResources

可在表单上调用 IFormBuilder.SaveResources,将字符串保存到 .resx 文件中,以便生成资源文件。You can generate a resource file by calling IFormBuilder.SaveResources on your form to save the strings to a .resx file.

使用 RViewUse RView

或者,可使用 BotBuilder SDK for .NET 附带的 RView 工具来生成基于 .dll 或 .exe 的资源文件。Alternatively, you can generate a resource file that is based upon your .dll or .exe by using the RView tool that is included in the BotBuilder SDK for .NET. 要生成 .resx 文件,请执行 rview 并指定包含静态表单生成方法及其路径的程序集 。To generate the .resx file, execute rview and specify the assembly that contains your static form-building method and the path to that method. 此片段演示如何使用 RView 生成 Microsoft.Bot.Sample.AnnotatedSandwichBot.SandwichOrder.resx 资源文件 。This snippet shows how to generate the Microsoft.Bot.Sample.AnnotatedSandwichBot.SandwichOrder.resx resource file using RView.

rview -g Microsoft.Bot.Sample.AnnotatedSandwichBot.dll Microsoft.Bot.Sample.AnnotatedSandwichBot.SandwichOrder.BuildForm

此节选内容展示了通过执行此 rview 命令生成的 .resx 文件的一部分 。This excerpt shows part of the .resx file that is generated by executing this rview command.

<data name="Specials_description;VALUE" xml:space="preserve">
<value>Specials</value>
</data>
<data name="DeliveryAddress_description;VALUE" xml:space="preserve">
<value>Delivery Address</value>
</data>
<data name="DeliveryTime_description;VALUE" xml:space="preserve">
<value>Delivery Time</value>
</data>
<data name="PhoneNumber_description;VALUE" xml:space="preserve">
<value>Phone Number</value>
</data>
<data name="Rating_description;VALUE" xml:space="preserve">
<value>your experience today</value>
</data>
<data name="message0;LIST" xml:space="preserve">
<value>Welcome to the sandwich order bot!</value>
</data>
<data name="Sandwich_terms;LIST" xml:space="preserve">
<value>sandwichs?</value>
</data>

配置项目Configure your project

生成资源文件后,将其添加到项目中,然后通过完成以下步骤设置中性语言:After you have generated a resource file, add it to your project and then set the neutral language by completing these steps:

  1. 右键单击项目并选择“应用程序” 。Right-click on your project and select Application.
  2. 单击“程序集信息” 。Click Assembly Information.
  3. 选择与开发机器人时所用语言对应的“中性语言”值 。Select the Neutral Language value that corresponds to the language in which you developed your bot.

创建表单时,IFormBuilder.Build 方法将自动查找包含你的表单类型名称的资源,并使用它们本地化处理表单中的静态字符串。When your form is created, the IFormBuilder.Build method will automatically look for resources that contain your form type name and use them to localize the static strings in your form.

备注

无法通过与静态字段相同的方式本地化处理使用 Advanced.Field.SetDefine(如使用动态字段中所述)定义的动态计算的字段,这是因为动态计算字段的字符串是在填充表单时构造的。Dynamically-computed fields that are defined using Advanced.Field.SetDefine (as described in Using Dynamic Fields) cannot be localized in the same manner as static fields, since strings for dynamically-computed fields are constructed at the time the form is populated. 但是,可使用常规 C# 本地化机制来本地化处理动态计算的字段。However, you can localize dynamically-computed fields by using normal C# localization mechanisms.

本地化处理资源文件Localize resource files

向项目添加资源文件后,可使用多语言应用工具包 (MAT) 对其进行本地化处理。After you have added resource files to your project, you can localize them by using the Multilingual App Toolkit (MAT). 安装 MAT,然后通过完成以下步骤为项目启用它 :Install MAT, then enable it for your project by completing these steps:

  1. 在 Visual Studio 解决方案资源管理器中选择你的项目。Select your project in the Visual Studio Solution Explorer.
  2. 依次单击“工具”、“多语言应用工具包”和“启用” 。Click Tools, Multilingual App Toolkit, and Enable.
  3. 右键单击项目,选择“多语言应用工具包”,再选择“添加翻译”以选择相关翻译 。Right-click the project and select Multilingual App Toolkit, Add Translations to select the translations. 这将创建能够自动或手动翻译的符合行业标准的 XLF 文件。This will create industry-standard XLF files that you can automatically or manually translate.

备注

虽然本文介绍了如何使用多语言应用工具包本地化处理内容,但你也通过各种其他方式实现本地化。Although this article describes how to use the Multilingual App Toolkit to localize content, you may implement localization via a variety of other means.

实际操作See it in action

此代码示例基于使用 FormBuilder 自定义表单中的代码,目的是实现上文所述的本地化。This code example builds upon the one in Customize a form using FormBuilder to implement localization as described above. 在本例中,DynamicSandwich 类(此处未显示)包含动态计算字段、消息和确认的的本地化信息。In this example, the DynamicSandwich class (not shown here) contains localization information for dynamically-computed fields, messages and confirmations.

public static IForm<SandwichOrder> BuildLocalizedForm()
{
    var culture = Thread.CurrentThread.CurrentUICulture;
    IForm<SandwichOrder> form;
    if (!_forms.TryGetValue(culture, out form))
    {
        OnCompletionAsyncDelegate<SandwichOrder> processOrder = async (context, state) =>
                {
                    await context.PostAsync(DynamicSandwich.Processing);
                }; 
        // FormBuilder uses the thread culture to automatically switch framework strings and static strings.
        // Dynamically defined fields must do their own localization.
        var builder = new FormBuilder<SandwichOrder>()
                .Message("Welcome to the sandwich order bot!")
                .Field(nameof(Sandwich))
                .Field(nameof(Length))
                .Field(nameof(Bread))
                .Field(nameof(Cheese))
                .Field(nameof(Toppings),
                    validate: async (state, value) =>
                    {
                        var values = ((List<object>)value).OfType<ToppingOptions>();
                        var result = new ValidateResult { IsValid = true, Value = values };
                        if (values != null && values.Contains(ToppingOptions.Everything))
                        {
                            result.Value = (from ToppingOptions topping in Enum.GetValues(typeof(ToppingOptions))
                                            where topping != ToppingOptions.Everything && !values.Contains(topping)
                                            select topping).ToList();
                        }
                        return result;
                    })
                .Message("For sandwich toppings you have selected {Toppings}.")
                .Field(nameof(SandwichOrder.Sauces))
                .Field(new FieldReflector<SandwichOrder>(nameof(Specials))
                    .SetType(null)
                    .SetActive((state) => state.Length == LengthOptions.FootLong)
                    .SetDefine(async (state, field) =>
                        {
                            field
                                .AddDescription("cookie", DynamicSandwich.FreeCookie)
                                .AddTerms("cookie", Language.GenerateTerms(DynamicSandwich.FreeCookie, 2))
                                .AddDescription("drink", DynamicSandwich.FreeDrink)
                                .AddTerms("drink", Language.GenerateTerms(DynamicSandwich.FreeDrink, 2));
                            return true;
                        }))
                .Confirm(async (state) =>
                    {
                        var cost = 0.0;
                        switch (state.Length)
                        {
                            case LengthOptions.SixInch: cost = 5.0; break;
                            case LengthOptions.FootLong: cost = 6.50; break;
                        }
                        return new PromptAttribute(string.Format(DynamicSandwich.Cost, cost) + "{||}");
                    })
                .Field(nameof(SandwichOrder.DeliveryAddress),
                    validate: async (state, response) =>
                    {
                        var result = new ValidateResult { IsValid = true, Value = response };
                        var address = (response as string).Trim();
                        if (address.Length > 0 && address[0] < '0' || address[0] > '9')
                        {
                            result.Feedback = DynamicSandwich.BadAddress;
                            result.IsValid = false;
                        }
                        return result;
                    })
                .Field(nameof(SandwichOrder.DeliveryTime), "What time do you want your sandwich delivered? {||}")
                .Confirm("Do you want to order your {Length} {Sandwich} on {Bread} {&Bread} with {[{Cheese} {Toppings} {Sauces}]} to be sent to {DeliveryAddress} {?at {DeliveryTime:t}}?")
                .AddRemainingFields()
                .Message("Thanks for ordering a sandwich!")
                .OnCompletion(processOrder);
        builder.Configuration.DefaultPrompt.ChoiceStyle = ChoiceStyleOptions.Auto;
        form = builder.Build();
        _forms[culture] = form;
    }
    return form;
}

此片段演示 CurrentUICulture 为法语时机器人与用户之间产生的交互 。This snippet shows the resulting interaction between bot and user when CurrentUICulture is French.

Bienvenue sur le bot d'ordre "sandwich" !
Quel genre de "sandwich" vous souhaitez sur votre "sandwich"?
 1. BLT
 2. Jambon Forêt Noire
 3. Poulet Buffalo
 4. Faire fondre le poulet et Bacon Ranch
 5. Combo de coupe à froid
 6. Boulette de viande Marinara
 7. Poulet rôti au four
 8. Rôti de boeuf
 9. Rotisserie poulet
 10. Italienne piquante
 11. Bifteck et fromage
 12. Oignon doux Teriyaki
 13. Thon
 14. Poitrine de dinde
 15. Veggie
> 2

Quel genre de longueur vous souhaitez sur votre "sandwich"?
 1. Six pouces
 2. Pied Long
> ?
* Vous renseignez le champ longueur.Réponses possibles:
* Vous pouvez saisir un numéro 1-2 ou des mots de la description. (Six pouces, ou Pied Long)
* Retourner à la question précédente.
* Assistance: Montrez les réponses possibles.
* Abandonner: Abandonner sans finir
* Recommencer remplir le formulaire. (Vos réponses précédentes sont enregistrées.)
* Statut: Montrer le progrès en remplissant le formulaire jusqu'à présent.
* Vous pouvez passer à un autre champ en entrant son nom. ("Sandwich", Longueur, Pain, Fromage, Nappages, Sauces, Adresse de remise, Délai de livraison, ou votre expérience aujourd'hui).
Quel genre de longueur vous souhaitez sur votre "sandwich"?
 1. Six pouces
 2. Pied Long
> 1

Quel genre de pain vous souhaitez sur votre "sandwich"?
 1. Neuf grains de blé
 2. Neuf grains miel avoine
 3. Italien
 4. Fromage et herbes italiennes
 5. Pain plat
> neuf
Par pain "neuf" vouliez-vous dire (1. Neuf grains miel avoine, ou 2. Neuf grains de blé)

代码示例Sample code

有关演示如何使用 Bot Framework SDK for .NET 实现 FormFlow 的完整示例,请参阅 GitHub 中的多对话机器人示例Contoso Flowers 机器人示例For complete samples that show how to implement FormFlow using the Bot Framework SDK for .NET, see the Multi-Dialog Bot sample and the Contoso Flowers Bot sample in GitHub.

其他资源Additional resources