diff --git a/etemplate/inc/class.etemplate_widget_menupopup.inc.php b/etemplate/inc/class.etemplate_widget_menupopup.inc.php
index 67c80ca2d7..eb1491816b 100644
--- a/etemplate/inc/class.etemplate_widget_menupopup.inc.php
+++ b/etemplate/inc/class.etemplate_widget_menupopup.inc.php
@@ -120,8 +120,8 @@ class etemplate_widget_menupopup extends etemplate_widget
{
$form_name = self::form_name($cname, $this->id);
// += to keep further options set by app code
- if (!isset(self::$request->sel_options[$form_name])) self::$request->sel_options[$form_name] = array();
- self::$request->sel_options[$form_name] += self::typeOptions($this->attrs['type'], $this->attrs['options']);
+ if (!is_array(self::$request->sel_options[$form_name])) self::$request->sel_options[$form_name] = array();
+ self::$request->sel_options[$form_name] += (array)self::typeOptions($this->attrs['type'], $this->attrs['options']);
}
}
diff --git a/etemplate/js/et2_baseWidget.js b/etemplate/js/et2_baseWidget.js
index e5529b3f48..fef2c554b3 100644
--- a/etemplate/js/et2_baseWidget.js
+++ b/etemplate/js/et2_baseWidget.js
@@ -36,7 +36,8 @@ var et2_baseWidget = et2_DOMWidget.extend(et2_IAligned, {
"statustext": {
"name": "Tooltip",
"type": "string",
- "description": "Tooltip which is shown for this element"
+ "description": "Tooltip which is shown for this element",
+ "translate": true
},
"align": {
"name": "Align",
diff --git a/etemplate/js/et2_button.js b/etemplate/js/et2_button.js
index 419cd482de..c7be43be98 100644
--- a/etemplate/js/et2_button.js
+++ b/etemplate/js/et2_button.js
@@ -27,7 +27,8 @@ var et2_button = et2_baseWidget.extend(et2_IInput, {
"label": {
"name": "caption",
"type": "string",
- "description": "Label of the button"
+ "description": "Label of the button",
+ "translate": true
},
"onclick": {
diff --git a/etemplate/js/et2_description.js b/etemplate/js/et2_description.js
index 9d3681ab76..4d253aff15 100644
--- a/etemplate/js/et2_description.js
+++ b/etemplate/js/et2_description.js
@@ -26,7 +26,8 @@ var et2_description = et2_baseWidget.extend({
"value": {
"name": "Caption",
"type": "string",
- "description": "Displayed text"
+ "description": "Displayed text",
+ "translate": true
},
/**
@@ -50,7 +51,7 @@ var et2_description = et2_baseWidget.extend({
"description": "If set, URLs in the text are automatically replaced " +
"by links"
},
- "label_for": {
+ "for": {
"name": "Label for widget",
"type": "string",
"description": "Marks the text as label for the given widget."
@@ -73,7 +74,7 @@ var et2_description = et2_baseWidget.extend({
}
},
- legacyOptions: ["font_style", "href", "activate_links", "label_for",
+ legacyOptions: ["font_style", "href", "activate_links", "for",
"extra_link_target", "extra_link_popup", "extra_link_title"],
init: function(_parent) {
@@ -83,13 +84,13 @@ var et2_description = et2_baseWidget.extend({
this.font_style = "";
// Create the span/label tag which contains the label text
- this.span = $j(document.createElement(this.options.label_for ? "label" : "span"))
+ this.span = $j(document.createElement(this.options["for"] ? "label" : "span"))
.addClass("et2_label");
- if (this.options.label_for)
+ if (this.options["for"])
{
// TODO: Get the real id of the widget in the doLoadingFinished method.
- this.span.attr("for", this.options.label_for);
+ this.span.attr("for", this.options["for"]);
}
et2_insertLinkText(this._parseText(), this.span[0], this.options.extra_link_target);
diff --git a/etemplate/js/et2_inputWidget.js b/etemplate/js/et2_inputWidget.js
index 23170cf53d..79d6c28a39 100644
--- a/etemplate/js/et2_inputWidget.js
+++ b/etemplate/js/et2_inputWidget.js
@@ -56,7 +56,8 @@ var et2_inputWidget = et2_valueWidget.extend(et2_IInput, {
"name": "Label",
"default": "",
"type": "string",
- "description": "The label is displayed by default in front (for radiobuttons behind) each widget (if not empty). If you want to specify a different position, use a '%s' in the label, which gets replaced by the widget itself. Eg. '%s Name' to have the label Name behind a checkbox. The label can contain variables, as descript for name. If the label starts with a '@' it is replaced by the value of the content-array at this index (with the '@'-removed and after expanding the variables)."
+ "description": "The label is displayed by default in front (for radiobuttons behind) each widget (if not empty). If you want to specify a different position, use a '%s' in the label, which gets replaced by the widget itself. Eg. '%s Name' to have the label Name behind a checkbox. The label can contain variables, as descript for name. If the label starts with a '@' it is replaced by the value of the content-array at this index (with the '@'-removed and after expanding the variables).",
+ "translate": true
},
"onchange": {
"name": "onchange",
@@ -97,10 +98,13 @@ var et2_inputWidget = et2_valueWidget.extend(et2_IInput, {
this._super.apply(this, arguments);
// Check whether an validation error entry exists
- var val = this.getArrayMgr("validation_errors").getValueForID(this.id);
- if (val)
+ if (this.id)
{
- _attrs["validation_error"] = val;
+ var val = this.getArrayMgr("validation_errors").getValueForID(this.id);
+ if (val)
+ {
+ _attrs["validation_error"] = val;
+ }
}
},
diff --git a/etemplate/js/et2_valueWidget.js b/etemplate/js/et2_valueWidget.js
index ac6bde4a9a..193b020325 100644
--- a/etemplate/js/et2_valueWidget.js
+++ b/etemplate/js/et2_valueWidget.js
@@ -36,7 +36,7 @@ var et2_valueWidget = et2_baseWidget.extend({
transformAttributes: function(_attrs) {
this._super.apply(this, arguments);
- if (this.id != "")
+ if (this.id)
{
// Set the value for this element
var contentMgr = this.getArrayMgr("content");
diff --git a/etemplate/js/et2_widget.js b/etemplate/js/et2_widget.js
index c81de268cc..0ed87a2566 100644
--- a/etemplate/js/et2_widget.js
+++ b/etemplate/js/et2_widget.js
@@ -13,6 +13,7 @@
"use strict";
/*egw:uses
+ jsapi/egw;
et2_xml;
et2_common;
et2_inheritance;
@@ -107,6 +108,13 @@ var et2_widget = Class.extend({
"description": "Unique identifier of the widget"
},
+ "no_lang": {
+ "name": "No translation",
+ "type": "boolean",
+ "default": false,
+ "description": "If true, no translations are made for this widget"
+ },
+
/**
* Ignore the "span" property by default - it is read by the grid and
* other widgets.
@@ -189,12 +197,12 @@ var et2_widget = Class.extend({
{
this.checkCreateNamespace();
}
-
- // Add all attributes hidden in the content arrays to the attributes
- // parameter
- this.transformAttributes(_attrs);
}
+ // Add all attributes hidden in the content arrays to the attributes
+ // parameter
+ this.transformAttributes(_attrs);
+
// Create a local copy of the options object
this.options = et2_cloneObject(_attrs);
},
@@ -484,18 +492,35 @@ var et2_widget = Class.extend({
},
/**
- * Apply the "modifications" to the element
+ * Apply the "modifications" to the element and translate attributes marked
+ * with "translate: true"
*/
transformAttributes: function(_attrs) {
- var data = this.getArrayMgr("modifications").getValueForID(this.id);
- if (data instanceof Object)
+ // Apply the content of the modifications array
+ if (this.id)
{
- for (var key in data)
+ var data = this.getArrayMgr("modifications").getValueForID(this.id);
+ if (data instanceof Object)
{
- if (!(data[key] instanceof Object))
+ for (var key in data)
{
- _attrs[key] = data[key];
+ if (!(data[key] instanceof Object))
+ {
+ _attrs[key] = data[key];
+ }
+ }
+ }
+ }
+
+ // Translate the attributes
+ if (!_attrs["no_lang"])
+ {
+ for (var key in _attrs)
+ {
+ if (typeof this.attributes[key] != "undefined" && this.attributes[key].translate)
+ {
+ _attrs[key] = egw.lang(_attrs[key]);
}
}
}
diff --git a/etemplate/js/test/test_xml.html b/etemplate/js/test/test_xml.html
index 56fb53b831..8d78f3a41e 100644
--- a/etemplate/js/test/test_xml.html
+++ b/etemplate/js/test/test_xml.html
@@ -33,6 +33,7 @@
+
diff --git a/etemplate/templates/default/app.css b/etemplate/templates/default/app.css
index 8574c15eb5..830747080f 100644
--- a/etemplate/templates/default/app.css
+++ b/etemplate/templates/default/app.css
@@ -144,4 +144,3 @@
padding-right: 15px;
}
-