Отображение различных сообщений в мультиязыке динамически - PullRequest
0 голосов
/ 23 ноября 2018

Я успешно создал мультиязычное приложение на основе здесь .Я был великолепен, когда смог сменить язык.

Теперь я застрял в этой ситуации.Мое приложение работает с оборудованием.Таким образом, есть один экран, который взаимодействует с оборудованием и отображает текстовый блок состояния.Это сообщение будет различным в зависимости от ответа оборудования, например, «Пожалуйста, подождите ..» , «Сканировать ваш идентификатор в сканер» , «Сканировать завершено» , «Профиль определен, продолжить транзакцию» .

Как этот вариант можно отобразить в многоязычном виде в один текстовый блок?

Предполагается, что текстовый блок будетназывать TbxStatus.Text.Как установить сообщение в файле ResourceDictionary и как мне обработать, какой ключ строки ресурса ему нужен?

РЕДАКТИРОВАНИЕ [ЧТО Я ПОПРОБОВАЛ]

Этокод, который я пишу для переключения языка и отображения на основе словаря ресурсов: -

App.cs

public static String Directory;
public static App Instance;
public static event EventHandler LanguageChangedEvent;
public App()
{
    // Initialize static variables
    Instance = this;
    Directory = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
    Instance.SetLanguageResourceDictionary(Instance.GetLocXAMLFilePath("en-US"));
}

public static void LoadLanguageLocalization()
{
    try
    {
        ViewModel.AppConfigViewModel.LocalizationProperty.LangLoc = new List<ApplicationModel.LanguageLocalization>
        {
            new ApplicationModel.LanguageLocalization { LanguageID = 1, CountryCode = "ms-MY", LanguageName = "Bahasa Malaysia" },
            new ApplicationModel.LanguageLocalization { LanguageID = 2, CountryCode = "en-US", LanguageName = "English" },
            new ApplicationModel.LanguageLocalization { LanguageID = 3, CountryCode = "zh-CN", LanguageName = "Chinese" },
            new ApplicationModel.LanguageLocalization { LanguageID = 4, CountryCode = "ta-IN", LanguageName = "Tamil" }
        };
    }
    catch (Exception ex)
    {
        LogEvents($"[App] Exception on LoadLanguageLocalization. Message-{ex.Message}. Stack Trace-{ex.StackTrace}", EventLogEntryType.Error);
        ViewModel.AppConfigViewModel.LocalizationProperty.LangLoc = null;
    }
}
public void SwitchLanguage(string inFiveCharLang)
{
    if (System.Globalization.CultureInfo.CurrentCulture.Name.Equals(inFiveCharLang))
        return;

    var ci = new System.Globalization.CultureInfo(inFiveCharLang);
    Thread.CurrentThread.CurrentCulture = ci;
    Thread.CurrentThread.CurrentUICulture = ci;

    SetLanguageResourceDictionary(GetLocXAMLFilePath(inFiveCharLang));
    LanguageChangedEvent?.Invoke(this, new EventArgs());
}
private string GetLocXAMLFilePath(string inFiveCharLang)
{
    string locXamlFile = "Resources." + inFiveCharLang + ".xaml";
    return Path.Combine(Directory, "Language", locXamlFile);
}
public void SetLanguageResourceDictionary(String inFile)
{
    if (File.Exists(inFile))
    {
        // Read in ResourceDictionary File
        var languageDictionary = new ResourceDictionary();
        languageDictionary.Source = new Uri(inFile);

        // Remove any previous Localization dictionaries loaded
        int langDictId = -1;
        for (int i = 0; i < Resources.MergedDictionaries.Count; i++)
        {
            var md = Resources.MergedDictionaries[i];
            // Make sure your Localization ResourceDictionarys have the ResourceDictionaryName
            // key and that it is set to a value starting with "Loc-".
            if (md.Contains("LanguageDictionaryName"))
            {
                if (md["LanguageDictionaryName"].ToString().StartsWith("Lang-"))
                {
                    langDictId = i;
                    break;
                }
            }
        }
        if (langDictId == -1)
        {
            // Add in newly loaded Resource Dictionary
            Resources.MergedDictionaries.Add(languageDictionary);
        }
        else
        {
            // Replace the current langage dictionary with the new one
            Resources.MergedDictionaries[langDictId] = languageDictionary;
        }
    }
}

SelectLanguage.cs

private async void Page_Loaded(object sender, RoutedEventArgs e)
{
    try
    {
        App.LogEvents($"[{PageTitle}] Loaded: Select language", System.Diagnostics.EventLogEntryType.Information);
        BindingToPropertyControl();
    }
    catch (System.Exception ex)
    {
        string error = $"[{PageTitle}] Exception on Page_Loaded. Message: {ex.Message}. StackTrace: {ex.StackTrace}";
        App.LogEvents(error, System.Diagnostics.EventLogEntryType.Error);
    }
}
private void BindingToPropertyControl()
{
    try
    {
        if (ViewModel.AppConfigViewModel.LocalizationProperty.LangLoc != null)
        {
            LanguagePack.ItemsSource = ViewModel.AppConfigViewModel.LocalizationProperty.LangLoc;
        }
    }
    catch (System.Exception ex)
    {
        string error = $"[{PageTitle}] Exception on BindingToPropertyControl. Message: {ex.Message}. StackTrace: {ex.StackTrace}";
        App.LogEvents(error, System.Diagnostics.EventLogEntryType.Error);
    }
}
private void Button_Click(object sender, RoutedEventArgs e)
{
    try
    {
        ScreenTimer.Stop();
        Button btn = (Button)sender;
        string LangCode = btn.Tag.ToString();
        App.LogEvents($"[{PageTitle}] Selecting language: {LangCode}", System.Diagnostics.EventLogEntryType.Information);
        App.Instance.SwitchLanguage(LangCode.ToString());
        Dispatcher.BeginInvoke(DispatcherPriority.Send, new Action(delegate ()
        {
            NavigationService.Navigate(new Uri(ApplicationModel.NaviModel.NaviSelectOptions, UriKind.RelativeOrAbsolute));
        }));
    }
    catch (System.Exception ex)
    {
        string error = $"[{PageTitle}] Exception on Button_Click. Message: {ex.Message}. StackTrace: {ex.StackTrace}";
        App.LogEvents(error, System.Diagnostics.EventLogEntryType.Error);
    }
}

SelectLanguage.xaml

<ScrollViewer x:Name="ScrollLanguage" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden">
    <WrapPanel Height="Auto" Width="{Binding ElementName=ScrollLanguage, Path=ViewportWidth}">
        <ItemsControl Name="LanguagePack">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Grid Margin="0,20" VerticalAlignment="Stretch" Width="{Binding ElementName=ScrollLanguage, Path=ViewportWidth}">
                        <Button Click="Button_Click" Tag="{Binding CountryCode}" Content="{Binding LanguageName}" VerticalAlignment="Center" Height="150" FontSize="60" Background="#FF1A5C9E" BorderBrush="{x:Null}"/>
                    </Grid>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </WrapPanel>
</ScrollViewer>

SelectOptions.xaml

<TextBlock x:Name="tbTitle" TextWrapping="Wrap" Text="{StaticResource ResourceKey=SelectMerchant_Title}" FontSize="100" TextAlignment="Center" Padding="0,0,0,50" Foreground="White"/>
<Button x:Name="btnEatIn" Content="{StaticResource ResourceKey=SelectMerchant_Opt1}" VerticalAlignment="Center" Height="150" FontSize="60" Background="#FF057A5A" BorderBrush="{x:Null}"/>
<Button x:Name="btnEatIn" Content="{StaticResource ResourceKey=SelectMerchant_Opt2}" VerticalAlignment="Center" Height="150" FontSize="60" Background="#FF057A5A" BorderBrush="{x:Null}"/>

Resources.en-US.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:sys="clr-namespace:System;assembly=mscorlib">

    <!-- The name of this ResourceDictionary. Should not be localized. -->
    <sys:String x:Key="LanguageDictionaryName" Localization.Comments="$Content(DoNotLocalize)">Lang-en-US</sys:String>

    <!-- Localization specific styles -->
    <FlowDirection x:Key="FlowDirection_Default" Localization.Comments="$Content(DoNotLocalize)">LeftToRight</FlowDirection>
    <!--<FlowDirection x:Key="FlowDirection_Reverse" Localization.Comments="$Content(DoNotLocalize)">RightToLeft</FlowDirection>-->

    <!-- SELECT ORDER TYPE -->
    <sys:String x:Key="SelectMerchant_Title">Self-Service Kiosk</sys:String>
    <sys:String x:Key="SelectMerchant_Opt1">Register new applicant</sys:String>
    <sys:String x:Key="SelectMerchant_Opt2">Meal Application</sys:String>
</ResourceDictionary>

Назад к тому, с чем я столкнулся, я могу показать разныеязык с помощью ключа ресурса, но как отобразить сообщение или статус, который динамически (не статично), отображается на нескольких языках?

Например, на экране проверки у меня есть один TextBlock, и в настоящее время яподпишитесь на повышение события от аппаратных средств.Как показать статус на основе выбранного языка?.

<StackPanel VerticalAlignment="Top" Margin="120,180,120,0" Grid.Row="1">
       <TextBlock x:Name="tbGeneralStatus" TextWrapping="Wrap" Text="Please wait..." TextAlignment="Center" FontSize="50" Foreground="Yellow"/>
</StackPanel>

tbGeneralStatus.Text покажет "Пожалуйста, подождите .." , "Сканировать ваш идентификатор в сканер" , "Сканировать завершен" , "Профиль определен, продолжить транзакцию" из события делегата из класса сканера штрих-кода.

1 Ответ

0 голосов
/ 23 ноября 2018

Я думаю, вам нужно немного изучить MVVM, чтобы упростить работу с WPF.Требуется некоторое усилие в начале, но это абсолютно стоит.Я думал, что вы застряли только на том, как получать и переводить статус, поэтому я постараюсь дать больше информации после просмотра кода.

Краткое руководство, основанное на Перечисление локализации но не подтверждено в отделе.

Вам нужна модель представления, которая будет действовать как текстовый текст окна, которое вы хотите обновить.В нем должен быть реализован интерфейс INotifyPropertyChange для обновления статуса в режиме реального времени.

class YourWindowViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private string _statusText = string.Empty;
    public string StatusText
    {
        get { return _statusText; }
        set
        {
            _statusText = value;
            OnPropertyChanged("StatusText");
        }
    }

    public void YourMessageHandler(Status newStatus)
    {
        StatusText = GetLocalizedStatusText(newStatus);
    }

    private string GetLocalizedStatusText(Status newStatus)
    {
        switch (newStatus)
        {
            case Status.Wait: return Resources.StatusWaiting;
            case Status.Continue: return Resources.StatusContinue;
            case Status.Scan: return Resources.StatusScanId;
            default: return string.Empty;
        }
    }
}

public enum Status
{
    Wait,
    Scan,
    Continue
}

Чтобы привязать свое окно, сделайте так:

<Window.DataContext>
    <local:YourWindowViewModel/>
</Window.DataContext>

и измените элемент управления TextBlock на привязку кStatusText на viewmodel

<StackPanel VerticalAlignment="Top" Margin="120,180,120,0" Grid.Row="1">
    <TextBlock TextWrapping="Wrap" Text="{Binding StatusText}" TextAlignment="Center" FontSize="50" Foreground="Yellow"/>
</StackPanel>

Обратите внимание, что, поскольку я не знаю ваш формат делегата / msgHandler, я поместил универсальный метод "YourMessageHandler", который получает изменяющийся статус

...