zpt2pot.xsl
Version 1.5 of my XSLT transformation for extract translatable strings in Zope Page Templates.
Size 22.8 kB - File type text/xmlFile contents
<?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 " " (MSDOS) or " " (Mac) if you want.
!-->
<!DOCTYPE xsl:transform [
<!ENTITY NL " ">
]>
<!--
! 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 != ' ' ">
<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><</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>></xsl:text>
<!-- Follow the tree in 'translating' mode (only elements and text) -->
<xsl:apply-templates select="*|text()" mode="translating"/>
<xsl:text></</xsl:text>
<xsl:value-of select="name(.)"/>
<xsl:text>></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(., '"')">
<xsl:value-of select="."/>
<xsl:if test="position() < last()">
<xsl:text>&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 > 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: <@>\n"&NL;</xsl:text>
<xsl:text>"Language-Team: <@>\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
!-->
zpt2pot
Click here to get the file
