1

我需要将 FormFlow 中的所有字符串和枚举本地化为德语。我查看了https://docs.microsoft.com/en-us/bot-framework/dotnet/bot-builder-dotnet-formflow-localize 它说有两种方法。一个使用IFormBuilder.SaveResources,第二个使用RView工具(我想不通)。如何使用第一种方法为 AnnotatedSandwich Bot 生成和保存德语和英语的 .resx 文件?

  • 例如,在下面的BuildLocalizeForm()中,我应该在哪里放置生成.resx.de.resx.en.resx文件的代码

这是该示例:https ://github.com/Microsoft/BotBuilder/tree/master/CSharp/Samples/AnnotatedSandwichBot

    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);
                            };
            // Form builder uses the thread culture to automatically switch framework strings
            // and also your static strings as well.  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;
    }
4

1 回答 1

2

行前

 form = builder.Build();

您可以调用builder.SaveResources传递一个IResourceWriter.

要了解如何创建ResourceWriter,请阅读https://msdn.microsoft.com/en-us/library/system.resources.resourcewriter(v=vs.110).aspx但它基本上是这样的:

ResourceWriter writer = new ResourceWriter("myResources.resources");

不过,我相信您应该选择 RView 选项。您没有按照这些步骤进行操作,就像让 Rview 工具位于 DLL 所在的同一路径中或者在调用 RView 时将完整路径传递给 DLL 一样简单。

于 2017-09-14T13:30:07.870 回答