<?xml version="1.0" encoding="iso-8859-1"?>
<!-- $Id: zpt2pot.xsl,v 1.5 2005/07/14 17:19:50 joan Exp $ -->

<!--====================================================================
 !	zpt2pot.xsl - A gettext extractor for (one) Zope Page Templates
 !
 !	Requeriments:
 !		The input template must be well-formed XML, and declare all the
 !		used namespaces. An example of a correct root element is this:
 !			<html	xmlns="http://www.w3.org/1999/xhtml"
 !					xmlns:tal="http://xml.zope.org/namespaces/tal"
 !					xmlns:metal="http://xml.zope.org/namespaces/metal"
 !					xmlns:i18n="http://xml.zope.org/namespaces/i18n"
 !					i18n:domain="plone"
 !					xml:lang="en"
 !					lang="en"
 !			>
 !
 !		The attribute 'i18n:domain', if present, must be in the root
 !		element, and is ignored in other elements.
 !
 !		The attributes 'i18n:data', 'i18n:source' and 'i18n:target' are
 !		not yet supported.
 !
 !		The 'split' function extension in the 'http://exslt.org/strings'
 !		module is used.
 !
 ! 	Author:
 !		Joan Ordinas <jordinas at gmail dot com>
 !
 !	License:
 !
 !	The source of this software is public domain and provided here "as is". I
 !	don't feel like commenting it more but if you have problems then feel free to
 !	ask me. If you derive your own software from the source or put a part of the
 !	source into your own software, please, give me a credit and send a copy to me.
 !
 !	The author accepts no liability for any damage or data loss caused by this
 !	software.
 !===================================================================-->

<!--
 !	New line character(s):
 !		Redefine as "&#13;&#10;" (MSDOS) or "&#13;" (Mac) if you want.
 !-->
<!DOCTYPE xsl:transform [
	<!ENTITY NL "&#10;">
]>

<!--
 !	Extra namespaces used:
 !		'i18n' is for catch i18n attributes in the input template.
 !		'data' is for local data located at the end of the file.
 !		'str' is for the string module extension.
 !-->
<xsl:transform
	version="1.0"
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:i18n="http://xml.zope.org/namespaces/i18n"
	xmlns:str="http://exslt.org/strings"
	xmlns:data="uri:xsl:zpt:pot:zpt2pot.xsl"
>

<!--
 !	Character encoding:
 !		If you change the original 'iso-8859-1' you must change also
 !		the 'Content-Type' definition in the template 'pot-headers'.
 !-->
<xsl:output
	method="text"
	encoding="iso-8859-1"
/>

<!--====================================================================
 !	Input parameters and global variables
 !===================================================================-->

<!--
 !	To be passed from environment to the processor
 !-->
<xsl:param name="creation-date" select="'YYYY-MM-DD HH:MM:SS+0000'"/>
<xsl:param name="input-filename" select="'stdin'"/>
<xsl:param name="on-errors-terminate" select="'yes'"/>
<xsl:param name="emit-warnings" select="'yes'"/>
<xsl:param name="user-domain" select="''"/>

<!--
 !	Local data
 !-->
<xsl:variable name="DATA" select="document('')/*/data:data"/>

<!--
 !	Constants extracted from input template
 !-->
<xsl:variable name="domain">
	<xsl:choose>
		<xsl:when test="$user-domain != ''"><xsl:value-of select="$user-domain"/></xsl:when>
		<xsl:when test="/*/@i18n:domain"><xsl:value-of select="/*/@i18n:domain"/></xsl:when>
		<!-- default to 'plone' -->
		<xsl:otherwise>plone</xsl:otherwise>
	</xsl:choose>
</xsl:variable>

<xsl:variable name="lang">
	<xsl:choose>
		<xsl:when test="/*/@lang"><xsl:value-of select="/*/@lang"/></xsl:when>
		<xsl:when test="/*/@xml:lang"><xsl:value-of select="/*/@xml:lang"/></xsl:when>
		<!-- default to 'en' -->
		<xsl:otherwise>en</xsl:otherwise>
	</xsl:choose>
</xsl:variable>

<!--====================================================================
 !	Utilities
 !===================================================================-->

<!-- Print a warning -->
<xsl:template name="warn">
	<xsl:param name="sMSG"/>

	<xsl:if test="$emit-warnings = 'yes'">
		<xsl:message terminate="no">
			<xsl:value-of select="concat('warning(', $input-filename, '): ')"/>
			<xsl:value-of select="normalize-space($sMSG)"/>
		</xsl:message>
	</xsl:if>
</xsl:template>

<!-- Print an error message and exit -->
<xsl:template name="error">
	<xsl:param name="sMSG" select="'Unknown error'"/>

	<xsl:choose>
		<xsl:when test="$on-errors-terminate = 'no'">
			<xsl:message terminate="no">
				<xsl:value-of select="concat('error(', $input-filename, '): ')"/>
				<xsl:value-of select="normalize-space($sMSG)"/>
			</xsl:message>
		</xsl:when>
		<xsl:when test="$on-errors-terminate = 'yes'">
			<xsl:message terminate="yes">
				<xsl:value-of select="concat('error(', $input-filename, '): ')"/>
				<xsl:value-of select="normalize-space($sMSG)"/>
			</xsl:message>
		</xsl:when>
		<xsl:otherwise>
			<xsl:message terminate="yes">
				<xsl:text>error: unexpected 'on-errors-terminate' value:</xsl:text>
				<xsl:value-of select="$on-errors-terminate"/>
			</xsl:message>
		</xsl:otherwise>
	</xsl:choose>
</xsl:template>

<!-- Output an entry -->
<xsl:template name="print-entry">
	<xsl:param name="sMsgid"/>
	<xsl:param name="sMsgstr"/>

	<!-- Generate entry (if necessary) -->
	<xsl:if test="$sMsgid != '' and $sMsgid != '&#160;' ">
		<xsl:text>msgid "</xsl:text>
		<xsl:value-of select="$sMsgid"/>
		<xsl:text>"&NL;msgstr "</xsl:text>
		<xsl:value-of select="$sMsgstr"/>
		<xsl:text>"&NL;&NL;</xsl:text>
	</xsl:if>
</xsl:template>

<!--====================================================================
 !	Main template
 !===================================================================-->

<xsl:template match="/">
	<!-- Detect unsupported attributes -->
	<xsl:if test="count(//@i18n:data | //@i18n:source | //@i18n:target) != 0">
		<xsl:call-template name="warn"><xsl:with-param name="sMSG">
			Unsupported i18n attributes detected
		</xsl:with-param></xsl:call-template>
	</xsl:if>
	<!-- Detect multiple domains -->
	<xsl:if test="count(//@i18n:domain)  > 1">
		<xsl:call-template name="warn"><xsl:with-param name="sMSG">
			Detected more than one i18n:domain attribute
		</xsl:with-param></xsl:call-template>
	</xsl:if>

	<!-- Generate headers for POT file -->
	<xsl:call-template name="pot-headers"/>

	<!-- Generate filename special comment -->
	<xsl:text>#: </xsl:text>
	<xsl:value-of select="$input-filename"/>
	<xsl:text>&NL;</xsl:text>

	<!-- Process input recursing over elements -->
	<xsl:apply-templates select="*"/>

	<!-- End of POT file -->
	<xsl:text># vim:syntax=po&NL;</xsl:text>
</xsl:template>

<xsl:template match="*">
	<!-- Follow the tree (only elements) -->
	<xsl:apply-templates select="*"/>
</xsl:template>

<!--====================================================================
 !	Enter and follow the 'translating' mode
 !===================================================================-->
 
<xsl:template match="*[@i18n:translate]" name="translate">
	<!-- Obtain and normalize text to translate -->
	<xsl:variable name="text">
		<!-- Follow the tree in 'translating' mode (only elements and text) -->
		<xsl:apply-templates select="*|text()" mode="translating"/>
	</xsl:variable>
	<xsl:variable name="msgstr" select="normalize-space($text)"/>

	<!-- Obtain msgid -->
	<xsl:variable name="msgid">
		<xsl:choose>
			<xsl:when test="@i18n:translate = ''">
				<xsl:value-of select="$msgstr"/>
			</xsl:when>
			<xsl:otherwise>
				<xsl:value-of select="@i18n:translate"/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:variable>

	<!-- Generate entry -->
	<xsl:call-template name="print-entry">
		<xsl:with-param name="sMsgid" select="$msgid"/>
		<xsl:with-param name="sMsgstr" select="$msgstr"/>
	</xsl:call-template>

	<!-- Follow other elements in normal mode -->
	<xsl:apply-templates select="*"/>
</xsl:template>

<xsl:template match="*" mode="translating">
	<!-- Render element -->
	<xsl:text>&lt;</xsl:text>
	<xsl:value-of select="name(.)"/>
	<xsl:for-each select="@*">
		<xsl:text> </xsl:text>
		<xsl:value-of select="name(.)"/>
		<xsl:text>='</xsl:text>
		<xsl:value-of disable-output-scaping="no" select="."/>
		<xsl:text>'</xsl:text>
	</xsl:for-each>
	<xsl:text>&gt;</xsl:text>
		<!-- Follow the tree in 'translating' mode (only elements and text) -->
		<xsl:apply-templates select="*|text()" mode="translating"/>
	<xsl:text>&lt;/</xsl:text>
	<xsl:value-of select="name(.)"/>
	<xsl:text>&gt;</xsl:text>
</xsl:template>

<xsl:template match="*[@i18n:name]" mode="translating">
	<!-- Generate ${name} macro -->
	<xsl:text>${</xsl:text>
	<xsl:value-of select="@i18n:name"/>
	<xsl:text>}</xsl:text>
</xsl:template>

<xsl:template match="text()" mode="translating">
	<!-- Quote '"' in text -->
	<xsl:for-each select="str:split(., '&quot;')">
		<xsl:value-of select="."/>
		<xsl:if test="position() &lt; last()">
			<xsl:text>&amp;quot;</xsl:text>
		</xsl:if>
	</xsl:for-each>
</xsl:template>

<!--
 !	Catch anomalous situations
 !-->

<xsl:template match="*[@i18n:translate and @i18n:name]" priority="1.0">
	<xsl:call-template name="warn"><xsl:with-param name="sMSG">
		Detected combination of 'i18n:translate' and 'i18n:name' attributes
	</xsl:with-param></xsl:call-template>
	<!-- Anyway do the work... -->
	<xsl:call-template name="translate"/>
</xsl:template>

<xsl:template match="*[@i18n:translate and not(@i18n:name)]" mode="translating">
	<xsl:call-template name="error"><xsl:with-param name="sMSG">
		Attribute 'i18n:translate' cannot nest as a child
	</xsl:with-param></xsl:call-template>
</xsl:template>

<xsl:template match="*[@i18n:name and not(ancestor::*/@i18n:translate)]" priority="1.0">
	<xsl:call-template name="error"><xsl:with-param name="sMSG">
		Element with attribute 'i18n:name' must be child of element
		with 'i18n:translate' attribute
	</xsl:with-param></xsl:call-template>
</xsl:template>

<xsl:template match="*[@i18n:attributes]" priority="1.0" mode="translating">
	<xsl:call-template name="error"><xsl:with-param name="sMSG">
		Element with attribute 'i18n:attributes' cannot be a child
		of element with 'i18n:translate' attribute
	</xsl:with-param></xsl:call-template>
</xsl:template>

<xsl:template match="*[@i18n:attributes and @i18n:attributes = '']" priority="1.0">
	<xsl:call-template name="error"><xsl:with-param name="sMSG">
		Expected attribute name(s)
	</xsl:with-param></xsl:call-template>
</xsl:template>

<!--
 !	Follow elements with the 'i18n:attributes' attribute
 !-->

<xsl:template match="*[@i18n:attributes]" name="attributes">
	<!-- Each case deserves a template... -->
	<xsl:choose>
		<!-- case 'a x; b y ...' -->
		<xsl:when test="contains(@i18n:attributes, ';')">
			<xsl:call-template name="attributes-with-msgid">
				<xsl:with-param name="nsPairs" select="str:split(@i18n:attributes, ';')"/>
				<xsl:with-param name="nsAttrset" select="@*"/>
			</xsl:call-template>
		</xsl:when>
		<!-- case 'a b c ...' -->
		<!-- case 'a b' -->
		<!-- case 'a x' ??? -->
		<xsl:when test="contains(@i18n:attributes, ' ')">
			<xsl:variable name="nsTokens" select="str:split(@i18n:attributes, ' ')"/>
			<xsl:variable name="nTokens" select="count($nsTokens)"/>
			<xsl:choose>
				<!-- 3 or more attribute names -->
				<xsl:when test="$nTokens &gt; 2">
					<xsl:call-template name="attribute-list">
						<xsl:with-param name="nsAttrnames" select="$nsTokens"/>
						<xsl:with-param name="nsAttrset" select="@*"/>
					</xsl:call-template>
				</xsl:when>
				<!-- 2 tokens and nsTokens[2] is not an attribute (is a msgid) -->
				<xsl:when test="not(@*[name()=$nsTokens[2]])">
					<xsl:call-template name="attribute-single">
						<xsl:with-param name="sAttrname" select="$nsTokens[1]"/>
						<xsl:with-param name="sId" select="$nsTokens[2]"/>
						<xsl:with-param name="nsAttrset" select="@*"/>
					</xsl:call-template>
				</xsl:when>
				<!-- 2 attribute names -->
				<xsl:otherwise>
					<xsl:call-template name="attribute-list">
						<xsl:with-param name="nsAttrnames" select="$nsTokens"/>
						<xsl:with-param name="nsAttrset" select="@*"/>
					</xsl:call-template>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:when>
		<!-- case 'a' -->
		<xsl:otherwise>
			<!-- 1 attribute name -->
			<xsl:call-template name="attribute-single">
				<xsl:with-param name="sAttrname" select="@i18n:attributes"/>
				<xsl:with-param name="nsAttrset" select="@*"/>
			</xsl:call-template>
		</xsl:otherwise>
	</xsl:choose>

	<!-- Follow other elements -->
	<xsl:apply-templates select="*"/>
</xsl:template>

<!-- Iterate pairs attribute-name/msgid -->
<xsl:template name="attributes-with-msgid">
	<xsl:param name="nsPairs"/>
	<xsl:param name="nsAttrset"/>

	<xsl:for-each select="$nsPairs">
		<xsl:variable name="nsPair" select="str:split(., ' ')"/>
		<xsl:call-template name="attribute-single">
			<xsl:with-param name="sAttrname" select="$nsPair[1]"/>
			<xsl:with-param name="sId">
				<xsl:choose>
					<xsl:when test="count($nsPair) = 1">
						<xsl:value-of select="''"/>
					</xsl:when>
					<xsl:otherwise>
						<xsl:value-of select="$nsPair[2]"/>
					</xsl:otherwise>
				</xsl:choose>
			</xsl:with-param>
			<xsl:with-param name="nsAttrset" select="$nsAttrset"/>
		</xsl:call-template>
	</xsl:for-each>
</xsl:template>

<!-- Iterate attribute names -->
<xsl:template name="attribute-list">
	<xsl:param name="nsAttrnames"/>
	<xsl:param name="nsAttrset"/>

	<xsl:for-each select="$nsAttrnames">
		<xsl:call-template name="attribute-single">
			<xsl:with-param name="sAttrname" select="."/>
			<xsl:with-param name="nsAttrset" select="$nsAttrset"/>
		</xsl:call-template>
	</xsl:for-each>
</xsl:template>

<!-- Generate an entry -->
<xsl:template name="attribute-single">
	<xsl:param name="sAttrname"/>
	<xsl:param name="nsAttrset"/>
	<xsl:param name="sId" select="''"/>

	<xsl:variable name="text" select="string($nsAttrset[name()=$sAttrname])"/>

	<!-- Check for attribute presence -->
	<xsl:if test="not($text)">
		<xsl:call-template name="warn"><xsl:with-param name="sMSG">
			Attribute '<xsl:value-of select="$sAttrname"/>' without text to translate
		</xsl:with-param></xsl:call-template>
	</xsl:if>

	<!-- Generate the entry -->
	<xsl:call-template name="print-entry">
		<xsl:with-param name="sMsgid">
			<xsl:choose>
				<xsl:when test="$sId = ''"><xsl:value-of select="$text"/></xsl:when>
				<xsl:otherwise><xsl:value-of select="$sId"/></xsl:otherwise>
			</xsl:choose>
		</xsl:with-param>
		<xsl:with-param name="sMsgstr" select="$text"/>
	</xsl:call-template>
</xsl:template>

<!--
 !	Catch elements with the 'i18n:attributes' an 'i18n:translate' attribute
 !-->

 <xsl:template match="*[@i18n:attributes and @i18n:translate]" priority="1.0">
	<xsl:call-template name="translate"/>
	<xsl:call-template name="attributes"/>
</xsl:template>

<!--====================================================================
 !	Generate POT headers
 !===================================================================-->

<xsl:template name="pot-headers">

	<xsl:text># Gettext Message File for </xsl:text>
	<xsl:value-of select="$domain"/>
	<xsl:text>&NL;</xsl:text>

	<xsl:text>msgid ""&NL;</xsl:text>
	<xsl:text>msgstr ""&NL;</xsl:text>

	<xsl:text>"Project-Id-Version: </xsl:text>
	<xsl:value-of select="$domain"/>
	<xsl:text>\n"&NL;</xsl:text>

	<xsl:text>"POT-Creation-Date: </xsl:text>
	<xsl:value-of select="$creation-date"/>
	<xsl:text>\n"&NL;</xsl:text>

	<xsl:text>"PO-Revision-Date: \n"&NL;</xsl:text>
	<xsl:text>"Last-Translator:  &lt;@&gt;\n"&NL;</xsl:text>
	<xsl:text>"Language-Team: &lt;@&gt;\n"&NL;</xsl:text>
	<xsl:text>"MIME-Version: 1.0\n"&NL;</xsl:text>
	<xsl:text>"Content-Type: text/plain; charset=iso-8859-1\n"&NL;</xsl:text>
	<xsl:text>"Content-Transfer-Encoding: 8bit\n"&NL;</xsl:text>
	<xsl:text>"Plural-Forms: nplurals=1; plural=0;\n"&NL;</xsl:text>

	<xsl:text>"Language-code: </xsl:text>
	<xsl:value-of select="$lang"/>
	<xsl:text>\n"&NL;</xsl:text>

	<xsl:text>"Language-name: </xsl:text>
	<xsl:value-of select="$DATA/data:code[@lang=$lang]"/>
	<xsl:text>\n"&NL;</xsl:text>
	
	<xsl:text>"Preferred-encodings: latin1 utf-8\n"&NL;</xsl:text>

	<xsl:text>"Domain: </xsl:text>
	<xsl:value-of select="$domain"/>
	<xsl:text>\n"&NL;</xsl:text>

	<xsl:text>"X-Is-Fallback-For: </xsl:text>
	<xsl:value-of select="$DATA/data:fallback[@lang=$lang]"/>
	<xsl:text>\n"&NL;</xsl:text>

	<xsl:text>&NL;</xsl:text>

</xsl:template>

<!--====================================================================
 !	Local data
 !===================================================================-->

<data:data>
	<!-- Language codes -->
	<data:code lang="aa">Afar</data:code>
	<data:code lang="ab">Abkhazian</data:code>
	<data:code lang="af">Afrikaans</data:code>
	<data:code lang="am">Amharic</data:code>
	<data:code lang="ar">Arabic</data:code>
	<data:code lang="as">Assamese</data:code>
	<data:code lang="ay">Aymara</data:code>
	<data:code lang="az">Azerbaijani</data:code>
	<data:code lang="ba">Bashkir</data:code>
	<data:code lang="be">Belarusian</data:code>
	<data:code lang="bg">Bulgarian</data:code>
	<data:code lang="bh">Bihari</data:code>
	<data:code lang="bi">Bislama</data:code>
	<data:code lang="bn">Bengali</data:code>
	<data:code lang="bo">Tibetan</data:code>
	<data:code lang="br">Breton</data:code>
	<data:code lang="ca">Catalan</data:code>
	<data:code lang="co">Corsican</data:code>
	<data:code lang="cs">Czech</data:code>
	<data:code lang="cy">Welsh</data:code>
	<data:code lang="da">Dansk</data:code>
	<data:code lang="de">German</data:code>
	<data:code lang="dz">Bhutani</data:code>
	<data:code lang="el">Greek</data:code>
	<data:code lang="en">English</data:code>
	<data:code lang="eo">Esperanto</data:code>
	<data:code lang="es">Spanish</data:code>
	<data:code lang="et">Estonian</data:code>
	<data:code lang="eu">Basque</data:code>
	<data:code lang="fa">Farsi</data:code>
	<data:code lang="fi">Finnish</data:code>
	<data:code lang="fj">Fiji</data:code>
	<data:code lang="fo">Faeroese</data:code>
	<data:code lang="fr">French</data:code>
	<data:code lang="fy">Frisian</data:code>
	<data:code lang="ga">Irish</data:code>
	<data:code lang="gd">Gaelic</data:code>
	<data:code lang="gl">Galician</data:code>
	<data:code lang="gn">Guarani</data:code>
	<data:code lang="gu">Gujarati</data:code>
	<data:code lang="ha">Hausa</data:code>
	<data:code lang="he">Hebrew</data:code>
	<data:code lang="hi">Hindi</data:code>
	<data:code lang="hr">Croatian</data:code>
	<data:code lang="hu">Hungarian</data:code>
	<data:code lang="hy">Armenian</data:code>
	<data:code lang="ia">Interlingua</data:code>
	<data:code lang="id">Indonesian</data:code>
	<data:code lang="ie">Interlingue</data:code>
	<data:code lang="ik">Inupiak</data:code>
	<data:code lang="is">Icelandic</data:code>
	<data:code lang="it">Italian</data:code>
	<data:code lang="iu">Inuktitut</data:code>
	<data:code lang="ja">Japanese</data:code>
	<data:code lang="jw">Javanese</data:code>
	<data:code lang="ka">Georgian</data:code>
	<data:code lang="kk">Kazakh</data:code>
	<data:code lang="kl">Greenlandic</data:code>
	<data:code lang="km">Cambodian</data:code>
	<data:code lang="kn">Kannada</data:code>
	<data:code lang="ko">Korean</data:code>
	<data:code lang="ks">Kashmiri</data:code>
	<data:code lang="ku">Kurdish</data:code>
	<data:code lang="ky">Kirghiz</data:code>
	<data:code lang="la">Latin</data:code>
	<data:code lang="ln">Lingala</data:code>
	<data:code lang="lo">Laothian</data:code>
	<data:code lang="lt">Lituanian</data:code>
	<data:code lang="lv">Latvian</data:code>
	<data:code lang="mg">Malagasy</data:code>
	<data:code lang="mi">Maori</data:code>
	<data:code lang="mk">Macedonian</data:code>
	<data:code lang="ml">Malayalam</data:code>
	<data:code lang="mn">Mongolian</data:code>
	<data:code lang="mo">Moldavian</data:code>
	<data:code lang="mr">Marathi</data:code>
	<data:code lang="ms">Malay</data:code>
	<data:code lang="mt">Maltese</data:code>
	<data:code lang="my">Burmese</data:code>
	<data:code lang="na">Nauru</data:code>
	<data:code lang="ne">Nepali</data:code>
	<data:code lang="nl">Dutch</data:code>
	<data:code lang="no">Norwegian</data:code>
	<data:code lang="oc">Occitan</data:code>
	<data:code lang="om">Oromo</data:code>
	<data:code lang="or">Oriya</data:code>
	<data:code lang="pa">Punjabi</data:code>
	<data:code lang="pl">Polish</data:code>
	<data:code lang="ps">Pashto</data:code>
	<data:code lang="pt">Portuguese</data:code>
	<data:code lang="qu">Quetchua</data:code>
	<data:code lang="rm">Rhaeto-Romanic</data:code>
	<data:code lang="rn">Kirundi</data:code>
	<data:code lang="ro">Romanian</data:code>
	<data:code lang="ru">Russian</data:code>
	<data:code lang="rw">Kinyarwanda</data:code>
	<data:code lang="sa">Sanskrit</data:code>
	<data:code lang="sc">Sardinian</data:code>
	<data:code lang="sd">Sindhi</data:code>
	<data:code lang="sg">Sangho</data:code>
	<data:code lang="sh">Serbo-Croatian</data:code>
	<data:code lang="si">Singhalese</data:code>
	<data:code lang="sk">Slovak</data:code>
	<data:code lang="sl">Slovenian</data:code>
	<data:code lang="sm">Samoan</data:code>
	<data:code lang="sn">Shona</data:code>
	<data:code lang="so">Somali</data:code>
	<data:code lang="sq">Albanian</data:code>
	<data:code lang="sr">Serbian</data:code>
	<data:code lang="ss">Siswati</data:code>
	<data:code lang="st">Sesotho</data:code>
	<data:code lang="su">Sundanese</data:code>
	<data:code lang="sv">Swedish</data:code>
	<data:code lang="sw">Swahili</data:code>
	<data:code lang="ta">Tamil</data:code>
	<data:code lang="te">Telugu</data:code>
	<data:code lang="tg">Tajik</data:code>
	<data:code lang="th">Thai</data:code>
	<data:code lang="ti">Tigrinya</data:code>
	<data:code lang="tk">Turkmen</data:code>
	<data:code lang="tl">Tagalog</data:code>
	<data:code lang="tn">Setswana</data:code>
	<data:code lang="to">Tonga</data:code>
	<data:code lang="tr">Turkish</data:code>
	<data:code lang="ts">Tsonga</data:code>
	<data:code lang="tt">Tatar</data:code>
	<data:code lang="tw">Twi</data:code>
	<data:code lang="ug">Uyghur</data:code>
	<data:code lang="uk">Ukrainian</data:code>
	<data:code lang="ur">Urdu</data:code>
	<data:code lang="uz">Uzbek</data:code>
	<data:code lang="vi">Vietnamese</data:code>
	<data:code lang="vo">Volapuk</data:code>
	<data:code lang="wo">Wolof</data:code>
	<data:code lang="xh">Xhosa</data:code>
	<data:code lang="yi">Yiddish</data:code>
	<data:code lang="yo">Yoruba</data:code>
	<data:code lang="za">Zhuang</data:code>
	<data:code lang="zh">Chinese</data:code>
	<data:code lang="zu">Zulu</data:code>
	<!-- Fallbacks -->
	<data:fallback lang="ca">ca-es ca-fr ca-it ca-ad</data:fallback>
	<data:fallback lang="de">de-at de-li de-lu de-ch de-de</data:fallback>
	<data:fallback lang="en">en-au en-bz en-ca en-ie en-jm en-nz en-ph en-za en-tt en-gb en-us en-zw</data:fallback>
	<data:fallback lang="es">es-bo es-cl es-co es-cr es-do es-ec es-sv es-gt es-hn es-mx es-ni es-pa es-py es-pe es-pr es-us es-uy es-ve</data:fallback>
	<data:fallback lang="eu">eu-es</data:fallback>
	<data:fallback lang="fr">fr-be fr-ca fr-lu fr-mc fr-ch fr-fr</data:fallback>
	<data:fallback lang="it">it-ch</data:fallback>
	<data:fallback lang="ja">ja-jp</data:fallback>
	<data:fallback lang="ko">ko-kr</data:fallback>
	<data:fallback lang="nl">nl-be</data:fallback>
	<data:fallback lang="nn">nn-no no-nyn</data:fallback>
	<data:fallback lang="no">nb nb-no no-bok</data:fallback>
	<data:fallback lang="sv">sv-fi</data:fallback>
	<data:fallback lang="tr">tr-tr</data:fallback>
	<data:fallback lang="zh">zh-cn zh-hk zh-mo zh-sg</data:fallback>
</data:data>

</xsl:transform>

<!--
 ! vim:syntax=xslt:nowrap:ts=4:sw=4:ai:nowrap
 !-->
