This article is for developers who have localised their XUL application using DTD entity files and want to provide their users with a mechanism to switch the locale in the application itself. Normally the application locale is inherited from the OS environment of the host system, however there are situations when you might want to give users the option to override the default setting and choose a different locale.
Here is an outline of the solution:
1. Modify the application preferences
First, you need to tell XULRunner that your application wishes to ignore the default OS locale and that it will do its own choosing instead. Edit the application preferences file and set "intl.locale.matchOS" to false. Your application is now going to ignore the OS locale, so it would be a good idea to define one to fall back on using the preference "general.useragent.locale".
defaults/preferences/prefs.js
/* Don't inherit OS locale */
pref("intl.locale.matchOS", "false");
/* Choose own fallback locale; later it can be overridden by the user */
pref("general.useragent.locale", "en-GB");
2. Include a XUL control for the locale selection
The next step is to add a XUL control to your application which lists the available locales in the package and makes it possible for the user to select one of them. I chose a listbox with a button.
Screenshot of sample locale switching control
3. Populate the XUL control with the available locales
The available package locales are declared in the chrome manifest.
Sample chrome/chrome.manifest
content localeswitchdemo content/ locale localeswitchdemo de-DE locale/de-DE/ locale localeswitchdemo en-GB locale/en-GB/ locale localeswitchdemo fr-FR locale/fr-FR/
How are you going to populate the XUL listbox?
You can hardwire the choices into the XUL code using fixed list items, or could take the elegant approach and construct the list dynamically.
The dynamic list population requires an XPCOM to query the currently selected locale as well as all locales available in the application package. Here is a code snippet showing how this is done:
The definition of the XUL control:
<listbox id="locale-listbox"> <!-- generated list items go in here --> </listbox> <button label="&switchLocale.button;" oncommand="changeLocale()"/>
The Javascript code to populate the control:
try { // Query available and selected locales var chromeRegService = Components.classes["@mozilla.org/chrome/chrome-registry;1"].getService(); var xulChromeReg = chromeRegService.QueryInterface(Components.interfaces.nsIXULChromeRegistry); var toolkitChromeReg = chromeRegService.QueryInterface(Components.interfaces.nsIToolkitChromeRegistry); var selectedLocale = xulChromeReg.getSelectedLocale("localeswitchdemo"); var availableLocales = toolkitChromeReg.getLocalesForPackage("localeswitchdemo"); // Render locale menulist by iterating through the query result from getLocalesForPackage() const XUL_NS = "https://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; var localeListbox = document.getElementById("locale-listbox"); var selectedItem = null; while(availableLocales.hasMore()) { var locale = availableLocales.getNext(); var listitem = document.createElementNS(XUL_NS, "listitem"); listitem.setAttribute("value", locale); listitem.setAttribute("label", locale); if (locale == selectedLocale) { // Is this the current locale? selectedItem = listitem; } localeListbox.appendChild(listitem); } // Highlight current locale localeListbox.selectedItem = selectedItem; } catch (err) { alert (err); }
4. Code to update the locale user preference and restart the application
Mozilla XULRunner doesn't allow runtime switching of the locale, therefore the application must be restarted to activate the new choice.
Here is an example event handler which is fired when the user clicks on the button to change the locale. It saves the new locale to the user application preferences (thereby overriding the default prefs.js above) and then asks XULRunner to restart.
function changeLocale() { try { // Which locale did the user select? var localeListbox = document.getElementById("locale-listbox"); var newLocale = localeListbox.selectedItem.value; // Write preferred locale to local user config var prefs = Components.classes["@mozilla.org/preferences-service;1"]. getService(Components.interfaces.nsIPrefBranch); prefs.setCharPref("general.useragent.locale", newLocale); // Restart application var appStartup = Components.classes["@mozilla.org/toolkit/app-startup;1"] .getService(Components.interfaces.nsIAppStartup); appStartup.quit(Components.interfaces.nsIAppStartup.eRestart | Components.interfaces.nsIAppStartup.eAttemptQuit); } catch(err) { alert("Couldn't change locale: " + err); } }
* * *
Here I include a complete XULRunner application example that demonstrates the locale switching. The code snippets above were taken from it.
LocaleSwitchExample.zip (7KB, tested with XULRunner 1.9.0 for Linux)