lightweight jQuery plugin for providing internationalization to javascript from ‘.properties’ files

Overview

jQuery.i18n.properties

About

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_BR.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.

Latest Version

1.2.7

Features

  • Use Java standard ‘.properties‘ files for translations
  • Use standard ISO-639 for language code and ISO-3166 for country code
  • Sequential loading of resource bundles from base language to user-specified/browser-specified so there is always a default value for an untranslated string (eg: Messages.properties, Messages_pt.properties, Messages_pt_BR.properties)
  • Use browser reported language if no language was specified
  • Placeholder substitution in resource bundle strings (eg, msg_hello = Hello {0}!!)
  • Suport for namespaces in keys (eg, com.company.msgs.hello = Hello!)
  • Support for multi-line property values
  • Resource bundle keys available as Javascript vars/functions or as a map
  • Support for namespacing.

History

This project was originally created by Nuno Miguel Correia Serra Fernandes and published on Google Code. In 2014 it has been migrated to Github which is now the official repository.

Since then, other great contributors joined the project (see Credits section below).

It has been used in various projects, including the WebRTC phone JSCommunicator (see the demo there to see jquery-i18n-properties in action), some Sakai Project tools, etc.

Example

Take as an example the following .properties files:

Messages.properties:

# This line is ignored by the plugin
msg_hello = Hello
msg_world = World
msg_complex = Good morning {0}!

Messages_pt.properties:

# We only provide a translation for the 'msg_hello' key
msg_hello = Bom dia

Messages_pt_BR.properties:

# We only provide a translation for the 'msg_hello' key
msg_hello = Olá

Now, suppose these files are located on the bundle/ folder. One can invoke the plugin like below:

// 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_BR',
    async: true,
    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).

Asynchronous Language File Loading

Synchronous Ajax has now been deprecated and will be removed at some point in the future, so web developers need to start thinking about writing their code as callbacks (https://xhr.spec.whatwg.org/).

With this in mind ...

If you supply the flag 'async' on the settings and set it to true, all ajax calls are executed asynchronously and the supplied callback is called after the language files have all been downloaded and parsed. If you leave the flag off, or set it to false, the behaviour is as before: all the files are parsed synchronously and the callback is called at the end of the process.

Usage

Using the plugin

  1. Include it on your <head> section:
<script type="text/javascript" language="JavaScript"
  src="js/jquery.i18n.properties-min.js"></script>
  1. Initialize the plugin (minimal usage, will use language reported by browser), and access a translated value (assuming a key named ‘org.somekey‘ exists, it will be setup as a variable you can use directly in your Javascript):
<script>
	jQuery.i18n.properties({
  		name: 'Messages', 
  		callback: function(){ alert( org.somekey ); }
	});
</script>

Additional requirement on Firefox

If using Firefox and a Tomcat webapp, you may get a syntax error in the Javascript console. The solution is to tell Tomcat the properties files should be interpreted as text/plain. To do this, add the following to your web.xml: <mime-mapping> <extension>properties</extension> <mime-type>text/plain</mime-type> </mime-mapping>

Building a minified JavaScript file

  1. Install the closure compiler tool:

    apt-get update && apt-get install closure-compiler

  2. Run it:

    closure-compiler --js jquery.i18n.properties.js \ --js_output_file jquery.i18n.properties.min.js

Options

Option Description Notes
name Partial name (or names) of files representing resource bundles (eg, ‘Messages’ or ['Msg1','Msg2']). Defaults to 'Messages' Optional String or String[]
language ISO-639 Language code and, optionally, ISO-3166 country code (eg, ‘en’, ‘en_US’, ‘pt_BR’). 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
namespace The namespace that you want your keys to be stored under. You'd access these keys like this: $.i18n.map[namespace][key]. Using a namespace minimises the chances of key clashes and overwrites. 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
debug Option to turn on console debug statement. Possible options: true or false. Optional boolean
cache Whether bundles should be cached by the browser, or forcibly reloaded on each page load. Defaults to false (i.e. forcibly reloaded). Optional boolean
encoding The encoding to request for bundles. Property file resource bundles are specified to be in ISO-8859-1 format. Defaults to UTF-8 for backward compatibility. Optional String
callback Callback function to be called uppon script execution completion. Optional function()

Copyright, Credits and License

Copyright © 2011 Nuno Miguel Correia Serra Fernandes (nunogrilo.com)

Special thanks to great contributors:

Licensed under the MIT License.

Comments
  • languages.json documentation

    languages.json documentation

    I see that the plugin attempts to load {path}/languages.json ... yet I don't see any documentation detailing what this file should be or what it should look like. Have I missed part of the documentation?

    opened by gregpettit 21
  • Uncaught ReferenceError: settings is not defined

    Uncaught ReferenceError: settings is not defined

    Hi!

    I put my language properties file under resources/bundle/Messages_**.properties

    I imported the plugin:

    <!-- Internacionalização --> <script src="resources/js/jquery.i18n.properties.min.js" type="text/javascript"></script>

    and loaded in my .js file:

    $(document).ready(function() { jQuery.i18n.properties({ name: 'Messages', path: 'resources/bundle/', mode: 'both', language: 'en', async: true, callback: function() { console.info('Iniciando internacionalização'); $('[data-i18n]').each(function(e) { var tagName = $(this).get(0).tagName; switch (tagName) { case "A": $(this).html(jQuery.i18n.prop($(this).attr("data-i18n"))); break; } }); } }); });

    but I`m getting the following error:

    jquery.i18n.properties.min.js:9 Uncaught ReferenceError: settings is not defined at Object.h.i18n.prop (jquery.i18n.properties.min.js:9) at HTMLAnchorElement. (default.js:35) at Function.each (jquery.min.js:2) at n.fn.init.each (jquery.min.js:2) at Object.callback (default.js:31) at v (jquery.i18n.properties.min.js:1) at n (jquery.i18n.properties.min.js:1) at jquery.i18n.properties.min.js:1 at Object.success (jquery.i18n.properties.min.js:2) at i (jquery.min.js:2)

    what am I doing wrong?

    opened by yuricampolongo 5
  • Why FF throws error about jquery-i18n-properties .properties content.

    Why FF throws error about jquery-i18n-properties .properties content.

    Hello

    I have the following structure for a Spring Web App

    structure

    To create a .properties files in many languages I use: essiembre/eclipse-rbe

    For example message.properties contains:

    id = Campo ID no puede estar vacio.
    

    and message_en_US.properties contains:

    #Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/)
    
    id = Field ID can't be empty.
    

    My code about jquery-i18n-properties is:

    jQuery.i18n.properties({
                    name: 'message',
                    path: '../resources/jquery.i18n.properties/messages/',
                    mode: 'both',
    
                    callback: function() {
                        console.log(jQuery.i18n.prop('id'));
                    }
                });
    

    When I execute the code on Opera and Chrome all work fine.

    But just in Firefox 43.0.2 (Mac) I can see the following:

    syntaxerror

    If I do click for each error syntax in the right part (blue text) I can see the following respectively.

    id = Campo ID no puede estar vacio.
    

    And

    #Generated by ResourceBundle Editor (http://essiembre.github.io/eclipse-rbe/)
    
    id = Field ID can't be empty.
    

    I don't know why that error is arising

    Some ideas?

    Thanks

    opened by manueljordan 4
  • if any key is not found in properties file it should not throw error. Exception should be handled.

    if any key is not found in properties file it should not throw error. Exception should be handled.

    if any key is not found in properties file it should not throw error. Exception should be handled by checking 'value' before accessing this object in the plugin.

    from line no 237 the below changes is required to handle the exception in jquery.i18n.properties.js

    if (value && value.length === 0) { return ""; } if (value && value.length == 1 && typeof(value[0]) == "string") { return value[0]; }

        var str = "";
        var len=0;
        if(value){
        	len = value.length;
        }
        for (i = 0, j = len; i < j; i++) {
    
    opened by jitchakraborty 3
  • async true version release.

    async true version release.

    I have same problem with this post. https://github.com/jquery-i18n-properties/jquery-i18n-properties/issues/25

    Trying async: true settings, but haven't clear warning. And I inspected the code in latest 1.2.0 version. But, in ver.1.2.0, settings.async seems to be ignored.

    ** ver.1.2.0 **

    function loadAndParseFile(filename, settings) {
        $.ajax({
            url:        filename,
            async:      false,
            cache:      settings.cache,
            contentType:'text/plain;charset='+ settings.encoding,
            dataType:   'text',
            success:    function(data, status) {
                            parseData(data, settings.mode); 
                        }
        });
    }
    

    ** latest code **

    function loadAndParseFile(filename, settings) {
        $.ajax({
            url: filename,
            async: settings.async,
            cache: settings.cache,
            dataType: 'text',
            success: function (data, status) {
            parseData(data, settings.mode);
                callbackIfComplete(settings);
            },
            error: function (jqXHR, textStatus, errorThrown) {
                console.log('Failed to download or parse ' + filename);
                callbackIfComplete(settings);
            }
        });
    }
    

    When do you release async true version.

    opened by dongully 3
  • synchronous ajax request

    synchronous ajax request

    $.ajax({
          url: indexFileUrl,
          async: false,
          cache: false,
          success: function (data, status) {
              languages = data.languages;
          }
        });
    

    why not async?

    opened by rileytg 3
  • plugin does not work if jquery is loaded again

    plugin does not work if jquery is loaded again

    I have a setup where multiple portlets are rendered inline into the same page. Each of these emits the jquery library as it has its own requirements.

    One of these uses i18n-properties. Unless it is the last one to be rendered, the subsequent loading of jquery overwrites the i18n registration.

    I end up with something like this:

    <script type="text/javascript" src="/library/webjars/jquery/1.11.3/jquery.min.js"></script>
    ...
    <script type="text/javascript" src="/library/webjars/jquery/1.11.3/jquery.min.js"></script>
    <script type="text/javascript" src="/my-calendar/scripts/jquery.i18n.properties.min.js"></script>
    ...
    <script type="text/javascript" src="/library/webjars/jquery/1.11.3/jquery.min.js"></script>
    

    This then causes: jQuery.i18n is undefined

    If the webapp using i18n-properties is the last one to be rendered, then it works, but this is not guaranteed as it is a portal.

    I am wondering if this could be resolved via namespacing the invocation of i18n-properties in the specific portlet? I currently load it like this:

    $(document).ready(function() {
    
        jQuery.i18n.properties({
            name:'Messages', 
            path:'/my-calendar/bundle/',
            mode: 'both',
            cache: true
        });
    
    ...
    
    opened by steveswinsburg 2
  • Using synchronous loading of properties with jquery.i18n.properties in deferred scripts fails in Firefox

    Using synchronous loading of properties with jquery.i18n.properties in deferred scripts fails in Firefox

    If one uses a script with the defer attribute to invoke synchronous property loading with jquery-i18n-properties then it may fail in Firefox.

    Ex:

    This may be fixed in future versions of Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=1212696#c33

    Not sure if switching to the async configuration when using deferred instead of a sync will fix the behavior but I think it might.

    opened by rajsite 2
  • jquery has deprecated synchronous XMLHTTPRequest

    jquery has deprecated synchronous XMLHTTPRequest

    opened by manueljordan 2
  • Dynamically load HTML contents based on translation keys

    Dynamically load HTML contents based on translation keys

    I didn't like the idea of having to edit the javascript every time I add a new key so I tried to come up with the following solution to dynamically load all HTML elements based on the translation key. Here's the HTML for a complex types with parameters.

    This also allows for dynamically passing the params from the HTML and not via javascript. by using an additional <span class="param"> inside the element I want to translate

    HTML

    <span translate="yes" class="msg_multi_placeholder">Welcome <span class="param">Jacob</span>.  Today is <span class="param">28-12-2014</span></span>
    

    Below is the javascript I'm using for this: javascript

    function updateSelected(translationKey) {
        var params = '';
        $('.' + translationKey + ' .param').each(function(i, param) {
            params = params + ', \'' + param.textContent + '\'';
        });
        var translationCommand = '$(\'.\'+translationKey).empty().append($.i18n.prop(translationKey'+ params + '));';
        eval(translationCommand);
    }
    function updateAll() {
        var keys = Object.keys(($.i18n.map));
        $.each(keys, function(i, key){
           updateSelected(key);
        });
    }
    

    messages_es.properties

    msg_multi_placeholder = Bienvenido <span class="param">{0}</span>. Hoy es el <span class="param">{1}</span>
    

    I must admit, this is not very neat. I would like to find a solution to make the property file a bit neater, a double placeholder for one parameter seems a bit much.

    opened by jacobandrews 2
  • issue while loading Arabic language

    issue while loading Arabic language

    I have integrated example of jquery-i18n-properties. It's working fine for Messages.properties and Messages_es_ES.properties. But when I tried to load arabic then it shows ?????? symbol.

    I have created Messages_ar.properties file with arabic content in it. when I pass value arto language then it shows me????? only..

    Am I missing something ?

    opened by kurbhatt 1
  • Support server-side merging of language files

    Support server-side merging of language files

    We are using jquery-i18n-properties with a java servlet based on a Spring MessageSource. This servlet merges the properties from the various default, country and language files to produce a single consolidated message file. It would be useful to have a setting, for example 'serverMerges', that indicates that only a single file request is needed instead of multiple requests to get the consolidated list of messages.

    opened by sloescape 0
  • In the case value is undefuned, it is throwing value undefined except…

    In the case value is undefuned, it is throwing value undefined except…

    In the case value is undefuned, it is throwing value undefined exception, by adding define control ti will be able to return empty value as expected value length check.

    opened by engmuratkocer 0
  • Load properties strings directly

    Load properties strings directly

    Can I load properties string directly? eg:

    var text = 'a=Hello\nb=World!'
    jQuery.i18n.[load](text, {[options]});
    

    Because I want to load by requirejs.

    opened by sumy7 0
  • Vulnerability issue

    Vulnerability issue

    Hi,

    I found this lib very helpful and wanted to use it. However, while reviewing the code I noticed that at multiple locations eval() has been used.

    And it has been reported on several forums that we should avoid using eval() in code as it makes your code open for XSS security issues.

    Kindly suggest what approach I should consider in using this lib in my application.

    Thanks

    opened by bbshub 0
  • 《 Cannot read property 'length' of undefined 》《Uncaught SyntaxError: Unexpected token <》

    《 Cannot read property 'length' of undefined 》《Uncaught SyntaxError: Unexpected token <》

    this so many error when i run the example, who can help

    Uncaught SyntaxError: Unexpected token < at jquery.i18n.properties.js:430 at Array.forEach () at checkKeyNamespace (jquery.i18n.properties.js:424) at jquery.i18n.properties.js:380 at Array.forEach () at parseData (jquery.i18n.properties.js:342) at Object.success (jquery.i18n.properties.js:317) at b (jquery.min.js:124) at XMLHttpRequest.x.onreadystatechange (jquery.min.js:129) at Function.ajax (jquery.min.js:130)

    Uncaught TypeError: Cannot read property 'length' of undefined at Object.$.i18n.prop (jquery.i18n.properties.js:240) at updateExamples ((index):74) at Object.callback ((index):59) at Object.$.i18n.properties (jquery.i18n.properties.js:107) at loadBundles ((index):53) at HTMLDocument. ((index):24) at Function.ready (jquery.min.js:26) at HTMLDocument.L (jquery.min.js:33)

    opened by lzr1994 1
Owner
null
:globe_with_meridians: Internationalization plugin for Vue.js

vue-i18n Internationalization plugin for Vue.js ?? Gold Sponsors ?? Silver Sponsors ?? Bronze Sponsors ⚠️ NOTICE This repository is for Vue I18n v8.x.

kazuya kawaguchi 6.9k Dec 29, 2022
A JavaScript Internationalization Framework

FBT is an internationalization framework for JavaScript designed to be not just powerful and flexible, but also simple and intuitive. It helps with th

Facebook 3.8k Jan 8, 2023
🌍📖 A readable, automated, and optimized (5 kb) internationalization for JavaScript

Linguijs ?? ?? A readable, automated, and optimized (5 kb) internationalization for JavaScript Documentation · Documentation 2.x · Quickstart · Exampl

Lingui 3.5k Jan 2, 2023
Internationalization for react done right. Using the i18next i18n ecosystem.

react-i18next IMPORTANT: Master Branch is the new v10 using hooks. $ v10.0.0 npm i react-i18next react-native: To use hooks within react-native, you m

i18next 7.9k Dec 30, 2022
A general purpose internationalization library in 292 bytes

A general purpose internationalization library in 298 bytes! Features Simple and Familiar API Unobstrusive and Unopinionated Less than 300 bytes – inc

Luke Edwards 713 Dec 21, 2022
The alternative internationalization (i18n) library for Angular

NGX Locutus The alternative Angular Translation Library used for large scale microfrontend translations. No more worrying about shared translation ass

Stefan Haas 9 May 31, 2022
Type-safe internationalization (i18n) for Next.js

Type-safe internationalization (i18n) for Next.js Features Usage Examples Scoped translations Change current locale Use JSON files instead of TS for l

Tom Lienard 251 Dec 22, 2022
a jQuery plugin that makes it easy to internationalize your web site.

jquery.localize.js A jQuery plugin that makes it easy to i18n your static web site. Synopsis Lazily loads JSON translation files based on a simple nam

Jim Garvin 469 Dec 17, 2022
Extract and merge i18n xliff translation files for angular projects.

Angular extract i18n and merge This extends Angular CLI to improve the i18n extraction and merge workflow. New/removed translations are added/removed

Daniel Schreiber 86 Jan 5, 2023
Merges XLIFF 1.2/2.0 files. Usable for Angular i18n automation.

XLIFF Simple Merge This program automates the merging of XLIFF files (version 1.2 and 2.0). New translations from the input file (e.g. "messages.xlf")

Daniel Schreiber 9 Dec 15, 2022
Give your JavaScript the ability to speak many languages.

Polyglot.js Polyglot.js is a tiny I18n helper library written in JavaScript, made to work both in the browser and in CommonJS environments (Node). It

Airbnb 3.6k Jan 2, 2023
human friendly i18n for javascript (node.js + browser)

BabelFish - human friendly i18n for JS Internationalisation with easy syntax for node.js and browser. Classic solutions use multiple phrases for plura

Nodeca 246 Nov 20, 2022
:orange_book: simple approach for javascript localization

ttag ⚠️ This project was previously named c-3po. Some of the talks, presentations, and documentation may reference it with both names. Modern javascri

ttag 307 Jan 2, 2023
ICU MessageFormat for Javascript - i18n Plural and Gender Capable Messages

messageformat The experience and subtlety of your program's text can be important. Messageformat is a mechanism for handling both pluralization and ge

null 1.6k Dec 23, 2022
ICU MessageFormat for Javascript - i18n Plural and Gender Capable Messages

messageformat The experience and subtlety of your program's text can be important. Messageformat is a mechanism for handling both pluralization and ge

null 1.6k Dec 23, 2022
Gettext Style i18n for Modern JavaScript Apps

Jed Gettext Style i18n for Modern JavaScript Apps For more info

null 879 Dec 14, 2022
Grupprojekt för kurserna 'Javascript med Ramverk' och 'Agil Utveckling'

JavaScript-med-Ramverk-Laboration-3 Grupprojektet för kurserna Javascript med Ramverk och Agil Utveckling. Utvecklingsguide För information om hur utv

Svante Jonsson IT-Högskolan 3 May 18, 2022
Hemsida för personer i Sverige som kan och vill erbjuda boende till människor på flykt

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

null 4 May 3, 2022
Kurs-repo för kursen Webbserver och Databaser

Webbserver och databaser This repository is meant for CME students to access exercises and codealongs that happen throughout the course. I hope you wi

null 14 Jan 3, 2023
🌐 Lightweight internationalization plugin for Vue 3

??️ vue-next-i18n Lightweight internationalization plugin for Vue 3 ?? Getting started To begin, you'll need to install vue-next-i18n use npm npm inst

Aaron Lam 12 Nov 21, 2022