jQuery.i18n.properties is a lightweight jQuery plugin for providing internationalization to javascript from ‘.properties’ files, just like in Java Resource Bundles. It loads and parses resource bundles (.properties) based on provided language and country codes (ISO-639 and ISO-3166) or language reported by browser.
Resource bundles are ‘.properties‘ files containing locale specific key-value pairs. The use of ‘.properties‘ files for translation is specially useful when sharing i18n files between Java and JavaScript projects. This plugin loads the default file (eg, Messages.properties) first and then locale specific files (Messages_pt.properties, then Messages_pt_PT.properties), so that a default value is always available when there is no translation provided. Translation keys will be available to developer as javascript variables/functions (functions, if translated value contains substitutions (eg, {0}) or as a map.
This plugin was inspired on the Localisation assistance for jQuery from Keith Wood, and is made available under a dual license (GPL and MIT).
Take as an example the following Messages.properties, Messages_pt.properties and Messages_pt_PT.properties:
1 2 3 4 | # This line is ignored by the plugin msg_hello = Hello msg_world = World msg_complex = Good morning {0}! |
1 2 | # We only provide a translation for the 'msg_hello' key msg_hello = Bom dia |
1 2 | # We only provide a trnaslation for the 'msg_hello' key msg_hello = Olá |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | // This will initialize the plugin // and show two dialog boxes: one with the text "Olá World" // and other with the text "Good morning John!" jQuery.i18n.properties({ name:'Messages', path:'bundle/', mode:'both', language:'pt_PT', callback: function() { // We specified mode: 'both' so translated values will be // available as JS vars/functions and as a map // Accessing a simple value through the map jQuery.i18n.prop('msg_hello'); // Accessing a value with placeholders through the map jQuery.i18n.prop('msg_complex', ['John']); // Accessing a simple value through a JS variable alert(msg_hello +' '+ msg_world); // Accessing a value with placeholders through a JS function alert(msg_complex('John')); } }); |
This will initialize the plugin (loading bundle files and parsing them) and show a dialog box with the text “Olá World” and other with “Good morning John!”. The english word “World” is shown because we didn’t provide a translation for the msg_world key. Also notice that keys are available as a map and also as javascript variables (for simple strings) and javascript functions (for strings with placeholders for substitution).
| Option | Description | Notes |
|---|---|---|
| name | Partial name (or names) of files representing resource bundles (eg, ‘Messages’ or ['Msg1','Msg2']) | Required String or String[] |
| language | ISO-639 Language code and, optionally, ISO-3166 country code (eg, ‘en’, ‘en_US’, ‘pt_PT’). If not specified, language reported by the browser will be used instead. | Optional String |
| path | Path to directory that contains ‘.properties‘ files to load. | Optional String |
| mode | Option to have resource bundle keys available as Javascript vars/functions OR as a map. The ‘map’ option is mandatory if your bundle keys contain Javascript Reserved Words. Possible options: ‘vars’ (default), ‘map’ or ‘both’ | Optional String |
| callback | Callback function to be called uppon script execution completion. | Optional function() |
1 2 | <script type="text/javascript" language="JavaScript" src="js/jquery.i18n-1.0.3-min.js"></script> |
1 | jQuery.i18n.properties({name: 'Messages'}); |
1 | alert( org.somekey ); |
Released jQuery plugin for I18N from .properties files, with support for placeholder subsititutions: http://codingwithcoffee.com/?p=272 #fb
This is fantastic work! I am trying it out in Sakai’s Course Evaluation Tool @ http://jira.sakaiproject.org/browse/EVALSYS-795
Hi, I’ve had little success implementing this so far. The following issue up:
The path bundle/messages.properties is not made available for direct access by tomcat restrictions. Hence only an RSF error page is called with no translation strings in it. Hence this parse error is thrown by jquery.i18n:
syntax error typeof <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1 == "undefined"
Hi Lovemore!
One approach you may try is to use the ’maven-resources-plugin’ to copy your bundle files at compile time to a tool webapp folder (accessible location by the webserver).
In the base pom.xml of the tool:
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.4</version>
</plugin>
</plugins>
</pluginManagement>
</build>
In the tool/pom.xml:
<build>
<!– …….. –>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<phase>process-resources</phase>
<goals><goal>resources</goal></goals>
<configuration>
<outputDirectory>${project.build.directory}/${project.build.finalName}/bundle</outputDirectory>
<resources>
<resource>
<!– Change THIS to get to you actual folder containing the .properties files –> <directory>${basedir}/../bundle/src/resources</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Hope this helps!
Please let me know if it solved your issue!
Nuno
Hey that worked! JS can access the properties file now. But there’s a bug with parsing the file:
not well-formed:
[Break on this error] # Application messages file – Sakai Evaluation System -AZ
the comments within the properties file prefixed with # throw this exception and the plugin just gives up.
Any thoughts?
Hi Lovemore!
I have already seen that message – is it from Firebug 1.4? I have a lot of things (like JS templates) that firebug reports as errors but everything is working fine. Before considering this a bug, can you please test this (replacing with the correct values):
jQuery.i18n.properties({name:’messages’, path:’bundle/’, language:’en’, callback: function() {
// replace by a parsed key from the bundle
alert(msg_some_key);
}});
If that doesn’t work, can you please send me your .properties file so I can test it locally? Just send me using the contact form on the top of this page
Thanks,
Nuno
Not sure if I have already update Firebug meanhile (now have 1.4.2) because similar error have gone from my console. Testing a .properties file with that comment line works fine for me…
Nuno
Here is the properties file: https://source.sakaiproject.org/contrib/evaluation/trunk/tool/src/java/org/sakaiproject/evaluation/tool/bundle/messages.properties
The callback function does not execute.
Firebug is 1.4.2
Thanks
Lovemore
I found the issue: since the bundle keys are available as javascript variables/functions, some do fail because Javascript reserved words cannot be used!
http://javascript.about.com/library/blreserved.htm
I will modify the plugin to have an option of accessing the bundle keys through an array (map) and will add a comment when ready!
Nuno
Hi Lovemore!
In your case, since Javascript reserved words are being used inside the .properties file (delete), you must download the 1.0.2 version and specify the option mode:’map’. Example:
jQuery.i18n.properties({name:’messages’, path:’bundle/’, language:’en’, mode:’map’, callback: function() {
// replace by a parsed key from the bundle
alert( jQuery.i18n.prop(‘msg_some_key’) );
}});
Hope this helps,
Nuno
Hi Nuno
A while back I had an idea of a twist to your idea. I’ve detailed it here: http://blogs.uct.ac.za/blog/lovemores-world/2009/09/28/consuming-a-sakai-java-messages-resource-bundle-in-javascript-with-fluid-i8n
Would love to know what you think. My code is running in the Sakai Course Evaluations tool
please try this:
layout.close_pane = \u5173\u95ED
alert(jQuery.i18n.prop(“layout.close_pane”));
alert(layout.close_pane);
first alert is show \u5173\u95ED and second alert will show 关闭 ,why?
I dig this – though I wish there was an easier way to over-ride w/a db as a message source, to support easy GUI customization of bundles w/o writing to files.
Dynamically generate the .properties files using a servlet that did dynamic db overlay ontop of the underlying file? (we use something similar for portlets – we standardized on tags to make db slightly easier as a message source.
Hi Jason!
If what you’re trying to achieve is some kind of dynamic generation of bundles (server-side) in Sakai, one possible approach (and alternative to this plugin) is to use EntityBroker RESTfull capability to return either a ResourceLoader object or a map {key,translation}. This way, you can simply query server through ajax and restfull urls to retrieve the results as a Javascript map (JSON)! Entitybroker return results encoded in JSON automatically.
Is this your objective?
Thank you for your thoughts,
Nuno
Hi Shotchen!
Thank you for reporting the issue! I have just updated the plugin to fix it (1.0.4). Thank you very much, Nuno