diff --git a/entity/KeywordEntry_entity/KeywordEntry_entity.aod b/entity/KeywordEntry_entity/KeywordEntry_entity.aod
index 4d1defec8473e3987314b18167899075a7213eb0..997ef899c33c00882f9bc3bd37239a3891e5028b 100644
--- a/entity/KeywordEntry_entity/KeywordEntry_entity.aod
+++ b/entity/KeywordEntry_entity/KeywordEntry_entity.aod
@@ -291,6 +291,9 @@
         <jDitoRecordFieldMapping>
           <name>UID.value</name>
         </jDitoRecordFieldMapping>
+        <jDitoRecordFieldMapping>
+          <name>CONTAINER.value</name>
+        </jDitoRecordFieldMapping>
       </recordFieldMappings>
     </jDitoRecordContainer>
   </recordContainers>
diff --git a/entity/KeywordEntry_entity/recordcontainers/jdito/contentProcess.js b/entity/KeywordEntry_entity/recordcontainers/jdito/contentProcess.js
index addb6c2a647520290524a55d47f4b1eb3f020e60..2324a3e62fbe9ad21c7b9c38e83b20f4b8a6c318 100644
--- a/entity/KeywordEntry_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/KeywordEntry_entity/recordcontainers/jdito/contentProcess.js
@@ -17,7 +17,7 @@ var CATEGORY_RESULT_INDEX_SORTINGBY = 2;
 var CATEGORY_RESULT_INDEX_SORTINGDIR = 3;
 
 var resultSet = [];
-var keywordStatement = newSelect("AB_KEYWORD_ENTRY.KEYID, AB_KEYWORD_ENTRY.TITLE, AB_KEYWORD_ENTRY.AB_KEYWORD_ENTRYID as UID")
+var keywordStatement = newSelect("AB_KEYWORD_ENTRY.KEYID, AB_KEYWORD_ENTRY.TITLE, AB_KEYWORD_ENTRY.AB_KEYWORD_ENTRYID as UID, AB_KEYWORD_CATEGORY.NAME")
                 .from("AB_KEYWORD_ENTRY")
                 .join("AB_KEYWORD_CATEGORY", "AB_KEYWORD_ENTRY.AB_KEYWORD_CATEGORY_ID = AB_KEYWORD_CATEGORY.AB_KEYWORD_CATEGORYID")
                 .where();
diff --git a/process/Observation_lib/process.js b/process/Observation_lib/process.js
index ae2bcc3a65a8ab12a99345314a0f8eb6c29db92c..7037b65adf630093f6efb2d95493cdc30aa1fffc 100644
--- a/process/Observation_lib/process.js
+++ b/process/Observation_lib/process.js
@@ -1,3 +1,4 @@
+import("Keyword_lib");
 import("Util_lib");
 import("system.neon");
 import("KeywordRegistry_basic");
@@ -29,8 +30,8 @@ import("system.neon");
 function Observation(pVariable, pStoredFilterResults, pStoredObservedFields)
 {
     this.callerVariables = pVariable || {};
-    this.storedFilterResults = pStoredFilterResults || {};
-    this.storedObservedFields = pStoredObservedFields || {};
+    this.storedFilterResults = pStoredFilterResults || new Map();
+    this.storedObservedFields = pStoredObservedFields || new Map();
 }
 
 Observation.OBJECT_TYPE = function () 
@@ -191,9 +192,9 @@ Observation.prototype.checkFilterAndPermissions = function (pUserTitle, pFilterO
     }
     
     // check if the observation has been alredy checkt
-    if (this.storedFilterResults[storedIndex])
+    if (this.storedFilterResults.has(storedIndex))
     {
-        return JSON.parse(this.storedFilterResults[storedIndex]);
+        return JSON.parse(this.storedFilterResults.get(storedIndex));
     }
     
     try 
@@ -225,7 +226,7 @@ Observation.prototype.checkFilterAndPermissions = function (pUserTitle, pFilterO
         filterResult = null;
     }
     
-    this.storedFilterResults[storedIndex] = JSON.stringify(filterResult);
+    this.storedFilterResults.set(storedIndex, JSON.stringify(filterResult));
     return filterResult
 }
 
@@ -238,22 +239,34 @@ Observation.prototype.checkFilterAndPermissions = function (pUserTitle, pFilterO
  */
 Observation.prototype.parseAndFilterObjectFields = function (pObjectFields, pUserTitle) 
 {
-    let storedIndex = pObjectFields + pUserTitle;
+    var storedIndex = pObjectFields + pUserTitle;
     
-    if (this.storedObservedFields[storedIndex])
+    if (this.storedObservedFields.has(storedIndex))
     {
-        return JSON.parse(this.storedObservedFields[storedIndex]);
+        return JSON.parse(this.storedObservedFields.get(storedIndex));
     }
     
-    let observeFields = {};
+    var observeFields = {};
     observeFields[Observation.RECORDS_SPECIFIC_VALUES()] = {};
-    text.decodeMS(pObjectFields).forEach(function (observeFiled) {
-        let field = text.decodeMS(observeFiled);
-        let fieldNames = text.decodeMS(field[0]);
-        if (this.callerVariables[WorkflowVariables.CHANGED_ROWS()].indexOf(fieldNames[0]) > -1)
+    var objectFields = text.decodeMS(pObjectFields);
+    objectFields.forEach(function (observeFiled) 
+    {
+        var field = text.decodeMS(observeFiled);
+        var fieldNames = text.decodeMS(field[0]);
+        var observedField = fieldNames[0];
+        if (this.callerVariables[WorkflowVariables.CHANGED_ROWS()].includes(observedField))
         {
-            let displayValueField = "#COLUMNEXP_____" + fieldNames[1] + ".displayValue";
-            let observedField = this.callerVariables[WorkflowVariables.ROWDATA()][displayValueField] ? displayValueField : fieldNames[0];
+            var displayValueField = "#COLUMNEXP_____" + fieldNames[1] + ".displayValue";
+            var fieldType = this.callerVariables[WorkflowVariables.CHANGED_ROWS_TYPES()][observedField];
+            if (Utils.isObject(fieldType))
+            {
+                fieldType = fieldType.type;
+            }
+            //Keywords are resolved separately so they can be translated correctly
+            if (displayValueField in this.callerVariables[WorkflowVariables.ROWDATA()] && fieldType != "KEYWORD")
+            {
+                observedField = displayValueField;
+            }
             if (tools.hasPermission(tools.PERMISSION_VIEW, this.callerVariables[Observation.ENTITY_NAME()], fieldNames[1], pUserTitle))
             {
                 observeFields[observedField] = field[1];
@@ -261,22 +274,21 @@ Observation.prototype.parseAndFilterObjectFields = function (pObjectFields, pUse
         }
     }, this);
     
-    this.storedObservedFields[storedIndex] = JSON.stringify(observeFields);
+    this.storedObservedFields.set(storedIndex, JSON.stringify(observeFields));
     return observeFields;
 }
 
 /**
  * Chack if the Observation has a Dependenencie and if it has the observation will be checked recursive.
- * This function is call by references and the dependent ids and context will saved in the pTempObserver object. 
  * 
- * @param {String} [pObserver] the Observer ID
  * @param {String} [pDependentContext] the context of the parend observation
  * @param {Object} [pTempObserver] the tempObservation of 
  * @param {String} [pDependentObservationId] the id of the parend observation
- * @return {Void}
+ * @return {Object} returns pTempObserver if something was found, or null if not
  */
-Observation.prototype._checkDependencies = function (pObserver, pDependentContext, pTempObserver, pDependentObservationId)
+Observation.prototype._checkDependencies = function (pDependentContext, pTempObserver, pDependentObservationId)
 {
+    
     let tempOriginalRowdata = JSON.stringify(this.callerVariables[WorkflowVariables.ROWDATA()]);
     let targetEntity = ContextUtils.getEntity(this.callerVariables[WorkflowVariables.TARGET_CONTEXT()]);
     let dependentEntity = ContextUtils.getEntity(pDependentContext); 
@@ -288,8 +300,10 @@ Observation.prototype._checkDependencies = function (pObserver, pDependentContex
     dependentCheckVars[WorkflowVariables.TARGET_CONTEXT()] = pDependentContext;
     dependentCheckVars[WorkflowVariables.EVENT_USER()] = this.callerVariables[WorkflowVariables.EVENT_USER()];
     
-    Object.keys(pTempObserver[pObserver][Observation.RECORDS_SPECIFIC_VALUES()]).forEach(function (pRecordID) {
-        let specificRecordValues = pTempObserver[pObserver][Observation.RECORDS_SPECIFIC_VALUES()][pRecordID];
+    var res = pTempObserver;
+    for (let recordId in pTempObserver[Observation.RECORDS_SPECIFIC_VALUES()])
+    {
+        let specificRecordValues = pTempObserver[Observation.RECORDS_SPECIFIC_VALUES()][recordId];
         Observation._syncRecordsSpecificValues(specificRecordValues, this.callerVariables[WorkflowVariables.ROWDATA()]);
     
         var dependentIds = dependentObject.getUIDsfn(this.callerVariables[WorkflowVariables.ROWDATA()], this.callerVariables[WorkflowVariables.INITIAL_ROWDATA()]);
@@ -310,10 +324,11 @@ Observation.prototype._checkDependencies = function (pObserver, pDependentContex
         }
         else
         {
-            pTempObserver[pObserver] = null;
+            res = null;
         }
-    }, this)
+    }
     this.callerVariables[WorkflowVariables.ROWDATA()] = JSON.parse(tempOriginalRowdata);
+    return res;
 }
 
 /**
@@ -371,7 +386,7 @@ Observation.prototype._formatFieldsToLoad =  function (pFilterResults)
 }
 
 /**
- * Checks the observations for the specific changed data set and then forwards them to the Observation._notifiyUsers() function.
+ * Checks the observations for the specific changed data set and then forwards them to the Observation._notifyUsers() function.
  * 
  * @param {String} [pObservationId] the id of the parent observation. This variable is required for the recursion.
  * 
@@ -381,9 +396,17 @@ Observation.prototype.checkObservation = function(pObservationId)
 {
     if (this.callerVariables[WorkflowVariables.TRIGGER()])
     {
+        const OBJECT_ID = 0;
+        const OBJECT_FILTER = 1;
+        const OBSERVER = 2;
+        const OBJECT_FIELD = 3;
+        const OBJECT_TYPE = 4;
+        const OBSERVATION_ID = 5;
+        const PRIO = 6;
+        
         Observation.parseALLVariable(this.callerVariables);
         
-        var observers = {};
+        var observers = new Map();
         this.observations = Observation.getObservations(
             this.callerVariables[WorkflowVariables.TRIGGER()], 
             this.callerVariables[WorkflowVariables.TARGET_ID()],
@@ -393,15 +416,16 @@ Observation.prototype.checkObservation = function(pObservationId)
         
         for (let i = 0; i < this.observations.length; i++)
         {
-            var tempObserver = {};
+            var tempObserver = null;
             var observation = this.observations[i];
-            var user = tools.getUserByAttribute(tools.NAME, observation[2], tools.PROFILE_DEFAULT);
+            var observerUser = observation[OBSERVER];
+            var user = tools.getUserByAttribute(tools.NAME, observerUser, tools.PROFILE_DEFAULT);
             var filterResult;
             
             // exclude the user who made the changes. 
-            if (user && this.callerVariables[WorkflowVariables.EVENT_USER()] !== user["name"])
+            if (user && this.callerVariables[WorkflowVariables.EVENT_USER()] !== user[tools.NAME])
             {
-                filterResult = this.checkFilterAndPermissions(user.title, observation[1], observation[0]);
+                filterResult = this.checkFilterAndPermissions(user[tools.TITLE], observation[OBJECT_FILTER], observation[OBJECT_ID]);
             
                 if (filterResult && Object.keys(filterResult).length)
                 {
@@ -410,28 +434,31 @@ Observation.prototype.checkObservation = function(pObservationId)
                         return filterResult;
                     }
                     
-                    if (Utils.isNullOrEmpty(observation[3]))
+                    if (Utils.isNullOrEmpty(observation[OBJECT_FIELD]))
                     {
-                        observation[3] = Observation.getAllFieldValue(this.callerVariables[WorkflowVariables.TARGET_CONTEXT()]);
+                        observation[OBJECT_FIELD] = Observation.getAllFieldValue(this.callerVariables[WorkflowVariables.TARGET_CONTEXT()]);
                     }
-                    tempObserver[observation[2]] = this.parseAndFilterObjectFields(observation[3], user.title, filterResult);
-                    tempObserver[observation[2]][Observation.RECORDS_SPECIFIC_VALUES()] = this._formatFieldsToLoad(filterResult);
+                    tempObserver = this.parseAndFilterObjectFields(observation[OBJECT_FIELD], user[tools.TITLE], filterResult);
+                    tempObserver[Observation.RECORDS_SPECIFIC_VALUES()] = this._formatFieldsToLoad(filterResult);
                 }
                 else if (this.callerVariables[WorkflowVariables.TRIGGER()] == WorkflowSignalSender.EVENT_DELETE())
                 {
-                    tempObserver[observation[2]] = {};
+                    tempObserver = {};
                 }
                 
-                if (tempObserver[observation[2]])
+                if (tempObserver)
                 {
-                    tempObserver[observation[2]][Observation.PRIO()] = observation[6];
+                    tempObserver[Observation.PRIO()] = observation[PRIO];
+                    tempObserver.locale = user[tools.PARAMS][tools.LOCALE];
+                    tempObserver.timezone = user[tools.PARAMS][tools.TIMEZONE];
             
-                    if (observation[4] && !pObservationId) 
+                    if (observation[OBJECT_TYPE] && !pObservationId) 
                     {
-                        this._checkDependencies(observation[2], observation[4], tempObserver, observation[5]);
+                        tempObserver = this._checkDependencies(observation[OBJECT_TYPE], tempObserver, observation[OBSERVATION_ID]);
                     }
                 }
-                Observation._syncTempObservationAndObservation(tempObserver, observers, observation[2], this.callerVariables[WorkflowVariables.CHANGED_ROWS()])
+                
+                Observation._syncTempObservationAndObservation(tempObserver, observers, observerUser);
             }
         }
         
@@ -440,7 +467,7 @@ Observation.prototype.checkObservation = function(pObservationId)
             return null;
         }
         
-        Observation._notifiyUsers(this.callerVariables, observers);
+        Observation._notifyUsers(this.callerVariables, observers);
     }
     return null;
 }
@@ -452,32 +479,32 @@ Observation.prototype.checkObservation = function(pObservationId)
  * @param {Void} [pTempObserver]
  * @param {Void} [pObservers]
  * @param {Void} [pObserverUserID]
- * @param {Void} [pChangedRows]
  * @return {Void}
  */
-Observation._syncTempObservationAndObservation = function (pTempObserver, pObservers, pObserverUserID, pChangedRows) 
+Observation._syncTempObservationAndObservation = function (pTempObserver, pObservers, pObserverUserID) 
 {
-    if (pTempObserver[pObserverUserID])
-        {
-        if (!pObservers[pObserverUserID])
+    if (pTempObserver)
+    {
+        if (!pObservers.has(pObserverUserID))
         {
-            pObservers[pObserverUserID] = pTempObserver[pObserverUserID];
+            pObservers.set(pObserverUserID, pTempObserver);
         }
         else
         {
-            if (Object.keys(pObservers[pObserverUserID][Observation.RECORDS_SPECIFIC_VALUES()]).length > 0) 
+            var observer = pObservers.get(pObserverUserID);
+            if (!Utils.isEmpty(observer[Observation.RECORDS_SPECIFIC_VALUES()])) 
             {
                 Observation._syncRecordsSpecificValues(
-                    pTempObserver[pObserverUserID][Observation.RECORDS_SPECIFIC_VALUES()],
-                    pObservers[pObserverUserID][Observation.RECORDS_SPECIFIC_VALUES()]);
+                    pTempObserver[Observation.RECORDS_SPECIFIC_VALUES()],
+                    observer[Observation.RECORDS_SPECIFIC_VALUES()]
+                );
             }
             else 
             {
-                pObservers[pObserverUserID][Observation.RECORDS_SPECIFIC_VALUES()] = pTempObserver[pObserverUserID][Observation.RECORDS_SPECIFIC_VALUES()];
+                observer[Observation.RECORDS_SPECIFIC_VALUES()] = pTempObserver[Observation.RECORDS_SPECIFIC_VALUES()];
             }
         }
     }
-    pTempObserver[pObserverUserID] = null;
 }
 
 /**
@@ -514,26 +541,26 @@ Observation._syncRecordsSpecificValues = function (pTempObject, pObject)
  * assembles the individual notification for each user
  * 
  * @param {Object} [pVariables] the Variables which were set in the Workflow_lib
- * @param {Object} [pObservers] the Observers with the observed fields
+ * @param {Map} [pObservers] the Observers with the observed fields
  */
-Observation._notifiyUsers = function (pVariables, pObservers)
+Observation._notifyUsers = function (pVariables, pObservers)
 {
-    var observers = Object.keys(pObservers)
-    if (pObservers && observers.length != 0 && pVariables)
+    if (pObservers && pObservers.size != 0 && pVariables)
     {
         var user = tools.getUserByAttribute(tools.NAME, pVariables[WorkflowVariables.EVENT_USER()], tools.PROFILE_DEFAULT);
-        var beginNotificationDescription = (user.params.firstname + " " + user.params.lastname).trim() + " " + translate.text("has") + " ";
         var filteredVariables = {
-            notificationUser : JSON.stringify(observers),
+            notificationUser : JSON.stringify(Array.from(pObservers.keys())),
             notificationType : "ObservationNotification"
         }
         
-        observers.forEach(function (pObserver) 
+        pObservers.forEach(function (observer, observerUser) 
         {
-            Object.keys(pObservers[pObserver][Observation.RECORDS_SPECIFIC_VALUES()]).forEach(function (pRecordUID) 
+            var locale = observer.locale || null;
+            var beginNotificationDescription = (user.params.firstname + " " + user.params.lastname).trim() + " " + translate.text("has", locale) + " ";
+            for (let recordUid in observer[Observation.RECORDS_SPECIFIC_VALUES()])
             {
-                pVariables[WorkflowVariables.TARGET_ID()] = pRecordUID;
-                let specificRecordValues = pObservers[pObserver][Observation.RECORDS_SPECIFIC_VALUES()][pRecordUID];
+                pVariables[WorkflowVariables.TARGET_ID()] = recordUid;
+                let specificRecordValues = observer[Observation.RECORDS_SPECIFIC_VALUES()][recordUid];
                 // If there is a OBJECT_TYPE, this is a dependency observation
                 if (specificRecordValues[Observation.OBJECT_TYPE()])
                 {
@@ -546,27 +573,27 @@ Observation._notifiyUsers = function (pVariables, pObservers)
                         Observation._notification(
                             pVariables, 
                             filteredVariables, 
-                            pObservers,
-                            pObserver, 
+                            observer,
+                            observerUser, 
                             context,
                             targetId);
                     }
                 }
                 else 
                 {
-                    if (!pObservers[pObserver][Observation.OBJECT_IDs()] || Object.keys(pObservers[pObserver][Observation.OBJECT_IDs()]).length > 0)
+                    if (!observer[Observation.OBJECT_IDs()] || !Utils.isEmpty(observer[Observation.OBJECT_IDs()]))
                     {
                         filteredVariables.notificationDescription = beginNotificationDescription;
                         Observation._notification(
                             pVariables, 
                             filteredVariables, 
-                            pObservers,
-                            pObserver, 
+                            observer,
+                            observerUser, 
                             pVariables[WorkflowVariables.TARGET_CONTEXT()], 
                             pVariables[WorkflowVariables.TARGET_ID()]);
                     }
                 }
-            }, this);
+            }
         }, this);
     }
 }
@@ -577,31 +604,33 @@ Observation._notifiyUsers = function (pVariables, pObservers)
  * 
  * @param {Object} [pVariables] the Variables which were set in the Workflow_lib.
  * @param {Object} [pFilteredVariables] Only for the notification used variables.
- * @param {Object} [pObservers] the Observers with the observed fields.
- * @param {Object} [pObserver] the current observer in the loop.
+ * @param {Object} [pObserver] the Observer with the observed fields.
+ * @param {Object} [pObserverUser] the current observer in the loop.
  * @param {Object} [pContext] the context from which the change is based.
  * @param {Object} [pTargetId] the id of the record from which the change is based.
  */
-Observation._notification = function (pVariables, pFilteredVariables, pObservers, pObserver, pContext, pTargetId) 
+Observation._notification = function (pVariables, pFilteredVariables, pObserver, pObserverUser, pContext, pTargetId) 
 {
-    let spezificRowData = pObservers[pObserver][Observation.RECORDS_SPECIFIC_VALUES()][pVariables[WorkflowVariables.TARGET_ID()]];
-    pFilteredVariables.notificationPriority =  pObservers[pObserver][Observation.PRIO()];
-    pFilteredVariables.notificationCaption = pVariables[WorkflowVariables.CONTENTTITLE()] || spezificRowData["#CONTENTTITLE"];
+    var specificRowData = pObserver[Observation.RECORDS_SPECIFIC_VALUES()][pVariables[WorkflowVariables.TARGET_ID()]];
+    pFilteredVariables.notificationPriority =  pObserver[Observation.PRIO()];
+    pFilteredVariables.notificationCaption = pVariables[WorkflowVariables.CONTENTTITLE()] || specificRowData["#CONTENTTITLE"];
     pFilteredVariables.notificationAffectedUID = pTargetId;
     pFilteredVariables.notificationAffectedContext = pContext;
     var isfirstField = true;
+    var locale = pObserver.locale || null;
+    var timezone = pObserver.timezone || null;
     switch (pVariables[WorkflowVariables.TRIGGER()])
     {
         case WorkflowSignalSender.EVENT_INSERT():
-            pFilteredVariables.notificationDescription += translate.text("inserted") + ":";
+            pFilteredVariables.notificationDescription += translate.text("inserted", locale) + ":";
             break;
         case WorkflowSignalSender.EVENT_UPDATE():
-            pFilteredVariables.notificationDescription += translate.text("changed") + ":";
+            pFilteredVariables.notificationDescription += translate.text("changed", locale) + ":";
             let subcategories = []
             if (pFilteredVariables.notificationSubcategory)
                 subcategories.push(pFilteredVariables.notificationSubcategory);
                 
-            notification.getUserNotifications(pObserver, [notification.STATE_SEEN, notification.STATE_UNSEEN], subcategories).forEach(function (pNotification) {
+            notification.getUserNotifications(pObserverUser, [notification.STATE_SEEN, notification.STATE_UNSEEN], subcategories).forEach(function (pNotification) {
                 if (pNotification.caption == pFilteredVariables.notificationCaption && 
                     pNotification.linkinfo == text.encodeMS([pContext, pTargetId]) &&
                     pNotification.type == pFilteredVariables.notificationType && 
@@ -615,23 +644,25 @@ Observation._notification = function (pVariables, pFilteredVariables, pObservers
             break;
         case WorkflowSignalSender.EVENT_DELETE():
             pFilteredVariables.notificationDescription += translate.text(pVariables[WorkflowVariables.TARGET_CONTEXT()]) + " \"" + pVariables[WorkflowVariables.CONTENTTITLE()] + "\" ";
-            pFilteredVariables.notificationDescription += translate.text("deleted") + ".";
+            pFilteredVariables.notificationDescription += translate.text("deleted", locale) + ".";
             Observation._createNotification(pFilteredVariables);
             return;
     }
     
-    pFilteredVariables.notificationUser = pObserver;
+    pFilteredVariables.notificationUser = pObserverUser;
     var isNewDescription = false;
-    if (!Utils.isNullOrEmpty(pFilteredVariables)){
+    if (!Utils.isNullOrEmpty(pFilteredVariables))
+    {
         var rowData = pVariables[WorkflowVariables.ROWDATA()];
-        Object.keys(pObservers[pObserver]).forEach(function (field) {
+        Object.keys(pObserver).forEach(function (field) 
+        {
             if (pVariables[WorkflowVariables.CHANGED_ROWS()].indexOf(field) > -1) 
             {
-                var formatedFieldValue = Observation.formatFieldValue(rowData,pVariables[WorkflowVariables.CHANGED_ROWS_TYPES()], field);
-                formatedFieldValue = formatedFieldValue || Observation.formatFieldValue(spezificRowData, pVariables[WorkflowVariables.CHANGED_ROWS_TYPES()], field);
+                var formatedFieldValue = Observation.formatFieldValue(rowData,pVariables[WorkflowVariables.CHANGED_ROWS_TYPES()], field, timezone, locale);
+                formatedFieldValue = formatedFieldValue || Observation.formatFieldValue(specificRowData, pVariables[WorkflowVariables.CHANGED_ROWS_TYPES()], field, timezone, locale);
                 
-                pFilteredVariables.notificationDescription += " " +(isfirstField ? "" : translate.text("and"))+ " " + 
-                pObservers[pObserver][field] + " " +  translate.text("was set to") + " \"" + formatedFieldValue + "\"";
+                pFilteredVariables.notificationDescription += " " +(isfirstField ? "" : translate.text("and", locale))+ " " + 
+                pObserver[field] + " " +  translate.text("was set to", locale) + " \"" + formatedFieldValue + "\"";
             
                 if (pFilteredVariables.notificationDescription.length > 980) 
                 {
@@ -652,7 +683,6 @@ Observation._notification = function (pVariables, pFilteredVariables, pObservers
     {
         Observation._createNotification(pFilteredVariables);
     }
-        
 }
 
 /**
@@ -724,17 +754,21 @@ Observation._createNotification = function (variables)
  * @param {Object} [pRowData] the RowData which were changed.
  * @param {Object} [pTypes] the types of the columns of the changed rows.
  * @param {String} [pField] the field whose value is to be formatted.
+ * @param {String} [pTimezone] the timezone for date formatting
+ * @param {String} [pLocale] the locale
  * @return {String} the formatted value
  */
-Observation.formatFieldValue = function (pRowData, pTypes, pField)
+Observation.formatFieldValue = function (pRowData, pTypes, pField, pTimezone, pLocale)
 {
-    var tempFormat = pTypes[pField] ? pTypes[pField].split("::") : [null];
-    switch (tempFormat[0]) 
+    var typeObject = Utils.isObject(pTypes[pField]) ? pTypes[pField] : {type: pTypes[pField]};
+    switch (typeObject.type) 
     {
         case "DATE":
-            return datetime.toDate(pRowData[pField], translate.text("dd.MM.yyyy"), "Europe/Berlin");
+            return datetime.toDate(pRowData[pField], translate.text(typeObject.dateFormat || "dd.MM.yyyy", pLocale), pTimezone, pLocale);
         case "DROP_DOWN":
-            return tempFormat[1];
+            return typeObject.displayValue;
+        case "KEYWORD":
+            return KeywordUtils.getViewValue(typeObject.keywordContainer, pRowData[pField], pLocale);
         default :
             return pRowData[pField]
     }
diff --git a/process/Workflow_lib/process.js b/process/Workflow_lib/process.js
index b28c50961e039a1eb2b09ea0342acf780f7a70de..ea29726019519a5c016234f70c75cb679c52a364 100644
--- a/process/Workflow_lib/process.js
+++ b/process/Workflow_lib/process.js
@@ -416,35 +416,76 @@ WorkflowVariables.CHANGED_ROWS_TYPES.getDefaultValue = function ()
     let types = {};
     if (vars.exists("$local.changed"))
     {
-        let isDBrc = project.getRecordContainerModel(ContextUtils.getEntity(ContextUtils.getCurrentContextId())).type ==  project.RECORDCONTAINERTYPE_DB;
+        var entityName = ContextUtils.getEntity(ContextUtils.getCurrentContextId());
+        var isDBrc = project.getRecordContainerModel(entityName).type == project.RECORDCONTAINERTYPE_DB;
+        var entityFields = project.getEntityStructure(entityName).fields;
     
-        vars.get("$local.changed").forEach(function(pField) { 
-            let splitedField = pField.split(".");
+        vars.get("$local.changed").forEach(function(pField) 
+        { 
+            let splittedField = pField.split(".");
             let fieldName;
             if  (isDBrc) 
             {
-                fieldName = splitedField[1]
+                fieldName = splittedField[1];
             } 
             else 
             {
-                fieldName = splitedField[0]
+                fieldName = splittedField[0];
             }
-        
-            if (splitedField[1] != "displayValue" && vars.exists("$property." + fieldName + ".contentType") )
+            
+            if (splittedField[1] != "displayValue" && vars.exists("$property." + fieldName + ".contentType"))
             {
-                let contentType = vars.get("$property." + fieldName + ".contentType").trim();
-                types[pField] = contentType;
+                types[pField] = vars.get("$property." + fieldName + ".contentType").trim();
             }
-        
-            if (splitedField[1] != "displayValue" && vars.exists("$field." + fieldName + ".displayValue") && vars.get("$field." + fieldName + ".displayValue") )
+            
+            if (types[pField] == "DATE")
+            {
+                types[pField] = {
+                    type: "DATE",
+                    dateFormat: _getDateFormat(entityFields, fieldName)
+                };
+            }
+            
+            var keywordContainer = splittedField[1] != "displayValue" ? _getKeywordContainer(entityFields, fieldName) : null;
+            if (keywordContainer)
             {
-                types[pField] = "DROP_DOWN" + "::" + vars.get("$field." + fieldName + ".displayValue").trim();
+                types[pField] = {
+                    type: "KEYWORD",
+                    keywordContainer: keywordContainer
+                };
+            }
+            else if (splittedField[1] != "displayValue" && vars.exists("$field." + fieldName + ".displayValue") && vars.get("$field." + fieldName + ".displayValue") )
+            {
+                types[pField] = {
+                    type: "DROP_DOWN",
+                    displayValue: vars.get("$field." + fieldName + ".displayValue").trim()
+                };
             }
                 
         });
     }
     
     return JSON.stringify(types);
+    
+    function _getKeywordContainer (pEntityFields, pFieldName)
+    {
+        var consumer = pFieldName in pEntityFields ? pEntityFields[pFieldName].consumer : null;
+        if (consumer && consumer in pEntityFields && pEntityFields[consumer].entityName == "KeywordEntry_entity")
+        {
+            var keywordConfig = entities.createConfigForLoadingConsumerRows().fields(["CONTAINER"]).consumer(consumer);
+            var keywordData = entities.getRows(keywordConfig);
+            if (keywordData.length > 0)
+            {
+                return keywordData[0]["CONTAINER"];
+            }
+        }
+        return null;
+    }
+    
+    function _getDateFormat (pEntityFields, pFieldName)
+    {
+        return pFieldName in pEntityFields ? pEntityFields[pFieldName].outputFormat : null;
+    }
 }
 
 /**