From e0cac7c756f6625a97f421c3a51ed58be85e1dcd Mon Sep 17 00:00:00 2001
From: maroy <maroy@cfc7b370-4200-0410-a6e3-cb6bdb053afe>
Date: Mon, 22 Nov 2004 10:30:12 +0000
Subject: [PATCH] added LocalizedObject base class, with one known failing test

---
 livesupport/modules/core/doc/.keepme          |   1 +
 livesupport/modules/core/etc/Makefile.in      |  42 +++-
 .../LiveSupport/Core/LocalizedObject.h        | 149 ++++++++++++++
 .../modules/core/src/LocalizedObject.cxx      |  87 ++++++++
 .../modules/core/src/LocalizedObjectTest.cxx  | 189 ++++++++++++++++++
 .../modules/core/src/LocalizedObjectTest.h    | 126 ++++++++++++
 livesupport/modules/core/var/.keepme          |   1 +
 livesupport/modules/core/var/en.txt           |   7 +
 livesupport/modules/core/var/hu.txt           |   9 +
 livesupport/modules/core/var/jp.txt           |   9 +
 livesupport/modules/core/var/root.txt         |   9 +
 11 files changed, 621 insertions(+), 8 deletions(-)
 create mode 100644 livesupport/modules/core/doc/.keepme
 create mode 100644 livesupport/modules/core/include/LiveSupport/Core/LocalizedObject.h
 create mode 100644 livesupport/modules/core/src/LocalizedObject.cxx
 create mode 100644 livesupport/modules/core/src/LocalizedObjectTest.cxx
 create mode 100644 livesupport/modules/core/src/LocalizedObjectTest.h
 create mode 100644 livesupport/modules/core/var/.keepme
 create mode 100644 livesupport/modules/core/var/en.txt
 create mode 100644 livesupport/modules/core/var/hu.txt
 create mode 100644 livesupport/modules/core/var/jp.txt
 create mode 100644 livesupport/modules/core/var/root.txt

diff --git a/livesupport/modules/core/doc/.keepme b/livesupport/modules/core/doc/.keepme
new file mode 100644
index 000000000..e0808fa16
--- /dev/null
+++ b/livesupport/modules/core/doc/.keepme
@@ -0,0 +1 @@
+keep me
diff --git a/livesupport/modules/core/etc/Makefile.in b/livesupport/modules/core/etc/Makefile.in
index 82a38e40b..7da4d305c 100644
--- a/livesupport/modules/core/etc/Makefile.in
+++ b/livesupport/modules/core/etc/Makefile.in
@@ -21,7 +21,7 @@
 #
 #
 #   Author   : $Author: maroy $
-#   Version  : $Revision: 1.12 $
+#   Version  : $Revision: 1.13 $
 #   Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/etc/Makefile.in,v $
 #
 #   @configure_input@
@@ -39,6 +39,8 @@ DOXYGEN = doxygen
 #-------------------------------------------------------------------------------
 #   Basic directory and file definitions
 #-------------------------------------------------------------------------------
+PACKAGE_NAME = @PACKAGE_NAME@
+
 BASE_DIR     = @builddir@
 DOC_DIR      = ${BASE_DIR}/doc
 DOXYGEN_DIR  = ${DOC_DIR}/doxygen
@@ -48,15 +50,27 @@ INCLUDE_DIR  = ${BASE_DIR}/include
 LIB_DIR      = ${BASE_DIR}/lib
 SRC_DIR      = ${BASE_DIR}/src
 TMP_DIR      = ${BASE_DIR}/tmp
+VAR_DIR      = ${BASE_DIR}/var
 
 USR_DIR         = ${BASE_DIR}/../../usr
 USR_INCLUDE_DIR = ${USR_DIR}/include
+USR_BIN_DIR     = ${USR_DIR}/bin
 USR_LIB_DIR     = ${USR_DIR}/lib
 BOOST_INCLUDE_DIR    = ${USR_INCLUDE_DIR}/boost-1_31
 LIBXMLPP_INCLUDE_DIR = ${USR_INCLUDE_DIR}/libxml++-1.0
 
+GENRB     = ${USR_BIN_DIR}/genrb
+GENRBOPTS = --destdir ${TMP_DIR} \
+            --encoding utf-8 \
+            --package-name ${PACKAGE_NAME} \
+            --strict
+
 VPATH    = ${SRC_DIR}
 
+# TODO: move ICU flag determination to configure script
+ICU_CFLAGS=
+ICU_LIBS=`${USR_DIR}/bin/icu-config --ldflags-toolutil --ldflags-icuio`
+
 TEST_RESULTS = ${DOC_DIR}/testResults.xml
 # the text result XSLT has to be relative to the test result file, e.g. TMP_DIR
 TEST_XSLT    = ../etc/testResultToHtml.xsl
@@ -67,6 +81,8 @@ TEST_RUNNER   = ${TMP_DIR}/testRunner
 
 DOXYGEN_CONFIG = ${ETC_DIR}/doxygen.config
 
+export LD_LIBRARY_PATH=${USR_LIB_DIR}
+
 
 #-------------------------------------------------------------------------------
 #  	Configuration parameters
@@ -74,6 +90,7 @@ DOXYGEN_CONFIG = ${ETC_DIR}/doxygen.config
 CPPFLAGS = @CPPFLAGS@
 CXXFLAGS = @CXXFLAGS@ @DEFS@ @COVERAGE_CXXFLAGS@ \
                              -pedantic -Wall -Wno-long-long \
+                             ${ICU_CFLAGS} \
                              -I${USR_INCLUDE_DIR} \
                              -I${BOOST_INCLUDE_DIR} \
                              -I${LIBXMLPP_INCLUDE_DIR} \
@@ -90,7 +107,8 @@ CORE_LIB_OBJS = ${TMP_DIR}/UniqueId.o \
                 ${TMP_DIR}/PlaylistElement.o \
                 ${TMP_DIR}/Playlist.o \
                 ${TMP_DIR}/TimeConversion.o \
-                ${TMP_DIR}/Thread.o
+                ${TMP_DIR}/Thread.o \
+                ${TMP_DIR}/LocalizedObject.o
 
 TEST_RUNNER_OBJS = ${TMP_DIR}/TestRunner.o \
                    ${TMP_DIR}/AudioClipTest.o \
@@ -99,9 +117,15 @@ TEST_RUNNER_OBJS = ${TMP_DIR}/TestRunner.o \
                    ${TMP_DIR}/PlaylistTest.o \
                    ${TMP_DIR}/TimeConversionTest.o \
                    ${TMP_DIR}/TestRunnable.o \
-                   ${TMP_DIR}/ThreadTest.o
+                   ${TMP_DIR}/ThreadTest.o \
+                   ${TMP_DIR}/LocalizedObjectTest.o
 
-TEST_RUNNER_LIBS = -l${CORE_LIB} -lxml++-1.0 -lboost_date_time-gcc \
+TEST_RUNNER_RES = ${TMP_DIR}/${PACKAGE_NAME}_root.res \
+                  ${TMP_DIR}/${PACKAGE_NAME}_en.res \
+                  ${TMP_DIR}/${PACKAGE_NAME}_hu.res \
+                  ${TMP_DIR}/${PACKAGE_NAME}_jp.res
+
+TEST_RUNNER_LIBS = -l${CORE_LIB} ${ICU_LIBS} -lxml++-1.0 -lboost_date_time-gcc \
                    -lcppunit -ldl
 
 
@@ -119,7 +143,7 @@ doc:
 
 clean:
 	${RM} ${CORE_LIB_OBJS} ${CORE_LIB_FILE}
-	${RM} ${TEST_RUNNER_OBJS} ${TEST_RUNNER}
+	${RM} ${TEST_RUNNER_OBJS} ${TEST_RUNNER_RES} ${TEST_RUNNER}
 	${RM} ${TMP_DIR}/*.bb ${TMP_DIR}/*.bbg ${TMP_DIR}/*.da ${TMP_DIR}/*.info
 
 docclean:
@@ -132,9 +156,8 @@ depclean: clean
 distclean: clean docclean
 	${RMDIR} ${TMP_DIR}/config* ${TMP_DIR}/autom4te*
 
-check: ${TEST_RUNNER}
-	LD_LIBRARY_PATH=${USR_LIB_DIR} ${TEST_RUNNER} \
-                                   -o ${TEST_RESULTS} -s ${TEST_XSLT}
+check: ${TEST_RUNNER} ${TEST_RUNNER_RES}
+	${TEST_RUNNER} -o ${TEST_RESULTS} -s ${TEST_XSLT}
 
 
 #-------------------------------------------------------------------------------
@@ -159,3 +182,6 @@ ${TEST_RUNNER}: ${TEST_RUNNER_OBJS} ${CORE_LIB_FILE}
 ${TMP_DIR}/%.o : ${SRC_DIR}/%.cxx
 	${CXX} ${CPPFLAGS} ${CXXFLAGS} -c -o $@ $<
 
+${TMP_DIR}/${PACKAGE_NAME}_%.res : ${VAR_DIR}/%.txt
+	${GENRB} ${GENRBOPTS} $^
+
diff --git a/livesupport/modules/core/include/LiveSupport/Core/LocalizedObject.h b/livesupport/modules/core/include/LiveSupport/Core/LocalizedObject.h
new file mode 100644
index 000000000..09501152d
--- /dev/null
+++ b/livesupport/modules/core/include/LiveSupport/Core/LocalizedObject.h
@@ -0,0 +1,149 @@
+/*------------------------------------------------------------------------------
+
+    Copyright (c) 2004 Media Development Loan Fund
+ 
+    This file is part of the LiveSupport project.
+    http://livesupport.campware.org/
+    To report bugs, send an e-mail to bugs@campware.org
+ 
+    LiveSupport is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+  
+    LiveSupport is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with LiveSupport; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ 
+ 
+    Author   : $Author: maroy $
+    Version  : $Revision: 1.1 $
+    Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/include/LiveSupport/Core/LocalizedObject.h,v $
+
+------------------------------------------------------------------------------*/
+#ifndef LiveSupport_Core_LocalizedObject_h
+#define LiveSupport_Core_LocalizedObject_h
+
+#ifndef __cplusplus
+#error This is a C++ include file
+#endif
+
+
+/* ============================================================ include files */
+
+#ifdef HAVE_CONFIG_H
+#include "configure.h"
+#endif
+
+#include <stdexcept>
+
+#include <unicode/resbund.h>
+
+#include "LiveSupport/Core/Ptr.h"
+
+namespace LiveSupport {
+namespace Core {
+
+/* ================================================================ constants */
+
+
+/* =================================================================== macros */
+
+
+/* =============================================================== data types */
+
+/**
+ *  Base class for localized objects, containing some helper functions
+ *  to make localized life easier.
+ *
+ *  @author $Author: maroy $
+ *  @version $Revision: 1.1 $
+ */
+class LocalizedObject
+{
+    private:
+        /**
+         *  The resource bundle holding the localized resources for this
+         *  object.
+         */
+        Ptr<ResourceBundle>::Ref    bundle;
+
+        /**
+         *  The default constructor.
+         */
+        LocalizedObject(void)                                   throw ()
+        {
+        }
+
+
+    public:
+        /**
+         *  Constructor.
+         *
+         *  @param bundle the resource bundle holding the localized
+         *         resources for this window
+         */
+        LocalizedObject(Ptr<ResourceBundle>::Ref    bundle)     throw ()
+        {
+            this->bundle = bundle;
+        }
+
+        /**
+         *  Virtual destructor.
+         */
+        virtual
+        ~LocalizedObject(void)                                  throw ()
+        {
+        }
+
+        /**
+         *  Get the resource bundle for this object.
+         *
+         *  @return the resource bundle for this object.
+         */
+        Ptr<ResourceBundle>::Ref
+        getBundle(void) const                                   throw ()
+        {
+            return bundle;
+        }
+
+        /**
+         *  Get a resource bundle nested inside our bundle.
+         *
+         *  @param key the name of the resource bundle to get.
+         *  @exception std::invalid_argument if there is no bundle by
+         *             the specified key
+         */
+        Ptr<ResourceBundle>::Ref
+        getBundle(const char  * key)            throw (std::invalid_argument);
+
+        /**
+         *  Get a string from the resource bundle.
+         *  ustring.
+         *
+         *  @param key the key identifying the requested string.
+         *  @return the requested string
+         *  @exception std::invalid_argument if there is no string for the
+         *             specified key.
+         */
+        virtual Ptr<UnicodeString>::Ref
+        getResourceString(const char  * key)
+                                                throw (std::invalid_argument);
+};
+
+/* ================================================= external data structures */
+
+
+/* ====================================================== function prototypes */
+
+
+} // namespace Core
+} // namespace LiveSupport
+
+#endif // LiveSupport_Core_LocalizedObject_h
+
diff --git a/livesupport/modules/core/src/LocalizedObject.cxx b/livesupport/modules/core/src/LocalizedObject.cxx
new file mode 100644
index 000000000..2ec951d3e
--- /dev/null
+++ b/livesupport/modules/core/src/LocalizedObject.cxx
@@ -0,0 +1,87 @@
+/*------------------------------------------------------------------------------
+
+    Copyright (c) 2004 Media Development Loan Fund
+ 
+    This file is part of the LiveSupport project.
+    http://livesupport.campware.org/
+    To report bugs, send an e-mail to bugs@campware.org
+ 
+    LiveSupport is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+  
+    LiveSupport is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with LiveSupport; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ 
+ 
+    Author   : $Author: maroy $
+    Version  : $Revision: 1.1 $
+    Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/LocalizedObject.cxx,v $
+
+------------------------------------------------------------------------------*/
+
+/* ============================================================ include files */
+
+#ifdef HAVE_CONFIG_H
+#include "configure.h"
+#endif
+
+#include "LiveSupport/Core/LocalizedObject.h"
+
+
+using namespace LiveSupport::Core;
+
+/* ===================================================  local data structures */
+
+
+/* ================================================  local constants & macros */
+
+
+/* ===============================================  local function prototypes */
+
+
+/* =============================================================  module code */
+
+/*------------------------------------------------------------------------------
+ *  Get a resource bundle by the specified key
+ *----------------------------------------------------------------------------*/
+Ptr<ResourceBundle>::Ref
+LocalizedObject :: getBundle(const char  * key)
+                                                throw (std::invalid_argument)
+{
+    UErrorCode                  status = U_ZERO_ERROR;
+    Ptr<ResourceBundle>::Ref    resourceBundle(new ResourceBundle(
+                                                    bundle->get(key, status)));
+    if (!U_SUCCESS(status)) {
+        throw std::invalid_argument("can't get resource bundle");
+    }
+
+    return resourceBundle;
+}
+
+
+/*------------------------------------------------------------------------------
+ *  Get a string from a resource bunlde un Glib ustring format
+ *----------------------------------------------------------------------------*/
+Ptr<UnicodeString>::Ref
+LocalizedObject :: getResourceString(const char * key)
+                                                throw (std::invalid_argument)
+{
+    UErrorCode                status = U_ZERO_ERROR;
+    Ptr<UnicodeString>::Ref   unicodeStr;
+
+    unicodeStr.reset(new UnicodeString(bundle->getStringEx(key, status)));
+    if (!U_SUCCESS(status)) {
+        throw std::invalid_argument("can't get string from bundle");
+    }
+
+    return unicodeStr;
+}
+
diff --git a/livesupport/modules/core/src/LocalizedObjectTest.cxx b/livesupport/modules/core/src/LocalizedObjectTest.cxx
new file mode 100644
index 000000000..f60677ce6
--- /dev/null
+++ b/livesupport/modules/core/src/LocalizedObjectTest.cxx
@@ -0,0 +1,189 @@
+/*------------------------------------------------------------------------------
+
+    Copyright (c) 2004 Media Development Loan Fund
+ 
+    This file is part of the LiveSupport project.
+    http://livesupport.campware.org/
+    To report bugs, send an e-mail to bugs@campware.org
+ 
+    LiveSupport is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+  
+    LiveSupport is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with LiveSupport; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ 
+ 
+    Author   : $Author: maroy $
+    Version  : $Revision: 1.1 $
+    Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/LocalizedObjectTest.cxx,v $
+
+------------------------------------------------------------------------------*/
+
+/* ============================================================ include files */
+
+#ifdef HAVE_CONFIG_H
+#include "configure.h"
+#endif
+
+#include <string>
+#include <iostream>
+#include <unicode/resbund.h>
+
+#include "LiveSupport/Core/LocalizedObject.h"
+#include "LocalizedObjectTest.h"
+
+
+using namespace LiveSupport::Core;
+
+/* ===================================================  local data structures */
+
+
+/* ================================================  local constants & macros */
+
+CPPUNIT_TEST_SUITE_REGISTRATION(LocalizedObjectTest);
+
+
+/* ===============================================  local function prototypes */
+
+
+/* =============================================================  module code */
+
+/*------------------------------------------------------------------------------
+ *  Set up the test environment
+ *----------------------------------------------------------------------------*/
+void
+LocalizedObjectTest :: setUp(void)                         throw ()
+{
+}
+
+
+/*------------------------------------------------------------------------------
+ *  Clean up the test environment
+ *----------------------------------------------------------------------------*/
+void
+LocalizedObjectTest :: tearDown(void)                      throw ()
+{
+}
+
+
+/*------------------------------------------------------------------------------
+ *  A simple smoke test.
+ *----------------------------------------------------------------------------*/
+void
+LocalizedObjectTest :: simpleTest(void)
+                                                throw (CPPUNIT_NS::Exception)
+{
+    UErrorCode                status = U_ZERO_ERROR;
+    Ptr<ResourceBundle>::Ref  bundle(new ResourceBundle("./tmp/" PACKAGE_NAME,
+                                                        "root",
+                                                        status));
+    CPPUNIT_ASSERT(U_SUCCESS(status));
+
+    try {
+        Ptr<LocalizedObject>::Ref   locObj(new LocalizedObject(bundle));
+        Ptr<LocalizedObject>::Ref   section1(new LocalizedObject(
+                                                locObj->getBundle("section1")));
+        Ptr<UnicodeString>::Ref     foo = section1->getResourceString("foo");
+        CPPUNIT_ASSERT(foo->compare("foo") == 0);
+    } catch (std::invalid_argument &e) {
+        CPPUNIT_FAIL(e.what());
+    }
+}
+
+
+/*------------------------------------------------------------------------------
+ *  A test to see different locales and fallback to work.
+ *----------------------------------------------------------------------------*/
+void
+LocalizedObjectTest :: fallbackTest(void)
+                                                throw (CPPUNIT_NS::Exception)
+{
+    UErrorCode                status = U_ZERO_ERROR;
+    Ptr<ResourceBundle>::Ref  rootBundle;
+    Ptr<ResourceBundle>::Ref  enBundle;
+
+    rootBundle.reset(new ResourceBundle("./tmp/" PACKAGE_NAME, "root", status));
+    CPPUNIT_ASSERT(U_SUCCESS(status));
+    enBundle.reset(new ResourceBundle("./tmp/" PACKAGE_NAME, "en", status));
+    CPPUNIT_ASSERT(U_SUCCESS(status));
+
+    // first, see the root bundle
+    try {
+        Ptr<LocalizedObject>::Ref   locObj(new LocalizedObject(rootBundle));
+        Ptr<LocalizedObject>::Ref   section1(new LocalizedObject(
+                                                locObj->getBundle("section1")));
+        Ptr<UnicodeString>::Ref     foo = section1->getResourceString("foo");
+        CPPUNIT_ASSERT(foo->compare("foo") == 0);
+        Ptr<UnicodeString>::Ref     bar = section1->getResourceString("bar");
+        CPPUNIT_ASSERT(bar->compare("bar") == 0);
+    } catch (std::invalid_argument &e) {
+        CPPUNIT_FAIL(e.what());
+    }
+
+    // now, the en bundle
+    try {
+        Ptr<LocalizedObject>::Ref   locObj(new LocalizedObject(enBundle));
+        Ptr<LocalizedObject>::Ref   section1(new LocalizedObject(
+                                                locObj->getBundle("section1")));
+        Ptr<UnicodeString>::Ref     foo = section1->getResourceString("foo");
+        CPPUNIT_ASSERT(foo->compare("fou") == 0);
+        Ptr<UnicodeString>::Ref     bar = section1->getResourceString("bar");
+        CPPUNIT_ASSERT(bar->compare("bar") == 0);
+    } catch (std::invalid_argument &e) {
+        CPPUNIT_FAIL(e.what());
+    }
+}
+
+
+/*------------------------------------------------------------------------------
+ *  A test to see funny unicode characters to work.
+ *----------------------------------------------------------------------------*/
+void
+LocalizedObjectTest :: unicodeTest(void)
+                                                throw (CPPUNIT_NS::Exception)
+{
+    UErrorCode                status = U_ZERO_ERROR;
+    Ptr<ResourceBundle>::Ref  huBundle;
+    Ptr<ResourceBundle>::Ref  jpBundle;
+
+    huBundle.reset(new ResourceBundle("./tmp/" PACKAGE_NAME, "hu", status));
+    CPPUNIT_ASSERT(U_SUCCESS(status));
+    try {
+        Ptr<LocalizedObject>::Ref   locObj(new LocalizedObject(huBundle));
+        Ptr<LocalizedObject>::Ref   section1(new LocalizedObject(
+                                                locObj->getBundle("section1")));
+        Ptr<UnicodeString>::Ref     foo = section1->getResourceString("foo");
+        CPPUNIT_ASSERT(foo->charAt(0) == 0x0066);  // 'f'
+        CPPUNIT_ASSERT(foo->charAt(1) == 0x00fa);  // 'u' with acute
+        Ptr<UnicodeString>::Ref     bar = section1->getResourceString("bar");
+        CPPUNIT_ASSERT(bar->charAt(0) == 0x0062);  // 'b'
+        CPPUNIT_ASSERT(bar->charAt(1) == 0x00e1);  // 'a' with acute
+        CPPUNIT_ASSERT(bar->charAt(2) == 0x0072);  // 'r'
+    } catch (std::invalid_argument &e) {
+        CPPUNIT_FAIL(e.what());
+    }
+
+    jpBundle.reset(new ResourceBundle("./tmp/" PACKAGE_NAME, "jp", status));
+    CPPUNIT_ASSERT(U_SUCCESS(status));
+    try {
+        Ptr<LocalizedObject>::Ref   locObj(new LocalizedObject(jpBundle));
+        Ptr<LocalizedObject>::Ref   section1(new LocalizedObject(
+                                                locObj->getBundle("section1")));
+        Ptr<UnicodeString>::Ref     foo = section1->getResourceString("foo");
+        CPPUNIT_ASSERT(foo->charAt(0) == 0x3075);  // hiragana fu
+        Ptr<UnicodeString>::Ref     bar = section1->getResourceString("bar");
+        CPPUNIT_ASSERT(bar->charAt(0) == 0x3070);  // hiragana ba
+        CPPUNIT_ASSERT(bar->charAt(1) == 0x308b);  // hiragana ru
+    } catch (std::invalid_argument &e) {
+        CPPUNIT_FAIL(e.what());
+    }
+}
+
diff --git a/livesupport/modules/core/src/LocalizedObjectTest.h b/livesupport/modules/core/src/LocalizedObjectTest.h
new file mode 100644
index 000000000..f78fa3d7f
--- /dev/null
+++ b/livesupport/modules/core/src/LocalizedObjectTest.h
@@ -0,0 +1,126 @@
+/*------------------------------------------------------------------------------
+
+    Copyright (c) 2004 Media Development Loan Fund
+ 
+    This file is part of the LiveSupport project.
+    http://livesupport.campware.org/
+    To report bugs, send an e-mail to bugs@campware.org
+ 
+    LiveSupport is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+  
+    LiveSupport is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with LiveSupport; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ 
+ 
+    Author   : $Author: maroy $
+    Version  : $Revision: 1.1 $
+    Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/LocalizedObjectTest.h,v $
+
+------------------------------------------------------------------------------*/
+#ifndef LocalizedObjectTest_h
+#define LocalizedObjectTest_h
+
+#ifndef __cplusplus
+#error This is a C++ include file
+#endif
+
+
+/* ============================================================ include files */
+
+#ifdef HAVE_CONFIG_H
+#include "configure.h"
+#endif
+
+#include <cppunit/extensions/HelperMacros.h>
+
+
+namespace LiveSupport {
+namespace Core {
+
+/* ================================================================ constants */
+
+
+/* =================================================================== macros */
+
+
+/* =============================================================== data types */
+
+/**
+ *  Unit test for the LocalizedObject class.
+ *
+ *  @author  $Author: maroy $
+ *  @version $Revision: 1.1 $
+ *  @see LocalizedObject
+ */
+class LocalizedObjectTest : public CPPUNIT_NS::TestFixture
+{
+    CPPUNIT_TEST_SUITE(LocalizedObjectTest);
+    CPPUNIT_TEST(simpleTest);
+    CPPUNIT_TEST(fallbackTest);
+    CPPUNIT_TEST(unicodeTest);
+    CPPUNIT_TEST_SUITE_END();
+
+    protected:
+
+        /**
+         *  A simple smoke test.
+         *
+         *  @exception CPPUNIT_NS::Exception on test failures.
+         */
+        void
+        simpleTest(void)                        throw (CPPUNIT_NS::Exception);
+
+        /**
+         *  Test to see if multiple locales work, and they fall back to
+         *  more generic values.
+         *
+         *  @exception CPPUNIT_NS::Exception on test failures.
+         */
+        void
+        fallbackTest(void)                      throw (CPPUNIT_NS::Exception);
+
+        /**
+         *  Test to see if funny unicode characters work properly.
+         *
+         *  @exception CPPUNIT_NS::Exception on test failures.
+         */
+        void
+        unicodeTest(void)                       throw (CPPUNIT_NS::Exception);
+
+
+    public:
+        
+        /**
+         *  Set up the environment for the test case.
+         */
+        void
+        setUp(void)                                     throw ();
+
+        /**
+         *  Clean up the environment after the test case.
+         */
+        void
+        tearDown(void)                                  throw ();
+};
+
+
+/* ================================================= external data structures */
+
+
+/* ====================================================== function prototypes */
+
+
+} // namespace Core
+} // namespace LiveSupport
+
+#endif // LocalizedObjectTest_h
+
diff --git a/livesupport/modules/core/var/.keepme b/livesupport/modules/core/var/.keepme
new file mode 100644
index 000000000..e0808fa16
--- /dev/null
+++ b/livesupport/modules/core/var/.keepme
@@ -0,0 +1 @@
+keep me
diff --git a/livesupport/modules/core/var/en.txt b/livesupport/modules/core/var/en.txt
new file mode 100644
index 000000000..a0b0a6d89
--- /dev/null
+++ b/livesupport/modules/core/var/en.txt
@@ -0,0 +1,7 @@
+en:table
+{
+    section1:table
+    {
+        foo:string      { "fou" }
+    }
+}
diff --git a/livesupport/modules/core/var/hu.txt b/livesupport/modules/core/var/hu.txt
new file mode 100644
index 000000000..7bbdc07a4
--- /dev/null
+++ b/livesupport/modules/core/var/hu.txt
@@ -0,0 +1,9 @@
+hu:table
+{
+    section1:table
+    {
+        foo:string      { "fú" }
+        bar:string      { "bár" }
+    }
+}
+
diff --git a/livesupport/modules/core/var/jp.txt b/livesupport/modules/core/var/jp.txt
new file mode 100644
index 000000000..ad23d8782
--- /dev/null
+++ b/livesupport/modules/core/var/jp.txt
@@ -0,0 +1,9 @@
+jp:table
+{
+    section1:table
+    {
+        foo:string      { "ふ" }
+        bar:string      { "ばる" }
+    }
+}
+
diff --git a/livesupport/modules/core/var/root.txt b/livesupport/modules/core/var/root.txt
new file mode 100644
index 000000000..d15b58d03
--- /dev/null
+++ b/livesupport/modules/core/var/root.txt
@@ -0,0 +1,9 @@
+root:table
+{
+    section1:table
+    {
+        foo:string      { "foo" }
+        bar:string      { "bar" }
+    }
+}
+