寻找价值,但用xslt替换同级



我有一个XLIFF文件,我用它来将iPhone应用程序翻译成不同的语言。

下面是它的外观:

<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="1.2"
xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd">
<file original="kWallet/Base.lproj/BonusProgram.storyboard"
source-language="de"
datatype="plaintext"
target-language="en">
<header>
<tool tool-id="com.apple.dt.xcode"
tool-name="Xcode"
tool-version="8.2.1"
build-num="8C1002"/>
</header>
<body>
<trans-unit id="VNf-SH-yf4.normalTitle">
<source>Nicht mehr teilnehmen</source>
<target>Nicht mehr teilnehmen</target>
<note>Class = "UIButton"; normalTitle = "Nicht mehr teilnehmen"; ObjectID = "VNf-SH-yf4";</note>
</trans-unit>
<trans-unit id="bks-T0-HXe.normalTitle">
<source>Teilnehmen</source>
<target>Teilnehmen</target>
<note>Class = "UIButton"; normalTitle = "Teilnehmen"; ObjectID = "bks-T0-HXe";</note>
</trans-unit>
<trans-unit id="inq-dy-gMC.title">
<source>Bonus</source>
<target>Bonus</target>
<note>Class = "UITabBarItem"; title = "Bonus"; ObjectID = "inq-dy-gMC";</note>
</trans-unit>
<trans-unit id="mub-0G-Dk1.title">
<source>Bonus Program</source>
<target>Bonus Program</target>
<note>Class = "UINavigationItem"; title = "Bonus Program"; ObjectID = "mub-0G-Dk1";</note>
</trans-unit>
<trans-unit id="rAv-9a-ssv.title">
<source>Bonus</source>
<target>Bonus</target>
<note>Class = "UINavigationItem"; title = "Bonus"; ObjectID = "rAv-9a-ssv";</note>
</trans-unit>
</body>
</file>
</xliff>

现在我需要执行以下操作:

我已经在以下格式的文本文件中提供了翻译:"source" = "target",例如"Im App Store anzeigen" = "Show in App Store"

/* Show in App Store Text */
"Im App Store anzeigen" = "Show in App Store";

所以我要创建一个脚本,它读取我的文本文件并在每一行之后调用 xslt 转换,向其传递 2 个值。

现在我需要了解如何使用 xslt 解决转换。基本上它需要搜索<source> == "Nicht mehr teilnehmen"然后用我要传递给 xslt 转换器的第二个值替换它<target>同级(在本例中为"Stop participating")

我认为这应该很容易,但不幸的是,我没有足够的 xslt 经验来自己解决这个问题。感谢您的帮助。

如果您能够使用 XSLT 2.0 或更高版本,则以下方法将起作用。 此处的三个不同功能在 XSLT 1.0 中不存在。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0"
xpath-default-namespace="urn:oasis:names:tc:xliff:document:1.2">
<!-- Note the `xpath-default-namespace` line here: this is only allowed in XSLT 2.0 and newer.
The input XLIFF file itself specifies this URI as the unprefixed namespace for the whole file.
If we don't specify this as the XPath default namespace, we have to specify element names
in ugly workaround syntax, such as `*[local-name() = 'xliff']`. -->
<!-- Parameter for feeding in the path to your translated-pairs text file. -->
<xsl:param name="transfile-path" select="'DEFAULTPATH'"/>
<!-- Sample path format: 'file:///C:/Users/[USERNAME]/AppData/Local/Temp/transdata.txt' -->
<!-- Variable containing whole content of your translated-pairs text file. Replace the file path as appropriate.
The `unparsed-text` XPath function is required to load plain text (as opposed to parsable XML).
This function is only available in XSLT 2.0 or newer. -->
<xsl:variable name="transfile" select="unparsed-text($transfile-path)"/>
<!-- Newline: this might need adjusting, depending on the newline format in your text file. -->
<xsl:variable name="newline" select="'&#xD;&#xA;'"/>
<xsl:template match="/xliff|file|body|trans-unit">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="header|source|note">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="target">
<xsl:copy>
<!-- This variable tokenizes the $transfile content by newline,
then grabs the first line where the source matches the current <target> element text
(wrapped with double-quotes, just in case),
then chops off the source portion and stores just the target portion, but with the last " on the end.
The `tokenize` XPath function requires XSLT 2.0 or newer. -->
<xsl:variable name="target-string" select="substring-after(tokenize($transfile, $newline)
[contains(., concat('&quot;', current(), '&quot;'))][1], '&quot; = &quot;')"/>
<!-- Output the target string, minus that last "  -->
<xsl:value-of select="substring($target-string, 1, string-length($target-string) - 1)"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

使用包含您指定格式的翻译对的简单文本文件,上述内容对我有用。 我试图包含信息丰富的注释来演练代码的功能。

警告

这假设您的数据完全是一对一的。 因此,"Fussbodenschleifmaschinenverleih"可能会在翻译对的文本文件中出现十四次,但它始终翻译为相同的目标字符串。 :)

旁注

如果您或您的团队可以使用 CAT 工具,则许多此类工具都包含"对齐"功能或配套应用程序,它可以像您描述的那样获取双语数据并生成翻译记忆库。 根据您的设置,这可能会更容易。

更新

根据 gasparuff 的评论,以下是从<source>元素而不是直接从<target>元素查找源文本的方法。 这涉及对先前代码的单个更改:

<xsl:variable name="target-string" select="substring-after(tokenize($transfile, $newline)
[contains(., concat('&quot;', current()/../source, '&quot;'))][1], '&quot; = &quot;')"/>
<!-- The previous version had `current()`, as in, the content of the current
context element, which is here the <target> element.  I changed that above to
`current()/../source` to instead get the text from the sibling <source>
element.  .. here evaluates to the parent of the current <target>, and then
we look for the <source> child of that parent.  This is often safer than 
using preceding-sibling::source, or following-sibling::source, since we
often cannot say 100% that the element we're looking for is *before* the
current context element, or *after* it. -->

最新更新