XSLT 从 UI 定义文件 gui.stetic 生成代码(XAML 的选项)
我们实现了一个想法,效果很好。
GTK# 中的 GUI 定义在 XML 文件中gtk-gui/gui.stetic
(WPF 有 XAML 文件)。这个想法是通过 XSLT 生成额外的代码文件。
额外生成的代码通过我们的 Translator 类支持 i18n。来自 Translator 的派生类提供属性,如果文化发生变化,这些属性会改变其值。
XML 文件中的每个可以翻译的文本gtk-gui/gui.stetic
都很容易提取:
<?xml version="1.0" encoding="utf-8"?>
<stetic-interface>
<!-- ... -->
<widget class="Gtk.Bin" id="NameSpaceXy.MenuWidget" design-size="800 480">
<!-- ... -->
<child>
<widget class="Gtk.VBox" id="MainVBox">
<!-- ... -->
<child>
<widget class="Gtk.Button" id="CJKButton">
<!-- ... -->
<property name="Label" translatable="yes" context="yes" comments="commented">context hint|happiness=Ω
㗔㲀䃽䄈䄙䄜礽祉...祿福囍</property>
<!-- ... -->
</widget>
<!-- ... -->
</child>
<!-- ... -->
</widget>
<!-- ... -->
</widget>
<widget class="Gtk.Button" id="ExitButton">
<!-- ... -->
<property name="Label" translatable="yes">Exit</property>
<!-- ... -->
</widget>
<!-- ... -->
<widget class="Gtk.Button" id="CJKButton">
<!-- ... -->
<property name="Label" translatable="yes" context="yes" comments="comment for translator">context hint for translator|happiness=㗔㲀䃽䄈䄙䄜礽祉...祿福囍</property>
<!-- ... -->
</widget>
<!-- ... -->
<widget class="Gtk.Image" id="KeyboardImage">
<!-- ... -->
<property name="Pixbuf">file:en-us-640x232.png</property>
<!-- ... -->
</widget>
<!-- ... -->
</stetic-interface>
在 GUI 设计器中,所有可以翻译的属性都将在 XML 文件中显示为一个 XML 节点,其名称property
具有一个名为translatable
value的属性yes
。节点的内容是可以翻译的字符串。此外,每个这样的元素都可以用注释和翻译者的上下文提示来装饰——这两个字段可以在 UI 设计器中通过属性窗口进行编辑。(奇怪的是上下文提示以节点内容为前缀,由管道字符分隔。)
- 这样一个节点的父
property
节点总是一个widget
节点
- 每个
widget
节点的属性中都包含 Widget 的名称和类型。
- 这种节点的父
widget
节点始终是一个child
节点——除非它不是根节点的子节点。
- 每个
child
节点的父节点又是父widget
节点。
因此,这个非常简单和智能的结构可以让我们找出哪个 Widget 实例的哪些属性是可翻译的,以及在哪里可以找到它的详细信息。
有了这些信息,我构建了预构建脚本和 XSL 文件:
获取所有类的列表,这些类派生自Gtk.Bin
, Gtk.Window
(临时 xml 文件)
从该列表创建一个批处理脚本文件
执行创建的批处理脚本文件,该文件为列表中的每个类执行:
生成的XXXXXTranslation
类看起来像这样:
namespace NameSpaceXy
{
public class EntryWidgetTranslation: TranslationTemplate
{
[Translation(@"default title")]
public string TitleLabel_LabelProp { get; set; }
//..
为每个 Gtk Widget 类生成部分类,它包含一个方法,如下所示:
namespace NameSpaceXy
{
public partial class EntryWidget: ITranslateMethod
{
public void Translate()
{
GtkUtility.SetLabel(TitleLabel, Translator.Translation<EntryWidgetTranslation>().TitleLabel_LabelProp);
GtkUtility.SetImage(KeyboardImage, Translator.Translation<EntryWidgetTranslation>().KeyboardImage_Pixbuf);
//..
}
}
}
最后,这两个生成的代码文件(每个类,派生自Gtk.Bin
// ... Gtk.Window
)Gtk.
必须插入到项目文件中——这是通过附加的 XSLT 完成的。
这行得通。
优点:
它的优点是可以自动提取翻译。每个新设计的 UI 类派生自 egGtk.Window
或Gtk.Bin
在每次构建时自动处理。这种类型的 i18n 可以适应带有适应 XSL 文件的 WPF。
坏处:
生成的方法Translate()
必须在适当的情况下在 Gtk# 中调用,至少在显示元素的位置和更改语言/文化时(如果元素可见)。Translate
(由于其绑定功能,WPF/XAML 将不需要该方法)。
译者
Translator 类是一个自己的公司内部实现,它为当前设置的文化提供正确的字符串 - 这里在内部读取该文化的 XML 文件。由于 Unicode 和添加换行符/多行字符串的优势,我们将语言文件更改为 XML 文件。它现在是一个序列化的 Dictionary 实例。
图片
我们还添加了依赖于文化的图片,可以gui.stetic
使用这个部分 XPath 表达式从调用的 XML 文件中轻松提取这些图片property[@name='Pixbuf'][../@class='Gtk.Image']
。
环境
我在 Windows 中运行 MonoDevelop 并MsXsl.exe
在批处理脚本中使用,它可能也可以在 Linux 中与其他 XSLT 处理器一起运行。