kpiroumian 2002/09/24 10:11:07 Modified: src/documentation/xdocs/userdocs/transformers Tag: cocoon_2_0_3_branch i18n-transformer.xml Log: Rewritten to reflect the current (real) features. (sync with HEAD) Revision Changes Path No revision No revision 1.1.2.2 +198 -173 xml-cocoon2/src/documentation/xdocs/userdocs/transformers/i18n-transformer.xml Index: i18n-transformer.xml =================================================================== RCS file: /home/cvs/xml-cocoon2/src/documentation/xdocs/userdocs/transformers/i18n-transformer.xml,v retrieving revision 1.1.2.1 retrieving revision 1.1.2.2 diff -u -r1.1.2.1 -r1.1.2.2 --- i18n-transformer.xml 7 Jun 2002 19:57:47 -0000 1.1.2.1 +++ i18n-transformer.xml 24 Sep 2002 17:11:06 -0000 1.1.2.2 @@ -1,80 +1,125 @@ <?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.0//EN" "../../dtd/document-v10.dtd"> +<!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.0//EN" "document-v10.dtd"> <document> <header> <title>I18n Transformer</title> - <version>0.9</version> + <version>1.0</version> <type>Technical document</type> <authors> - <person name="Konstantin Piroumian" email="[EMAIL PROTECTED]"/> + <person name="Konstantin Piroumian" email="[EMAIL PROTECTED]"/> + <person name="Marcus Crafter" email="[EMAIL PROTECTED]"/> + <person name="Michael Enke" email="[EMAIL PROTECTED]"/> </authors> <abstract> This document describes an approach for internationalization of XML - documents within Cocoon. It introduces some tags to markup text + applications within Cocoon. It introduces some tags to markup text that should be translated and a format for dictionaries. - The first proposal was made by Infozone Group (http://www.infozone-group.org). + The original proposal was made by Infozone Group (http://www.infozone-group.org). </abstract> </header> <body> - <s1 title="I18n Transformer"> + <s1 title="Introduction"> <p> Developing and maintaining multi-language sites is a common problem for web developers. - The usage of XML and XSL makes this task much more easier, especially with Cocoon's + The usage of XML and XSL makes this task much more easier, especially with content, logic and presentation separation concept. </p> + <dl> + <dt>Internationalization (i18n)</dt> + <dd>Process of developing a product in such a way that it works with data in different languages and can be adapted to various target markets without engineering changes.</dd> + <dt>Localization (l10n)</dt> + <dd>Subsequent process of translating and adapting a product to a given market's cultural conventions.</dd> + </dl> <p> This approach for internationalization (further - i18n) of XML documents within Cocoon is based on a transformer - <link href="../../apidocs/org/apache/cocoon/transformation/I18nTransformer.html"> <code>I18nTransformer</code> </link> - , which uses XML dictionaries for all the i18n data. The namespace of i18n is defined as follows: - <code>xmlns:i18n="http://apache.org/cocoon/i18n/2.0"</code> - </p> - <p> - The first implementation was developed by <link href="mailto:[EMAIL PROTECTED]">Lassi Immonen</link>. In this implementation the syntax was changed according to the <link href="http://www.infozone-group.org">Infozone Group</link>'s i18n proposal (with small changes) and some new features were implemented. - </p> - <p> - Enhancements for number, date and time have been contributed by <link href="mailto:[EMAIL PROTECTED]">Michael Enke</link>. - </p> + , which uses XML dictionaries for all the multilingual data. The namespace URI of i18n transformer is defined as follows: + </p> + <source>xmlns:i18n="http://apache.org/cocoon/i18n/2.0</source> + <s2 title="Other implementation details"> <ul> - <li>Name : i18n</li> + <li>Default name in sitemap: i18n</li> <li>Class: org.apache.cocoon.transformation.I18nTransformer</li> <li>Cacheable: no.</li> + <li>Poolable: yes.</li> </ul> + </s2> </s1> - <s1 title="Features supported"> + <s1 title="Brief description"> <p> - The following features are supported by the i18n transformer: + The following features are supported by the i18n transformer:<br/> </p> <ul> <li>Text translation</li> <li>Attribute translation</li> - <li>Param substitution</li> - <li>Substitution param translation</li> - <li>Date internationalization (New!)</li> - <li>Number internationalization (New!)</li> - <li>Locale support (New!)</li> - <li>A dictionary update and language addition automation stylesheet (New!)</li> + <li>Parameter substitution (with translation if needed)</li> + <li>Date, number and currency formatting</li> </ul> <p> - A simple example of i18n: + A simple example of i18n markup: </p> - <source><![CDATA[ -<para title="first" name="article" i18n:attr="title name"> + <source> +<![CDATA[<para title="first" name="article" i18n:attr="title name"> <i18n:text>This text will be translated.</i18n:text> </para>]]></source> <p> The text inside the <code><![CDATA[<i18n:text>]]></code> will be used as a key to find the - translation in the dictionary. All attributes that are listed in the <code><![CDATA[<i18n:attr>]]></code> attribute also will be translated and their values will be used as dictionary keys. + translation in the message catalogue. All attributes (of any other namespace element) that are listed in the <code><![CDATA[i18n:attr]]></code> attribute also will be translated and their values will be used as dictionary keys. </p> <note> - This i18n approach was re-designed to implement i18n of dates, currencies, etc. - Although the possibilities supported allow for complicated formatting, you will need to use XSP to achieve more flexibility in some cases. + Although, date, time, number and currency formatting is also supported, in some cases it is needed to use XSP or some other dynamic means to achieve more flexibility. </note> </s1> - <s1 title="Markup content for translation"> - <s2 title="Simple text translation"> + <s1 title="Markup Reference"> + <s2 title="Summary"> + <p> + Special tags in i18n namespace are used to mark parts of XML document that should be substituted with dictionary messages. + </p> + <table> + <caption>Tags list</caption> + <tr> + <th>Element</th> + <th>Description</th> + </tr> + <tr> + <td><link href="#i18n_text">i18n:text</link></td> + <td>Used for simple text translation</td> + </tr> + <tr> + <td><link href="#i18n_attr">i18n:attr</link></td> + <td>Attribute for any element (not in i18n-namespace). Contains the names of other attributes of that element to be translated</td> + </tr> + <tr> + <td><link href="#i18n_translate">i18n:translate</link></td> + <td>Translates text with parameter substitution</td> + </tr> + <tr> + <td><link href="#i18n_param">i18n:param</link></td> + <td>Used with <code>i18n:translate</code> to provide substitution parameter</td> + </tr> + <tr> + <td><link href="#i18n_date">i18n:date</link></td> + <td>Formats the date in localized manner</td> + </tr> + <tr> + <td><link href="#i18n_time">i18n:time</link></td> + <td>Formats the time in localized manner</td> + </tr> + <tr> + <td><link href="#i18n_datetime">i18n:date-time</link></td> + <td>Formats the date and time in localized manner</td> + </tr> + <tr> + <td><link href="#i18n_number">i18n:number</link></td> + <td>Formats numbers, currencies and percent in localized manner</td> + </tr> + </table> + <p></p> + </s2> + <anchor id="i18n_text"/><s2 title="i18n:text"> <p> To translate some simple text we use the <code><![CDATA[<i18n:text>]]></code> tag: </p> @@ -92,19 +137,8 @@ </p> <source><![CDATA[ <i18n:text i18n:key="key_text">Default value</i18n:text>]]></source> - <note> - Maybe it would be better to have a possibility to use i18n:key in any element and not only in i18n:text? - E.g.: - <code><![CDATA[ -<ul> - <li i18n:key="Item1" /> - <li i18n:key="Item2" /> - ... -</ul> - ]]></code> - </note> </s2> - <s2 title="Translation with param substitution"> + <anchor id="i18n_translate"/><s2 title="Translation with param substitution"> <p> To translate the text with param substitution the <code><![CDATA[<i18n:translate>]]></code> tag must be used. We can specify some <code><![CDATA[<i18n:param>]]></code>-tags which contain @@ -155,10 +189,13 @@ Generally, it is not necessary for the text for param substitution to be translated. E.g., it can come from a database with predefined placeholders for i18n params and there is no need to use <code><![CDATA[<i18n:text>]]></code> for its translation. </note> + <p> + Parameters can be dates, numbers and currencies. Use <strong>type</strong> attribute to specify one of the possible types: <code>date | time | date-time | number | currency | currency-no-unit | int-currency | percent </code>. See more on params <link href="#i18n_param">here</link>. + </p> </s2> - <s2 title="Attributes"> + <anchor id="i18n_attr"/><s2 title="Attributes"> <p> - Additionally we can translate Attributes. This is very useful for + Additionally we can translate attributes. This is very useful for HTML-forms since labels of buttons are set via an attribute in HTML. To translate attributes of a tag, add an additional attribute named 'i18n:attr' containing a list of attributes, which should be @@ -170,13 +207,18 @@ The attribute, which will be translated is 'value'. Parameter replacement is not available for attributes at this time. </p> + <note> + Some versions of Xerces have a bug in removeAttribute() method implementation and this + results in a NullPointerException if attributes translation is used. The solution is to upgrade + to a newer version of Xerces. + </note> </s2> <s2 title="Date, time and number formatting"> - <p>To format dates according to the current locale use <code><![CDATA[<i18n:date src-pattern="dd/MM/yyyy" pattern="dd:MMM:yyyy" value="01/01/2001" />]]></code>. The <code>'src-pattern'</code> attribute will be used to parse the <code>'value'</code>, then the date will be formatted according to the current locale using the format specified by <code>'pattern'</code> attribute. + <anchor id="i18n_date"/><p>To format dates according to the current locale use <code><![CDATA[<i18n:date src-pattern="dd/MM/yyyy" pattern="dd:MMM:yyyy" value="01/01/2001" />]]></code>. The <code>'src-pattern'</code> attribute will be used to parse the <code>'value'</code>, then the date will be formatted according to the current locale using the format specified by <code>'pattern'</code> attribute. </p> - <p>To format time for a locale (e.g. de_DE) use <code><![CDATA[<i18n:time src-pattern="dd/MM/yyyy" locale="de_DE" value="01/01/2001" />]]></code>. The <code>'src-pattern'</code> and <code>'pattern'</code> attribute may also contain <code>'short'</code>, <code>'medium'</code>, <code>'long'</code> or <code>'full'</code>. The date will be formatted according to this format. + <anchor id="i18n_time"/><p>To format time for a locale (e.g. de_DE) use <code><![CDATA[<i18n:time src-pattern="dd/MM/yyyy hh:mm" locale="de_DE" value="01/01/2001 12:00" />]]></code>. The <code>'src-pattern'</code> and <code>'pattern'</code> attribute may also contain <code>'short'</code>, <code>'medium'</code>, <code>'long'</code> or <code>'full'</code>. The date will be formatted according to this format. </p> - <p>To format date and time use <code><![CDATA[<i18n:date-time />]]></code>. + <anchor id="i18n_datetime"/><p>To format date and time use <code><![CDATA[<i18n:date-time />]]></code>. </p> <p>It is also possible to specify a src-locale: <code><![CDATA[<i18n:date src-pattern="short" src-locale="en_US" locale="de_DE"> 12/24/01 </i18n:date> ]]></code> will result in 24.12.2001 </p> @@ -186,16 +228,16 @@ <p> If no pattern was specified then the date will be formatted with the <code>DateFormat.DEFAULT</code> format (both date and time). If no value for the date is specified then the current date will be used. E.g.: <code><![CDATA[<i18n:date/> ]]></code> will result in the current date, formatted with default localized pattern. </p> - <p>To format numbers in locale sensitive manner use <code><![CDATA[<i18n:number pattern="0.##" value="2.0" />]]></code>. This will be useful for Arabic, Indian, etc. number formatting. Additionally, currencies and percent formatting can be used, known types are <code>currency</code>, <code>currency-no-unit</code>, <code>int-currency</code>, <code>int-currency-no-unit</code> and <code>percent</code>. Another useful attribute is <code>fraction-digits</code>, E.g.: + <anchor id="i18n_number"/><p>To format numbers in locale sensitive manner use <code><![CDATA[<i18n:number pattern="0.##" value="2.0" />]]></code>. This will be useful also for Arabic, Indian, etc. number formatting. Additionally, currencies and percent formatting can be used, known types are <code>currency</code>, <code>currency-no-unit</code>, <code>int-currency</code>, <code>int-currency-no-unit</code> and <code>percent</code>. Another useful attribute is <code>fraction-digits</code>, E.g.: </p> <ul> - <li><code><![CDATA[<i18n:number type="currency" value="1703.7434" />]]></code> will result in localized presentation of the <code>value</code> - $1,703.74 for US locale.</li> - <li><code><![CDATA[<i18n:number type="currency" fraction-digits="3" value="1703.7434" />]]></code> will result in localized presentation of the <code>value</code> - $1,703.743 for US locale so you can print gasonline prices.</li> - <li><code><![CDATA[<i18n:number type="int-currency" value="170374" />]]></code> will result in localized presentation of the <code>value</code> - $1,703.74 for US locale, 170374 (with unit) for a currency without subunit.</li> - <li><code><![CDATA[<i18n:number type="int-currency-no-unit" value="170374" />]]></code> will result in localized presentation of the <code>value</code> - 1,703.74 for US locale, 170374 (without) for a currency without subunit.</li> - <li><code><![CDATA[<i18n:number type="percent" value="1.2" />]]></code> will result in localized percent <code>value</code> - %120 for most of the locales.</li> + <li><code><![CDATA[<i18n:number type="currency" value="1703.7434" />]]></code> will result in localized presentation of the value for US locale: $1,703.74</li> + <li><code><![CDATA[<i18n:number type="currency" fraction-digits="3" value="1703.7434" />]]></code> will result in localized presentation of the value for US locale so you can print gasonline prices: $1,703.743</li> + <li><code><![CDATA[<i18n:number type="int-currency" value="170374" />]]></code> will result in localized presentation of the value for US locale: $1,703.74, and 170374 (with currency unit) for a currency without subunit.</li> + <li><code><![CDATA[<i18n:number type="int-currency-no-unit" value="170374" />]]></code> will result in localized presentation of the value for US locale: 1,703.74, and 170374 (without currency unit) for a currency without subunit.</li> + <li><code><![CDATA[<i18n:number type="percent" value="1.2" />]]></code> will result in localized percent value: %120 for most of the locales.</li> </ul> - <p> + <anchor id="i18n_param"/><p> Also, date and number formatting can be used with substitution params. <code>type</code> attribute must be used with params to indicate the param type (date, number, currency, ...). Default type is <code>string</code>. </p> <source><![CDATA[ @@ -213,125 +255,110 @@ Result will be like this: <code>You have to pay $102.5 for 2.5 pounds or 10% of your profit. Valid from 13-Jun-01</code> </p> </s2> - <s2 title="Dictionaries"> - <p> - Dictionaries contain the translations for the text to be translated. - They consist of a list of entries, where each entry specifies the - translation(s) for a key. An entry may contain the translation for - various languages. An example: - </p> - <source><![CDATA[ -<translations> - <entry> - <key>Some {0} was inserted {1}.</key> - <translation lang="en">Some {0} was {1} inserted.</translation> - <translation lang="de">Etwas {0} wurde {1} eingesetzt.</translation> - </entry> -</translations>]]></source> - <p> - For each text, we want to translate, we must provide a key, where - the key is either text as we have written it in the document or the value - of the 'i18n:key' attribute. The key must be written exactly like in - the document, including spaces, linefeeds, etc. - </p> - <p> - Then we must enter a translation for the text with the <code><![CDATA[<translation>]]></code>-tag, - where the 'lang'-attribute specifies the language of the translated - text. If the text contains placeholders, they'll be replaced at the - correct places in the translation with the given parameters. - </p> - </s2> - <s2 title="How to migrate from the old I18nTransformer"> - <p> - Dictionary structure remained the same, so old dictionaries can be used. - Previous <code><![CDATA[<i:tr>]]></code> tags are renamed to <code><![CDATA[<i18n:text>]]></code>. (The namespace prefix is not important, you can choose any you like). - </p> - <p> - The old transformer supported translation of any tag using its text value as the key: - </p> - <source><![CDATA[ -<elem i18n:tr="y">This text will be translated.</elem>]]> - </source> - <p> - You have to change that for the new transformer like this: - </p> - <source><![CDATA[ -<elem><i18n:text>This text will be translated.</i18n:text></elem>]]> - </source> - <p> - There was a possibility in the old transformer for choosing image paths depending on the language. - Now you can achieve the same result by translating the 'src' attribute of img element. - </p> - <note> - I am not sure that image path translation in the old manner is possible without XSP, - because the language code was used and not a dictionary. - I'll add a feature for this kind of translation in the near future. - </note> - </s2> - </s1> - <s1 title="Sample"> - <s2 title="Sitemap configuration"> - <p> - To use I18nTransformer, it must be added to the sitemap: - </p> - <source><![CDATA[ -<map:transformers default="xslt"> - <map:transformer name="i18n" - src="org.apache.cocoon.transformation.I18nTransformer"/> -</map:transformers>]]></source> - <p> - Then, a <code>match</code> must be declared, something like this: - </p> - <source><![CDATA[ + <s2 title="Catalogues (Dictionaries)"> + <p>Message catalogues contain translations to be used by the i18n transformer.</p> + <s3 title="Catalogues format"> + <p>A single message catalogue file contains translations for a particular language, e.g.:</p> + <source><![CDATA[ +<?xml version="1.0"?> + <!-- message catalogue file for locale ... --> + <catalogue xml:lang="locale"> + <message key="key">text</message> + <message key="other_key">Other text</message> + .... + </catalogue>]]></source> + <p>Where <strong>key</strong> attribute specifies a particular message for that language.</p> + </s3> + <s3 title="Usage"> + <p>Files to be translated contain i18n markup. + At runtime, the i18n transformer will find a message catalogue for the + user's locale, and will appropriately replace the text between the + <code><i18n:text></code> markup, using either the value between the tags as + the lookup key or the value of the <code>key</code> attribute if specified. In the latter + case the body value of the tag will be used in case of the not found translation.</p> + <p>If the i18n transformer cannot find an appropriate message catalogue for + the user's given locale, it will recursively try to locate a <em>parent</em> + message catalogue, until a valid catalogue can be found. ie:</p> + <ul> + <li><strong>catalogue</strong>_<em>language</em>_<em>country</em>_<em>variant</em>.xml</li> + <li><strong>catalogue</strong>_<em>language</em>_<em>country</em>.xml</li> + <li><strong>catalogue</strong>_<em>language</em>.xml</li> + <li><strong>catalogue</strong>.xml</li> + </ul> + <p> + eg: Assuming a basename of <em>messages</em> and a locale of <em>en_AU</em> + (no variant), the following search will occur:</p> + <ul> + <li><strong>messages</strong>_<em>en</em>_<em>AU</em>.xml</li> + <li><strong>messages</strong>_<em>en</em>.xml</li> + <li><strong>messages</strong>.xml</li> + </ul> + <p>This allows the developer to write a hierarchy of message catalogues, + at each defining messages with increasing depth of variation.</p> + </s3> + </s2> + <s2 title="Sitemap configuration"> + <source><![CDATA[ +<map:transformer name="i18n" + src="org.apache.cocoon.transformation.I18nTransformer"> + + <catalogue-name>messages</catalogue-name> + <catalogue-location>translations</catalogue-location> + <untranslated-text>untranslated</untranslated-text> + <cache-at-startup>true</cache-at-startup> +</map:transformer>]]></source> + <p>where:</p> + <ul> + <li><strong>catalogue-name</strong>: base name of the message + catalogue (<em>mandatory</em>).</li> + <li><strong>catalogue-location</strong>: location of the + message catalogues (<em>mandatory</em>).</li> + <li><strong>untranslated-text</strong>: text used for + untranslated keys (default is to output the key name).</li> + <li><strong>cache-at-startup</strong>: flag whether to cache + messages at startup (false by default).</li> + </ul> + <p>To use the transformer in a pipeline, simply specify it in a particular transform and indicate the needed locale. eg:</p> + <source><![CDATA[ <map:match pattern="file"> - <map:generate src="{1}"/> - <map:transform type="i18n"> - <parameter name="available_lang_1" value="en"/> - <parameter name="available_lang_2" value="ru"/> - <parameter name="src" value="translations/dictionary.xml"/> - </map:transform> - <map:transform src="stylesheet.xsl"/> - <map:serialize /> + <map:generate src="file.xml"/> + <map:transform type="i18n"> + <map:parameter name="locale" value="en_AU" + </map:transform> + <map:serialize/> </map:match>]]></source> + <note>Note, that since Cocoon version 2.0.1 you should specify the needed locale as a parameter at pipeline level. This gives more flexibility in locale selection, e.g. URI parts can be used: <code>/en_AU/file</code>. See LocaleAction documentation for other possibilities.</note> + <p>Also, <strong>catalogue-name</strong>, <strong>catalogue-location</strong> + and <strong>untranslated-text</strong> can all be overridden at the + pipeline level by specifying them as parameters to the transform statement.</p> </s2> - <s2 title="Simple i18n file"> - <p> - To use i18n pages you will need to declare the i18n namespace in your src - files and wrap all i18n text by <code><![CDATA[<i18n:text>]]></code> tags. - To translate attributes of an element, add an additional attribute named 'i18n:attr' containing a list of - attributes, which should be translated, separated by spaces. - </p> - <source><![CDATA[ -<?xml version="1.0" encoding="UTF-8"?> -<root xmlns:i18n="http://apache.org/cocoon/i18n/2.0"> - <elem title="main_title" i18n:attr="title"> - <i18n:text>Text to be translated</i18n:text> - </elem> -</root>]]> - </source> + </s1> + <s1 title="Samples"> <p> - A more interesting example of usage you can find in the samples/i18n directory. + i18n samples from Cocoon demonstrate all the features of i18n transformer and give some ideas on user's locale determination. </p> - </s2> - <note> - To make attribute translation work the newer than 1.3.0 version of Xerces is needed, where the removeAttribute() - bug is fixed. - </note> </s1> <s1 title="Usage Pattern for Dictionary Generator Stylesheet"> <p> - Description is given for a real world example: - To correct/add Spanish translation in/to an existing dictionary: + It is sometimes better to maintain a master dictionary that contains + all the keys with translations in all the supported languages. For this purposes several helper stylesheets can be used. + The stylesheets are found in Cocoon sources: <code>src/resources/dev/i18n</code> (in version 2.1 and higher).<br/> + Below is given an example for a new language addition using a master dictionary. </p> - <s2 title="Key generation"> + <s2 title="Initial key generation"> + <p>To generate all the i18n keys from a source file (XML or XSP) use the <strong>markup2message.xsl</strong> stylesheet. Simply transform your content file using this stylesheet. Result will be an empty message catalogue for the given language.</p> + </s2> + <s2 title="Key generation from master dictionary"> <p> - Generate a dictionary with keys and placeholders for Spanish translations. - Optionally, for one of the languages existing translations can be kept. + Generate a dictionary with keys and placeholders for Spanish translations using the <strong>merge.xsl</strong> stylesheet. Optionally, for one of the languages existing translations can be kept. To do it set stylesheet params (manually in stylesheet or in command-line): - mode = keys (indicates, that only keys must be in result) - new-lang = es (language to be added) - keep-lang = en (language to be kept in result, for convenience) - + </p> + <ul> + <li><strong>mode = keys</strong> (indicates, that only keys must be in result)</li> + <li><strong>new-lang = es </strong> (language to be added)</li> + <li><strong>keep-lang = en </strong> (language to be kept in result, for convenience)</li> + </ul> + <p> Command line for Xalan (Of course, Xerces and Xalan must be in your classpath): </p> <source><![CDATA[ @@ -349,11 +376,8 @@ translations, if they were kept during generation. </p> </s2> - <s2 title="Add to the original dictionary"> + <s2 title="Add to the master dictionary"> <p> - (Note. This step will be unnecessary when multiple dictionary - support will be implemented. Hope, this will be soon) - Use the same stylesheet for this purpose with this params: </p> <source><![CDATA[ @@ -376,15 +400,16 @@ <s1 title="Finally"> <s2 title="To be done"> <ul> - <li>Multiple dictionary support</li> - <li>Dictionary import and include capabilities (like in XSLT)</li> - <li>Command line dictionary-from-source generation</li> + <li>Multiple dictionaries per pipeline support</li> + <li>Markup support in translations</li> + <li>Named parameters support</li> <li>Dictionary caching</li> + <li>Different bundle implementations</li> </ul> </s2> <s2 title="Contacts"> <p> - Feel free to contact for any comments and improvement ideas either directly <link href="mailto:[EMAIL PROTECTED]">Konstantin Piroumian</link> + Feel free to contact for any comments and improvement ideas either directly <link href="mailto:[EMAIL PROTECTED]">Konstantin Piroumian</link> or through the <link href="../../mail-lists.html">Cocoon Mail List</link>. </p> </s2>
---------------------------------------------------------------------- In case of troubles, e-mail: [EMAIL PROTECTED] To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]