cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Mike Engelhart <mengelh...@earthtrip.com>
Subject ResourceBundles - was [RT] i18n
Date Mon, 12 Jun 2000 15:45:12 GMT
I've been following the i18n thread and last night had a few minutes to whip
up some code. 

Here's my thoughts (I guess "random" thoughts :-))

1)  We all like XML for configuration.  Properties are OK but XML is better
and portable.
2)  I've been using ResourceBundle's a lot and like them for several reasons
some of which are that they've already been developed (my personal
favorite), they're debugged, they're standard Java and really easy to use
and caching is handled automatically so they only get loaded once by the
classloader

i've been using PropertyResourceBundle's in my code but have wanted an XML
based solution. My suggestion is this (please remove code and ideas that
suck and replace them with better code & ideas that don't suck).  Also be
advised that I have not even looked at C2 yet so my understanding of the
sitemap is basically non-existant so I didn't try and integrate this within
the C2 architecture.. :-(  This is solely to allow us to use XML documents
but still get all the ResourceBundle qualities that are cool.

anyway, we define an i18n directory in the sitemap where langauge based XML
documents reside using standard naming conventions for the documents, e.g.,
lang.xml, lang_en.xml, lang_es.xml, etc. (the default file being lang.xml
with no suffix that is used when an attempt to use a language that doesn't
have an associated ResourceBundle is made).

Then use the following class, I'm calling it CocoonResourceBundle which
reads in XML files of the following format (again replace XML that sucks
with XML that doesn't suck).
<!-- lang_en.xml -->
<?xml version="1.0"?>
<document xml:lang="en">
    <word>
        <key>_DATE</key>
        <value>Date</value>
    </word>
    <word>
        <key>_TIME</key>
        <value>Time</value>
    </word>
</document>

<!-- lang_es.xml -->
<?xml version="1.0"?>
<document xml:lang="es">
  <word>
    <key>_DATE</key>
    <value>Dia</value>
  </word>

  <word>
    <key>_TIME</key>
    <value>Tiempo</value>
  </word>
</document>

Here's the code for CocoonResourceBundle.  It extends
java.util.ListResourceBundle which itself subclasses
java.util.ResourceBundle.
This allows for us to customize the filling in of the "contents" array with
the XML based language file.



/** JDK classes **/
import java.io.IOException;
import java.util.ListResourceBundle;

/** W3C DOM classes **/
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/** xerces classes **/
import org.apache.xerces.dom.TextImpl;
import org.apache.xerces.parsers.DOMParser;
import org.xml.sax.SAXException;

public class CocoonResourceBundle extends ListResourceBundle
{
    public CocoonResourceBundle()
    {
        super();
        try
        {
            setContents();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
    
    public Object[][] getContents()
    {
        return this.contents;
    }

    private void setContents() throws IOException, SAXException
    {
        DOMParser parser = new DOMParser();
        parser.parse("lang.xml");
        Document doc = parser.getDocument();
        Element e = doc.getDocumentElement();
        NodeList nodes = e.getElementsByTagName("word");
        int numberNodes = nodes.getLength();

        contents = new Object[numberNodes][2];
        
        for (int i = 0; i < numberNodes; i++)
        {
            Node node = nodes.item(i);
            contents[i][0] = getTextNodeData((Element) node, "key");
            contents[i][1] = getTextNodeData((Element) node, "value");
        }
    }
    
    
    public String getTextNodeData(Element element, String elementName)
    {
        NodeList nodes = element.getElementsByTagName(elementName);
        if (nodes.getLength() < 1)
            return "";
        Node node = nodes.item(0).getFirstChild();
        if (node.getNodeType() == Node.TEXT_NODE)
            return ((TextImpl) node).getData();
        else
            return "";
    }

    static Object[][] contents;
}

Then in XSP code or anywhere else in C2 you can do these kinds of accesses
(pseudo code follows)

<xsp:page>
    <document>
        <xsp:logic>
            Locale loc = request.getLocale();
            java.util.ResourceBundle bundle =
ResourceBundle.getBundle("org.apache.CocoonResourceBundle", loc);
        </xsp:logic>
        <!-- do something useful -->
        <p><xsp:expr>The word for 'Date' in your browsers default locale is
<xsp:expr>bundle.getString("_DATE")</xsp:expr></p >
    </document>
<xsp:page>

I'm not sure if this is possible but can we have Cocoon 2 (on startup) scan
the pre-defined language repository for files and then create classes on the
fly for each language?  Otherwise you need separate object code for each
language like CocoonResourceBundle_en.java, CocoonResouceBundle_es.java,
etc.   That's just how ResourceBundle's are designed.  If we could do this
without hardcoding the path names to the lang.xml files, that would be
ideal.  Again, this is just a concept so there is more work to do to get
this to work within C2 but it seems like a relatively simple solution that
gives us both of the best worlds.

Mike


Mime
View raw message