Как общественность решает проблему многоязычности при генерации HTML
страничек XSL? Скажем есть XML:
<page>
<header/>
<menu/>
<content>
...
</content>
</page>
И есть XSL, который, когда видит тэг <header/> генерирует заголовок. Hа
конкретном языке. То есть помимо собственно выдачи HTML-тэгов он еще и текст
выдает. Hе слишком удобно, если требуется сделать интерфейс одновременно для
русского, английского и немецкого языков.
Что делать? Вводить еще один уровень косвенности и вместо "Welcome, " писать
<xsl:value-of select="$MsgWelcome">? (вообще-то я это еще не поверял, возможно
это не лучшая или даже вовсе не рабочая идея).
--
С уважением, Konstantin.
Tuesday November 27 2001 21:20, you wrote to All:
KS> И есть XSL, который, когда видит тэг <header/> генерирует заголовок.
KS> Hа конкретном языке. То есть помимо собственно выдачи HTML-тэгов он
KS> еще и текст выдает. Hе слишком удобно, если требуется сделать
KS> интерфейс одновременно для русского, английского и немецкого
KS> языков. Что делать? Вводить еще один уровень косвенности и вместо
KS> "Welcome, " писать <xsl:value-of select="$MsgWelcome">? (вообще-то я
KS> это еще не поверял, возможно это не лучшая или даже вовсе не рабочая
KS> идея).
Hа мой взгляд мультиязыковые ресурсы лучше организовывать в виде bundle, как в
java. Hехорошо, если xsl напрямую генерирует текст, он должен храниться
отдельно, в виде xml, в котором каждому ресурсу поставлен в соответствие язык,
тогда имея bundle.xml файл в виде, например
<header>
<text lang="ru">Русский заголовок</text>
<text lang="en">English header</text>
</header>
можно из xsl вставлять языковые ресурсы в зависимости от текущего языка
<xsl:template match="header">
<h3>
<xsl:value-of select="document('bundle.xml')//header/text[@lang=$lang]"/>
</h3>
</xsl:template>
Это, конечно, только один из вариантов.
Wbr, Oleg Tkachenko
ol...@multiconn.com
Multiconn International
У меня была такая задача. Из способов, которые я рассматривал можно привести
следующие:
0. Во всех случаях языковые ресурсы хранятся в XML-файлах приблизительно
следующего формата;
<resources xml:lang="de">
<resource name="recordTITLE">Titel</resource>
<resource name="recordABSTRACT">Kurzbeschreibung</resource>
<resource
name="recordACCESSCONSTRAINTS">Zugriffsbeschr├дnkungen</resource>
......
</resources>
<resources xml:lang="en">
<resource name="recordTITLE">Title</resource>
<resource name="recordABSTRACT">Abstract</resource>
<resource name="recordACCESSCONSTRAINTS">Access Constraints</resource>
......
</resources>
<resources xml:lang="fr">
<resource name="recordTITLE">Titre</resource>
<resource name="recordABSTRACT">R├йsum├й</resource>
<resource name="recordACCESSCONSTRAINTS">Contraintes d'acc├иs</resource>
.......
</resources>
Это - общее для всей систем, испульзуется в
апплетах/сервлетах/JSP/XSLT/whatever.
Файлы поименованы как en.xml, de.xml и так далее в соответствии с ISO 3166.
Документ выбирается примерно так:
<xsl:variable name="locale-given" select="$session/locale"/>
<xsl:variable name="locale">
<xsl:if test="not($locale-given)">en</xsl:if>
<xsl:if test="$locale-given"><xsl:value-of
select="$locale-given"/></xsl:if>
</xsl:variable>
<xsl:variable name="locale-filename" select="concat($locale,'.xml')"/>
<xsl:variable name="locale-document" select="document($locale-filename)"/>
Теперь варианты доступа:
1. Имена ресурсов уникальные, по ним можно строить ключи:
<xsl:key name="label" match="resources[lang($locale)]/resource"
use="@name"/>
И обращаться:
<xsl:for-each select="$locale-document">
<xsl:value-of select="key('label', 'gemetREMOVEITEM')"/>
</xsl:for-each>
Это самый эффективный способ (JServ/Oracle XSQL Servlet/Oracle XDK), но
писать громоздко. Когда в 2.0 сделают смену документа чтобы с key нормально
работало, будет лучший способ, типа:
<xsl:value-of select="key('label', 'gemetREMOVEITEM',$ld)"/>
2. Функция расширения:
<xsl:value-of select="lang:term('gemetREMOVEITEM')"/>
Модификация: экземаляр какого-нибудь наследника Dictionary, в него один раз
загружаются все ресурсы а затем
<xsl:value-of select="lang:term($res, 'gemetREMOVEITEM')"/>
3. Элемент расширения:
<lang:term name="gemetREMOVEITEM"/>
4. 2-step processing.
Первый шаг: выполняем преобразование, вместо текста, который требуется
перевести выводим
<term:gemetREMOVEITEM/>
Второй шаг:
<xsl:template match="term:*">
<xsl:variable name="name" select="local-name()"/>
<xsl:for-each select="$locale-document">
<xsl:value-of select="key('label', $name)"/>
</xsl:for-each>
</xsl:template>
Я думаю, еще можно с десяток способов придумать.
Я пользую первый, вотому как он хоть и неуклюжий но работает довольно
шустрый и переносим.
Bye.
/lexi
--
Отправлено через сервер Talk.Ru - http://www.talk.ru
> <xsl:value-of select="document('bundle.xml')//header/text[@lang=$lang]"/>
Лучше использовать функцию lang().
document('bundle.xml')//header/text[lang($lang)]
>><xsl:value-of select="document('bundle.xml')//header/text[@lang=$lang]"/>
> Лучше использовать функцию lang().
> document('bundle.xml')//header/text[lang($lang)]
Да, точно, это я просто забыл про нее, поскольку у нас в процессоре ее нетути. Тогда и атрибут должен быть xml:lang, а не просто lang.
--
Oleg Tkachenko
Multiconn International, Israel
[Answer on] [Konstantin Scheglov wrote to All at [27 Nov 01 21:20]]:
KS> И есть XSL, который, когда видит тэг <header/> генерирует
KS> заголовок.
KS> Hа конкретном языке. То есть помимо собственно выдачи HTML-тэгов он
KS> еще и текст выдает. Hе слишком удобно, если требуется сделать
KS> интерфейс одновременно для русского, английского и немецкого
KS> языков. Что делать? Вводить еще один уровень косвенности и вместо
KS> "Welcome, " писать <xsl:value-of select="$MsgWelcome">? (вообще-то я
KS> это еще не поверял, возможно это не лучшая или даже вовсе не рабочая
KS> идея).
Я сделал файл strings.xml (типичный ресурс :) ) вот такого вида:
<?xml version="1.0" encoding="koi8-r"?>
<strings>
<lang id="en">
<string id="name">page name</string>
<string id="title">project's homepage</string>
<string id="version">version</string>
<string id="download">download</string>
<string id="stable">stable</string>
<string id="dev">development</string>
</lang>
<lang id="ru">
<string id="name">имя страницы</string>
<string id="title">домашняя страница проекта</string>
<string id="version">версия</string>
<string id="download">брать</string>
<string id="stable">стабильная</string>
<string id="dev">разрабатываемая</string>
</lang>
</strings>
В начале стиля гружу его в переменную STRINGS, а потом достаю из нее по мере
надобности:
<xsl:value-of select="$STRINGS/strings/lang[@id=$lang]/string[@id='title']"/>
Remember, pain is part of pleasure, Konstantin.
... Моя душа села в поезд за горизонт.
28 Nov 01 11:22, you wrote to me:
AV> Я думаю, еще можно с десяток способов придумать.
AV> Я пользую первый, вотому как он хоть и неуклюжий но работает довольно
AV> шустрый и переносим.
Wow, сколько от тебя сразу вариантов. ;-)
Всем спасибо, теперь у меня есть над чем подумать и из чего выбрать.
--
С уважением, Konstantin.
[Answer on] [Aleksei Valikov wrote to Oleg Tkachenko at [28 Nov 01 11:26]]:
>> <xsl:value-of
>> select="document('bundle.xml')//header/text[@lang=$lang]"/>
AV> Лучше использовать функцию lang().
AV> document('bundle.xml')//header/text[lang($lang)]
lang() возвращает false, когда языка нет вообще, а иногда полезно отсутсвие
lang засчитывать за '*', скажем так. Правда, тогда и условия надо написать
посложнее.
Remember, pain is part of pleasure, Aleksei.
... Мне бы ... Через камни струиться водой ледяной,/Господин мой Смерть.