Как создать ресурсный файл, используя IFormBuilder.SaveResources в FormFlow (Bot Builder C# SDK)

Мне нужно локализовать все строки и перечисления в FormFlow для немецкого языка. Я посмотрел на https://docs.microsoft.com/en-us/bot-framework/dotnet/bot-builder-dotnet-formflow-localize и там говорится, что есть два метода. Один с использованием IFormBuilder.SaveResources, а второй с использованием инструмента RView (что я не мог понять). Как я могу использовать первый метод для создания и сохранения файлов.resx для немецкого и английского языков, как в AnnotatedSandwich Bot?

  • Например, в следующем 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;
    }

1 ответ

Решение

Перед линией

 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.

Другие вопросы по тегам