我已经成功基于here创建了一个多语言应用程序。能够更改语言时我很棒。
现在,我陷入了这种情况。我的应用程序在硬件上运行。因此,存在一个与硬件交互并显示状态文本块的屏幕。该消息将有所不同,具体取决于硬件的响应,例如“请稍候。” ,“将您的ID扫描到扫描仪中” ,“扫描完成” ,“已识别个人资料,继续交易” 。
假设文本块将命名为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.zh-CN.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将显示“请稍等。” ,“将ID扫描到扫描仪中” ,“扫描完成” ,<来自条形码扫描器类的委托事件中的strong>“已识别个人资料,继续进行交易” 。
答案 0 :(得分:0)
我认为您需要对MVVM有所了解,以使使用WPF更容易。在开始时需要付出一些努力,但绝对值得。我以为您只停留在如何接收和转换状态上,所以在查看代码后我将尝试提供更多信息。
基于Enum localization,但未经过部门验证的快速指南。
您需要一个viewmodel来充当您要更新的窗口的数据上下文。它必须实现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
<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”方法来接收更改的状态