Index: main/plugin-core-ui/i18n/messages_en.xml
===================================================================
--- main/plugin-core-ui/i18n/messages_en.xml	(revision 38750)
+++ main/plugin-core-ui/i18n/messages_en.xml	(working copy)
@@ -805,4 +805,15 @@
     <message key="PLUGINS_CORE_UI_TOOLS_NOTIFICATIONS_RIBBON_TIP_TITLE">Notifications</message>
     <message key="PLUGINS_CORE_UI_TOOLS_NOTIFICATIONS_RIBBON_TIP_DESCRIPTION">Open the notification tool.&lt;br/&gt;&lt;br/&gt;A figure on the ribbon icon displays the number of unread message. The color indicates the most serious message type among these unread messages: red for error, yellow for warning, and blue for simple information.</message>
     
+    <!-- +
+         | ABOUT AMETYS
+         + -->
+    <message key="PLUGINS_CORE_UI_ABOUT_LABEL">About Ametys...</message>
+    <message key="PLUGINS_CORE_UI_ABOUT_DESCRIPTION">Information about Ametys</message>
+    <message key="PLUGINS_CORE_UI_ABOUT_DIALOG_TITLE">About</message>
+    <message key="PLUGINS_CORE_UI_ABOUT_DIALOG_BUTTON_OK">OK</message>
+    <message key="PLUGINS_CORE_UI_ABOUT_DIALOG_VERSIONS_VERSION_SEPARATOR"> - </message>
+    <message key="PLUGINS_CORE_UI_ABOUT_DIALOG_VERSIONS_DATE_PREFIX"> from </message>
+    <message key="PLUGINS_CORE_UI_ABOUT_DIALOG_DAO_ERROR">Error retrieving information about the application</message>
+    
 </catalogue>
Index: main/plugin-core-ui/i18n/messages_fr.xml
===================================================================
--- main/plugin-core-ui/i18n/messages_fr.xml	(revision 38750)
+++ main/plugin-core-ui/i18n/messages_fr.xml	(working copy)
@@ -805,5 +805,16 @@
     <message key="PLUGINS_CORE_UI_TOOLS_NOTIFICATIONS_FILTER_NAVHISTORY_DESC">Cliquez ici pour filtrer l'événements de l'historique de navigation</message>
     <message key="PLUGINS_CORE_UI_TOOLS_NOTIFICATIONS_RIBBON_TIP_TITLE">Notifications</message>
     <message key="PLUGINS_CORE_UI_TOOLS_NOTIFICATIONS_RIBBON_TIP_DESCRIPTION">Ouvrir l'outil des notifications.&lt;br/&gt;&lt;br/&gt;Le chiffre indique le nombre de message non lus. La couleur indique le type de message le plus grave parmi ces messages non lus : rouge pour erreur, orange pour avertissement et bleu pour simple information.</message>
+    
+    <!-- +
+         | ABOUT AMETYS
+         + -->
+    <message key="PLUGINS_CORE_UI_ABOUT_LABEL">A propos d'Ametys...</message>
+    <message key="PLUGINS_CORE_UI_ABOUT_DESCRIPTION">Informations à propos d'Ametys</message>
+    <message key="PLUGINS_CORE_UI_ABOUT_DIALOG_TITLE">A propos de</message>
+    <message key="PLUGINS_CORE_UI_ABOUT_DIALOG_BUTTON_OK">OK</message>
+    <message key="PLUGINS_CORE_UI_ABOUT_DIALOG_VERSIONS_VERSION_SEPARATOR"> - </message>
+    <message key="PLUGINS_CORE_UI_ABOUT_DIALOG_VERSIONS_DATE_PREFIX"> du </message>
+    <message key="PLUGINS_CORE_UI_ABOUT_DIALOG_DAO_ERROR">Erreur lors de la récupération des informations sur l'application</message>
 
 </catalogue>
Index: main/plugin-core-ui/plugin.xml
===================================================================
--- main/plugin-core-ui/plugin.xml	(revision 38750)
+++ main/plugin-core-ui/plugin.xml	(working copy)
@@ -1283,6 +1283,35 @@
        </extensions>
     </feature>
     
+    <feature name="about">
+    	<components>
+    		<component id="org.ametys.plugins.core.ui.about.AboutInfoProvider"
+    				   role="org.ametys.plugins.core.ui.about.AboutInfoProvider"
+    				   class="org.ametys.plugins.core.ui.about.AboutInfoProvider">
+ 			</component>
+    	</components>
+    	<extensions>
+    		<extension id="org.ametys.plugins.core.ui.about"
+    				   point="org.ametys.core.ui.RibbonAppMenuControlsManager"
+    				   class="org.ametys.core.ui.StaticClientSideElement">
+    			<class name="">
+    				<action>Ametys.plugins.coreui.about.AboutActions.openAboutDialogBox</action>
+    				
+    				<label i18n="true">PLUGINS_CORE_UI_ABOUT_LABEL</label>
+    				<description i18n="true">PLUGINS_CORE_UI_ABOUT_DESCRIPTION</description>
+    				
+    				<icon-glyph>flaticon-question13</icon-glyph>
+    			</class>
+	    		<scripts>
+	    			<file>js/Ametys/plugins/coreui/about/AboutActions.js</file>
+	    		</scripts>
+	    		<css>
+				    <file>css/about/About.css</file>
+				</css>
+    		</extension>
+    	</extensions>
+    </feature>
+    
     <feature name="core.user.profile">
         <components>
             <component class="org.ametys.plugins.core.ui.user.ProfileImageProvider"
Index: main/plugin-core-ui/resources/css/about/About.css
===================================================================
--- main/plugin-core-ui/resources/css/about/About.css	(revision 0)
+++ main/plugin-core-ui/resources/css/about/About.css	(revision 0)
@@ -0,0 +1,44 @@
+/*
+ *  Copyright 2016 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+ 
+/*.about-dialog .x-box-item {
+ 	padding: 0 0 12px 0;
+}*/
+.about-dialog .about-logo {
+	padding: 0 0 35px 0;
+}
+
+.about-dialog .about-app-name {
+	font-weight: bold;
+	font-size: 20px;
+	padding: 0 0 8px 0;
+}
+
+.about-dialog .about-versions {
+	padding: 0 0 30px 0;
+}
+ 
+.about-dialog .about-versions .about-version-name {
+	font-weight: bold;
+}
+ 
+.about-dialog .about-license {
+	border: 1px;
+	border-color: #804080; /* get the conf app color */
+	border-style: solid;
+	font-weight: lighter;
+	padding: 5px;
+}
\ No newline at end of file
Index: main/plugin-core-ui/resources/js/Ametys/plugins/coreui/about/AboutActions.js
===================================================================
--- main/plugin-core-ui/resources/js/Ametys/plugins/coreui/about/AboutActions.js	(revision 0)
+++ main/plugin-core-ui/resources/js/Ametys/plugins/coreui/about/AboutActions.js	(revision 0)
@@ -0,0 +1,202 @@
+/*
+ *  Copyright 2016 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * This class is a singleton to handle actions on "About Ametys" feature.
+ * @private
+ */
+Ext.define('Ametys.plugins.coreui.about.AboutActions', {
+    singleton: true,
+    
+    /**
+     * @private
+     * @property {Ametys.window.DialogBox} _aboutBox The "About Ametys" dialog box.
+     */
+    
+    /**
+     * @private
+     * @property {Boolean} _aboutIsInitialized Indicates if the "About Ametys" dialog box is initialized.
+     */
+    
+    /**
+     * Opens the "About Ametys" dialog box
+     */
+    openAboutDialogBox: function()
+    {
+        this._delayedInitializeAboutDialog();
+        this._aboutBox.show();
+    },
+    
+    /**
+     * Opens the details dialog box
+     */
+    openDetailsDialogBox: function()
+    {
+        alert('Not yet implemented');
+    },
+    
+    /**
+     * @private
+     * Creates the "About Ametys" dialog box
+     */
+    _delayedInitializeAboutDialog: function ()
+    {
+        if (!this._aboutIsInitialized)
+        {
+            var itemsCfg = this._createItemsCfg();
+            
+            this._aboutBox = Ext.create('Ametys.window.DialogBox', {
+                title: "<i18n:text i18n:key='PLUGINS_CORE_UI_ABOUT_DIALOG_TITLE'/>",
+                iconCls: "flaticon-question13",
+                maxHeight: 600,
+                
+                width: 500,
+                layout: {
+                    type: "vbox",
+                    align: "middle",
+                    padding: '0 0 15px 0'
+                },
+                
+                items: itemsCfg,
+                bodyCls: 'about-dialog',
+                
+                closeAction: 'hide',
+                buttons: [{
+                    text: "<i18n:text i18n:key='PLUGINS_CORE_UI_ABOUT_DIALOG_BUTTON_OK'/>",
+                    handler: function() { this._aboutBox.close(); },
+                    scope: this
+                }]    
+            });
+            
+            Ametys.data.ServerComm.callMethod({
+                role: "org.ametys.plugins.core.ui.about.AboutInfoProvider",
+                methodName: "getInfo",
+                parameters: [Ametys.getAppParameter("user").locale],
+                callback: {
+                    handler: this._getInfoCb,
+                    scope: this
+                },
+                waitMessage: false
+            });
+            //Ametys.about.AboutDAO.getInfo([Ametys.getAppParameter("user").locale], this._getInfoCb, {scope: this});
+            
+            this._aboutIsInitialized = true;
+        }
+    },
+    
+    /**
+     * @private
+     * Creates the items config of the "about" dialogbox
+     * @return {Object[]} The configs of the box items  
+     */
+    _createItemsCfg: function()
+    {
+        var itemsCfg = [
+	        {
+                xtype: "image",
+                src: Ametys.getPluginResourcesPrefix('core-ui') + '/img/Ametys/common/logo.png',
+                alt: 'Ametys',
+                cls: 'about-logo'
+	        },
+	        {
+	            xtype: "component",
+                itemId: "appName",
+                cls: 'about-app-name',
+                html: "",
+                scrollable: false
+	        },
+	        {
+	            xtype: "component",
+                itemId: "versions",
+                cls: 'about-versions',
+                html: "",
+                scrollable: false
+	        },
+	        {
+	            xtype: "component",
+                itemId: "license",
+                width: "95%",
+                flex: 1,
+                cls: 'about-license',
+                html: "",
+                scrollable: true
+	        }
+        ];
+        return itemsCfg;
+    },
+    
+    /**
+     * @private
+     * Callback method after the information are retrieved from the server.
+     * Updates the texts of the dialog box (app name, versions, license).
+     * @param {Object} response The server response
+     */
+    _getInfoCb: function(response)
+    {
+        this._updateAppName(response.applicationName);
+        this._updateVersions(response.versions);
+        this._updateLicenseText(response.licenseText);
+    },
+    
+    /**
+     * @private
+     * Updates the displayed application name
+     * @param {String} appName The application name
+     */
+    _updateAppName: function(appName)
+    {
+        var cmp = this._aboutBox.items.get("appName");
+        cmp.update(appName);
+    },
+    
+    /**
+     * @private
+     * Updates the displayed versions
+     * @param {Object} versions The versions handled by the application as a map. The key is the version name, and the value is a mpa containing the version number and the date.
+     */
+    _updateVersions: function(versions)
+    {
+        var cmp = this._aboutBox.items.get("versions");
+        
+        var html = "";
+        Ext.Object.each(versions, function(key, value) {
+            html += '<span class="about-version-name">' + key + "<i18n:text i18n:key='PLUGINS_CORE_UI_ABOUT_DIALOG_VERSIONS_VERSION_SEPARATOR'/>" + "</span>" + value['version'];
+            
+            var millisDate = value["date"];
+            var dateFormat = Ext.Date.patterns.FriendlyDateTime;
+            if (millisDate != "")
+            {
+                html += "<i18n:text i18n:key='PLUGINS_CORE_UI_ABOUT_DIALOG_VERSIONS_DATE_PREFIX'/>" + Ext.util.Format.date(new Date(value["date"]), dateFormat);
+            }
+            
+            html += "<br/>";
+        }, this);
+        
+        cmp.update(html );
+    },
+    
+    /**
+     * @private
+     * Updates the license text
+     * @param {String} license The license text
+     */
+    _updateLicenseText: function(license)
+    {
+        var cmp = this._aboutBox.items.get("license");
+        cmp.update(license);
+    }
+    
+});
\ No newline at end of file
Index: main/plugin-core-ui/src/org/ametys/plugins/core/ui/about/AboutInfoProvider.java
===================================================================
--- main/plugin-core-ui/src/org/ametys/plugins/core/ui/about/AboutInfoProvider.java	(revision 0)
+++ main/plugin-core-ui/src/org/ametys/plugins/core/ui/about/AboutInfoProvider.java	(revision 0)
@@ -0,0 +1,166 @@
+/*
+ *  Copyright 2016 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.ametys.plugins.core.ui.about;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.avalon.framework.component.Component;
+import org.apache.avalon.framework.context.Context;
+import org.apache.avalon.framework.context.ContextException;
+import org.apache.avalon.framework.context.Contextualizable;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.Serviceable;
+import org.apache.cocoon.Constants;
+
+import org.ametys.core.ui.Callable;
+import org.ametys.core.util.I18nUtils;
+import org.ametys.core.version.Version;
+import org.ametys.core.version.VersionsHandler;
+import org.ametys.runtime.i18n.I18nizableText;
+import org.ametys.runtime.plugin.component.AbstractLogEnabled;
+
+/**
+ * Helper providing information for "About Ametys" feature.
+ */
+public class AboutInfoProvider extends AbstractLogEnabled implements Serviceable, Component, Contextualizable
+{
+    /** The Avalon role */
+    public static final String ROLE = AboutInfoProvider.class.getName();
+    
+    /** The path of the license text file */
+    private static final String LICENSE_FILE_PATH = "/";
+    /** The name of the license text file */
+    private static final String LICENSE_FILE_NAME = "NOTICE.txt";
+    
+    /** The versions handler */
+    private VersionsHandler _versionsHandler;
+    /** The cocoon context */
+    private org.apache.cocoon.environment.Context _cocoonContext;
+    
+    @Override
+    public void service(ServiceManager manager) throws ServiceException
+    {
+        _versionsHandler = (VersionsHandler) manager.lookup(VersionsHandler.ROLE);
+    }
+    
+    @Override
+    public void contextualize(Context context) throws ContextException
+    {
+        _cocoonContext = (org.apache.cocoon.environment.Context) context.get(Constants.CONTEXT_ENVIRONMENT_CONTEXT);
+    }
+    
+    /**
+     * Gets the information for "About Ametys" feature
+     * @param lang the lang
+     * @return A map of information needed for "About Ametys" feature.
+     * Contains the application name, the versions of the application and the license text.
+     * @throws FileNotFoundException
+     * @throws IOException
+     */
+    @Callable
+    public Map<String, Object> getInfo(String lang) throws FileNotFoundException, IOException
+    {
+        Map<String, Object> result = new LinkedHashMap<>();
+        
+        result.put("applicationName", getApplicationName(lang));
+        result.put("versions", getVersions());
+        result.put("licenseText", getLicenseText());
+        
+        return result;
+    }
+    
+    /**
+     * Gets the application name
+     * @param lang The lang
+     * @return The name of the application.
+     */
+    @Callable
+    public String getApplicationName(String lang)
+    {
+        return I18nUtils.getInstance().translate(new I18nizableText("application", "APPLICATION_PRODUCT_LABEL"), lang);
+    }
+    
+    /**
+     * Gets the available versions of the application.
+     * @return A map of versions.
+     */
+    @Callable
+    public Map<String, Object> getVersions()
+    {
+        Map<String, Object> result = new LinkedHashMap<>();
+        
+        Collection<Version> versions = _versionsHandler.getVersions();
+        
+        Iterator<Version> it = versions.iterator();
+        while (it.hasNext())
+        {
+            Version version = it.next();
+            Map<String, Object> versionInfos = new LinkedHashMap<>();
+            versionInfos.put("version", "4.0.0alpha");
+            //versionInfos.put("version", version.getVersion() != null ? version.getVersion() : "");
+            versionInfos.put("date", new Date());
+            //versionInfos.put("date", version.getDate() != null ? version.getDate() : "");
+            result.put(version.getName(), versionInfos);
+        }
+        
+        return result;
+    }
+    
+    /**
+     * Gets the content of the license text.
+     * @return The content of the license text.
+     * @throws FileNotFoundException
+     * @throws IOException
+     */
+    @Callable
+    public String getLicenseText() throws FileNotFoundException, IOException
+    {
+        String path = _cocoonContext.getRealPath(AboutInfoProvider.LICENSE_FILE_PATH);
+        String fileName = AboutInfoProvider.LICENSE_FILE_NAME;
+        File licenseFile = new File(path + fileName);
+        if (licenseFile.exists() && licenseFile.isFile())
+        {
+            StringBuffer sb = new StringBuffer();
+            try ( BufferedReader reader = new BufferedReader(new FileReader(licenseFile)) )
+            {
+                String line;
+                while ((line = reader.readLine()) != null)
+                {
+                    sb.append(line);
+                    sb.append("<br/>");
+                }
+            }
+            
+            return sb.toString();
+        }
+        else
+        {
+            getLogger().warn("License file {} is not present at {}", fileName, path);
+            return "";
+        }
+    }
+
+}