Fixed FELIX-2277 /Allow the user to select display language/
https://issues.apache.org/jira/browse/FELIX-2277
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@984311 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/AbstractWebConsolePlugin.java b/webconsole/src/main/java/org/apache/felix/webconsole/AbstractWebConsolePlugin.java
index f179137..4a96fa2 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/AbstractWebConsolePlugin.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/AbstractWebConsolePlugin.java
@@ -614,9 +614,37 @@
pw.println("<div id='technav' class='ui-widget ui-widget-header'>");
for ( Iterator li = map.values().iterator(); li.hasNext(); )
{
+ pw.print(' ');
pw.println( li.next() );
}
pw.println( "</div>" );
+
+ }
+
+ // render lang-box
+ Map langMap = (Map) request.getAttribute(WebConsoleConstants.ATTR_LANG_MAP);
+ if (null != langMap && !langMap.isEmpty())
+ {
+ pw.println("<div id='langSelect'>"); //$NON-NLS-1$
+ pw.println(" <span class='ui-icon ui-icon-comment'> </span>"); //$NON-NLS-1$
+ pw.println(" <span class='flags ui-helper-hidden'>"); //$NON-NLS-1$
+ for (Iterator li = langMap.keySet().iterator(); li.hasNext();)
+ {
+ // <img src="us.gif" alt="en" title="English"/>
+ final Object l = li.next();
+ pw.print(" <img src='"); //$NON-NLS-1$
+ pw.print(appRoot);
+ pw.print("/res/flags/"); //$NON-NLS-1$
+ pw.print(l);
+ pw.print(".gif' alt='"); //$NON-NLS-1$
+ pw.print(l);
+ pw.print("' title='"); //$NON-NLS-1$
+ pw.print(langMap.get(l));
+ pw.println("'/>"); //$NON-NLS-1$
+ }
+
+ pw.println(" </span>"); //$NON-NLS-1$
+ pw.println("</div>"); //$NON-NLS-1$
}
}
@@ -709,7 +737,7 @@
* Note: This method is intended to be used internally by the Web Console
* to update the log level according to the Web Console configuration.
*
- * @param logLevel the maximum allowed log level. If message is logged with
+ * @param logLevel the maximum allowed log level. If message is logged with
* lower level it will not be forwarded to the logger.
*/
public static final void setLogLevel( int logLevel )
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/WebConsoleConstants.java b/webconsole/src/main/java/org/apache/felix/webconsole/WebConsoleConstants.java
index daaf9aa..a8590e0 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/WebConsoleConstants.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/WebConsoleConstants.java
@@ -18,6 +18,8 @@
*/
package org.apache.felix.webconsole;
+import java.util.Locale;
+
/**
* WebConsoleConstants provides some common constants that are used by plugin
* developers.
@@ -129,4 +131,24 @@
* @since 3.0
*/
static final String ATTR_CONSOLE_VARIABLE_RESOLVER = "felix.webconsole.variable.resolver";
+
+ /**
+ * The name of the request attribute holding the language {@link Map}
+ * for the request (value is "felix.webconsole.langMap").
+ *
+ * This map contains the web console supported languages, which are automatically detected.
+ * The keys of the map are the language codes, like "en", "en_US" .. and so-on.
+ * The value for each key is the locale user-friendly name - exactly the same as
+ * returned by {@link Locale#getDisplayLanguage()}.
+ *
+ * The automatic detection of languages is very simple. It relies on having a
+ * 'res/flags/[lang].gif' file in the bundle. So translators should not only provide
+ * localized l10n/bundle.properties but also a flag image.
+ *
+ * The image should be obtained from http://famfamfam.com/lab/icons/flags/ and eventually
+ * renamed to the correct locale.
+ *
+ * @since 3.1.2
+ */
+ public static final String ATTR_LANG_MAP = "felix.webconsole.langMap"; //$NON-NLS-1$
}
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java
index 3f667d2..a41fa6f 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/servlet/OsgiManager.java
@@ -18,11 +18,13 @@
import java.io.IOException;
+import java.net.URL;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Dictionary;
import java.util.Enumeration;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
@@ -40,6 +42,7 @@
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.io.FilenameUtils;
import org.apache.felix.webconsole.AbstractWebConsolePlugin;
import org.apache.felix.webconsole.BrandingPlugin;
import org.apache.felix.webconsole.WebConsoleConstants;
@@ -50,6 +53,7 @@
import org.apache.felix.webconsole.internal.filter.FilteringResponseWrapper;
import org.apache.felix.webconsole.internal.i18n.ResourceBundleManager;
import org.apache.felix.webconsole.internal.misc.ConfigurationRender;
+import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
@@ -407,6 +411,7 @@
final Map labelMap = holder.getLocalizedLabelMap( resourceBundleManager, locale );
// the official request attributes
+ request.setAttribute( WebConsoleConstants.ATTR_LANG_MAP, getLangMap() );
request.setAttribute( WebConsoleConstants.ATTR_LABEL_MAP, labelMap );
request.setAttribute( WebConsoleConstants.ATTR_APP_ROOT, request.getContextPath() + request.getServletPath() );
request.setAttribute( WebConsoleConstants.ATTR_PLUGIN_ROOT, request.getContextPath() + request.getServletPath()
@@ -945,6 +950,32 @@
}
return stringConfig;
}
+
+ private Map langMap;
+
+ private final Map getLangMap()
+ {
+ if (null != langMap) return langMap;
+ final Map map = new HashMap();
+ final Bundle bundle = bundleContext.getBundle();
+ final Enumeration e = bundle.findEntries("res/flags", null, false);
+ while (e != null && e.hasMoreElements())
+ {
+ final URL img = (URL) e.nextElement();
+ final String name = FilenameUtils.getBaseName(img.getFile());
+ try
+ {
+ final String locale = new Locale(name).getDisplayLanguage();
+ map.put(name, null != locale ? locale : name);
+ }
+ catch (Throwable t)
+ {
+ t.printStackTrace();
+ /* ignore invalid locale? */
+ }
+ }
+ return langMap = map;
+ }
static class SecurityProvider implements WebConsoleSecurityProvider {
diff --git a/webconsole/src/main/resources/res/flags/bg.gif b/webconsole/src/main/resources/res/flags/bg.gif
new file mode 100644
index 0000000..11cf8ff
--- /dev/null
+++ b/webconsole/src/main/resources/res/flags/bg.gif
Binary files differ
diff --git a/webconsole/src/main/resources/res/flags/de.gif b/webconsole/src/main/resources/res/flags/de.gif
new file mode 100644
index 0000000..75728dd
--- /dev/null
+++ b/webconsole/src/main/resources/res/flags/de.gif
Binary files differ
diff --git a/webconsole/src/main/resources/res/flags/en.gif b/webconsole/src/main/resources/res/flags/en.gif
new file mode 100644
index 0000000..8f198f7
--- /dev/null
+++ b/webconsole/src/main/resources/res/flags/en.gif
Binary files differ
diff --git a/webconsole/src/main/resources/res/lib/support.js b/webconsole/src/main/resources/res/lib/support.js
index 3687e40..2228174 100644
--- a/webconsole/src/main/resources/res/lib/support.js
+++ b/webconsole/src/main/resources/res/lib/support.js
@@ -252,3 +252,15 @@
}
return element;
}
+
+// language selection element
+var langSelect = false;
+$(document).ready(function() {
+ langSelect = $('#langSelect').hover(
+ function() { $(this).find('.flags').show('blind') },
+ function() { $(this).find('.flags').hide('blind') });
+ langSelect.find('.flags img').click(function() {
+ $.cookies.set('felix.webconsole.locale', $(this).attr('alt'));
+ location.reload();
+ });
+});
diff --git a/webconsole/src/main/resources/res/ui/webconsole.css b/webconsole/src/main/resources/res/ui/webconsole.css
index 2219e94..4cf950d 100644
--- a/webconsole/src/main/resources/res/ui/webconsole.css
+++ b/webconsole/src/main/resources/res/ui/webconsole.css
@@ -170,3 +170,6 @@
float: left;
list-style: none
}
+/* language selection element */
+#langSelect { position: absolute; top: 5px; right: 5px }
+#langSelect img { display: block; padding: 2px 0 }