kpiroumian 2004/01/15 07:24:32
Modified: src/java/org/apache/cocoon/i18n BundleFactory.java
XMLResourceBundleFactory.java
src/java/org/apache/cocoon/transformation
I18nTransformer.java
src/webapp/samples/i18n menu.xml simple.xml simple2page.xsl
sitemap.xmap
Added: src/webapp/samples/i18n tiered.xml
src/webapp/samples/i18n/translations/tiered messages_en.xml
messages_ru.xml
Log:
Add 'tiered' dictionary lookup.
Thanks to Ralph Goers <[EMAIL PROTECTED]>
Revision Changes Path
1.7 +13 -1
cocoon-2.1/src/java/org/apache/cocoon/i18n/BundleFactory.java
Index: BundleFactory.java
===================================================================
RCS file:
/home/cvs/cocoon-2.1/src/java/org/apache/cocoon/i18n/BundleFactory.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- BundleFactory.java 23 Dec 2003 15:28:33 -0000 1.6
+++ BundleFactory.java 15 Jan 2004 15:24:31 -0000 1.7
@@ -103,6 +103,18 @@
Bundle select(String base, String bundleName, Locale locale) throws
ComponentException;
/**
+ * Select a bundle based on the catalogue base location, bundle name,
+ * and the locale.
+ *
+ * @param directories catalogue base location (URI)
+ * @param bundleName bundle name
+ * @param locale locale
+ * @return the bundle
+ * @exception ComponentException if a bundle is not found
+ */
+ Bundle select(String[] directories, String bundleName, Locale locale)
throws ComponentException;
+
+ /**
* Select a bundle based on the bundle name and the locale name from
* the default catalogue.
*
1.9 +57 -37
cocoon-2.1/src/java/org/apache/cocoon/i18n/XMLResourceBundleFactory.java
Index: XMLResourceBundleFactory.java
===================================================================
RCS file:
/home/cvs/cocoon-2.1/src/java/org/apache/cocoon/i18n/XMLResourceBundleFactory.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- XMLResourceBundleFactory.java 23 Dec 2003 15:28:33 -0000 1.8
+++ XMLResourceBundleFactory.java 15 Jan 2004 15:24:31 -0000 1.9
@@ -68,6 +68,7 @@
import org.apache.avalon.framework.service.Serviceable;
import org.apache.avalon.framework.thread.ThreadSafe;
import org.apache.excalibur.source.SourceNotFoundException;
+import org.apache.cocoon.ResourceNotFoundException;
import org.xml.sax.SAXParseException;
/**
@@ -121,7 +122,7 @@
public void enableLogging(Logger logger) {
this.logger = logger;
}
-
+
public Logger getLogger() {
return this.logger;
}
@@ -232,56 +233,75 @@
* @exception ComponentException if a bundle is not found
*/
public Bundle select(String directory, String name, Locale locale)
throws ComponentException {
- Bundle bundle = _select(directory, name, locale);
- if (bundle == null) {
- throw new ComponentException(name, "Unable to locate resource: "
+ name);
- }
- return bundle;
+ String []directories = new String[1];
+ directories[0] = directory;
+ return select(directories, name, locale);
}
/**
- * Select the parent bundle of the current bundle, based on
- * bundle name and locale.
+ * Select a bundle based on the catalogue base location, bundle name,
+ * and the locale.
*
- * @param name bundle name
- * @param locale locale
- * @return the bundle
+ * @param directories catalogue base location (URI)
+ * @param name bundle name
+ * @param locale locale
+ * @return the bundle
+ * @exception ComponentException if a bundle is not found
*/
- protected Component selectParent(String name, Locale locale) {
- return _select(getDirectory(), name, getParentLocale(locale));
+ public Bundle select(String[] directories, String name, Locale locale)
+ throws ComponentException {
+ Bundle bundle = _select(directories, 0, name, locale);
+ if (bundle == null) {
+ throw new ComponentException(name, "Unable to locate resource: "
+ name);
+ }
+ return bundle;
}
/**
* Select a bundle based on bundle name and locale.
*
- * @param base catalogue location
+ * @param directories catalogue location(s)
* @param name bundle name
* @param locale locale
* @return the bundle
*/
- private Bundle _select(String base, String name, Locale locale) {
- String fileName = getFileName(base, name, locale);
+ private XMLResourceBundle _select(String[] directories, int index,
String name,
+ Locale locale) {
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("selecting from: " + name + ", locale: " +
locale +
+ ", directory: " + directories[index]);
+ }
+ String fileName = getFileName(directories[index], name, locale);
XMLResourceBundle bundle = (XMLResourceBundle)selectCached(fileName);
- if (bundle == null && !isNotFoundBundle(fileName)) {
+ if (bundle == null) {
synchronized (this) {
bundle = (XMLResourceBundle)selectCached(fileName);
- if (bundle == null && !isNotFoundBundle(fileName)) {
- bundle = _loadBundle(name, fileName, locale);
-
- while (bundle == null && locale != null &&
!locale.getLanguage().equals("")) {
- if (getLogger().isDebugEnabled()) {
- getLogger().debug("Bundle '" + fileName + "' not
found; trying parent");
+ if (bundle == null) {
+ XMLResourceBundle parentBundle = null;
+ if (locale != null && !locale.getLanguage().equals("")) {
+ if (++index == directories.length)
+ {
+ parentBundle = _select(directories, 0, name,
getParentLocale(locale));
}
- locale = getParentLocale(locale);
- String parentFileName = getFileName(base, name,
locale);
- bundle = _loadBundle(name, parentFileName, locale);
+ else
+ {
+ parentBundle = _select(directories, index, name,
locale);
+ }
+ }
+
+ if (!isNotFoundBundle(fileName)) {
+ bundle = _loadBundle(name, fileName, locale,
parentBundle);
+
+ updateCache(fileName, bundle);
+ }
+
+ if (bundle == null) {
+ return parentBundle;
}
-
- updateCache(fileName, bundle);
}
}
}
-
+
return bundle;
}
@@ -293,26 +313,26 @@
* @param locale locale
* @return the bundle, null if loading failed
*/
- private XMLResourceBundle _loadBundle(String name, String fileName,
Locale locale) {
+ private XMLResourceBundle _loadBundle(String name, String fileName,
Locale locale,
+ XMLResourceBundle parentBundle) {
if (getLogger().isDebugEnabled()) {
getLogger().debug("Loading bundle: " + name + ", locale: " +
locale +
", uri: " + fileName);
}
XMLResourceBundle bundle = null;
- XMLResourceBundle parentBundle = null;
try {
- if (locale != null && !locale.getLanguage().equals("")) {
- parentBundle = (XMLResourceBundle)selectParent(name, locale);
- }
bundle = new XMLResourceBundle();
bundle.enableLogging(this.logger);
bundle.service(this.manager);
bundle.init(name, fileName, locale, parentBundle);
return bundle;
+ } catch (ResourceNotFoundException e) {
+ getLogger().info("Resource not found: " + name + ", locale: " +
locale +
+ ", bundleName: " + fileName + ". Exception: " +
e.toString());
} catch (SourceNotFoundException e) {
getLogger().info("Resource not found: " + name + ", locale: " +
locale +
- ", bundleName: " + fileName + ". Exception: " +
e.getMessage());
+ ", bundleName: " + fileName + ". Exception: " +
e.toString());
} catch (SAXParseException e) {
getLogger().error("Incorrect resource format", e);
} catch (Exception e) {
@@ -359,7 +379,7 @@
if (base == null) {
base = "";
}
-
+
StringBuffer sb = new StringBuffer(base);
if (!base.endsWith("/")) {
sb.append('/').append(name);
1.23 +114 -30
cocoon-2.1/src/java/org/apache/cocoon/transformation/I18nTransformer.java
Index: I18nTransformer.java
===================================================================
RCS file:
/home/cvs/cocoon-2.1/src/java/org/apache/cocoon/transformation/I18nTransformer.java,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- I18nTransformer.java 14 Jan 2004 00:51:15 -0000 1.22
+++ I18nTransformer.java 15 Jan 2004 15:24:31 -0000 1.23
@@ -102,7 +102,7 @@
* [EMAIL PROTECTED]
org.apache.cocoon.acting.LocaleAction#getLocaleAttribute(Map, String) } for
details.
* It then attempts to find a <strong>message catalogue</strong> that
satisifies
* the particular locale, and use it for for text replacement within i18n
markup.
- *
+ *
* <p>Catalogues are maintained in separate files, with a naming convention
* similar to that of ResourceBundle (See java.util.ResourceBundle).
* ie.
@@ -155,6 +155,21 @@
* This allows the developer to write a hierarchy of message catalogues,
* at each defining messages with increasing depth of variation.
*
+ * In addition, catalogues can be split across multiple locations. For
example,
+ * there can be a default catalogue in one directory with a user or client
specific
+ * catalogue in another directory. The catalogues will be searched in the
order of
+ * the locations specified still following the locale ordering specified
above.
+ * eg: Assuming a basename of <i>messages</i> and a locale of <i>en_AU</i>
+ * (no variant) and locations of <i>translations/client</i> and
<i>translations</i>,
+ * the following search will occur:
+ * <ul>
+ *
<li><i>translations/client/</i><strong>messages</strong>_<i>en</i>_<i>AU</i>.xml
+ *
<li><i>translations/</i><strong>messages</strong>_<i>en</i>_<i>AU</i>.xml
+ * <li><i>translations/client/</i><strong>messages</strong>_<i>en</i>.xml
+ * <li><i>translations/</i><strong>messages</strong>_<i>en</i.xml
+ * <li><i>translations/client/</i><strong>messages</strong>.xml
+ * <li><i>translations/</i><strong>messages</strong>.xml
+ *
* <p>The i18n:text element can optionally take an attribute
<strong>i18n:catalogue</strong>
* to specify a specific catalogue to use. The value of this attribute
should be
* the id of the catalogue to use (see sitemap configuration).
@@ -165,7 +180,10 @@
* src="org.apache.cocoon.transformation.I18nTransformer">
*
* <catalogues default="someId">
- * <catalogue id="someId" name="messages"
location="translations">
+ * <catalogue id="someId" name="messages"
[location="translations"]>
+ * [<location>translations/client</location>]
+ * [<location>translations</location>]
+ * </catalogue>
* </catalogues>
* <untranslated-text>untranslated</untranslated-text>
* <cache-at-startup>true</cache-at-startup>
@@ -175,19 +193,26 @@
* <li><strong>catalogues</strong>: container element in which the
catalogues
* are defined. It must have an attribute 'default' whose value is one
* of the id's of the catalogue elements. (<i>mandatory</i>).
- * <li><strong>catalogue</strong>: specifies a catalogue. It takes 3
required
- * attributes: id (can be wathever you like), name (base name of the
catalogue)
- * and location (location of the message catalogue). The name and
location attributes
- * can contain references to inputmodules (same syntax as in other
places in the
+ * <li><strong>catalogue</strong>: specifies a catalogue. It takes 2
required
+ * attributes: id (can be wathever you like) and name (base name of the
catalogue).
+ * The location (location of the message catalogue) is also required,
but can be
+ * specified either as an attribute or as one or more subelements, but
not both.
+ * If more than one location is specified the catalogues will be
searched in the
+ * order they appear in the configuration. The name and location can
contain
+ * references to inputmodules (same syntax as in other places in the
* sitemap). They are resolved on each usage of the transformer, so
they can
* refer to e.g. request parameters. (<i>at least 1 catalogue
- * element required</i>).
+ * element required</i>). After input module references are resolved
the location
+ * string can be the root of a URI. For example, specifying a location
of
+ * cocoon:/test with a name of messages and a locale of en_GB will
cause the
+ * sitemap to try to process cocoon:/test/messages_en_GB.xml,
+ * cocoon:/test/messages_en.xml and cocoon:/test/messages.xml.
* <li><strong>untranslated-text</strong>: text used for
* untranslated keys (default is to output the key name).
* <li><strong>cache-at-startup</strong>: flag whether to cache
* messages at startup (false by default).
* </ul>
- *
+ *
* <p><strong>NOTE:</strong> before using multiple catalogues was supported,
* the catalogue name and location was specified using elements named
* <code>catalogue-name</code> and <code>catalogue-location</code>. This
syntax is
@@ -305,8 +330,8 @@
public static final String I18N_TRANSLATE_ELEMENT = "translate";
/**
- * <strong>i18n:choose<strong> element is used to translate elements
in-place.
- * The first <strong>i18n:when<strong> element matching the current
locale
+ * <strong>i18n:choose</strong> element is used to translate elements
in-place.
+ * The first <strong>i18n:when</strong> element matching the current
locale
* is selected and the others are discarded.
*
* <p>To specify what to do if no locale matched, simply add a node with
@@ -526,7 +551,7 @@
public static final String I18N_NUMBER_ELEMENT = "number";
/**
- * Currency element name
+ * Currency element name
*/
public static final String I18N_CURRENCY_ELEMENT = "currency";
@@ -721,7 +746,7 @@
//
// States of the transformer
//
-
+
private static final int STATE_OUTSIDE = 0;
private static final int STATE_INSIDE_TEXT = 10;
private static final int STATE_INSIDE_PARAM = 20;
@@ -817,7 +842,7 @@
//
// Current state of the transformer
//
-
+
protected Map objectModel;
/**
@@ -905,7 +930,7 @@
CatalogueInfo catalogueInfo =
(CatalogueInfo)catalogues.get(defaultCatalogueId);
StringBuffer key = new StringBuffer();
if (catalogueInfo != null) {
- key.append(catalogueInfo.resolvedLocation);
+ key.append(catalogueInfo.getLocation()[0]);
}
key.append("?");
if (locale != null) {
@@ -956,10 +981,46 @@
for (int i = 0; i < catalogueConfs.length; i++) {
String id = catalogueConfs[i].getAttribute("id");
String name = catalogueConfs[i].getAttribute("name");
- String location = catalogueConfs[i].getAttribute("location");
+ String[] locations = null;
+ String location = catalogueConfs[i].getAttribute("location",
null);
+ Configuration[] locationConf =
+ catalogueConfs[i].getChildren("location");
+ if (location != null) {
+ if (locationConf.length > 0) {
+ String msg = "I18nTransformer: location attribute cannot
be " +
+ "specified with location elements";
+ getLogger().error(msg);
+ throw new ConfigurationException(msg);
+ }
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("I18nTransformer: name=" + name + ",
location=" +
+ location);
+ }
+ locations = new String[1];
+ locations[0] = location;
+ }
+ else
+ {
+ if (locationConf.length == 0) {
+ String msg = "I18nTransformer: A location attribute or
location " +
+ "elements must be specified";
+ getLogger().error(msg);
+ throw new ConfigurationException(msg);
+ }
+
+ locations = new String[locationConf.length];
+ for (int j=0; j < locationConf.length; ++j) {
+ locations[j] = locationConf[j].getValue();
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("I18nTransformer: name=" + name +
", location=" +
+ locations[j]);
+ }
+ }
+
+ }
CatalogueInfo newCatalogueInfo;
try {
- newCatalogueInfo = new CatalogueInfo(name, location);
+ newCatalogueInfo = new CatalogueInfo(name, locations);
} catch (PatternException e) {
throw new ConfigurationException("I18nTransformer: error in
name or location " +
"attribute on catalogue
element with id " + id, e);
@@ -1161,7 +1222,7 @@
if (getLogger().isDebugEnabled()) {
getLogger().debug("Start i18n element: " + name);
- }
+ }
if (I18N_TEXT_ELEMENT.equals(name)) {
if (current_state != STATE_OUTSIDE
@@ -1575,7 +1636,7 @@
if (getLogger().isDebugEnabled()) {
getLogger().debug("Translation not found for key
'" + current_key + "'");
}
-
+
// Use the untranslated-text only when the content
of the i18n:text
// element was empty
if (text_recorder.isEmpty() && untranslatedRecorder
!= null) {
@@ -2020,6 +2081,9 @@
* @return SaxBuffer containing message, or null if not found.
*/
private ParamSaxBuffer getMessage(String catalogueID, String key) {
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("Getting key " + key + " from catalogue " +
catalogueID);
+ }
try {
Bundle catalogue = defaultCatalogue;
if (catalogueID != null) {
@@ -2068,7 +2132,7 @@
* A default value is returned if message is not found.
*
* @return SaxBuffer containing message, or defaultValue if not found.
- */
+ */
private ParamSaxBuffer getMessage(String key, ParamSaxBuffer
defaultValue) {
SaxBuffer value = getMessage(currentCatalogueId, key);
if (value == null) {
@@ -2111,27 +2175,47 @@
*/
private final class CatalogueInfo {
PreparedVariableResolver name;
- PreparedVariableResolver location;
+ PreparedVariableResolver[] locations;
String resolvedName;
- String resolvedLocation;
+ String[] resolvedLocations;
Bundle catalogue;
- public CatalogueInfo(String name, String location) throws
PatternException {
+ public CatalogueInfo(String name, String[] locations) throws
PatternException {
this.name = new PreparedVariableResolver(name, manager);
- this.location = new PreparedVariableResolver(location, manager);
+ this.locations = new PreparedVariableResolver[locations.length];
+ for (int i=0; i < locations.length; ++i) {
+ this.locations[i] = new
PreparedVariableResolver(locations[i], manager);
+ }
}
public String getName() {
+ try {
+ if (resolvedName == null) {
+ resolve();
+ }
+ } catch (Exception e) {
+ // Ignore the error for now
+ }
return resolvedName;
}
- public String getLocation() {
- return resolvedLocation;
+ public String[] getLocation() {
+ try {
+ if (resolvedName == null) {
+ resolve();
+ }
+ } catch (Exception e) {
+ // Ignore the error for now
+ }
+ return resolvedLocations;
}
private void resolve() throws Exception {
- if (resolvedLocation == null) {
- resolvedLocation = location.resolve(null, objectModel);
+ if (resolvedLocations == null) {
+ resolvedLocations = new String[locations.length];
+ for (int i=0; i < resolvedLocations.length; ++i) {
+ resolvedLocations[i] = locations[i].resolve(null,
objectModel);
+ }
}
if (resolvedName == null) {
resolvedName = name.resolve(null, objectModel);
@@ -2141,7 +2225,7 @@
public Bundle getCatalogue() throws Exception {
if (catalogue == null) {
resolve();
- catalogue = factory.select(resolvedLocation, resolvedName,
locale);
+ catalogue = factory.select(resolvedLocations, resolvedName,
locale);
}
return catalogue;
}
@@ -2152,7 +2236,7 @@
}
catalogue = null;
resolvedName = null;
- resolvedLocation = null;
+ resolvedLocations = null;
}
}
}
1.8 +1 -0 cocoon-2.1/src/webapp/samples/i18n/menu.xml
Index: menu.xml
===================================================================
RCS file: /home/cvs/cocoon-2.1/src/webapp/samples/i18n/menu.xml,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- menu.xml 12 May 2003 13:47:38 -0000 1.7
+++ menu.xml 15 Jan 2004 15:24:31 -0000 1.8
@@ -14,6 +14,7 @@
<menu-item label="Dynamic (XSP)" href="simple.xsp" i18n:attr="label"/>
<menu-item label="Sitemap source" href="sitemap.xmap"
i18n:attr="label"/>
<menu-item label="Multi catalogues" href="multi.xml" i18n:attr="label"/>
+ <menu-item label="Tiered catalogues" href="tiered.xml"
i18n:attr="label"/>
<menu-item label="Back" href=".." i18n:attr="label"/>
</menu>
1.6 +1 -1 cocoon-2.1/src/webapp/samples/i18n/simple.xml
Index: simple.xml
===================================================================
RCS file: /home/cvs/cocoon-2.1/src/webapp/samples/i18n/simple.xml,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- simple.xml 9 Dec 2003 21:33:10 -0000 1.5
+++ simple.xml 15 Jan 2004 15:24:31 -0000 1.6
@@ -23,7 +23,7 @@
<content>
<i18n:if locale="ru">
<para title="ru" name="i18n:when">
- <i>Этот текст отображается только для
<strong>русского</strong> языка.</i>
+ Этот текст отображается только для
<strong>русского</strong> языка.
</para>
</i18n:if>
1.3 +1 -1 cocoon-2.1/src/webapp/samples/i18n/simple2page.xsl
Index: simple2page.xsl
===================================================================
RCS file: /home/cvs/cocoon-2.1/src/webapp/samples/i18n/simple2page.xsl,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- simple2page.xsl 9 Dec 2003 21:35:36 -0000 1.2
+++ simple2page.xsl 15 Jan 2004 15:24:31 -0000 1.3
@@ -59,7 +59,7 @@
<xsl:value-of select="@title"/>
</font>
<br/>
- <xsl:apply-templates select="text() | strong"/>
+ <xsl:apply-templates select="text() | strong | i"/>
</p>
</xsl:template>
1.8 +15 -1 cocoon-2.1/src/webapp/samples/i18n/sitemap.xmap
Index: sitemap.xmap
===================================================================
RCS file: /home/cvs/cocoon-2.1/src/webapp/samples/i18n/sitemap.xmap,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- sitemap.xmap 12 Dec 2003 14:48:43 -0000 1.7
+++ sitemap.xmap 15 Jan 2004 15:24:31 -0000 1.8
@@ -17,6 +17,10 @@
<catalogues default="messages">
<catalogue id="messages" name="messages" location="translations"/>
<catalogue id="menu" name="menu" location="translations"/>
+ <catalogue id="tiered" name="messages"
location="translations/tiered">
+ <location>translations/tiered</location>
+ <location>translations</location>
+ </catalogue>
</catalogues>
<cache-at-startup>true</cache-at-startup>
</map:transformer>
@@ -98,6 +102,16 @@
<!-- Generate dynamic output (simple.xsp) -->
<map:match pattern="*.xsp">
<map:call resource="composite"/>
+ </map:match>
+
+ <!-- A helper matcher for static content translation and generation
-->
+ <map:match pattern="content/tiered.xml">
+ <map:generate src="tiered.xml"/>
+ <map:transform type="i18n">
+ <map:parameter name="default-catalogue-id" value="tiered"/>
+ <map:parameter name="locale" value="{../locale}"/>
+ </map:transform>
+ <map:serialize/>
</map:match>
<!-- A helper matcher for static content translation and generation
-->
1.1 cocoon-2.1/src/webapp/samples/i18n/tiered.xml
Index: tiered.xml
===================================================================
<?xml version="1.0" encoding="UTF-8"?>
<document xmlns:i18n="http://apache.org/cocoon/i18n/2.1"
i18n:attr="language"
language="language">
<title>
<i18n:text>titletext</i18n:text>
</title>
<sub-title>
<i18n:date-time pattern="FULL"/>
</sub-title>
<annotation>
<i18n:translate>
<i18n:text key="doclink"/>
<i18n:param>
<link
href="http://cocoon.apache.org/2.1/userdocs/transformers/i18n-transformer.html">Cocoon
2 Web Site</link>
</i18n:param>
</i18n:translate>
</annotation>
<content>
<i18n:if locale="ru">
<para title="ru" name="i18n:when">
Этот текст отображается только для
<strong>русского</strong> языка.
</para>
</i18n:if>
<para title="first" name="article" i18n:attr="title name">
<i18n:text key="a_key">article_text1</i18n:text>
</para>
<para title="second" name="article" i18n:attr="title name">
<i18n:text>article_text2</i18n:text>
</para>
<para title="third" name="article" i18n:attr="title name">
<i18n:translate>
<i18n:text key="Hello"/>
<i18n:param>
<strong><i18n:text>Kot</i18n:text></strong>
</i18n:param>
</i18n:translate>
</para>
<para title="forth" name="article" i18n:attr="title name">
<i18n:translate>
One = {one}, two = {two}, {third}!
{forth} This line is not translated {forth}.
No{fifth}thing here.
<i18n:param name="one"><i18n:text>one</i18n:text></i18n:param>
<i18n:param name="two"><i18n:text>two</i18n:text></i18n:param>
<i18n:param name="third">baby</i18n:param>
<i18n:param name="forth"> ~ </i18n:param>
</i18n:translate>
</para>
<para title="Number formatting (not translated)" name="article"
i18n:attr="name">
<i18n:translate>
Number: {0} | Currency: {1} | Percent: {2} | Processed on: {3}
<!--Old format: i18n:param type="number" src-locale="en"
value="1703.74" /-->
<i18n:param><i18n:number src-locale="en"
value="1703.74"/></i18n:param>
<!--Old format: i18n:param type="currency"
src-locale="en">27.24</i18n:param-->
<i18n:param><i18n:number type="currency" src-locale="en"
value="27.24"/></i18n:param>
<i18n:param><i18n:number type="percent" src-locale="en"
value="1.2"/></i18n:param>
<i18n:param><i18n:date-time pattern="MEDIUM"/></i18n:param>
</i18n:translate>
</para>
</content>
<bottom>
<copyright>
<i18n:text>copyright</i18n:text>
</copyright>
</bottom>
</document>
1.1
cocoon-2.1/src/webapp/samples/i18n/translations/tiered/messages_en.xml
Index: messages_en.xml
===================================================================
<?xml version="1.0" encoding="UTF-8"?>
<!--+
| English override message catalogue file for Cocoon 2 i18n sample
|
| CVS $Id: messages_en.xml,v 1.1 2004/01/15 15:24:32 kpiroumian Exp $
+-->
<catalogue xml:lang="en">
<message key="a_key">This is a tiered key value.</message>
</catalogue>
1.1
cocoon-2.1/src/webapp/samples/i18n/translations/tiered/messages_ru.xml
Index: messages_ru.xml
===================================================================
<?xml version="1.0" encoding="UTF-8"?>
<!--+
| Russian override message catalogue file for Cocoon 2 i18n sample
|
| CVS $Id: messages_ru.xml,v 1.1 2004/01/15 15:24:32 kpiroumian Exp $
+-->
<catalogue xml:lang="ru">
<message key="a_key">Это локально перекрытое
значение по ключу.</message>
</catalogue>