← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 15278: Merge from ThoughtWorks/MSF team branch. Makes Translation.java an IdentifiableObject. Exposes tr...

 

Merge authors:
  Aravind M (arav-psgtech)
  Kiran Prakash (kiran-f)
  Mahendra Kariya (mahendrakariya-k)
------------------------------------------------------------
revno: 15278 [merge]
committer: Lars Helge Overland <larshelge@xxxxxxxxx>
branch nick: dhis2
timestamp: Thu 2014-05-15 18:58:37 +0200
message:
  Merge from ThoughtWorks/MSF team branch. Makes Translation.java an IdentifiableObject. Exposes translations in Web API.
added:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/translation/Translations.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/TranslationController.java
modified:
  .bzrignore
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/translation/Translation.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/translation/TranslationService.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/translation/TranslationStore.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/user/UserSettingService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/common/DefaultIdentifiableObjectManager.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/i18n/DefaultI18nService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/i18n/I18nService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/startup/TableAlteror.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/translation/DefaultTranslationService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/translation/hibernate/HibernateTranslationStore.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/user/DefaultUserSettingService.java
  dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/translation/hibernate/Translation.hbm.xml
  dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/i18n/I18nServiceTest.java
  dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/translation/TranslationServiceTest.java
  dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/translation/TranslationStoreTest.java
  dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/user/UserSettingServiceTest.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/utils/JacksonUtils.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/StatementBuilder.java
  dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/statementbuilder/AbstractStatementBuilder.java
  dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/statementbuilder/HsqlStatementBuilder.java
  dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/statementbuilder/MySQLStatementBuilder.java
  dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/statementbuilder/PostgreSQLStatementBuilder.java
  dhis-2/dhis-support/dhis-support-system/src/test/java/org/hisp/dhis/system/util/LocaleUtilsTest.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/UserSettingController.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/user/UserController.java
  dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/i18n/translate.vm
  dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/commons.js
  dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/i18n/action/GetTranslationsAction.java
  dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/i18n/action/I18nAction.java
  dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/i18n/action/TranslateAction.java


--
lp:dhis2
https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk

Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== modified file '.bzrignore'
--- .bzrignore	2013-12-06 05:00:46 +0000
+++ .bzrignore	2014-04-14 11:59:03 +0000
@@ -26,3 +26,4 @@
 ./.gitignore
 ./.travis.yml
 .DS_Store
+dhis-2/projectFilesBackup

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/translation/Translation.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/translation/Translation.java	2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/translation/Translation.java	2014-05-15 16:58:37 +0000
@@ -28,23 +28,24 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import java.io.Serializable;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import org.hisp.dhis.common.BaseIdentifiableObject;
+import org.hisp.dhis.common.DxfNamespaces;
 
 /**
  * @author Oyvind Brucker
  */
+@JacksonXmlRootElement( localName = "translation", namespace = DxfNamespaces.DXF_2_0 )
 public class Translation
-    implements Serializable
+    extends BaseIdentifiableObject
 {
-    /**
-     * Determines if a de-serialized file is compatible with this class.
-     */
-    private static final long serialVersionUID = 4432944068677351446L;
+    private String objectUid;
 
     private String className;
 
-    private int id;
-
     private String locale;
 
     private String property;
@@ -57,30 +58,34 @@
 
     public Translation()
     {
+       setAutoFields();
     }
 
-    public Translation( String className, int id, String locale, String property, String value )
+    public Translation( String className, String locale, String property, String value, String objectUid )
     {
+        this();
         this.className = className;
-        this.id = id;
         this.locale = locale;
         this.property = property;
         this.value = value;
+        this.objectUid = objectUid;
     }
 
     // -------------------------------------------------------------------------
     // Logic
     // -------------------------------------------------------------------------
 
+    @JsonIgnore
     public String getClassIdPropKey()
     {
-        return className + "-" + id + "-" + property;
+        return className + "-" + objectUid + "-" + property;
     }
-    
+
     // -------------------------------------------------------------------------
     // Getters and setters
     // -------------------------------------------------------------------------
-
+    @JsonProperty
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public String getClassName()
     {
         return className;
@@ -91,16 +96,8 @@
         this.className = className;
     }
 
-    public int getId()
-    {
-        return id;
-    }
-
-    public void setId( int id )
-    {
-        this.id = id;
-    }
-
+    @JsonProperty
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public String getLocale()
     {
         return locale;
@@ -111,6 +108,8 @@
         this.locale = locale;
     }
 
+    @JsonProperty
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public String getProperty()
     {
         return property;
@@ -121,6 +120,8 @@
         this.property = property;
     }
 
+    @JsonProperty
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public String getValue()
     {
         return value;
@@ -131,10 +132,22 @@
         this.value = value;
     }
 
-    // -------------------------------------------------------------------------
+
     // hashCode, equals and toString
     // -------------------------------------------------------------------------
 
+    @JsonProperty
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public String getObjectUid()
+    {
+        return objectUid;
+    }
+
+    public void setObjectUid( String objectUid )
+    {
+        this.objectUid = objectUid;
+    }
+
     @Override
     public int hashCode()
     {
@@ -142,10 +155,10 @@
         int result = 1;
 
         result = result * prime + className.hashCode();
-        result = result * prime + id;
+        result = result * prime + objectUid.hashCode();
         result = result * prime + locale.hashCode();
         result = result * prime + property.hashCode();
-        
+
         return result;
     }
 
@@ -169,13 +182,13 @@
 
         Translation translation = (Translation) o;
 
-        return className.equals( translation.getClassName() ) && id == translation.getId() &&
+        return className.equals( translation.getClassName() ) &&  objectUid == translation.getObjectUid() &&
             locale.equals( translation.getLocale() ) && property.equals( translation.getProperty());
     }
 
     @Override
     public String toString()
     {
-        return "[Class name: " + className + " id: " + id + " locale: " + locale + " property: " + property + " value: " + value + "]";
+        return "[Class name: " + className + " objectUid: " + objectUid + " uid: " + uid + " locale: " + locale + " property: " + property + " value: " + value + "]";
     }
 }
\ No newline at end of file

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/translation/TranslationService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/translation/TranslationService.java	2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/translation/TranslationService.java	2014-05-15 06:21:07 +0000
@@ -47,6 +47,13 @@
     void addTranslation( Translation translation );
 
     /**
+     * Adds a collection of Translation.
+     *
+     * @param translations the collection of translations
+     */
+    void createOrUpdate( Collection<Translation> translations );
+
+    /**
      * Updates a Translation.
      * 
      * @param translation the Translation.
@@ -56,46 +63,52 @@
     /**
      * Retrieves a Translation.
      * 
+     *
+     *
      * @param className the class name.
-     * @param id the id.
      * @param locale the locale.
      * @param property the property.
+     * @param objectUid
      * @return a Translation.
      */
-    Translation getTranslation( String className, int id, Locale locale, String property );
+    Translation getTranslation( String className, Locale locale, String property, String objectUid );
 
     /**
      * Retrieves a Translation. Only exact matches on the given
      * Locale will be returned.
      * 
+     *
+     *
      * @param className the class name.
-     * @param id the id.
      * @param locale the locale.
      * @param property the property.
+     * @param objectUid
      * @return a Translation.
      */
-    Translation getTranslationNoFallback( String className, int id, Locale locale, String property );
+    Translation getTranslationNoFallback( String className, Locale locale, String property, String objectUid );
 
     /**
      * Retrieves a Collection of Translations.
      * 
+     *
      * @param className the class name.
-     * @param id the id.
      * @param locale the locale.
      * @return a Collection of Translations.
      */
-    Collection<Translation> getTranslations( String className, int id, Locale locale );
+    Collection<Translation> getTranslations( String className, Locale locale, String objectUid );
 
     /**
      * Retrieves a Collection of Translations. Only exact matches on the given
      * Locale will be returned.
      * 
+     *
+     *
      * @param className the class name.
-     * @param id the id.
      * @param locale the locale.
+     * @param objectUid the id.
      * @return a Collection of Translations.
      */
-    Collection<Translation> getTranslationsNoFallback( String className, int id, Locale locale );
+    Collection<Translation> getTranslationsNoFallback( String className, Locale locale, String objectUid );
 
     /**
      * Retrieves a Collection of Translations.
@@ -130,9 +143,11 @@
 
     /**
      * Deletes Translations.
-     * 
+     *
      * @param className the class name.
-     * @param id the id.
+     * @param objectUid the id.
      */
-    void deleteTranslations( String className, int id );
+    void deleteTranslations( String className, String objectUid );
+
+    void createOrUpdate( Translation translation );
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/translation/TranslationStore.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/translation/TranslationStore.java	2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/translation/TranslationStore.java	2014-05-15 06:21:07 +0000
@@ -55,46 +55,53 @@
     /**
      * Retrieves a Translation.
      * 
+     *
+     *
      * @param className the class name.
-     * @param id the id.
      * @param locale the locale.
      * @param property the property.
+     * @param objectUid
      * @return a Translation.
      */
-    Translation getTranslation( String className, int id, Locale locale, String property );
+    Translation getTranslation( String className, Locale locale, String property, String objectUid );
 
     /**
      * Retrieves a Translation. Only exact matches on the given
      * Locale will be returned.
      * 
+     *
+     *
      * @param className the class name.
-     * @param id the id.
      * @param locale the locale.
      * @param property the property.
+     * @param objectUid
      * @return a Translation.
      */
-    Translation getTranslationNoFallback( String className, int id, Locale locale, String property  );
+    Translation getTranslationNoFallback( String className, Locale locale, String property, String objectUid );
 
     /**
      * Retrieves a Collection of Translations.
      * 
+     *
+     *
      * @param className the class name.
-     * @param id the id.
      * @param locale the locale.
+     * @param objectUid the id.
      * @return a Collection of Translations.
      */
-    Collection<Translation> getTranslations( String className, int id, Locale locale );
+    Collection<Translation> getTranslations( String className, Locale locale, String objectUid );
 
     /**
      * Retrieves a Collection of Translations. Only exact matches on the given
      * Locale will be returned.
      * 
+     *
      * @param className the class name.
-     * @param id the id.
+     * @param objectUid the id.
      * @param locale the locale.
      * @return a Collection of Translations.
      */
-    Collection<Translation> getTranslationsNoFallback( String className, int id, Locale locale );
+    Collection<Translation> getTranslationsNoFallback( String className, String objectUid, Locale locale );
     
     /**
      * Retrieves a Collection of Translations.
@@ -129,9 +136,9 @@
 
     /**
      * Deletes Translations.
-     * 
+     *
      * @param className the class name.
-     * @param id the id.
+     * @param objectUid the id.
      */
-    void deleteTranslations( String className, int id );
+    void deleteTranslations( String className, String objectUid );
 }
\ No newline at end of file

=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/translation/Translations.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/translation/Translations.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/translation/Translations.java	2014-05-14 11:03:46 +0000
@@ -0,0 +1,66 @@
+package org.hisp.dhis.translation;
+
+/*
+ * Copyright (c) 2004-2014, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of the HISP project nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import org.hisp.dhis.common.DxfNamespaces;
+
+import java.util.Collection;
+
+/**
+ * @author Kiran Prakash
+ */
+@JacksonXmlRootElement( localName = "translations", namespace = DxfNamespaces.DXF_2_0 )
+public class Translations
+{
+    private Collection<Translation> translations;
+
+    public Translations()
+    {
+    }
+
+    public Translations( Collection<Translation> translations )
+    {
+        this.translations = translations;
+    }
+
+    @JsonProperty
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public Collection<Translation> getTranslations()
+    {
+        return translations;
+    }
+
+    public void setTranslations( Collection<Translation> translations )
+    {
+        this.translations = translations;
+    }
+}
\ No newline at end of file

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/user/UserSettingService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/user/UserSettingService.java	2014-04-03 11:32:51 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/user/UserSettingService.java	2014-05-15 16:58:37 +0000
@@ -91,6 +91,16 @@
     Serializable getUserSetting( String name );
 
     /**
+     * Returns the value of the user setting specified by the given name.
+     * 
+     * @param name the name of the user setting.
+     * @return the value corresponding to the named user setting, or null if
+     *         there is no match.
+     * @throws NoCurrentUserException if there is no current user.
+     */
+    Serializable getUserSetting( String name, String username );
+
+    /**
      * Returns the value of the user setting specified by the given name. If
      * there is no current user or the user setting doesn't exist, the specified
      * default value is returned.

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/common/DefaultIdentifiableObjectManager.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/common/DefaultIdentifiableObjectManager.java	2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/common/DefaultIdentifiableObjectManager.java	2014-05-05 12:22:43 +0000
@@ -498,7 +498,7 @@
     {
         for ( GenericIdentifiableObjectStore<IdentifiableObject> objectStore : identifiableObjectStores )
         {
-            if ( simpleClassName.equals( objectStore.getClass().getSimpleName() ) )
+            if ( simpleClassName.equals( objectStore.getClazz().getSimpleName() ) )
             {
                 return objectStore.getByUid( uid );
             }

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/i18n/DefaultI18nService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/i18n/DefaultI18nService.java	2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/i18n/DefaultI18nService.java	2014-05-15 06:21:07 +0000
@@ -28,21 +28,6 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import static org.hisp.dhis.system.util.ReflectionUtils.getClassName;
-import static org.hisp.dhis.system.util.ReflectionUtils.getId;
-import static org.hisp.dhis.system.util.ReflectionUtils.getProperty;
-import static org.hisp.dhis.system.util.ReflectionUtils.isCollection;
-import static org.hisp.dhis.system.util.ReflectionUtils.setProperty;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
 import org.hisp.dhis.common.IdentifiableObject;
 import org.hisp.dhis.common.NameableObject;
 import org.hisp.dhis.dataelement.DataElement;
@@ -50,6 +35,10 @@
 import org.hisp.dhis.translation.TranslationService;
 import org.hisp.dhis.user.UserSettingService;
 
+import java.util.*;
+
+import static org.hisp.dhis.system.util.ReflectionUtils.*;
+
 /**
  * @author Oyvind Brucker
  */
@@ -119,7 +108,7 @@
         List<String> properties = getObjectPropertyNames( object );
 
         Collection<Translation> translations = translationService.getTranslations( getClassName( object ),
-            getId( object ), locale );
+            locale, getProperty( object, "uid" ) );
 
         Map<String, String> translationMap = convertTranslations( translations );
 
@@ -149,7 +138,7 @@
 
         for ( Object object : objects )
         {
-            Map<String, String> translationMap = getTranslationsForObject( translations, getId( object ) );
+            Map<String, String> translationMap = getTranslationsForObject( translations, getProperty( object, "uid" ) );
 
             for ( String property : properties )
             {
@@ -201,7 +190,7 @@
     {
         if ( object != null )
         {
-            translationService.deleteTranslations( getClassName( object ), getId( object ) );
+            translationService.deleteTranslations( getClassName( object ), getProperty( object, "uid" ) );
         }
     }
 
@@ -209,7 +198,7 @@
     // Translation
     // -------------------------------------------------------------------------
 
-    public void updateTranslation( String className, int id, Locale locale, Map<String, String> translations )
+    public void updateTranslation( String className, Locale locale, Map<String, String> translations, String objectUid )
     {
         if ( locale != null && className != null )
         {
@@ -217,55 +206,37 @@
             {
                 String key = translationEntry.getKey();
                 String value = translationEntry.getValue();
-                
-                Translation translation = translationService.getTranslationNoFallback( className, id, locale, key );
-
-                if ( value != null && !value.trim().isEmpty() )
-                {                    
-                    if ( translation != null )
-                    {
-                        translation.setValue( value );
-                        translationService.updateTranslation( translation );
-                    }
-                    else
-                    {
-                        translation = new Translation( className, id, locale.toString(), key, value );
-                        translationService.addTranslation( translation );
-                    }
-                }
-                else if ( translation != null )
-                {
-                    translationService.deleteTranslation( translation );
-                }
+                Translation t = new Translation( className, locale.toString(), key, value, objectUid );
+                translationService.createOrUpdate( t );
             }
         }
     }
 
-    public Map<String, String> getTranslations( String className, int id )
+    public Map<String, String> getTranslations( String className, String objectUid )
     {
-        return getTranslations( className, id, getCurrentLocale() );
+        return getTranslations( className, getCurrentLocale(), objectUid );
     }
 
-    public Map<String, String> getTranslations( String className, int id, Locale locale )
+    public Map<String, String> getTranslations( String className, Locale locale, String objectUid )
     {
         if ( locale != null && className != null )
         {
-            return convertTranslations( translationService.getTranslations( className, id, locale ) );
+            return convertTranslations( translationService.getTranslations( className, locale, objectUid ) );
         }
 
         return new HashMap<String, String>();
     }
 
-    public Map<String, String> getTranslationsNoFallback( String className, int id )
+    public Map<String, String> getTranslationsNoFallback( String className, String objectUid )
     {
-        return getTranslationsNoFallback( className, id, getCurrentLocale() );
+        return getTranslationsNoFallback( className, objectUid, getCurrentLocale() );
     }
 
-    public Map<String, String> getTranslationsNoFallback( String className, int id, Locale locale )
+    public Map<String, String> getTranslationsNoFallback( String className, String objectUid, Locale locale )
     {
         if ( locale != null && className != null )
         {
-            return convertTranslations( translationService.getTranslationsNoFallback( className, id, locale ) );
+            return convertTranslations( translationService.getTranslationsNoFallback( className, locale, objectUid ) );
         }
 
         return new HashMap<String, String>();
@@ -299,17 +270,18 @@
      * id where the key is the translation property and the value is the
      * translation value.
      * 
+     *
      * @param translations Collection to search.
-     * @param id the object id.
+     * @param objectUid
      * @return Map of property/value pairs.
      */
-    private Map<String, String> getTranslationsForObject( Collection<Translation> translations, int id )
+    private Map<String, String> getTranslationsForObject( Collection<Translation> translations, String objectUid )
     {
         Collection<Translation> objectTranslations = new ArrayList<Translation>();
 
         for ( Translation translation : translations )
         {
-            if ( translation.getId() == id )
+            if (translation.getObjectUid().equals( objectUid ))
             {
                 objectTranslations.add( translation );
             }

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/i18n/I18nService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/i18n/I18nService.java	2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/i18n/I18nService.java	2014-05-15 06:21:07 +0000
@@ -63,15 +63,15 @@
     // Translation
     // -------------------------------------------------------------------------
 
-    void updateTranslation( String className, int id, Locale thisLocale, Map<String, String> translations );
-    
-    Map<String, String> getTranslations( String className, int id );
-
-    Map<String, String> getTranslations( String className, int id, Locale locale );
-    
-    Map<String, String> getTranslationsNoFallback( String className, int id );
-
-    Map<String, String> getTranslationsNoFallback( String className, int id, Locale locale );
+    void updateTranslation( String className, Locale thisLocale, Map<String, String> translations, String objectUid );
+    
+    Map<String, String> getTranslations( String className, String objectUid );
+
+    Map<String, String> getTranslations( String className, Locale locale, String objectUid );
+    
+    Map<String, String> getTranslationsNoFallback( String className, String objectUid );
+
+    Map<String, String> getTranslationsNoFallback( String className, String objectUid, Locale locale );
     
     // -------------------------------------------------------------------------
     // Locale

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/startup/TableAlteror.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/startup/TableAlteror.java	2014-05-14 11:22:05 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/startup/TableAlteror.java	2014-05-15 16:58:37 +0000
@@ -266,14 +266,6 @@
         // orgunit shortname uniqueness
         executeSql( "ALTER TABLE organisationunit DROP CONSTRAINT organisationunit_shortname_key" );
 
-        // update dataset-dataentryform association and programstage-cde
-        // association
-        if ( updateDataSetAssociation() && updateProgramStageAssociation() )
-        {
-            // delete table dataentryformassociation
-            executeSql( "DROP TABLE dataentryformassociation" );
-        }
-
         executeSql( "ALTER TABLE section DROP CONSTRAINT section_name_key" );
         executeSql( "UPDATE patientattribute set inheritable=false where inheritable is null" );
         executeSql( "UPDATE dataelement SET numbertype='number' where numbertype is null and valuetype='int'" );
@@ -727,7 +719,8 @@
 
         upgradeDataValuesWithAttributeOptionCombo();
         upgradeMapViewsToAnalyticalObject();
-        
+        upgradeTranslations();
+
         log.info( "Tables updated" );
     }
 
@@ -739,8 +732,7 @@
 
         if ( no >= 5 )
         {
-            return; // attributeoptioncomboid already part of datavalue primary
-                    // key
+            return; // attributeoptioncomboid already part of datavalue pkey
         }
 
         int optionComboId = getDefaultOptionCombo();
@@ -995,6 +987,22 @@
             log.debug( ex );
         }
     }
+    
+    private void upgradeTranslations()
+    {
+        final String sql = statementBuilder.getNumberOfColumnsInPrimaryKey( "translation" );
+
+        Integer no = statementManager.getHolder().queryForInteger( sql );
+
+        if ( no == 1 )
+        {
+            return; // translationid already set as single pkey
+        }
+        
+        executeSql( statementBuilder.getDropPrimaryKey( "translation" ) );
+        executeSql( statementBuilder.getAddPrimaryKeyToExistingTable( "translation", "translationid" ) );
+        executeSql( statementBuilder.getDropNotNullConstraint( "translation", "objectid", "integer" ) );
+    }
 
     private List<Integer> getDistinctIdList( String table, String col1 )
     {
@@ -1039,7 +1047,8 @@
             {
                 List<Integer> foreignIds = new ArrayList<Integer>();
 
-                ResultSet resultSet = statement.executeQuery( "SELECT " + col2 + " FROM " + table + " WHERE " + col1
+                ResultSet resultSet = stat
+                    alter table translation modify column locale varchar(45) null;ement.executeQuery( "SELECT " + col2 + " FROM " + table + " WHERE " + col1
                     + "=" + distinctId );
 
                 while ( resultSet.next() )
@@ -1120,77 +1129,4 @@
         return statementManager.getHolder().queryForInteger( sql );
     }
 
-    private boolean updateDataSetAssociation()
-    {
-        StatementHolder holder = statementManager.getHolder();
-
-        try
-        {
-            Statement statement = holder.getStatement();
-
-            ResultSet isUpdated = statement
-                .executeQuery( "SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'dataentryformassociation'" );
-
-            if ( isUpdated.next() )
-            {
-
-                ResultSet resultSet = statement
-                    .executeQuery( "SELECT associationid, dataentryformid FROM dataentryformassociation WHERE associationtablename = 'dataset'" );
-
-                while ( resultSet.next() )
-                {
-                    executeSql( "UPDATE dataset SET dataentryform=" + resultSet.getInt( 2 ) + " WHERE datasetid="
-                        + resultSet.getInt( 1 ) );
-                }
-                return true;
-            }
-
-            return false;
-
-        }
-        catch ( Exception ex )
-        {
-            log.debug( ex );
-            return false;
-        }
-        finally
-        {
-            holder.close();
-        }
-    }
-
-    private boolean updateProgramStageAssociation()
-    {
-        StatementHolder holder = statementManager.getHolder();
-
-        try
-        {
-            Statement statement = holder.getStatement();
-
-            ResultSet isUpdated = statement
-                .executeQuery( "SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'dataentryformassociation'" );
-
-            if ( isUpdated.next() )
-            {
-                ResultSet resultSet = statement
-                    .executeQuery( "SELECT associationid, dataentryformid FROM dataentryformassociation WHERE associationtablename = 'programstage'" );
-
-                while ( resultSet.next() )
-                {
-                    executeSql( "UPDATE programstage SET dataentryform=" + resultSet.getInt( 2 )
-                        + " WHERE programstageid=" + resultSet.getInt( 1 ) );
-                }
-            }
-            return true;
-        }
-        catch ( Exception ex )
-        {
-            log.debug( ex );
-            return false;
-        }
-        finally
-        {
-            holder.close();
-        }
-    }
 }

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/translation/DefaultTranslationService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/translation/DefaultTranslationService.java	2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/translation/DefaultTranslationService.java	2014-05-15 06:21:07 +0000
@@ -31,6 +31,7 @@
 import java.util.Collection;
 import java.util.Locale;
 
+import org.hisp.dhis.system.util.LocaleUtils;
 import org.springframework.transaction.annotation.Transactional;
 
 /**
@@ -61,29 +62,37 @@
         translationStore.addTranslation( translation );
     }
 
+    public void createOrUpdate( Collection<Translation> translations )
+    {
+        for ( Translation translation : translations )
+        {
+            createOrUpdate( translation );
+        }
+    }
+
     public void updateTranslation( Translation translation )
     {
         translationStore.updateTranslation( translation );
     }
 
-    public Translation getTranslation( String className, int id, Locale locale, String property )
-    {
-        return translationStore.getTranslation( className, id, locale, property );
-    }
-
-    public Translation getTranslationNoFallback( String className, int id, Locale locale, String property )
-    {
-        return translationStore.getTranslationNoFallback( className, id, locale, property );
-    }
-
-    public Collection<Translation> getTranslations( String className, int id, Locale locale )
-    {
-        return translationStore.getTranslations( className, id, locale );
-    }
-
-    public Collection<Translation> getTranslationsNoFallback( String className, int id, Locale locale )
-    {
-        return translationStore.getTranslationsNoFallback( className, id, locale );
+    public Translation getTranslation( String className, Locale locale, String property, String objectUid )
+    {
+        return translationStore.getTranslation( className, locale, property, objectUid );
+    }
+
+    public Translation getTranslationNoFallback( String className, Locale locale, String property, String objectUid )
+    {
+        return translationStore.getTranslationNoFallback( className, locale, property, objectUid );
+    }
+
+    public Collection<Translation> getTranslations( String className, Locale locale, String objectUid )
+    {
+        return translationStore.getTranslations( className, locale, objectUid );
+    }
+
+    public Collection<Translation> getTranslationsNoFallback( String className, Locale locale, String objectUid )
+    {
+        return translationStore.getTranslationsNoFallback( className, objectUid, locale );
     }
 
     public Collection<Translation> getTranslations( String className, Locale locale )
@@ -106,8 +115,30 @@
         translationStore.deleteTranslation( translation );
     }
 
-    public void deleteTranslations( String className, int id )
-    {
-        translationStore.deleteTranslations( className, id );
+    public void deleteTranslations( String className, String objectUid )
+    {
+        translationStore.deleteTranslations( className, objectUid );
+    }
+
+    public void createOrUpdate( Translation translation )
+    {
+        Translation translationNoFallback = getTranslationNoFallback( translation.getClassName(), LocaleUtils.getLocale( translation.getLocale() ), translation.getProperty(), translation.getObjectUid() );
+
+        if ( translation.getValue() != null && !translation.getValue().trim().isEmpty() )
+        {
+            if ( translationNoFallback != null )
+            {
+                translationNoFallback.setValue( translation.getValue() );
+                updateTranslation( translationNoFallback );
+            }
+            else
+            {
+                addTranslation( translation );
+            }
+        }
+        else if ( translationNoFallback != null )
+        {
+            deleteTranslation( translationNoFallback );
+        }
     }
 }

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/translation/hibernate/HibernateTranslationStore.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/translation/hibernate/HibernateTranslationStore.java	2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/translation/hibernate/HibernateTranslationStore.java	2014-05-15 06:21:07 +0000
@@ -77,14 +77,14 @@
     }
 
     @SuppressWarnings( "unchecked" )
-    public Translation getTranslation( String className, int id, Locale locale, String property )
+    public Translation getTranslation( String className, Locale locale, String property, String objectUid )
     {
         Session session = sessionFactory.getCurrentSession();
 
         Criteria criteria = session.createCriteria( Translation.class );
 
         criteria.add( Restrictions.eq( "className", className ) );
-        criteria.add( Restrictions.eq( "id", id ) );
+        criteria.add( Restrictions.eq( "objectUid", objectUid ) );
         criteria.add( Restrictions.in( "locale", LocaleUtils.getLocaleFallbacks( locale ) ) );
         criteria.add( Restrictions.eq( "property", property ) );
 
@@ -98,14 +98,14 @@
     }
 
     @SuppressWarnings( "unchecked" )
-    public Translation getTranslationNoFallback( String className, int id, Locale locale, String property )
+    public Translation getTranslationNoFallback( String className, Locale locale, String property, String objectUid )
     {
         Session session = sessionFactory.getCurrentSession();
 
         Criteria criteria = session.createCriteria( Translation.class );
 
         criteria.add( Restrictions.eq( "className", className ) );
-        criteria.add( Restrictions.eq( "id", id ) );
+        criteria.add( Restrictions.eq( "objectUid", objectUid ) );
         criteria.add( Restrictions.eq( "locale", locale.toString() ) );
         criteria.add( Restrictions.eq( "property", property ) );
 
@@ -117,14 +117,14 @@
     }
     
     @SuppressWarnings( "unchecked" )
-    public Collection<Translation> getTranslations( String className, int id, Locale locale )
+    public Collection<Translation> getTranslations( String className, Locale locale, String objectUid )
     {
         Session session = sessionFactory.getCurrentSession();
 
         Criteria criteria = session.createCriteria( Translation.class );
 
         criteria.add( Restrictions.eq( "className", className ) );
-        criteria.add( Restrictions.eq( "id", id ) );
+        criteria.add( Restrictions.eq( "objectUid", objectUid ) );
         criteria.add( Restrictions.in( "locale", LocaleUtils.getLocaleFallbacks( locale ) ) );
 
         criteria.setCacheable( true );
@@ -135,14 +135,14 @@
     }
 
     @SuppressWarnings( "unchecked" )
-    public Collection<Translation> getTranslationsNoFallback( String className, int id, Locale locale )
+    public Collection<Translation> getTranslationsNoFallback( String className, String objectUid, Locale locale )
     {
         Session session = sessionFactory.getCurrentSession();
 
         Criteria criteria = session.createCriteria( Translation.class );
 
         criteria.add( Restrictions.eq( "className", className ) );
-        criteria.add( Restrictions.eq( "id", id ) );
+        criteria.add( Restrictions.eq( "objectUid", objectUid ) );
         criteria.add( Restrictions.eq( "locale", locale.toString() ) );
 
         criteria.setCacheable( true );
@@ -201,14 +201,14 @@
     }
 
     @SuppressWarnings( "unchecked" )
-    public void deleteTranslations( String className, int id )
+    public void deleteTranslations( String className, String objectUid )
     {
         Session session = sessionFactory.getCurrentSession();
 
-        Query query = session.createQuery( "from Translation t where t.className = :className and t.id = :id" );
+        Query query = session.createQuery( "from Translation t where t.className = :className and t.objectUid = :objectUid" );
 
         query.setString( "className", className );
-        query.setInteger( "id", id );
+        query.setString( "objectUid", objectUid );
 
         List<Object> objlist = query.list();
 

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/user/DefaultUserSettingService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/user/DefaultUserSettingService.java	2014-04-03 12:22:48 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/user/DefaultUserSettingService.java	2014-05-15 16:58:37 +0000
@@ -28,12 +28,12 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+import org.springframework.transaction.annotation.Transactional;
+
 import java.io.Serializable;
 import java.util.Collection;
 import java.util.Collections;
 
-import org.springframework.transaction.annotation.Transactional;
-
 /**
  * @author Torgeir Lorange Ostby
  * @version $Id: DefaultUserSettingService.java 5724 2008-09-18 14:37:01Z larshelg $
@@ -110,7 +110,19 @@
     public Serializable getUserSetting( String name )
     {
         User currentUser = currentUserService.getCurrentUser();
-
+        return getUserSetting(name, currentUser);
+    }
+
+
+    public Serializable getUserSetting( String name, String username )
+    {
+        UserCredentials credentials = userService.getUserCredentialsByUsername( username );
+        
+        return getUserSetting( name, credentials == null ? null : credentials.getUser() );
+    }
+
+    private Serializable getUserSetting( String name, User currentUser ) 
+    {
         if ( currentUser == null )
         {
             return null;

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml	2014-05-15 13:16:11 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml	2014-05-15 16:58:37 +0000
@@ -956,6 +956,7 @@
         <value>dataelementcategoryoption</value>
         <value>categorycombo</value>
         <value>categoryoptioncombo</value>
+        <value>translation</value>
         <value>userinfo</value>
         <value>usergroup</value>
         <value>userrole</value>

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/translation/hibernate/Translation.hbm.xml'
--- dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/translation/hibernate/Translation.hbm.xml	2013-09-25 08:46:13 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/translation/hibernate/Translation.hbm.xml	2014-05-15 16:58:37 +0000
@@ -1,19 +1,24 @@
 <?xml version="1.0"?>
 <!DOCTYPE hibernate-mapping PUBLIC
   "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
-  "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd";>
+  "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd";
+  [<!ENTITY identifiableProperties SYSTEM "classpath://org/hisp/dhis/common/identifiableProperties.hbm">]
+  >
 
 <hibernate-mapping>
   <class name="org.hisp.dhis.translation.Translation" table="translation">
 
     <cache usage="read-write" />
 
-    <composite-id>
-      <key-property name="className" column="objectclass" length="127" />
-      <key-property name="id" column="objectid" />
-      <key-property name="locale" column="locale" length="15" />
-      <key-property name="property" column="objectproperty" length="63" />
-    </composite-id>
+    <id name="id" column="translationid">
+      <generator class="native" />
+    </id>
+    &identifiableProperties;
+
+    <property name="className" column="objectclass" length="127" unique-key="translation_composite_key" />
+    <property name="objectUid" column="objectUid" length="11" unique-key="translation_composite_key" />
+    <property name="locale" column="locale" length="15" unique-key="translation_composite_key" />
+    <property name="property" column="objectproperty" length="63" unique-key="translation_composite_key" />
 
     <property name="value" column="value" type="text" not-null="true" />
 

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/i18n/I18nServiceTest.java'
--- dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/i18n/I18nServiceTest.java	2014-04-27 21:28:37 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/i18n/I18nServiceTest.java	2014-05-14 05:24:50 +0000
@@ -84,16 +84,16 @@
         String className = DataElement.class.getSimpleName();
         
         DataElement dataElementA = createDataElement( 'A' );
-        int idA = dataElementService.addDataElement( dataElementA );
+        String idA = dataElementA.getUid();
         
         Map<String, String> translationsA = new HashMap<String, String>();
         translationsA.put( "name", "frenchNameA" );
         translationsA.put( "shortName", "frenchShortNameA" );
         translationsA.put( "description", "frenchDescriptionA" );        
         
-        i18nService.updateTranslation( className, idA, locale, translationsA );
+        i18nService.updateTranslation( className, locale, translationsA, dataElementA.getUid());
         
-        Map<String, String> actual = i18nService.getTranslations( className, idA, locale );
+        Map<String, String> actual = i18nService.getTranslations( className, locale, idA );
         
         assertNotNull( actual );
         assertEquals( 3, actual.size() );
@@ -115,7 +115,7 @@
         translationsA.put( "shortName", "frenchShortNameA" );
         translationsA.put( "description", "frenchDescriptionA" );        
         
-        i18nService.updateTranslation( className, idA, locale, translationsA );
+        i18nService.updateTranslation( className, locale, translationsA,dataElementA.getUid() );
 
         assertEquals( "DataElementA", dataElementA.getDisplayName() );
         assertEquals( "DataElementShortA", dataElementA.getDisplayShortName() );
@@ -163,9 +163,9 @@
         translationsC.put( "shortName", "frenchShortNameC" );
         translationsC.put( "description", "frenchDescriptionC" );        
 
-        i18nService.updateTranslation( className, idA, locale, translationsA );
-        i18nService.updateTranslation( className, idB, locale, translationsB );
-        i18nService.updateTranslation( className, idC, locale, translationsC );
+        i18nService.updateTranslation( className, locale, translationsA,dataElementA.getUid() );
+        i18nService.updateTranslation( className, locale, translationsB,dataElementB.getUid() );
+        i18nService.updateTranslation( className, locale, translationsC, dataElementC.getUid());
         
         i18nService.internationalise( elements, locale );
         

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/translation/TranslationServiceTest.java'
--- dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/translation/TranslationServiceTest.java	2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/translation/TranslationServiceTest.java	2014-05-15 06:21:07 +0000
@@ -28,23 +28,16 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.Locale;
-
 import org.hisp.dhis.DhisSpringTest;
-import org.hisp.dhis.dataelement.DataElement;
-import org.hisp.dhis.organisationunit.OrganisationUnit;
-import org.junit.Ignore;
 import org.junit.Test;
 
+import java.util.Locale;
+
+import static org.junit.Assert.*;
+
 /**
  * @author Lars Helge Overland
  */
-@Ignore //TODO fails on ci
 public class TranslationServiceTest
     extends DhisSpringTest
 {
@@ -54,15 +47,15 @@
     // Testdata
     // -------------------------------------------------------------------------
 
-    private int id1 = 0;
-    private int id2 = 1;
+    private String uid1 = "uid1";
+    private String uid2 = "uid2";
 
     private String locale1 = Locale.UK.toString();
     private String locale2 = Locale.US.toString();
     private String locale3 = Locale.FRANCE.toString();
 
-    private String className1 = OrganisationUnit.class.getName();
-    private String className2 = DataElement.class.getName();
+    private String className1 = "class1";
+    private String className2 = "class2";
 
     private Translation translation1a;
     private Translation translation1b;
@@ -78,14 +71,14 @@
     public void setUpTest()
     {
         translationService = (TranslationService) getBean( TranslationService.ID );
-        
-        translation1a = new Translation( className1, id1, locale1, "name", "cheers" );
-        translation1b = new Translation( className1, id1, locale1, "shortName", "goodbye" );
-        translation2a = new Translation( className1, id1, locale2, "name", "hello" );
-        translation2b = new Translation( className2, id1, locale2, "name", "hey" );
-        translation2c = new Translation( className2, id2, locale3, "name", "bonjour" );
+
+        translation1a = new Translation( className1, locale1, "name", "cheers", uid1 );
+        translation1b = new Translation( className1, locale1, "shortName", "goodbye", uid1 );
+        translation2a = new Translation( className1, locale2, "name", "hello", uid1 );
+        translation2b = new Translation( className2, locale2, "name", "hey", uid1 );
+        translation2c = new Translation( className2, locale3, "name", "bonjour", uid2 );
     }
-    
+
     // -------------------------------------------------------------------------
     // Tests
     // -------------------------------------------------------------------------
@@ -95,46 +88,46 @@
     {
         translationService.addTranslation( translation1a );
         translationService.addTranslation( translation1b );
-        
-        assertEquals( translation1a, translationService.getTranslation( className1, id1, Locale.UK, "name" ) );
-        assertEquals( translation1b, translationService.getTranslation( className1, id1, Locale.UK, "shortName" ) );
+
+        assertEquals( translation1a, translationService.getTranslationNoFallback( className1, Locale.UK, "name", uid1 ) );
+        assertEquals( translation1b, translationService.getTranslationNoFallback( className1, Locale.UK, "shortName", uid1 ) );
     }
-    
+
     @Test
     public void delete()
     {
-        Translation translation1a = new Translation( className1, id1, locale1, "name", "habari" );
-        Translation translation1b = new Translation( className1, id1, locale1, "shortName", "kesho" );
-        
+        Translation translation1a = new Translation( className1, locale1, "name", "habari",  uid1 );
+        Translation translation1b = new Translation( className1, locale1, "shortName", "kesho",  uid1 );
+
         translationService.addTranslation( translation1a );
         translationService.addTranslation( translation1b );
-        
-        assertNotNull( translationService.getTranslation( className1, id1, Locale.UK, "name" ) );
-        assertNotNull( translationService.getTranslation( className1, id1, Locale.UK, "shortName" ) );
-        
+
+        assertNotNull( translationService.getTranslationNoFallback( className1, Locale.UK, "name", uid1 ) );
+        assertNotNull( translationService.getTranslationNoFallback( className1, Locale.UK, "shortName", uid1 ) );
+
         translationService.deleteTranslation( translation1a );
-        
-        assertNull( translationService.getTranslation( className1, id1, Locale.UK, "name" ) );
-        assertNotNull( translationService.getTranslation( className1, id1, Locale.UK, "shortName" ) );
-
-        translationService.deleteTranslation( translation1b );
-
-        assertNull( translationService.getTranslation( className1, id1, Locale.UK, "name" ) );
-        assertNull( translationService.getTranslation( className1, id1, Locale.UK, "shortName" ) );
+
+        assertNull( translationService.getTranslationNoFallback( className1, Locale.UK, "name", uid1 ) );
+        assertNotNull( translationService.getTranslationNoFallback( className1, Locale.UK, "shortName", uid1 ) );
+
+        translationService.deleteTranslations( translation1b.getClassName(),translation1b.getObjectUid() );
+
+        assertNull( translationService.getTranslationNoFallback( className1, Locale.UK, "name", uid1 ) );
+        assertNull( translationService.getTranslationNoFallback( className1, Locale.UK, "shortName", uid1 ) );
     }
 
     @Test
     public void testUpdateTranslation()
     {
         translationService.addTranslation( translation1a );
-        
-        assertEquals( translation1a, translationService.getTranslation( className1, id1, Locale.UK, "name" ) );
-        
+
+        assertEquals( translation1a, translationService.getTranslationNoFallback( className1, Locale.UK, "name",  uid1 ) );
+
         translation1a.setValue( "regards" );
-        
+
         translationService.updateTranslation( translation1a );
 
-        assertEquals( "regards", translationService.getTranslation( className1, id1, Locale.UK, "name" ).getValue() );
+        assertEquals( "regards", translationService.getTranslationNoFallback( className1, Locale.UK, "name",  uid1 ).getValue() );
     }
 
     @Test
@@ -145,12 +138,12 @@
         translationService.addTranslation( translation2a );
         translationService.addTranslation( translation2b );
         translationService.addTranslation( translation2c );
-        
+
         assertEquals( 2, translationService.getTranslations( className1, Locale.UK ).size() );
-        assertTrue( translationService.getTranslations( className1, id1, Locale.UK ).contains( translation1a ) );
-        assertTrue( translationService.getTranslations( className1, id1, Locale.UK ).contains( translation1b ) );
+        assertTrue( translationService.getTranslationsNoFallback( className1, Locale.UK, uid1 ).contains( translation1a ) );
+        assertTrue( translationService.getTranslationsNoFallback( className1, Locale.UK, uid1 ).contains( translation1b ) );
     }
-    
+
     @Test
     public void testGetAllTranslations()
     {
@@ -159,7 +152,7 @@
         translationService.addTranslation( translation2a );
         translationService.addTranslation( translation2b );
         translationService.addTranslation( translation2c );
-        
+
         assertEquals( 5, translationService.getAllTranslations().size() );
     }
 }

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/translation/TranslationStoreTest.java'
--- dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/translation/TranslationStoreTest.java	2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/translation/TranslationStoreTest.java	2014-05-14 05:24:50 +0000
@@ -45,7 +45,7 @@
  * @author Oyvind Brucker
  */
 @Ignore //TODO fails on ci
-public class TranslationStoreTest 
+public class TranslationStoreTest
     extends DhisSpringTest
 {
     private TranslationStore translationStore;
@@ -64,8 +64,8 @@
     // Testdata
     // -------------------------------------------------------------------------
 
-    private int id1 = 0;
-    private int id2 = 1;
+    private String uid1 = "uid1";
+    private String uid2 = "uid2";
 
     private String locale1 = Locale.UK.toString();
     private String locale2 = Locale.US.toString();
@@ -87,17 +87,17 @@
     @Test
     public void testAddGet()
     {
-        translation1a = new Translation( className1, id1, locale1, "name", "cheers" );
-        translation1b = new Translation( className1, id1, locale1, "shortName", "goodbye" );
-        translation2a = new Translation( className1, id1, locale2, "name", "hello" );
-        translation2b = new Translation( className2, id1, locale2, "name", "hey" );
-        translation2c = new Translation( className2, id2, locale3, "name", "bonjour" );
+        translation1a = new Translation( className1, locale1, "name", "cheers", className1 + uid1 );
+        translation1b = new Translation( className1, locale1, "shortName", "goodbye",className1 + uid1 );
+        translation2a = new Translation( className1, locale2, "name", "hello",className1 + uid1 );
+        translation2b = new Translation( className2, locale2, "name", "hey",className1 + uid1 );
+        translation2c = new Translation( className2, locale3, "name", "bonjour",className1 + uid2 );
         
         translationStore.addTranslation( translation1a );
         translationStore.addTranslation( translation1b );
         
-        assertEquals( translation1a, translationStore.getTranslation( className1, id1, Locale.UK, "name" ) );
-        assertEquals( translation1b, translationStore.getTranslation( className1, id1, Locale.UK, "shortName" ) );
+        assertEquals( translation1a, translationStore.getTranslation( className1, Locale.UK, "name", uid1 ) );
+        assertEquals( translation1b, translationStore.getTranslation( className1, Locale.UK, "shortName", uid1 ) );
     }
     
     @Test
@@ -106,18 +106,18 @@
         translationStore.addTranslation( translation1a );
         translationStore.addTranslation( translation1b );
         
-        assertNotNull( translationStore.getTranslation( className1, id1, Locale.UK, "name" ) );
-        assertNotNull( translationStore.getTranslation( className1, id1, Locale.UK, "shortName" ) );
+        assertNotNull( translationStore.getTranslation( className1, Locale.UK, "name", uid1 ) );
+        assertNotNull( translationStore.getTranslation( className1, Locale.UK, "shortName", uid1 ) );
         
         translationStore.deleteTranslation( translation1a );
         
-        assertNull( translationStore.getTranslation( className1, id1, Locale.UK, "name" ) );
-        assertNotNull( translationStore.getTranslation( className1, id1, Locale.UK, "shortName" ) );
+        assertNull( translationStore.getTranslation( className1, Locale.UK, "name", uid1 ) );
+        assertNotNull( translationStore.getTranslation( className1, Locale.UK, "shortName", uid1 ) );
 
         translationStore.deleteTranslation( translation1b );
 
-        assertNull( translationStore.getTranslation( className1, id1, Locale.UK, "name" ) );
-        assertNull( translationStore.getTranslation( className1, id1, Locale.UK, "shortName" ) );
+        assertNull( translationStore.getTranslation( className1, Locale.UK, "name", uid1 ) );
+        assertNull( translationStore.getTranslation( className1, Locale.UK, "shortName", uid1 ) );
     }
     
     @Test
@@ -125,13 +125,13 @@
     {
         translationStore.addTranslation( translation1a );
         
-        assertEquals( translation1a, translationStore.getTranslation( className1, id1, Locale.UK, "name" ) );
+        assertEquals( translation1a, translationStore.getTranslation( className1, Locale.UK, "name", uid1 ) );
         
         translation1a.setValue( "regards" );
         
         translationStore.updateTranslation( translation1a );
 
-        assertEquals( "regards", translationStore.getTranslation( className1, id1, Locale.UK, "name" ).getValue() );
+        assertEquals( "regards", translationStore.getTranslation( className1, Locale.UK, "name", uid1 ).getValue() );
     }
 
     @Test
@@ -143,9 +143,9 @@
         translationStore.addTranslation( translation2b );
         translationStore.addTranslation( translation2c );
         
-        assertEquals( 2, translationStore.getTranslations( className1, id1, Locale.UK ).size() );
-        assertTrue( translationStore.getTranslations( className1, id1, Locale.UK ).contains( translation1a ) );
-        assertTrue( translationStore.getTranslations( className1, id1, Locale.UK ).contains( translation1b ) );
+        assertEquals( 2, translationStore.getTranslations( className1, Locale.UK, uid1 ).size() );
+        assertTrue( translationStore.getTranslations( className1, Locale.UK, uid1 ).contains( translation1a ) );
+        assertTrue( translationStore.getTranslations( className1, Locale.UK, uid1 ).contains( translation1b ) );
     }
 
     @Test
@@ -158,8 +158,8 @@
         translationStore.addTranslation( translation2c );
         
         assertEquals( 2, translationStore.getTranslations( className1, Locale.UK ).size() );
-        assertTrue( translationStore.getTranslations( className1, id1, Locale.UK ).contains( translation1a ) );
-        assertTrue( translationStore.getTranslations( className1, id1, Locale.UK ).contains( translation1b ) );
+        assertTrue( translationStore.getTranslations( className1, Locale.UK, uid1 ).contains( translation1a ) );
+        assertTrue( translationStore.getTranslations( className1, Locale.UK, uid1 ).contains( translation1b ) );
     }
     
     @Test

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/user/UserSettingServiceTest.java'
--- dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/user/UserSettingServiceTest.java	2014-04-28 19:23:37 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/user/UserSettingServiceTest.java	2014-05-06 12:15:56 +0000
@@ -28,13 +28,15 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import static org.junit.Assert.assertEquals;
-
 import org.hisp.dhis.DhisSpringTest;
 import org.junit.Ignore;
 import org.junit.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 
+import java.io.Serializable;
+
+import static org.junit.Assert.assertEquals;
+
 /**
  * @author Kiran Prakash
  */
@@ -52,7 +54,7 @@
     private UserCredentialsStore userCredentialStore;
 
     private User testUser;
-    
+
     @Override
     protected void setUpTest()
         throws Exception
@@ -73,4 +75,14 @@
         assertEquals( "myvalue", setting.getValue() );
         assertEquals( "mykey", setting.getName() );
     }
+
+   @Test
+   public void testShouldGetUserSettings() {
+       UserCredentials userCredentials = testUser.getUserCredentials();
+       userCredentials.setUser( testUser );
+       userCredentialStore.addUserCredentials( userCredentials );
+       userSettingService.saveUserSetting("mykey", "value", "username");
+       Serializable preference = userSettingService.getUserSetting("mykey", "username");
+       assertEquals(preference, "value");
+   }
 }

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/utils/JacksonUtils.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/utils/JacksonUtils.java	2014-05-05 18:01:22 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/utils/JacksonUtils.java	2014-05-12 08:45:52 +0000
@@ -30,6 +30,8 @@
 
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.MapperFeature;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -46,10 +48,12 @@
 import org.hisp.dhis.common.view.ShortNameView;
 import org.hisp.dhis.common.view.UuidView;
 import org.hisp.dhis.common.view.WithoutOrganisationUnitsView;
+import org.hisp.dhis.translation.Translation;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -209,4 +213,9 @@
     {
         return (T) xmlMapper.readValue( input, clazz );
     }
+
+    public static <T> T fromJson( InputStream inputStream, TypeReference<?> typeReference ) throws IOException
+    {
+        return (T) jsonMapper.readValue( inputStream, typeReference );
+    }
 }

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/resources/META-INF/dhis/beans.xml	2014-04-04 21:24:04 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/resources/META-INF/dhis/beans.xml	2014-05-15 07:04:43 +0000
@@ -98,6 +98,10 @@
     <constructor-arg name="importerClass" type="java.lang.Class" value="org.hisp.dhis.dataset.DataSet" />
   </bean>
 
+  <bean id="dataApprovalLevelImporter" class="org.hisp.dhis.dxf2.metadata.importers.DefaultIdentifiableObjectImporter" scope="prototype">
+    <constructor-arg name="importerClass" type="java.lang.Class" value="org.hisp.dhis.dataapproval.DataApprovalLevel" />
+  </bean>
+
   <bean id="documentImporter" class="org.hisp.dhis.dxf2.metadata.importers.DefaultIdentifiableObjectImporter" scope="prototype">
     <constructor-arg name="importerClass" type="java.lang.Class" value="org.hisp.dhis.document.Document" />
   </bean>

=== modified file 'dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/StatementBuilder.java'
--- dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/StatementBuilder.java	2014-04-07 14:27:23 +0000
+++ dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/StatementBuilder.java	2014-05-15 16:58:37 +0000
@@ -28,8 +28,9 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+import java.util.List;
+
 import org.hisp.dhis.period.Period;
-import java.util.List;
 
 /**
  * @author Lars Helge Overland
@@ -42,7 +43,7 @@
     //--------------------------------------------------------------------------
     // General
     //--------------------------------------------------------------------------
-
+    
     /**
      * Encodes the provided SQL value. Value will be wrapped in quotes.
      * 
@@ -205,4 +206,10 @@
     String queryDataElementStructureForOrgUnit();
 
     String queryRawDataElementsForOrgUnitBetweenPeriods( Integer orgUnitId, List<Integer> betweenPeriodIds );
+    
+    String getDropPrimaryKey( String table );
+    
+    String getAddPrimaryKeyToExistingTable( String table, String column );
+    
+    String getDropNotNullConstraint( String table, String column, String type );
 }

=== modified file 'dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/statementbuilder/AbstractStatementBuilder.java'
--- dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/statementbuilder/AbstractStatementBuilder.java	2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/statementbuilder/AbstractStatementBuilder.java	2014-05-15 16:58:37 +0000
@@ -194,4 +194,22 @@
             "where tc.constraint_type='PRIMARY KEY' " +
             "and cu.table_name='" + table + "';";
     }
+
+    @Override
+    public String getDropPrimaryKey( String table )
+    {
+        return "alter table " + table + " drop primary key;";
+    }
+
+    @Override
+    public String getAddPrimaryKeyToExistingTable( String table, String column )
+    {
+        return "alter table " + table + " add column " + column + " integer auto_increment primary key not null;";
+    }
+    
+    @Override
+    public String getDropNotNullConstraint( String table, String column, String type )
+    {
+        return "alter table " + table + " modify column " + column + " " + type + " null;";
+    }
 }

=== modified file 'dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/statementbuilder/HsqlStatementBuilder.java'
--- dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/statementbuilder/HsqlStatementBuilder.java	2014-04-07 14:37:39 +0000
+++ dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/statementbuilder/HsqlStatementBuilder.java	2014-05-15 16:58:37 +0000
@@ -35,7 +35,7 @@
  */
 public class HsqlStatementBuilder
     extends AbstractStatementBuilder
-{    
+{
     @Override
     public String getDoubleColumnType()
     {

=== modified file 'dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/statementbuilder/MySQLStatementBuilder.java'
--- dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/statementbuilder/MySQLStatementBuilder.java	2014-04-07 14:37:39 +0000
+++ dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/statementbuilder/MySQLStatementBuilder.java	2014-05-15 16:58:37 +0000
@@ -35,7 +35,7 @@
  */
 public class MySQLStatementBuilder
     extends AbstractStatementBuilder
-{
+{    
     @Override
     public String getDoubleColumnType()
     {

=== modified file 'dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/statementbuilder/PostgreSQLStatementBuilder.java'
--- dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/statementbuilder/PostgreSQLStatementBuilder.java	2014-04-07 14:27:23 +0000
+++ dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/statementbuilder/PostgreSQLStatementBuilder.java	2014-05-15 16:58:37 +0000
@@ -35,7 +35,7 @@
  */
 public class PostgreSQLStatementBuilder
     extends AbstractStatementBuilder
-{    
+{
     @Override
     public String getDoubleColumnType()
     {
@@ -239,4 +239,26 @@
         
         return sqlsb.toString();
     }
+
+    @Override
+    public String getDropPrimaryKey( String table )
+    {
+        return "alter table " + table + " drop constraint " + table + "_pkey;";
+    }
+
+    @Override
+    public String getAddPrimaryKeyToExistingTable( String table, String column )
+    {
+        return
+            "alter table " + table + " add column " + column + " integer;" +
+            "update " + table + " set " + column + " = nextval('hibernate_sequence') where " + column + " is null;" +
+            "alter table " + table + " alter column " + column + " set not null;" +
+            "alter table " + table + " add primary key(" + column + ");";
+    }
+
+    @Override
+    public String getDropNotNullConstraint( String table, String column, String type )
+    {
+        return "alter table " + table + " alter column " + column + " drop not null;";
+    }
 }

=== modified file 'dhis-2/dhis-support/dhis-support-system/src/test/java/org/hisp/dhis/system/util/LocaleUtilsTest.java'
--- dhis-2/dhis-support/dhis-support-system/src/test/java/org/hisp/dhis/system/util/LocaleUtilsTest.java	2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-support/dhis-support-system/src/test/java/org/hisp/dhis/system/util/LocaleUtilsTest.java	2014-05-05 12:22:43 +0000
@@ -50,14 +50,14 @@
         Locale l2 = new Locale( "en", "UK" );
         Locale l3 = new Locale( "en" );
         
-        Translation t1 = new Translation( DataElement.class.getSimpleName(), 1, l1.toString(), "name", "Name" );
-        Translation t2 = new Translation( DataElement.class.getSimpleName(), 1, l2.toString(), "name", "Name" );
-        Translation t3 = new Translation( DataElement.class.getSimpleName(), 1, l3.toString(), "name", "Name" );
+        Translation t1 = new Translation( DataElement.class.getSimpleName(), l1.toString(), "name", "Name", "1" );
+        Translation t2 = new Translation( DataElement.class.getSimpleName(), l2.toString(), "name", "Name","1" );
+        Translation t3 = new Translation( DataElement.class.getSimpleName(), l3.toString(), "name", "Name","1" );
 
-        Translation t4 = new Translation( DataElement.class.getSimpleName(), 1, l1.toString(), "shortName", "Short name" );
-        Translation t5 = new Translation( DataElement.class.getSimpleName(), 1, l2.toString(), "shortName", "Short name" );
+        Translation t4 = new Translation( DataElement.class.getSimpleName(), l1.toString(), "shortName", "Short name", "1");
+        Translation t5 = new Translation( DataElement.class.getSimpleName(), l2.toString(), "shortName", "Short name", "1");
         
-        Translation t6 = new Translation( DataElement.class.getSimpleName(), 1, l2.toString(), "code", "Code" );
+        Translation t6 = new Translation( DataElement.class.getSimpleName(), l2.toString(), "code", "Code", "1");
         
         List<Translation> list = Arrays.asList( t1, t2, t3, t4, t5, t6 );
         

=== added file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/TranslationController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/TranslationController.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/TranslationController.java	2014-05-14 11:03:46 +0000
@@ -0,0 +1,50 @@
+package org.hisp.dhis.api.controller;
+
+import org.hisp.dhis.api.utils.ContextUtils;
+import org.hisp.dhis.dxf2.utils.JacksonUtils;
+import org.hisp.dhis.translation.TranslationService;
+import org.hisp.dhis.translation.Translations;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+import static org.hisp.dhis.api.utils.ContextUtils.CONTENT_TYPE_JSON;
+
+/**
+ * Created by kprakash on 05/05/14.
+ */
+
+@Controller
+@RequestMapping(value = TranslationController.RESOURCE_PATH)
+public class TranslationController
+{
+    public static final String RESOURCE_PATH = "/translations";
+
+    @Autowired
+    private ContextUtils contextUtils;
+
+
+    @Autowired
+    private TranslationService translationService;
+
+
+    @RequestMapping( produces = CONTENT_TYPE_JSON, method = RequestMethod.GET )
+    public void exportJson( HttpServletResponse response ) throws IOException
+    {
+        contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_JSON, ContextUtils.CacheStrategy.NO_CACHE, "translations.json", false );
+        JacksonUtils.toJson( response.getOutputStream(), new Translations( translationService.getAllTranslations() ) );
+    }
+
+    @RequestMapping(method = RequestMethod.POST, consumes = CONTENT_TYPE_JSON)
+    public void importJson( HttpServletRequest request ) throws IOException
+    {
+        Translations translations = JacksonUtils.fromJson( request.getInputStream(), Translations.class );
+        translationService.createOrUpdate( translations.getTranslations() );
+    }
+
+}
\ No newline at end of file

=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/UserSettingController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/UserSettingController.java	2014-04-03 12:22:48 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/UserSettingController.java	2014-05-15 16:58:37 +0000
@@ -28,18 +28,13 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import javax.servlet.http.HttpServletResponse;
-
 import org.hisp.dhis.api.utils.ContextUtils;
 import org.hisp.dhis.user.UserSettingService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
 
 /**
  * @author Lars Helge Overland
@@ -85,9 +80,9 @@
     }
 
     @RequestMapping( value = "/{key}", method = RequestMethod.GET, produces = ContextUtils.CONTENT_TYPE_TEXT )
-    public @ResponseBody String getSystemSetting( @PathVariable( "key" ) String key )
+    public @ResponseBody String getSystemSetting( @PathVariable( "key" ) String key, @RequestParam(value = "user", required = false) String username ) 
     {
-        return (String) userSettingService.getUserSetting( key );
+        return (String) ( username == null ? userSettingService.getUserSetting( key ) : userSettingService.getUserSetting( key, username ) );
     }
 
     @RequestMapping( value = "/{key}", method = RequestMethod.DELETE )

=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/user/UserController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/user/UserController.java	2014-04-02 11:36:07 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/user/UserController.java	2014-04-14 14:37:03 +0000
@@ -188,10 +188,12 @@
 
         User parsed = renderService.fromXml( request.getInputStream(), getEntityClass() );
         parsed.setUid( uid );
-
-        String encodePassword = passwordManager.encodePassword( parsed.getUsername(),
-            parsed.getUserCredentials().getPassword() );
-        parsed.getUserCredentials().setPassword( encodePassword );
+        if (parsed.getUserCredentials().getPassword() != null)
+        {
+            String encodePassword = passwordManager.encodePassword( parsed.getUsername(),
+                parsed.getUserCredentials().getPassword() );
+            parsed.getUserCredentials().setPassword( encodePassword );
+        }
 
         ImportTypeSummary summary = importService.importObject( currentUserService.getCurrentUser().getUid(), parsed, ImportStrategy.UPDATE );
         renderService.toJson( response.getOutputStream(), summary );
@@ -218,9 +220,12 @@
         User parsed = renderService.fromJson( request.getInputStream(), getEntityClass() );
         parsed.setUid( uid );
 
-        String encodePassword = passwordManager.encodePassword( parsed.getUsername(),
-            parsed.getUserCredentials().getPassword() );
-        parsed.getUserCredentials().setPassword( encodePassword );
+        if (parsed.getUserCredentials().getPassword() != null)
+        {
+            String encodePassword = passwordManager.encodePassword( parsed.getUsername(),
+                parsed.getUserCredentials().getPassword() );
+            parsed.getUserCredentials().setPassword( encodePassword );
+        }
 
         ImportTypeSummary summary = importService.importObject( currentUserService.getCurrentUser().getUid(), parsed, ImportStrategy.UPDATE );
         renderService.toJson( response.getOutputStream(), summary );

=== modified file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/i18n/translate.vm'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/i18n/translate.vm	2013-10-01 16:44:42 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/i18n/translate.vm	2014-05-05 12:22:43 +0000
@@ -6,7 +6,7 @@
 <h3>$i18n.getString( "translation_translate" ) #openHelp( "translation" )</h3>
 
 <div>
-	<input type="hidden" id="objectId" name="objectId" value="$objectId"/>
+	<input type="hidden" id="uid" name="uid" value="$uid"/>
 	<input type="hidden" id="className" name="className" value="$className"/>
 	<input type="hidden" id="returnUrl" name="returnUrl" value="$returnUrl"/>
 </div>

=== modified file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/commons.js'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/commons.js	2014-01-23 14:09:55 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/commons.js	2014-05-05 09:21:46 +0000
@@ -86,7 +86,7 @@
  * @param context Context vars from context menu
  */
 function translateWithContext( context ) {
-  translate( context.type, context.id );
+  translate( context.type, context.uid );
 }
 
 /**
@@ -95,9 +95,9 @@
  * @param className the name of the object class.
  * @param objectId the identifier of the object.
  */
-function translate( className, objectId )
+function translate( className, uid )
 {
-    var url = "../dhis-web-commons/i18n.action?className=" + className + "&objectId=" + objectId + "&returnUrl=" + htmlEncode( window.location.href ); 
+    var url = "../dhis-web-commons/i18n.action?className=" + className + "&uid=" + uid + "&returnUrl=" + htmlEncode( window.location.href );
     
     window.location.href = url; 
 }

=== modified file 'dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/i18n/action/GetTranslationsAction.java'
--- dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/i18n/action/GetTranslationsAction.java	2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/i18n/action/GetTranslationsAction.java	2014-05-05 12:22:43 +0000
@@ -41,10 +41,11 @@
  */
 public class GetTranslationsAction 
     extends ActionSupport
+
 {
     private String className;
 
-    private Integer id;
+    private String uid;
 
     private String loc;
 
@@ -70,9 +71,9 @@
         this.className = className;
     }
 
-    public void setId( Integer id )
+    public void setUid( String uid )
     {
-        this.id = id;
+        this.uid = uid;
     }
 
     public void setLoc( String locale )
@@ -94,7 +95,7 @@
     {
         Locale locale = LocaleUtils.getLocale( loc );
 
-        translations = i18nService.getTranslationsNoFallback( className, id, locale );
+        translations = i18nService.getTranslationsNoFallback( className, uid, locale );
         
         return SUCCESS;
     }

=== modified file 'dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/i18n/action/I18nAction.java'
--- dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/i18n/action/I18nAction.java	2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/i18n/action/I18nAction.java	2014-05-05 12:22:43 +0000
@@ -51,7 +51,7 @@
 {
     private String className;
 
-    private Integer objectId;
+    private String uid;
 
     private String returnUrl;
 
@@ -94,9 +94,9 @@
         this.className = className;
     }
 
-    public void setObjectId( Integer objectId )
+    public void setUid( String uid )
     {
-        this.objectId = objectId;
+        this.uid = uid;
     }
 
     public void setReturnUrl( String returnUrl )
@@ -118,9 +118,9 @@
         return className;
     }
 
-    public Integer getObjectId()
+    public String getUid()
     {
-        return objectId;
+        return uid;
     }
 
     public String getReturnUrl()
@@ -169,9 +169,9 @@
         
         availableLocales = i18nService.getAvailableLocales();
         
-        translations = i18nService.getTranslationsNoFallback( className, objectId );
+        translations = i18nService.getTranslationsNoFallback( className, uid );
 
-        IdentifiableObject object = identifiableObjectManager.getObject( objectId, className );
+        IdentifiableObject object = identifiableObjectManager.getObject( uid, className );
 
         referenceTranslations = i18nService.getObjectPropertyValues( object );
 

=== modified file 'dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/i18n/action/TranslateAction.java'
--- dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/i18n/action/TranslateAction.java	2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/i18n/action/TranslateAction.java	2014-05-05 12:22:43 +0000
@@ -56,7 +56,7 @@
 
     private String className;
 
-    private String objectId;
+    private String uid;
 
     private String loc;
 
@@ -91,9 +91,9 @@
         this.className = className;
     }
 
-    public void setObjectId( String objectId )
+    public void setUid( String uid )
     {
-        this.objectId = objectId;
+        this.uid = uid;
     }
 
     public void setLoc( String locale )
@@ -115,9 +115,9 @@
         return className;
     }
 
-    public String getObjectId()
+    public String getUid()
     {
-        return objectId;
+        return uid;
     }
 
     public String getLocale()
@@ -142,9 +142,9 @@
     public String execute()
         throws Exception
     {
-        log.info( "Classname: " + className + ", id: " + objectId + ", loc: " + loc );
+        log.info( "Classname: " + className + ", uid: " + uid + ", loc: " + loc );
 
-        IdentifiableObject object = identifiableObjectManager.getObject( Integer.parseInt( objectId ), className );
+        IdentifiableObject object = identifiableObjectManager.getObject( uid , className );
 
         List<String> propertyNames = i18nService.getObjectPropertyNames( object );
         
@@ -168,7 +168,7 @@
 
         if ( thisLocale != null && !loc.equals( "NONE" ) )
         {
-            i18nService.updateTranslation( className, Integer.parseInt( objectId ), thisLocale, translations );
+            i18nService.updateTranslation( className, thisLocale, translations,object.getUid() );
         }
 
         return SUCCESS;