XSLT - 使用 key() 查找翻译字符串

XSLT - Translate strings using key() lookup

我正在尝试解决一个问题,我必须使用 xslt 翻译字符串。

我看到了这个:XSLT key() lookup 还有这个:

但我无法让它工作。我试图想出下面的最小示例,它显示了我面临的问题。 “真正的”xsl 是使用构建过程从代码片段组装而成的。这涉及到一些限制。

翻译查找 table 的内部结构始终是相同的,因为它们是从翻译工具以平面 xml 格式下载的 http://docs.translatehouse.org/projects/translate-toolkit/en/latest/formats/flatxml.html。我只能将它们包装到不同的父节点中,这是我尝试使用“lu”命名空间所做的。 所有语言的翻译 tables 必须存储在 xsl 中,因为具有不同翻译的不同代 xsl 可能彼此相邻存在。所以没有“sidecar”文件。

到现在我还拿不到工作钥匙。 xsltproc 的输出如下:

Setup Key - Start
German
xsltApplyOneTemplate: key was not compiled
Setup Key - End
de # skipped #
de # failed #

预期输出:

Setup Key - Start
German
Setup Key - End
de # skipped # Übersprungen
de # failed # Fehlgeschlagen

XML 文件只需要包含一个根元素。

很明显,我尝试根据目标语言定义密钥的方式是错误的,但我的 xsl 知识现在已经达到了极限。语言在转换过程中保持不变,因此所有翻译查找的键只需在开始时设置一次。

xsl 转换:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
  xmlns:lu="http://www.my.domain.de/lookup"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:variable name="vLanguageCode">
    <!-- <xsl:value-of select="/root/@language"/> -->
    <xsl:value-of select="'de'"/>
  </xsl:variable>

  <xsl:template match="/">
    <xsl:call-template name="setupKey"/>

    <xsl:call-template name="getLabel">
      <xsl:with-param name="pKey" select="'skipped'"/>
    </xsl:call-template>

    <xsl:call-template name="getLabel">
      <xsl:with-param name="pKey" select="'failed'"/>
    </xsl:call-template>
  </xsl:template>

  <xsl:template name="setupKey">
    <xsl:message>Setup Key - Start</xsl:message>
    <xsl:choose>
      <xsl:when test="$vLanguageCode='DE' or $vLanguageCode='de'">
        <xsl:message>German</xsl:message>
        <xsl:key name="kLanguageDict" match="/lu:de/root/str" use="@key"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:message>English (default)</xsl:message>
        <xsl:key name="kLanguageDict" match="/lu:en/root/str" use="@key"/>
      </xsl:otherwise>
    </xsl:choose>
    <xsl:message>Setup Key - End</xsl:message>
  </xsl:template>

  <xsl:template name="getLabel">
    <xsl:param name="pKey"/>
    <xsl:variable name="vResult">
      <xsl:value-of select="key('kLanguageDict', $pKey)/@str"/>
    </xsl:variable>
    <xsl:choose>
      <xsl:when test="$vResult!=''">
        <xsl:value-of select="$vResult"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$pKey"/>
      </xsl:otherwise>
    </xsl:choose>
    <xsl:message>
      <xsl:value-of select="concat($vLanguageCode, ' # ', $pKey, ' # ', $vResult)"/>
    </xsl:message>
  </xsl:template>


  <lu:de>
    <root>
      <str key="skipped">Übersprungen</str>
      <str key="failed">Fehlgeschlagen</str>
    </root>
  </lu:de>

  <lu:en>
    <root>
      <str key="skipped">Skipped</str>
      <str key="failed">Failed</str>
    </root>
  </lu:en>

</xsl:stylesheet>

根据@michael.hor257k 的回答补充:

  1. 谢谢。我不知道。所以这意味着我不能根据语言有选择地定义一个键?
  2. 翻译系统最初在顶层有一个键和一个翻译 table,每种语言都有交错的条目。它使用双索引(语言+id)来查找值。

我正在尝试找到一个解决方案,我可以将翻译管理系统 (weblate) 返回的 xml 文件直接嵌入到 xsl 中,而无需修改它们。不幸的是,看起来我能得到的东西有限(只有默认节点和属性)。

这是原始工作翻译查找代码的核心:


  <xsl:variable name="vLanguageDict" select="document('')/*/lu:strings"/>
  <xsl:key name="kLanguageDict" match="lu:string" use="concat(@lang,@id)"/>

  <xsl:template name="getLabel">
    <xsl:param name="pKey"/>
    <xsl:variable name="vResult">
      <xsl:for-each select="$vLanguageDict">
        <xsl:value-of select="key('kLanguageDict', concat($vLanguageCode,$pKey))/@value" />
      </xsl:for-each>
    </xsl:variable>
    <xsl:choose>
      <xsl:when test="$vResult!=''">
        <xsl:value-of select="$vResult"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$pKey"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

<lu:strings>
  <lu:string lang="DE" id="skipped" value="Übersprungen"/>
  <lu:string lang="EN" id="skipped" value="skipped"/>
  <lu:string lang="DE" id="failed" value="Fehlgeschlagen"/>
  <lu:string lang="EN" id="failed" value="failed"/>
</lu:strings>

您的 XSLT 样式表中有两个错误立即跳出:

  1. xsl:key 元素只允许在顶层作为子元素 xsl:stylesheet 元素。
  2. 在 XSLT 1.0 中,键仅对当前文档起作用。如果要从样式表本身进行查找,则必须在调用 key() 函数之前将上下文更改为样式表文档。这里有两个例子:

恐怕没有可复制的例子就只能说这么多了。

---添加---

So this means that I can't selectively define a key depending on language?

您不能有条件地定义键 - 但您可以定义多个键,并且 select 根据指定的语言定义要使用的键。这是一个简化的例子:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:dict="http://example.com/dict">
<xsl:output method="text" encoding="UTF-8"/>

<xsl:key name="de" match="dict:de/entry" use="@key" />
<xsl:key name="en" match="dict:en/entry" use="@key" />

<xsl:param name="input">skipped</xsl:param>
<xsl:param name="lang">de</xsl:param>

<xsl:template match="/">
    <xsl:value-of select="$lang"/>
    <xsl:text> # </xsl:text>
    <xsl:value-of select="$input"/>
    <xsl:text> = </xsl:text>
    <!-- switch context to stylesheet in order to use key -->
    <xsl:for-each select="document('')">
        <xsl:value-of select="key($lang, $input)"/>
    </xsl:for-each>
</xsl:template> 
    
<dict:de>
    <entry key="skipped">Übersprungen</entry>
    <entry key="failed">Fehlgeschlagen</entry>
</dict:de>

<dict:en>
    <entry key="skipped">Skipped</entry>
    <entry key="failed">Failed</entry>
</dict:en>

</xsl:stylesheet>

应用于任何 XML 输入,这将 return:

结果

de : skipped = Übersprungen