XSLT国际化核心是解耦文本与格式,通过外部消息文件和locale参数实现多语言输出。使用xsl:key和document()高效查找文本,XSLT 2.0+支持format-date()和format-number()进行地域敏感数据格式化,1.0版本需依赖外部处理或条件逻辑。

XSLT在国际化输出方面,核心思路是将可翻译的文本内容与格式化规则从XSLT样式表中解耦,根据运行时传入的语言环境(locale)参数,动态地引用对应的文本资源和格式化逻辑。这通常通过外部消息文件或条件判断来实现,确保同一份XML数据可以根据用户的语言偏好,渲染出不同语言的界面或文档。
解决方案
要实现XSLT的国际化输出,我们主要关注两个方面:文本内容的国际化和地域敏感数据(如日期、数字)的格式化。
对于文本内容的国际化,最常见且推荐的做法是使用外部消息目录(message catalog)。这通常是一个独立的XML文件,其中包含键值对,每个键对应一个可翻译的字符串,并且为不同的语言环境提供不同的值。
例如,我们可以有一个
messages_en.xml
<!-- messages_en.xml -->
<messages lang="en">
<message key="welcome_message">Welcome to our site!</message>
<message key="product_name_label">Product Name:</message>
<message key="price_label">Price:</message>
</messages>和一个
messages_zh.xml
<!-- messages_zh.xml -->
<messages lang="zh">
<message key="welcome_message">欢迎访问我们的网站!</message>
<message key="product_name_label">产品名称:</message>
<message key="price_label">价格:</message>
</messages>在XSLT样式表中,我们可以通过一个参数来接收当前的语言环境,然后使用
document()
xsl:key
<!-- main.xsl -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="locale" select="'en'"/> <!-- 默认语言为英语 -->
<!-- 定义一个key,用于高效查找消息 -->
<xsl:key name="msg" match="message" use="@key"/>
<xsl:variable name="messages_doc" select="document(concat('messages_', $locale, '.xml'))"/>
<xsl:template match="/">
<html>
<body>
<h1>
<xsl:value-of select="key('msg', 'welcome_message', $messages_doc)"/>
</h1>
<p>
<xsl:value-of select="key('msg', 'product_name_label', $messages_doc)"/>
<xsl:value-of select="/data/product/name"/>
</p>
<p>
<xsl:value-of select="key('msg', 'price_label', $messages_doc)"/>
<xsl:value-of select="/data/product/price"/>
</p>
</body>
</html>
</xsl:template>
</xsl:stylesheet>调用时,你可以传入
locale
transformer.setParameter("locale", "zh");对于日期和数字的国际化,XSLT 2.0及更高版本提供了内置的函数,如
format-date()
format-number()
lang
format
<!-- XSLT 2.0+ 示例 -->
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="locale" select="'en'"/>
<xsl:template match="/">
<p>
Current Date (default): <xsl:value-of select="current-date()"/>
</p>
<p>
Current Date (formatted for locale):
<xsl:value-of select="format-date(current-date(), '[D01]/[M01]/[Y0001]', $locale)"/>
</p>
<p>
Number (formatted for locale):
<xsl:value-of select="format-number(1234567.89, '#,##0.00', $locale)"/>
</p>
</xsl:template>
</xsl:stylesheet>XSLT 1.0在这方面就比较受限,通常需要更复杂的条件判断或者将格式化逻辑推到调用XSLT的应用程序端处理。
在XSLT 1.0这个相对“古老”的环境下,国际化文本资源的管理和引用确实需要一些技巧,因为它不像XSLT 2.0+那样有强大的
xsl:function
document()
xsl:key
具体来说,我会为每种支持的语言创建一个独立的XML文件,比如
messages_en.xml
messages_fr.xml
messages_zh.xml
<message>
key
<!-- messages_en.xml -->
<messages lang="en">
<message key="greeting">Hello</message>
<message key="goodbye">Goodbye</message>
<message key="error_message">An error occurred.</message>
</messages>
<!-- messages_zh.xml -->
<messages lang="zh">
<message key="greeting">你好</message>
<message key="goodbye">再见</message>
<message key="error_message">发生了一个错误。</message>
</messages>在主XSLT样式表中,我会定义一个参数来接收当前的语言代码(例如
locale
document(concat('messages_', $locale, '.xml'))xsl:key
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="locale" select="'en'"/>
<!-- 定义一个key,将message元素的@key属性作为查找键 -->
<xsl:key name="message-by-key" match="message" use="@key"/>
<!-- 存储当前语言的消息文档 -->
<xsl:variable name="current-messages-doc" select="document(concat('messages_', $locale, '.xml'))"/>
<xsl:template match="/">
<html>
<body>
<!-- 使用key函数查找并输出文本 -->
<h1><xsl:value-of select="key('message-by-key', 'greeting', $current-messages-doc)"/></h1>
<p><xsl:value-of select="key('message-by-key', 'error_message', $current-messages-doc)"/></p>
</body>
</html>
</xsl:template>
</xsl:stylesheet>这种方式的好处是,所有的翻译文本都集中在外部文件中,便于翻译人员维护,也避免了XSLT样式表内部的冗长
xsl:choose
xsl:key
document()
处理日期和数字这类地域敏感数据,国际化实践的差异在XSLT 1.0和XSLT 2.0+之间是巨大的,坦白说,XSLT 1.0在这方面是相当“痛苦”的。
XSLT 2.0+ 的实践: 如果你能使用XSLT 2.0或更高版本,那么恭喜你,生活会变得简单很多。XSLT 2.0引入了强大的内置函数,专门用于处理日期、时间和数字的格式化。
format-date()
format-dateTime()
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="locale" select="'en'"/>
<xsl:template match="/">
<root>
<!-- 假设XML输入中有日期字符串:<date>2023-10-26T14:30:00</date> -->
<p>
Date (en-US): <xsl:value-of select="format-date(xs:date('2023-10-26'), '[M01]/[D01]/[Y0001]', 'en-US')"/>
</p>
<p>
Date (zh-CN): <xsl:value-of select="format-date(xs:date('2023-10-26'), '[Y0001]年[M01]月[D01]日', 'zh-CN')"/>
</p>
<p>
DateTime (en-US): <xsl:value-of select="format-dateTime(xs:dateTime('2023-10-26T14:30:00'), '[M01]/[D01]/[Y0001] [h01]:[m01]:[s01] [PN]', 'en-US')"/>
</p>
</root>
</xsl:template>
</xsl:stylesheet>这里的
[M01]/[D01]/[Y0001]
'en-US'
'zh-CN'
format-number()
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="locale" select="'en'"/>
<xsl:template match="/">
<root>
<!-- 假设XML输入中有数字:<amount>1234567.89</amount> -->
<p>
Amount (en-US): <xsl:value-of select="format-number(1234567.89, '#,##0.00', 'en-US')"/>
</p>
<p>
Amount (zh-CN): <xsl:value-of select="format-number(1234567.89, '#,##0.00', 'zh-CN')"/>
</p>
<p>
Currency (en-US): <xsl:value-of select="format-number(1234567.89, '$#,##0.00', 'en-US')"/>
</p>
<p>
Currency (zh-CN): <xsl:value-of select="format-number(1234567.89, '¥#,##0.00', 'zh-CN')"/>
</p>
</root>
</xsl:template>
</xsl:stylesheet>#,##0.00
'en-US'
'zh-CN'
XSLT 1.0 的实践: 在XSLT 1.0中,没有这些内置的强大函数,所以我们必须采取更“手工”的方式。
日期格式化:
xsl:choose
xsl:if
substring()
concat()
SimpleDateFormat
数字格式化:
format-number()
format-number()
lang
decimal-format
decimal-format
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="locale" select="'en'"/>
<!-- 定义英语数字格式 -->
<xsl:decimal-format name="en-format" decimal-separator="." grouping-separator=","/>
<!-- 定义中文数字格式 (可能与英语相同,但分隔符可能不同,或货币符号不同) -->
<xsl:decimal-format name="zh-format" decimal-separator="." grouping-separator=","/>
<!-- 假设中文环境下,我们可能希望千位分隔符是逗号,但货币符号是¥ -->
<xsl:decimal-format name="zh-currency-format" decimal-separator="." grouping-separator="," infinity="Infinity" minus-sign="-" NaN="NaN" percent="%" per-mille="‰" zero-digit="0"/>
<xsl:template match="/">
<root>
<xsl:variable name="num" select="1234567.89"/>
<p>
Amount (en): <xsl:value-of select="format-number($num, '#,##0.00', 'en-format')"/>
</p>
<p>
Amount (zh): <xsl:value-of select="format-number($num, '#,##0.00', 'zh-format')"/>
</p>
<!-- 注意:货币符号需要手动添加或在格式字符串中定义 -->
<xsl:choose>
<xsl:when test="$locale = 'en'">
<p>Currency (en): $<xsl:value-of select="format-number($num, '#,##0.00', 'en-format')"/></p>
</xsl:when>
<xsl:when test="$locale = 'zh'">
<p>Currency (zh): ¥<xsl:value-of select="format-number($num, '#,##0.00', 'zh-format')"/></p>
</xsl:when>
<xsl:otherwise>
<p>Currency (default): <xsl:value-of select="format-number($num, '#,##0.00', 'en-format')"/></p>
</xsl:otherwise>
</xsl:choose>
</root>
</xsl:template>
</xsl:stylesheet>这仍然需要根据
locale
decimal-format
xsl:choose
总的来说,对于地域敏感数据,如果项目允许,升级到XSLT 2.0+是最佳实践。如果受限于XSLT 1.0,那么将部分复杂的格式化逻辑推给外部应用程序,或者通过细致的
decimal-format
在大型项目中,XSLT的国际化架构设计绝不是简单地堆砌
xsl:choose
document()
模块化样式表与职责分离:
i18n-messages.xsl
xsl:import
xsl:include
统一的消息目录管理:
messages_en-US.xml
messages_zh-CN.xml
@key
module.section.item
灵活的语言环境(Locale)传递机制:
locale
lang
fr-CA
fr
fr
en
xsl:choose
document-available()
性能考量与缓存:
document()
document()
测试与验证:
举个例子,在一个电子商务
以上就是XSLT如何国际化输出?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号