WPF中包含下标和内联图像的文本本地化
我有一个小的WPF应用程序,我正在本地化。我已经阅读了大量文档,但没有找到处理“丰富”内容的良好信息来源,例如:WPF中包含下标和内联图像的文本本地化,wpf,xaml,localization,user-interface,Wpf,Xaml,Localization,User Interface,我有一个小的WPF应用程序,我正在本地化。我已经阅读了大量文档,但没有找到处理“丰富”内容的良好信息来源,例如: <ResourceDictionary> <ControlTempate x:Key="Something" TargetType="ContentControl"> <DockPanel> <ContentPresenter DockPanel.Dock="Left" /> <TextBloc
<ResourceDictionary>
<ControlTempate x:Key="Something" TargetType="ContentControl">
<DockPanel>
<ContentPresenter DockPanel.Dock="Left" />
<TextBlock Text="En español en el botón a la izquierda del texto" />
<!-- In spanish the button is to the left of the text -->
</DockPanel>
</ControlTemplate>
</ResourceDictionary>
我有一个ui元素(TextBlock),它包含了文本与格式、内联图像和符号的混合。我想本地化这个元素。我认为,在另一种语言中,以一种自然的方式对该元素进行本地化,即公式/符号的位置需要相对于周围文本进行移动,并且文本的最佳格式在其他语言中也可能略有不同
我正在寻找在XAML/WPF中本地化“丰富”内容(混合文本、格式和内联ui元素的内容)的建议、资源和/或方法。考虑到WPF中对合成和“丰富”UI的强调,我很惊讶没有找到关于上述场景的任何信息——我遗漏了什么
我曾考虑过将XAML存储在资源文件中,然后在运行时对其进行解析,以便包含在UI中,并考虑过创建一个基于区域设置的视图/用户控件,但我没有看到任何关于这些方法的提及(这让我怀疑我是否走错了方向)我希望有人有经验或信息可以分享
谢谢 假设您有一条文本:
"Hello, my <b>dear</b> user!"
“你好,我亲爱的用户!”
您希望将该文本本地化为其他语言:
"Привет, мой <b>дорогой</b> пользователь!!"
“Пццццццццзззазаава1072
因此,您的本地化框架应该将其存储在一个包含所有格式的完整字符串中,并依靠翻译人员耐心、努力工作并保留所有格式标记。或者,如果格式化非常重要,则应将字符串拆分为(3)个部分,并在构造字符串时应用格式化,并将每个部分作为单个条目存储在翻译存储中
编辑:如果您的富文本包含图像引用,则应使用以下内容本地化图像链接的生成方式:
<img src="$current_locale/logo.jpg" />
或者甚至有一个函数,如果当前区域设置的图像丢失,该函数将返回默认图像位置:
<img src="$get_current_locale_or_default_locale_image(logo.jpg)" />
对于您试图实现的目标,
静态资源
标记扩展非常有效。使用StaticResource几乎可以包含任何内容,即使DynamicSource不工作:
<Window ...>
<Window.Resources>
<Span x:Key="Whatever">
<Bold>Hello</Bold> there<LineBreak/>
A green circle:
<InlineUIContainer>
<Ellipse Width="10" Height="10" Fill="Green" />
</InlineUIContainer>
</Inline>
</Window.Resources>
...
<TextBlock>
<StaticResource ResourceKey="Whatever" />
</TextBlock>
请注意,消息类似,但对于西班牙语,圆圈为红色,文本的布局不同
如果愿意,您可以使用ControlTemplates进一步了解这一点。使用ControlTemplates将允许您根据区域设置以不同的顺序排列按钮。例如,如果您的通用词典包含:
<ResourceDictionary>
<ControlTempate x:Key="Something" TargetType="ContentControl">
<StackPanel>
<TextBlock Text="In English we want the text above the button" />
<ContentPresenter />
</StackPanel>
</ControlTemplate>
</ResourceDictionary>
您可以将其添加到窗口或用户控件:
<ContentControl Template="{StaticResource Something}">
<Button Command="Save">Save File</Button>
</ContentControl>
保存文件
然后更改另一种语言的布局,例如:
<ResourceDictionary>
<ControlTempate x:Key="Something" TargetType="ContentControl">
<DockPanel>
<ContentPresenter DockPanel.Dock="Left" />
<TextBlock Text="En español en el botón a la izquierda del texto" />
<!-- In spanish the button is to the left of the text -->
</DockPanel>
</ControlTemplate>
</ResourceDictionary>
注意:如果您只在DependencyProperties中使用本地化(例如没有InlineCollections等),您可以使用{DynamicResource}
,它允许通过即时更新UI随时更改区域设置。要在我的第一个示例中实现这一点,您可以将TextBlock放在ResourceDictionary中的ControlTemplate中,而不是将
包含在ResourceDictionary
中并将其包含在TextBlock中
这只是WPF本地化灵活性的开始。你可以更进一步。我用StaticResource扩展标记了Ray Burns的答案,作为公认的答案,我认为关于该方法的很多细节都是完美的。我还想展示另一个想法——使用T4模板生成“松散”xaml文件,这些文件包含在输出中,并在运行时基于CurrentCulture进行解析 下面的代码是base_block.tt文件的内容。下面一个重要的细节是encoding=“Unicode”的使用(我假设Utf-8可以工作,但是当模板指定Utf-8时,XamlParser会在某些字符上出错,这显然是因为BOM设置)
base_block.tt可用于指定所需值的.tt文件中的include中-对于英语,这里是我的en.tt文件,它将生成en.xaml:
<#
xml_lang = @"en-US";
textblock_constant_C_contents =
@"Enter a constant, <Italic>C</Italic>, that satisfies
<InlineUIContainer Style='{StaticResource image_container_style}'>
<Image x:Name='formula_11' Source='{StaticResource equation_11}' Style='{StaticResource image_style}' Tag='3.0'>
<Image.Height>
<MultiBinding Converter='{StaticResource image_size}'>
<Binding Mode='OneWay' ElementName='formula_11' Path='Tag'/>
<Binding Mode='OneWay' ElementName='c_textblock' Path='FontSize'/>
</MultiBinding>
</Image.Height>
</Image>
</InlineUIContainer>";
textblock_automation_name = @"Enter a Constant, C, that satisfies the following equation: the standard error of the estimate is equal to the constant C over the square root of the sample size";
hyperlink_textblock_contents = @"(<Hyperlink AutomationProperties.Name='More information about the constant C'
x:Name='c_hyperlink'>more info</Hyperlink>)";
#>
<#@ include file="base_block.tt" #>
或者对于法语-fr.tt->fr.xaml:
<#
xml_lang = @"fr";
textblock_constant_C_contents =
@"Entrez une constante, <Italic>C</Italic>, pour satisfaire
<InlineUIContainer Style='{StaticResource image_container_style}'>
<Image x:Name='formula_11' Source='{StaticResource equation_11}' Style='{StaticResource image_style}' Tag='3.0'>
<Image.Height>
<MultiBinding Converter='{StaticResource image_size}'>
<Binding Mode='OneWay' ElementName='formula_11' Path='Tag'/>
<Binding Mode='OneWay' ElementName='c_textblock' Path='FontSize'/>
</MultiBinding>
</Image.Height>
</Image>
</InlineUIContainer>";
textblock_automation_name = @"Entrez une constante, C, qui satisfait l'équation suivante: l'erreur-type de l'estimation est égale à la constante C sur la racine carrée de la taille de l'échantillon.";
hyperlink_textblock_contents = @"(<Hyperlink AutomationProperties.Name=""Plus d'informations sur la constante C"">en savoir plus</Hyperlink>)";
#>
<#@ include file="base_block.tt" #>
上面的法语生成以下.xaml文件:
<UserControl
xml:lang="fr"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="basic_styles.xaml" />
<ResourceDictionary Source="equations.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<WrapPanel Style="{StaticResource description_wrap_panel_style}">
<TextBlock x:Name="c_textblock"
Style="{StaticResource description_textblock_style}"
AutomationProperties.Name = "Entrez une constante, C, qui satisfait l'équation suivante: l'erreur-type de l'estimation est égale à la constante C sur la racine carrée de la taille de l'échantillon.">
Entrez une constante, <Italic>C</Italic>, pour satisfaire
<InlineUIContainer Style='{StaticResource image_container_style}'>
<Image x:Name='formula_11' Source='{StaticResource equation_11}' Style='{StaticResource image_style}' Tag='3.0'>
<Image.Height>
<MultiBinding Converter='{StaticResource image_size}'>
<Binding Mode='OneWay' ElementName='formula_11' Path='Tag'/>
<Binding Mode='OneWay' ElementName='c_textblock' Path='FontSize'/>
</MultiBinding>
</Image.Height>
</Image>
</InlineUIContainer>
</TextBlock>
<TextBlock Style="{StaticResource description_textblock_style}"
KeyboardNavigation.TabIndex="1">
(<Hyperlink AutomationProperties.Name="Plus d'informations sur la constante C">en savoir plus</Hyperlink>)
</TextBlock>
<TextBox Style="{StaticResource entry_textbox_style}"
AutomationProperties.LabeledBy="{Binding ElementName=c_textblock}"
KeyboardNavigation.TabIndex="0">
</TextBox>
</WrapPanel>
</UserControl>
君士坦丁主菜,C,令人满意
(en savoir plus)
在运行时,我查看CurrentCulture,将其与生成的可用xaml文件进行比较,将文件提供给XamlReader.Load(),并在需要的地方添加生成的Usercontrol。一个小样本应用程序演示了这一点。本地化的“丰富”内容和非“丰富”内容有什么区别?本地化是否应该关心这一点?我猜它只是把文本数据存储在一些普通的地方,格式化标签就是PAR。
<UserControl
xml:lang="fr"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="basic_styles.xaml" />
<ResourceDictionary Source="equations.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<WrapPanel Style="{StaticResource description_wrap_panel_style}">
<TextBlock x:Name="c_textblock"
Style="{StaticResource description_textblock_style}"
AutomationProperties.Name = "Entrez une constante, C, qui satisfait l'équation suivante: l'erreur-type de l'estimation est égale à la constante C sur la racine carrée de la taille de l'échantillon.">
Entrez une constante, <Italic>C</Italic>, pour satisfaire
<InlineUIContainer Style='{StaticResource image_container_style}'>
<Image x:Name='formula_11' Source='{StaticResource equation_11}' Style='{StaticResource image_style}' Tag='3.0'>
<Image.Height>
<MultiBinding Converter='{StaticResource image_size}'>
<Binding Mode='OneWay' ElementName='formula_11' Path='Tag'/>
<Binding Mode='OneWay' ElementName='c_textblock' Path='FontSize'/>
</MultiBinding>
</Image.Height>
</Image>
</InlineUIContainer>
</TextBlock>
<TextBlock Style="{StaticResource description_textblock_style}"
KeyboardNavigation.TabIndex="1">
(<Hyperlink AutomationProperties.Name="Plus d'informations sur la constante C">en savoir plus</Hyperlink>)
</TextBlock>
<TextBox Style="{StaticResource entry_textbox_style}"
AutomationProperties.LabeledBy="{Binding ElementName=c_textblock}"
KeyboardNavigation.TabIndex="0">
</TextBox>
</WrapPanel>
</UserControl>