GithubHelp home page GithubHelp logo

wikimedia / jquery.i18n Goto Github PK

View Code? Open in Web Editor NEW
697.0 52.0 143.0 858 KB

๐ŸŒ jQuery based internationalization library

License: GNU General Public License v2.0

JavaScript 97.86% HTML 2.14%
javascript i18n intl

jquery.i18n's Introduction

jQuery.i18n

npm

NOTE: For jquery independent version of this library, see https://github.com/wikimedia/banana-i18n

jQuery.i18n is a jQuery based JavaScript internationalization library. It helps you to internationalize your web applications easily.

This is a project by Wikimedia foundation's Language Engineering team and used in some of the Wikimedia Foundation projects like Universal Language Selector.

The jquery.i18n library uses a json based localization file format, "banana", which is used as the localization file format for MediaWiki and other projects.

Features

  • Simple file format - JSON. Easily readable for humans and machines.
  • Author and metadata information is not lost anywhere. There are other file formats using comments to store this.
  • Uses MediaWiki convention for placeholders. Easily readable and proven convention. Example: There are $1 cars
  • Supports plural conversion without using extra messages for all plural forms. Plural rule handling is done using CLDR. Covers a wide range of languages
  • Supports gender. By passing the gender value, you get correct sentences according to gender.
  • Supports grammar forms. jquery.i18n has a basic but extensible grammar conversion support
  • Fallback chains for all languages.
  • Data api- the message key. Example: <li data-i18n="message-key"></li>.
  • Dynamic change of interface language without refreshing a webpage.
  • Nestable grammar, plural, gender support. These constructs can be nested to any arbitrary level for supporting sophisticated message localization
  • Message documentation through special language code qqq
  • Extensible message parser to add or customize magic words in the messages. Example: {sitename} or [[link]]

Quick start

git clone https://github.com/wikimedia/jquery.i18n.git
cd jquery.i18n
git submodule update --init

Testing

npm install

To run tests locally, run npm test, and this will run the tests.

Running demo

# If you're using python3, open demo as a local server using port 8000
python -m http.server
# If you're using python2, use this command instead
# python -m SimpleHTTPServer  

Open localhost:8000/demo in your browser, you can see the demo index page.

Message File Format

The message files are json formatted. As a convention, you can have a folder named i18n inside your source code. For each language or locale, have a file named like languagecode.json.

Example:

App
	|--src
	|--doc
	|--i18n
		|--ar.json
		|--de.json
		|--en.json
		|--he.json
		|--hi.json
		|--fr.json
		|--qqq.json

A simple en.json file example is given below

{
	"@metadata": {
		"authors": [
			"Alice",
			"David",
			"Santhosh"
		],
		"last-updated": "2012-09-21",
		"locale": "en",
		"message-documentation": "qqq",
		"AnotherMetadata": "AnotherMedatadataValue"
	},
	"appname-title": "Example Application",
	"appname-sub-title": "An example application with jquery.i18n",
	"appname-header-introduction": "Introduction",
	"appname-about": "About this application",
	"appname-footer": "Footer text"
}

The json file should be a valid json. The @metadata holds all kind of data that are not messages. You can store author information, copyright, updated date or anything there.

Messages are key-value pairs. It is a good convention to prefix your appname to message keys to make the messages unique. It acts as the namespace for the message keys. It is also a good convention to have the message keys with - separated words, all in lower case.

If you are curious to see some real jquery.i18n message file from other projects:

Single message file for all languages

There are some alternate message file formats supported for different use cases. If your application is not big, and want all the translation in a single file, you can have it as shown in the below example:

{
	"@metadata": {
		"authors": [
			"Alice",
			"David",
			"Santhosh"
		],
		"last-updated": "2012-09-21",
		"locale": "en",
		"message-documentation": "qqq",
		"AnotherMetadata": "AnotherMedatadataValue"
	},
	"en": {
		"appname-title": "Example Application",
		"appname-sub-title": "An example application with jquery.i18n",
		"appname-header-introduction": "Introduction",
		"appname-about": "About this application",
		"appname-footer": "Footer text"
		},
	"ml": {
		"appname-title": "เด…เดชเตเดฒเดฟเด•เตเด•เต‡เดทเดจเตโ€ เด‰เดฆเดพเดนเดฐเดฃเด‚",
		"appname-sub-title": "jquery.i18n เด‰เดชเดฏเต‹เด—เดฟเดšเตเดšเตเดณเตเดณ เด…เดชเตเดฒเดฟเด•เตเด•เต‡เดทเดจเตโ€ เด‰เดฆเดพเดนเดฐเดฃเด‚",
		"appname-header-introduction": "เด†เดฎเตเด–เด‚",
		"appname-about": "เดˆ เด…เดชเตเดฒเดฟเด•เตเด•เต‡เดทเดจเต†เดชเตเดชเดฑเตเดฑเดฟ",
		"appname-footer": "เด…เดŸเดฟเด•เตเด•เตเดฑเดฟเดชเตเดชเตเต"
	}
}

Here the json file contains language code as key-value and messagekey-message pairs as the value for all language pairs. You can choose this format or per-language file formats depending on your use case. Per-language files are more convenient for collaboration, version controlling, scalability, etc.

In this approach, it is also possible to give a file name as the value of language code.

{
	"@metadata": {
		"authors": [
			"Alice",
			"David",
			"Santhosh"
		],
		"last-updated": "2012-09-21",
		"locale": "en",
		"message-documentation": "qqq",
		"AnotherMetadata": "AnotherMedatadataValue"
	},
	"en": {
		"appname-title": "Example Application",
		"appname-sub-title": "An example application with jquery.i18n",
		"appname-header-introduction": "Introduction",
		"appname-about": "About this application",
		"appname-footer": "Footer text"
		},
	"ml": "path/to/ml.json"
}

Translation

To translate the jquery.i18n application, depending on the expertise of the translator, there are multiple ways.

  • Editing the json files directly - Suitable for translators with technical background. Also suitable if your application is small and you want to work with only a small number of languages
  • Providing a translation interface along with your application: Suitable for proprietary or private applications with significant amount of translators
  • Using open source translation platforms like translatewiki.net. The MediaWiki and jquery.uls from previous examples use translatewiki.net for crowdsourced message translation. Translatewiki.net can update your code repo at regular intervals with updated translations. Highly recommended if your application is opensource and want it to be localized to as many as languages possible with maximum number of translators.

Usage

Switching locale

While initializing the jquery.i18n, the locale for the page can be given using the locale option. For example

$.i18n( {
    locale: 'he' // Locale is Hebrew
} );

In case locale option is not given, jquery.i18n plugin will use the language attribute given for the html tag. For example

<html lang="he" dir="rtl">

In this case, the locale will be he(Hebrew). If that lang attribute is also missing, it will try to use the locale specified by the browser.

It is possible to switch to another locale after plugin is initialized. See below example:

$.i18n({
    locale: 'he' // Locale is Hebrew
});
$.i18n( 'message-hello' ); // This will give the Hebrew translation of message key `message-hello`.
$.i18n().locale = 'ml'; // Now onwards locale is 'Malayalam'
$.i18n( 'message-hello' ); // This will give the Malayalam translation of message key `message-hello`.

Message Loading

JSON formatted messages can be loaded to the plugin using multiple ways.

Dynamic loading using load method.

Following example shows loading messages for two locales- localex, and localey. Here localex and localey are just examples. They should be valid IS0 639 language codes(eg: en, ml, hi, fr, ta etc)

$.i18n().load( {
	'localex' : {
		'message-key1' : 'message1' // Message for localex.
	},
	'localey' : {
		'message-key1' : 'message1'
	}
} );

If we want to load the messages for a specific locale, it can be done like this:

$.i18n().load({
    'message-hello': 'Hello World',
    'message-welcome': 'Welcome'
}, 'en');

Note the second argument for the load method. It should be a valid language code.

It is also possible to refer messages from an external URL. See below example

$.i18n().load( {
	en: {
		'message-hello': 'Hello World',
		'message-welcome': 'Welcome'
	},
	hi: 'i18n/messages-hi.json', // Messages for Hindi
	de: 'i18n/messages-de.json'
} );

Messages for a locale can be also loaded in parts. Example

$.i18n().load( {
	en: {
		'message-hello': 'Hello World',
		'message-welcome': 'Welcome'
	}
} );

$.i18n().load( {
    	// This does not remove the previous messages.
	en: {
		'message-header' : 'Header',
		'message-footer' : 'Footer',
		// This will overwrite message-welcome message
		'message-welcome' : 'Welcome back'
	}
} );

Since it is desirable to render interface messages instantly and not after a delay of loading the message files from a server, make sure that the messages are present at client side before using jQuery.i18n.

The library should expose an API to load an object containing key-value pair of messages. Example: $.i18n.load(data). This will return a jQuery.Promise.

jquery.i18n plugin

The jQuery plugin defines $.i18n() and $.fn.i18n()

$.i18n( 'message-key-sample1' );
$.i18n( 'message-key-sample1' );
$.i18n( 'Found $1 {{plural:$1|result|results}}', 10 ); // Message key itself is message text
$.i18n( 'Showing $1 out of $2 {{plural:$2|result|results}}', 5,100 );
$.i18n( 'User X updated {{gender|his|her}} profile', 'male' );

$( '#foo' ).i18n(); // to translate the element matching jquery selector based on data-i18n key

Data API

It is possible to display localized messages without any custom JavaScript. For the HTML tags, add an attribute data-i18n with value as the message key. Example:

<li data-i18n="message-key"></li>.

It is also possible to have the above li node with fallback text already in place.

<li data-i18n="message-key">Fallback text</li>

The framework will place the localized message corresponding to message-key as the text value of the node. Similar to $('selector').i18n( ... ). This will not work for dynamically created elements.

Note that if data-i18n contains html markup, that html will not be used as the element content, instead, the text version will be used. But if the message key is prefixed with [html], the element's html will be changed. For example <li data-i18n="[html]message-key">Fallback html</li>, in this if the message-key has a value containing HTML markup, the <li> tags html will be replaced by that html.

If you want to change the html of the element, you can also use: $(selector).html($.i18n(messagekey))

Examples

See https://thottingal.in/projects/js/jquery.i18n/demo/

Message format

Placeholders

Messages take parameters. They are represented by $1, $2, $3, โ€ฆ in the message texts, and replaced at run time. Typical parameter values are numbers (Example: "Delete 3 versions?"), or user names (Example: "Page last edited by $1"), page names, links, and so on, or sometimes other messages.

var message = "Welcome, $1";
$.i18n(message, 'Alice'); // This gives "Welcome, Alice"

Plurals

To make the syntax of sentence correct, plural forms are required. jquery.i18n support plural forms in the message using the syntax {{PLURAL:$1|pluralform1|pluralform2|...}}

For example:

var message = "Found $1 {{PLURAL:$1|result|results}}";
$.i18n(message, 1); // This gives "Found 1 result"
$.i18n(message, 4); // This gives "Found 4 results"

Note that {{PLURAL:...}} is not case sensitive. It can be {{plural:...}} too.

In case of English, there are only 2 plural forms, but many languages use more than 2 plural forms. All the plural forms can be given in the above syntax, separated by pipe(|). The number of plural forms for each language is defined in CLDR. You need to provide all those plural forms for a language. Please note that many languages will require the inclusion of CLDRPluralRuleParser.js (from here) as well as this project's own files to work properly.

For example, English has 2 plural forms and the message format will look like {{PLURAL:$1|one|other}}. for Arabic there are 6 plural forms and format will look like {{PLURAL:$1|zero|one|two|few|many|other}}.

You cannot skip a plural form from the middle or beginning. However, you can skip from end. For example, in Arabic, if the message is like {{PLURAL:$1|A|B}}, for 0, A will be used, for numbers that fall under one, two, few, many, other categories B will be used.

If there is an explicit plural form to be given for a specific number, it is possible with the following syntax

var message = 'Box has {{PLURAL:$1|one egg|$1 eggs|12=a dozen eggs}}.';
$.i18n(message, 4 ); // Gives "Box has 4 eggs."
$.i18n(message, 12 ); // Gives "Box has a dozen eggs."

Gender

Similar to plural, depending on gender of placeholders, mostly user names, the syntax changes dynamically. An example in English is "Alice changed her profile picture" and "Bob changed his profile picture". To support this {{GENDER...}} syntax can be used as shown in example

var message = "$1 changed {{GENDER:$2|his|her}} profile picture";
$.i18n(message, 'Alice', 'female' ); // This gives "Alice changed her profile picture"
$.i18n(message, 'Bob', 'male' ); // This gives "Bob changed his profile picture"

Note that {{GENDER:...}} is not case sensitive. It can be {{gender:...}} too.

Grammar

$.i18n( { locale: 'fi' } );

var message = "{{grammar:genitive|$1}}";

$.i18n(message, 'talo' ); // This gives "talon"

$.i18n().locale = 'hy'; // Switch to locale Armenian
$.i18n(message, 'ี„ีกีธึ‚ีถีก'); // This gives "ี„ีกีธึ‚ีถีกีตีซ"

Directionality-safe isolation

To avoid BIDI corruption that looks like "(Foo_(Bar", which happens when a string is inserted into a context with the reverse directionality, you can use {{bidi:โ€ฆ}}. Directionality-neutral characters at the edge of the string can get wrongly interpreted by the BIDI algorithm. This would let you embed your substituted string into a new BIDI context, //e.g.//:

"Shalom, {{bidi:$1}}, hi!"

The embedded context's directionality is determined by looking at the argument for $1, and then explicitly inserted into the Unicode text, ensuring correct rendering (because then the bidi algorithm "knows" the argument text is a separate context).

Fallback

The plugin takes an option 'fallback' with the default value 'en'. The library reuses the fallback data available in MediaWiki for calculating the language fallbacks. Fallbacks are used when a message key is not found in a locale. Example fallbacks: sa->hi->en or tt->tt-cyrl->ru.

See jquery.i18n.fallbacks.js in the source.

Magic word support

  • For plural, gender and grammar support, MediaWiki template-like syntax - {{...}} will be used.
  • There will be a default implementation for all these in $.i18n.language['default']
  • The plural, gender and grammar methods in $.i18n.language[ 'default' ] can be overridden or extended in $.i18n.language['languageCode'].
  • Language-specific rules about Gender and Grammar can be written in languages/langXYZ.js files
  • Plural forms will be dynamically calculated using the CLDR plural parser.

Extending the parser

Following example illustrates extending the parser to support more magic words

$.extend( $.i18n.parser.emitter, {
	// Handle SITENAME keywords
	sitename: function () {
		return 'Wikipedia';
	},
	// Handle LINK keywords
	link: function ( nodes ) {
		return '<a href="' + nodes[1] + '">' + nodes[0] + '</a>';
	}
} );

This will parse the message

$.i18n( '{{link:{{SITENAME}}|https://en.wikipedia.org}}' );

to

<a href="https://en.wikipedia.org">Wikipedia</a>

Message documentation

The message keys and messages won't give a enough context about the message being translated to the translator. Whenever a developer adds a new message, it is a usual practice to document the message to a file named qqq.json with same message key.

Example qqq.json:

{
	"@metadata": {
		"authors": [
			"Developer Name"
		]
	},
	"appname-title": "Application name. Transliteration is recommended",
	"appname-sub-title": "Brief explanation of the application",
	"appname-header-introduction": "Text for the introduction header",
	"appname-about": "About this application text",
	"appname-footer": "Footer text"
}

In MediaWiki and its hundreds of extensions, message documentation is a strictly followed practice. There is a grunt task to check whether all messages are documented or not. See https://www.npmjs.org/package/grunt-banana-checker

jquery.i18n's People

Contributors

abijeet avatar amire80 avatar catrope avatar dependabot[bot] avatar edg2s avatar hartman avatar jdforrester avatar jishnu7 avatar kartikm avatar krinkle avatar ldittmar81 avatar legoktm avatar llech avatar lucaswerkmeister avatar mathieubodin avatar meno25 avatar nikerabbit avatar pl217 avatar prevadu avatar reedy avatar ricordisamoa avatar santhoshtr avatar siebrand avatar smalyshev avatar soulmare avatar ssuess avatar stephenhuge avatar winstonsung avatar xsavitar avatar yarons avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jquery.i18n's Issues

data-i18n on tag attributes

I don't know how to solve this problem: How would you use the transparent technique, $('[data-i18n]').i18n(), to localize an element attribute such as <input value="msgname" ,,, ?

JSON Object in Object

Friends library has support for objects inside objects because my script is criticizing:
Uncaught TypeError: message.indexOf is not a function


example json:

{
    "en": {
        "appname-title": "Example Application",
        "appname-sub-title": "An example application with jquery.i18n",
        "appname-header-introduction": "Introduction",
         "example": {
                "appname-title": "Example Application",
               "appname-sub-title": "An example application with jquery.i18n"
        },
        "appname-about": "About this application",
        "appname-footer": "Footer text"
        },
    "ml": {
        "appname-title": "เด…เดชเตเดฒเดฟเด•เตเด•เต‡เดทเดจเตโ€ เด‰เดฆเดพเดนเดฐเดฃเด‚",
        "appname-sub-title": "jquery.i18n เด‰เดชเดฏเต‹เด—เดฟเดšเตเดšเตเดณเตเดณ เด…เดชเตเดฒเดฟเด•เตเด•เต‡เดทเดจเตโ€ เด‰เดฆเดพเดนเดฐเดฃเด‚",
        "appname-header-introduction": "เด†เดฎเตเด–เด‚",
         "example": {
                "appname-title": "Example Application",
               "appname-sub-title": "An example application with jquery.i18n"
        },
        "appname-about": "เดˆ เด…เดชเตเดฒเดฟเด•เตเด•เต‡เดทเดจเต†เดชเตเดชเดฑเตเดฑเดฟ",
        "appname-footer": "เด…เดŸเดฟเด•เตเด•เตเดฑเดฟเดชเตเดชเตเต"
    }
}
}
```

document plural form

Hello, the document mentions CLDR plurals but does not show how they map to messages. It might be helpful to show that for English the form is {{PLURAL:$1|one|other}}, for Arabic {{PLURAL:$1|zero|one|two|few|many|other}} etc. Since the format does not have the keyword names in the text, it was particularly confusing at first that the keywords are skipped if not found in the language (so for example zero is omitted from English).

Thanks!

plural fallback includes "other="

in language.js, near "// default fallback."
Shouldn't the fallback exclude what's left of the equal sign?

            var fallback = ( count === 1 ) ? forms[0] : forms[1];
            fallback = fallback.substr( fallback.indexOf( '=' ) + 1 );
            return fallback;

Preventing inner HTML items replacement

Say I want to replace just the Exit text for an HTML button,

<button data-i18n="Exit">Exit
  <i class="sign out icon"></i>
</button>

If I do $('[data-i18n]').i18n() the inner i HTML element is lost,

<button data-i18n="Exit">Exit</button>

I'm afraid this is not an issue, but I couldn't find how to do it properly.

Thanks in advance.-

Can I use i18n for DOM attrs like title or placeholder?

Can I use i18n for DOM attrs like title or placeholder without using JS to change it's attribute? for example:

<div class="content">
 <input type="text" placeholder="translate me" title="translate me">
</div>

How can I use:

$('div.content').i18n();

To update the translated messages for placeholder or title?

What is wrong with my JSON content ?

I followed documentation about file format. So I've supplied i18n/fr.json as follow :

{
   "@metadata": {
      "authors": [
         "Mathieu BODIN"
      ],
      "last-updated": "2014-07-23",
      "locale": "fr",
      "message-documentation": "qqq"
   },
   "fr": {
      "something": "qqchose"
   }
}

I've loaded that file somewhere like that :

$.i18n().load("i18n/fr.json","fr")

Then I tried to use it, like that :

var label = $.i18n("something");

It just NEVER happened to work until, after reading the code of the example, I tried the following content for i18n/fr.json file:

{
   "something": "qqchose"
} 

So my question is : why didn't it work at first with message source formatted as documented ?

By the way, what's the point of:

  • Having to supply the path to the file when it could be guessed ? I mean, when people follow your recommendations as documented, having the lang attribute supplied on html tag should be enough to deduce a default path to data.
  • Perform initialization asynchronously ? I want to use this jQuery plugin to perform i18n translation in my whole application, so loading the file is kind of a mandatory feature. I still don't get the use case you're supporting... Show me the light !

Load in Firefox not working

In Firefox $.i18n.load() does not work.

I fixed it in this way:

In jquery.i18n.messagestore.js substitute $.getJSON with $.ajax and add contentType and mimeType as "text/plain".

function jsonMessageLoader( url ) {
var deferred = $.Deferred();

                   $.ajax({
            dataType: "json",
            url: url,
            contentType:'text/plain',
            mimeType: "text/plain",
            dataType:   'text',
            success: success
        })
        .done( deferred.resolve )
        .fail( function ( jqxhr, settings, exception ) {
            $.i18n.log( 'Error in loading messages from ' + url + ' Exception: ' + exception );
            // Ignore 404 exception, because we are handling fallabacks explicitly
            deferred.resolve();
        } );

    return deferred.promise();

}

Plural parser does not use rules of the fallback language

With fa set as the language, the Langviews tool tried to translate a particular message that is not defined in fa.json, so it falls back to English. The English message uses {{PLURAL}}, which errors out presumably because the rules differ than what is defined for fa. E.g. if I removed the rules for fa here then I get no error. I am seeing the same issue for some other RTL languages.

Console shows pluralRuleParser is undefined here.

If I'm understanding this correctly, I think we just need to resort to the en defined rules when falling back to an English message.

Special JSON Location

I want to define my JSON file location from script. Maybe like this:

$.i18n( {
locale: "../an.app/locale/en.json"
} );

Is it possible?

PLURAL not working for some languages

Apparently there are pluralization issues for language codes bs, hr and sr.

Bosnian for instance:

Message: "num-languages": "$1 {{PLURAL:$1|jezik|jezika}}"
In the JavaScript console:

$.i18n('num-languages', 115);
=> "115 jezik"

When it should be 115 jezika.

If you need a go-to for Bosnian, @srdjanm has offered to help. They said the plural rules look correct, so maybe it's something else.

Thanks!

Attach an event handler function for on language change?

Is it possible to use something like

$( document ).on( "language-change", function() {
    console.log( "Language just changed." );
});

to detect language change so that I can make corresponding changes to the interface's UI? Thanks! :)

Bower package

Hello,

It would be useful to have a Bower package for this library.

Regards,

Update Russian rules in jquery.l18n.language.js

Hi,

It looks like the plural rules for Russian need to be updated. If I'm reading this correctly, the current version in this repository only has one/many rules, whereas CLDRPluralRuleParser, even at the version on this repository, has a few more. This causes the wrong plural to be chosen sometimes (specifically, I've seen it happen for the "few" case).

(This may be related to #26 or #125, but the former is old and a bit cryptic, and the latter mentions that the plural rules are correct, so I figured I'd file something separate, feel free to duplicate).

Can I use nested locale structure?

Hello:
Can I use nested locale structure? For example, change the following:

{
    "@metadata": {
        "authors": [
            "Developer Name"
        ]
    },
    "appname-title": "Application name. Transliteration is recommended",
    "appname-sub-title": "Brief explanation of the application",
    "appname-header-introduction": "Text for the introduction header",
    "appname-about": "About this application text",
    "appname-footer": "Footer text"
}

to:

{
    "@metadata": {
        "authors": [
            "Developer Name"
        ]
    },
"appname":{
    "title": "Application name. Transliteration is recommended",
    "sub-title": "Brief explanation of the application",
    "header-introduction": "Text for the introduction header",
    "about": "About this application text",
    "ooter": "Footer text"
  }
}

Thanks a lot!

Using $.i18n().load() to load from a URL or object destroys other messages

I'm loading messages from two different sources, and it looks like only the messages from the source that is last to arrive actually get picked up.

$.i18n().load( 'a.json', 'en' );
$.i18n().load( 'b.json', 'en' );

Ends up with one of the two messages sets being loaded into the message store, but not the other, and which one makes it is not always consistent (but it's usually b).

The following confirmed my suspicions:

>>> $.i18n().load({'foo':'bar'}, 'en');
Object {resolve: function, resolveWith: function, ...}
>>> $.i18n().messageStore.messages.en
Object {foo: "bar"}
>>> $.i18n().load({'bar':'bar'}, 'en');
Object {resolve: function, resolveWith: function, ...}
>>> $.i18n().messageStore.messages.en
Object {bar: "bar"}

This clearing effect does not happen across languages, only within the same language (so loading messages for 'nl' does not clear messages loaded for 'en', but loading additional messages for 'en' does).

Functional escape for '$' needed

$ immediately followed by any characters will cause an error when used in a json array. The error is Uncaught TypeError: Cannot read property '2' of undefined in simpleParse js file.

$1, $2, $3 are placeholders for the library so it seems $4500 causes an error whereas $ 4500 doesn't cause any issues. Replacing$ with &#36; doesn't solve the issue.

How does one escape $ in a message then?

Versioning

Could you tag v0.1.0 at 2837060? (Creates package.json which first mentioned that number afaics.)

Also a more recent tag would be nice so end users can link to a less random point of master for their downstream copies (maybe tag current master at v0.2.0 or something?).

Lastly, a versioning section in the readme would be nice to make sure there's a somewhat defined path for maintainers to follow and users of the code to expect (not important until it goes 1.x but good to put in place ahead of time).

Something like https://github.com/wikimedia/oojs#versioning or https://github.com/twbs/bootstrap#versioning (if you like Semantic Versioning).

Make it work with Node.js

I understand that this request may seem unreasonable for a library with "jquery" in its name, but some components like the parser would be amazingly useful for server-side apps.

Waiting for Resouces to Load

Love this project - just have one issue...I have the following code where i call initResources() as soon as the document ready fires. I have a race condition in that other js code executes before the load() completes and I cannot get the string resource. How can I block/wait for the load to complete before trying to access the string resources in a safe way?

that.getResource = function(key, param1) {

    if (!localeInitialized) {
        that.log('resource not loaded!');
    }

    return $.i18n(key, param1);
}, 
that.initResources = function() {
    i18N = $.i18n();
    i18N.locale = $('html').attr('lang');
    i18N.load('/scripts/lang/' + i18N.locale + '.json', i18N.locale).done(function () {
        localeInitialized = true;
    });
},

Files to include -- documentation improvement?

In the absence of a "dist" folder, it seems safe to assume that the contents of the "src" file (the JavaScript files) are the distributables that should be included on a page.

Looking at the source code of the example seems to support this, with the following files being included:

<script src="../src/jquery.i18n.js"></script>
<script src="../src/jquery.i18n.messagestore.js"></script>
<script src="../src/jquery.i18n.fallbacks.js"></script>
<script src="../src/jquery.i18n.parser.js"></script>
<script src="../src/jquery.i18n.emitter.js"></script>
<script src="../src/jquery.i18n.language.js"></script>

Followed by a few specific language files. It wasn't until I looked at the contents of the language files that I understood that they are extensions for formatting.

Also, higher up in the sample page, I see that the CLDR parser is included. I imagine that it is a requirement?

If my build script concatenates the following into one file, am I meeting the requirements for what is needed on the page (for the browser) in order to use i18n? I am just using the sample page's paths here; I would provide my own paths within the Grunt or Gulp:

../libs/CLDRPluralRuleParser/src/CLDRPluralRuleParser.js
../src/jquery.i18n.js
../src/jquery.i18n.messagestore.js
../src/jquery.i18n.fallbacks.js
../src/jquery.i18n.parser.js
../src/jquery.i18n.emitter.js
../src/jquery.i18n.language.js

And then language-specific functions and the emitter.bidi.js if needed?

Although I think my inferences are correct here, the documentation could be improved with a clear section on what needs to be included in order to have a functioning instance of i18n.


Also: the latest zip doesn't seem to include the CDLRPluralRuleParser that's being referenced. I imagine it can be had from CLDR's own repository, but I don't believe that it's documented anywhere. It seems to be assumed that the JavaScript file would appear in that directory.

Message loader with cache invalidation

Currently the json files are loaded directly from the server. At translatewiki.net I have configured 30 minute caching time for them. This however means that if new messages are introduced, ULS will display placeholders until the file is recached client side. Nginx doesn't do etags, so another solution would be most welcome (at simplest appending ULS version string to the url of loaded files).

Getting Unexpected syntax

Hi,

I am trying to use the package with asp.net application. I loaded the base, messagestore and language js files with jquert 1.10.2. I am vie my application on chrome 49. when my language files are loaded I am getting an error message "Uncaught SyntaxError: Unexpected token :" in the browser console. My language file (en-GB.json) as only one entry { "welcome": "my message" }. Please guide me to resolve this issue

changing locale multiple times

EDIT: minutes after posting i found out I need to do $.i18n().locale = 'nl'; instead of $.i18n.locale = 'nl';

// on a sidenode, the test "jquery.i18n: Message load tests (1, 13, 14)" in my browser gives me a failed test on each rerun (on first run the test passes)

forget below.

Using jquery.i18n for the first time, I expected jquery.i18n to be working in the way i have set up in the third test-case. (i tought i wouldn't need to keep a reference to the instance of i18n i created.)
In short, my intention was to load all language-resources on pageload, then on user-request changing the locale and calling $("*").i18n(); to have every data-i18n tag like <div data-i18n=demo></div> translated.

Can anyone confirm the way i18n is intended to be used is by keeping a reference myself, or is this a bug in the library?

See the 3 testcases below for more info

`
( function ( $ ) {
'use strict';

QUnit.module( 'jquery.i18n - is this a bug?', {
	setup: function () {
		$.i18n( {
			locale: 'localex'
		} );
	},
	teardown: function () {
		$.i18n().destroy();
	}
} );

QUnit.test( 'WORKS: switch locale using $( document ).data( "i18n" ) instance', 4, function ( assert ) {
    $.i18n.locale = "localeinitial";
	// Load messages for two locales - nl , fr
	$.i18n().load( { 
        nl: { one: 'nl-ONE' },
		fr: { one: 'fr-ONE' }
	} );

    var $elem = $("<li data-i18n=one>initial text</li>");

	// Switch to locale nl
	$( document ).data( 'i18n' ).locale = 'nl';
	assert.strictEqual( $( document ).data( 'i18n' ).locale, 'nl', 'Locale switched to nl' );

    $elem.i18n();
    assert.strictEqual($elem.text(), 'nl-ONE', 'first translation');

	$( document ).data( 'i18n' ).locale = 'fr';
	assert.strictEqual( $( document ).data( 'i18n' ).locale, 'fr', 'Switch Locale to fr' );

    $elem.i18n();
    assert.strictEqual($elem.text(), 'fr-ONE', 'second translation');
} );
QUnit.test( 'WORKS: switch locale holding the instance', 4, function ( assert ) {
    var i18n = $.i18n();
	//$.i18n();
	//var i18n = $( document ).data( 'i18n' );

    i18n.locale = "localeinitial";
	// Load messages for two locales - nl , fr
	i18n.load( { 
        nl: { one: 'nl-ONE' },
		fr: { one: 'fr-ONE' }
	} );

    var $elem = $("<li data-i18n=one>initial text</li>");
    //assert.strictEqual($elem.text(), 'initial text', 'assertion of initial text works');

	// Switch to locale localey
	i18n.locale = 'nl';
	assert.strictEqual( i18n.locale, 'nl', 'Locale switched to nl' );

    $elem.i18n();
    assert.strictEqual($elem.text(), 'nl-ONE', 'first translation');

	i18n.locale = 'fr';
	assert.strictEqual( i18n.locale, 'fr', 'Switch Locale to fr' );

    $elem.i18n();
    assert.strictEqual($elem.text(), 'fr-ONE', 'second translation');
} );
QUnit.test( 'FAILS: switch locale using $.i18n', 4, function ( assert ) {
    $.i18n.locale = "localeinitial";
	// Load messages for two locales - nl , fr
	$.i18n().load( { 
        nl: { one: 'nl-ONE' },
		fr: { one: 'fr-ONE' }
	} );

    var $elem = $("<li data-i18n=one>initial text</li>");

	// Switch to locale localey
	$.i18n.locale = 'nl';
	assert.strictEqual( $.i18n.locale, 'nl', 'Locale switched to nl' );

    $elem.i18n();
    assert.strictEqual($elem.text(), 'nl-ONE', 'first translation');

	$.i18n.locale = 'fr';
	assert.strictEqual( $.i18n.locale, 'fr', 'Switch Locale to fr' );

    $elem.i18n();
    assert.strictEqual($elem.text(), 'fr-ONE', 'second translation');
} );

}( jQuery ) );

`

Support fallback loading

This bears some relation to #18

It should be possible to specify a URL to a directory that contains files of the form LANGCODE.json, and have jquery.i18n automatically fetch the .json file for the current language and its fallbacks.

The former is something that a caller can fairly easily emulate by doing something like $.i18n().load( 'path/to/i18n/' + $.i18n().locale + '.json', $.i18n().locale ); or whatever, but following the fallback chain is more complicated and should be implemented in jquery.i18n itself.

HTML Tags in Translations

I've got some translations with html markup (specifically ). Due to varying word order, I would like to somehow keep the ability to add these tags in the translation files. Something like this:

http://stackoverflow.com/questions/16038458/html-tags-in-i18next-translation

I have tried both directly inputing the HTML directly into the JSON data and creating my own magic word to no avail. In both cases the raw html shows up. Is it possible to use HTML tags in the translations?

jquery.i18n breaks with default locale in Chrome

In a normal, non-MediaWiki page in Chrome, I get:

>>> $.i18n().locale
"en-US"
>>> promise = $.i18n().load({'foobar':'Wheeee!'}, $.i18n().locale)
Object
>>> promise.state()
"resolved"
>>> $.i18n('foobar')
"foobar"

It looks like the default locale in Chrome is en-US and this is breaking jQuery.i18n. I can't set arbitrary messages into en-US and then read them back out.

This does work in a MediaWiki context because of , but this makes jQuery.i18n unusable in non-MediaWiki contexts.

Document difference from jqueryMsg

mediawiki.org documentation and jquery.i18n README don't specify in what cases jquery.i18n is preferred/needed over jqueryMsg (reported by @ebernhardson).
I'm adding a link on https://www.mediawiki.org/w/index.php?title=Manual:Messages_API&diff=1064527&oldid=1057080 but at least the README here should clarify the difference. Ideally we'd also have a one-line explanation of the difference, which could then be usable on [[Manual:Messages API]] with appropriate prominence.

Fallbacks fail with uppercase locale tags

The fallbacks are all defined in lowercase, but a lot of browsers report the locale with uppercase region. For example, the browser is reporting zh-TW, which should fall back to zh-hant. However, because it doesn't match zh-tw in the fallbacks file, it uses en instead.

The standard as far as I know is that the tags should be case insensitive (https://tools.ietf.org/html/bcp47), so it should correctly fall back regardless of the input case.

For now, I'm just forcing the locale to lowercase, which resolves this issue, but it should probably be fixed in the library itself.

Clarification: License (?)

Hi Guys,

I see that there are two LICENSE files in the repository: GPL and MIT. Which is correct?
And from my knowledge (may be wrong) you cannot have both, as GPL is in conflict with MIT.

Thanks for clarification!

Errors with minified version

Hi
First of all great job, very nice and useful plugin!
In my application I using Grunt with grunt uglify.
All looks good, but on load I got a lot of ajax error on cosole.
After deep investigation I found that inside function load in for in loop it takes Array.prototype functions and pushes them inside ajax load urls:
image

On debug mode you can see that array length is 1, but the code continue to take prototype function:
image
The result is many errors in console of ajax failed requests:
image
I around the array prototype functions on the PS.
I found that if I replace for in to array.foreach this problem is not happend

// for ( locIndex in fallbackLocales ) {
                // 	fallbackLocale = fallbackLocales[locIndex];
                // 	sourceMap[fallbackLocale] = source + '/' + fallbackLocale + '.json';
                // }
				
                fallbackLocales.forEach(function(locale) {
                    sourceMap[fallbackLocale] = source + '/' + locale + '.json';
                });

For your review

$.i18n().load not working

jQuery.Deferred exception: this.messageStore.load is not a function TypeError: this.messageStore.load is not a function
at I18N.load

Could not load json file

Hello,

could you please help me how to load my json resource file with key/value strings pairs ?

image

This is how I load my json source file. I used ASP.NET MVC classical folder hierarchy (View, Controllers, Scripts) where should I add this file ? If I place it into e.g. /Scripts should be my path = "~/Scripts/MyFolder/en.json" ? I could not load json file. And I try to access to my string resource like

image

Or Am I doing something wrong ?

Thx

Lukas

HTML elements are escaped

I have a message containing and HTML element like "test
text", but my "br" is displayed as escaped element. How to avoid elements escaping? I'm using the transparent $('[data-i18n]').i18n(); technique to translate all the content in my single page app.

data-i18n parameters

It would be great if there were a way to pass message parameters as html5 data attributes.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.