xsl:include with a computed filename

S

Simon Brooke

I'm trying to do internationalisation by using xsl:include to include
a different file depending on the locale setting, and I'm completely
failing.

I've tried several different approaches:


<xsl:include href="concat( 'i18n-', $locale, '-include.xslt)"/>

fails with XSLT compile error: FileNotFoundException
---------------------
Could not find file 'C:\Projects\ADL\transforms01\concat( 'i18n-',
$locale, '-include.xslt)'.


<xsl:include>
<xsl:attribute name="href">
<xsl:value-of select="concat( 'i18n-', $locale, '-include.xslt)"/>
</xsl:attribute>
</xsl:include>

fails with 'Missing mandatory attribute'


<xsl:param name="i18n-include" select="i18n-en-GB-include.xslt"/>

<xsl:include href="$i18n-include"/>

fails with XSLT compile error:.FileNotFoundException
---------------------
Could not find file 'C:\Projects\ADL\transforms01\$i18n-include'.


xsl:choose is not a valid child of xsl:stylesheet, so I can't do at
top level

<xsl:choose>
<xsl:when test="$lang='en-GB'">
<xsl:include href='i18n-en-GB-include.xslt'/>
</xsl:when>
</xsl:choose>

I'm running out of ideas. If anyone has successful recipes for
conditional include in XSL I'd love to hear them.
 
B

Bjoern Hoehrmann

* Simon Brooke wrote in comp.text.xml:
I'm trying to do internationalisation by using xsl:include to include
a different file depending on the locale setting, and I'm completely
failing.

I've tried several different approaches:

<xsl:include href="concat( 'i18n-', $locale, '-include.xslt)"/>

You would have to use { ... } for an attribute value template, but in
XSLT 1.0 the href attribute does not take an attribute value template.
<xsl:include>
<xsl:attribute name="href">
<xsl:value-of select="concat( 'i18n-', $locale, '-include.xslt)"/>
</xsl:attribute>
</xsl:include>

The xsl:attribute element applies only to result elements, I think.
<xsl:include href="$i18n-include"/>

See above.
xsl:choose is not a valid child of xsl:stylesheet, so I can't do at
top level

<xsl:choose>
<xsl:when test="$lang='en-GB'">
<xsl:include href='i18n-en-GB-include.xslt'/>
</xsl:when>
</xsl:choose>

Indeed.

What you want to do is not supported by XSLT 1.0. It might be wise to
separate the transformation code and the localized text, then you could
use e.g. the document() function to include the localized text.
 
R

Richard Tobin

Simon Brooke said:
I'm trying to do internationalisation by using xsl:include to include
a different file depending on the locale setting, and I'm completely
failing.

I've tried several different approaches:


<xsl:include href="concat( 'i18n-', $locale, '-include.xslt)"/>

As Bjoern says, you can't do that. <xsl:include> is a compile-time
inclusion, like #include in C. XSLT 1.0 doesn't have any dynamic
features of that kind, though EXSLT has a dyn:evaluate function
for (effectively) compiling an XPath at run-time.

Can you parametrise your internationalisation so that you dynamically
select data rather than code?

-- Richard
 
S

Simon Brooke

As Bjoern says, you can't do that.  <xsl:include> is a compile-time
inclusion, like #include in C.  XSLT 1.0 doesn't have any dynamic
features of that kind, though EXSLT has a dyn:evaluate function
for (effectively) compiling an XPath at run-time.

Can you parametrise your internationalisation so that you dynamically
select data rather than code?

[Hi Richard, long time no see]

Thanks to you both.

The problem with i18n is not the languages and cultures with which we
are familiar, but extension to languages and cultures with which we
are not. In particular, with making a framework which has enough
flexibility to extend to languages and cultures with which we are not.
For example, the indefinite article:

<xsl:template name="i18n-indefinite-article">
<!-- a string, presumed to be a noun- e.g. the name of a domain
entity -->
<xsl:param name="noun"/>
<xsl:variable name="initial" select="substring( $noun, 1, 1)"/>
<xsl:choose>
<xsl:when test="$initial = 'A' or $initial = 'a'">
<xsl:value-of select="concat( 'an ', $noun)"/>
</xsl:when>
<xsl:when test="$initial = 'E' or $initial = 'e'">
<xsl:value-of select="concat( 'an ', $noun)"/>
</xsl:when>
<xsl:when test="$initial = 'I' or $initial = 'i'">
<xsl:value-of select="concat( 'an ', $noun)"/>
</xsl:when>
<xsl:when test="$initial = 'O' or $initial = 'o'">
<xsl:value-of select="concat( 'an ', $noun)"/>
</xsl:when>
<xsl:when test="$initial = 'U' or $initial = 'u'">
<xsl:value-of select="concat( 'an ', $noun)"/>
</xsl:when>
<xsl:eek:therwise>
<xsl:value-of select="concat( 'a ', $noun)"/>
</xsl:eek:therwise>
</xsl:choose>
</xsl:template>

In English, the indefinite article prefixes the noun to which it
applies; in many Scandinavian languages is postfixes the noun; and in
most Slavonic languages it is missing altogether. English also
demonstrates special cases - the indefinite article used depends on
whether the noun has an initial vowel. Or again, consider plurals:

<xsl:template name="i18n-plural">
<!-- a string, presumed to be a noun -->
<xsl:param name="noun"/>
<xsl:choose>
<xsl:when test="$noun='Person'">People</xsl:when>
<!-- add other special cases here -->
<xsl:when test="starts-with( substring($noun, string-
length($noun) ), 's')">
<xsl:value-of select="concat( $noun, 'es')"/>
</xsl:when>
<xsl:when test="starts-with( substring($noun, string-
length($noun) ), 'y')">
<xsl:value-of select="concat( substring( $noun, string-
length($noun)), 'ies')"/>
</xsl:when>
<xsl:eek:therwise>
<xsl:value-of select="concat( $noun, 's')"/>
</xsl:eek:therwise>
</xsl:choose>
</xsl:template>

In British English - and, I'm sure, in many other languages - this is
a mess of special cases.

If internationalisation were simply a matter of a lookup table which
returned fixed boilerplate strings, then the document() solution would
work. And if anyone could suggest a (reasonably efficient) way in
which things like indefinite article rules could be encoded as pure
data then that would interest me greatly. But I think that to do the
things I need to do I need the flexibility of having code - so that
people coming after me who write the internationalisation code for
other locales with which I'm completely unfamiliar have enough
richness to do what they need to do.

The alternate solution I can see is to do a two-phase transformation,
where the first transformation builds an xslt stylesheet with the
correct internationalisation data in it and the second transformation
builds the end-user document... which I can do, since this is a
transformation which gets run at build time not at run time, so
performance is not critical. I'm sort of glad I hadn't missed
anything, but I'm sorry there isn't a more elegant solution.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top