i18n in RKWard's js files and sections

In contrast to the .xml files, making the js files of a plugin translatable requires more custom work. The key difference, here, is that there is no decent automatic way to tell, whether a string is meant to be displayed as a human readable string, or a piece of code. So you need to mark this up, yourself. We have already shown examples of this, all along. Here is a more complete description of the i18n-functions available in js code, and some hints for more complex cases:

i18n (msgid, [...])

The most important function. Marks the string for translation. The string (whether translated or not) is returned quoted using double quotes ('"'). An arbitrary number of placeholders can be used in the string like shown below. Using such placeholders instead of concatenating small substrings is much easier for translators:

			i18n ("Compare objects %1 and %2", getString ('x'), getString ('y'));
		
i18nc (msgctxt, msgid, [...])

Same as i18n(), but additionally providing a message context:

			i18nc ("proper name, not state of mind", "Mood test");
		
i18np (msgid_singular, msgid_plural, n, [...])

Same as i18n(), but for messages that may be different in singular or plural form (and some languages have differentiate yet more numerical forms). Note that just like with i18n(), you can use an arbitrary number of replacements, but the first ('%1') is required, and has to be an integer.

			i18np ("Comparing a single pair", "Comparing %1 distinct pairs", n_pairs);
		
i18ncp (msgctxt, msgid_singular, msgid_plural, n, [...])

i18np() with added message context.

comment (comment, [indentation])

Echos a code comment, marked for translation. In contrast to the other i18n() functions, this is not quoted, but a '#' is added to each line of the comment.

			comment ("Transpose the matrix");
			echo ('x <- t (x)\n');
		

To add comments to the translators (see above for a discussion of the differences between comment and context), add a comment starting with "i18n:" or "translators:" directly above the i18n()-call to comment. E.g.:

		// i18n: Spelling is correct: Scree plot.
		echo ('rk.header (' + i18n ("Scree plot") + ')\n');
	

i18n and quotes

For the most part, you will not have to worry about i18n() behavior with respect to quotes. As, typically, translatable strings are string literals, quoting them is just the right thing to do, and saves you some typing. Also, in functions like makeHeaderCode()/Header() that usually quote their arguments, i18n()'ed strings are protected from duplicate quoting. Essentially, this works, by sending the translated string first through quote() (to make it quoted), then through noquote() (to protect it from additional quoting). Should you require a translatable string that is not quoted, use i18n(noquote ("My message")). Should you require a translatable string to be quoted, a second time, send it through quote(), twice.

That said, it is generally not a good idea to make bits like function names or variable names translatable. For one thing, R, the programming language, is inherently in English, and there is no internationalization of the language itself. Code comments are a different beast, but you should use the comment()-function for those. Secondly, making syntactically relevant parts of the generated code translatable means that translations could actually break your plugin. E.g. if an unsuspecting translator translates a string meant as a variable name in two distinct words with a space in between.

i18n and backwards compatibility

One unfortunate aspect of the lack of i18n()-support in RKWard versions up to 0.6.2 is that adding i18n() calls will make the plugin require RKWard version 0.6.3. If your plugin is developed outside RKWard's official release, this may be a problem. Here are some possible options on how to handle this:

  • Provide the plugin in two versions for RKWard >= 0.6.3 and RKWard < 0.6.3, as described in the chapter on handling dependencies

  • Simply don't translate the strings in the .js-file, yet. Obviously this is an easy, but rather inelegant solution.

  • Include some support code in your .js-file(s) like shown below:

			// js-function "comment" was not defined before 0.6.3
			if (typeof (comment) == 'undefined) {
				// define function i18n(), and any others you may need. Note that your implementation could actually be simpler than
				// shown, here, e.g. if you do not make use of placeholders.
				i18n = function (msgid) {
					var ret = msgid;
					for (var i = 1; i < arguments.length; i++) {
						ret = ret.replace(new RegExp("%" + i, 'g'), arguments[i]);
					}
					if (msgid.noquote) {
						ret.noquote = msgid.noquote;
						return (ret);
					}
					return (noquote (quote (ret)));
				}
			}