Extensions designed to enrich your browsing experience

Localizing injectedscripts

Good morning all of you,

I bet some of you already came across this issue:
you injected something in a website which contained a text that had to be translated into different languages. Unlike all of the other scenarios (popup, options page, background script), injectedscripts do not have any access to the files within the extension – until now.

Opera 12.10 introduces the new Resource Loader API, which is capable of fetching files according to Opera's folder-localization algorithm. Ready to rumble? Let's get started! …

(1)

if you haven't done it already for localizing e.g. the options page, create a new folder "locales" in the main folder of your extension. In this folder create another folder for each localization you want to add, e.g. "en" for English, "fr" for French and so on. At last, go into one of the language-folders (e.g. "es" (Spanish in this case)) and create a new file (the name as well as the file extension doesn't really matter; I'll stick with "interface.txt" for this little tutorial)

(2)

Now that the necessary structure is set up, we'll begin coding:
Open your new "interface.txt"-file. We'll put a javascript object into it. Therefore start with a pair of curly braces ({ and }). Between them we can now add as many translation strings as we want to. The syntax for it is

"original string" : "translated string"

Separate multiple pairs of translation strings by a comma. So the result will look like this:

{
"Hello" : "Hola",
"world" : "mundo"
}

(3)

That was easy, wasn't it?
So now open your injectedscript. It's time to bring it to live ๐Ÿ˜‰

If you want your extension to work in Opera below version 12.10 as well (unlocalized though!), you have to add a javascript object containing the default (English) localization. It looks pretty much the same like the code we've put into interface.txt. The only difference is, that we're naming this object in here:

var strings = {
"Hello" : "Hello",
"world" : "world"
}

Your extension surely does something already. If you've put your code directly in an event listener (e.g. "DOMContentLoaded"), move it into an extra function. Mine initially looks like this:

function do_the_fancy_stuff(){ alert("Hello world!"); }

In order to localize it, we'll exchange the static strings by parts of our localized object:

function do_the_fancy_stuff(){ alert(strings["Hello"]+" "+strings["world"]+"!"); }

Now the main part of the magic. I'll just put it here and explain it afterwards:

if(opera.extension.getFile){
	strings = opera.extension.getFile("/interface_strings.txt");
	var fr = new FileReader();
	fr.readAsText(strings,"UTF-8");
	fr.onload = function(event){ strings = JSON.parse(event.target.result);	do_the_fancy_stuff(); };
}
else do_the_fancy_stuff();

Now step by step. What have we done?

if(opera.extension.getFile){ [...] do_the_fancy_stuff(); }
else do_the_fancy_stuff();

First test if Opera supports the new getFile-method (Opera 12.10+). If it is supported, we'll localize it and then call our initial function. If not, we'll proceed directly.

strings = opera.extension.getFile("/interface_strings.txt");

use the getFile-method to load your localized string (Opera will automatically fetch it from the correct language-folder :up:)

var fr = new FileReader();
fr.readAsText(strings,"UTF-8");

now we need to get the content of that file. It's read as plain text in UTF-8-encoding

fr.onload = function(event){ strings = JSON.parse(event.target.result);	do_the_fancy_stuff(); };

FileReaders are asynchronous just like Ajax is. That's why we can't just write

strings = JSON.parse(event.target.result);
do_the_fancy_stuff();

, but we have to wait for it to finish loading the file. As soon as the unload-event fires, all we have to do now is parsing what we got. Until now, we only got a big string of text out of the file. Using

JSON.parse()

, the text is converted into the javascript object which it contains. If you missed a comma or made any other mistake in the translation file, this is where you will get the error. Finally call your do_the-fancy_stuff-function.

That's it ๐Ÿ™‚

I hope it's helpful to you. If you're struggling to understand a part let me know in the comments ๐Ÿ˜‰

Note:

if you want to, you can use a function for translating your stuff as well:

function _(original){ return strings[original]?strings[original]:original; }

This function ensures, that your extension will not seize to function, if you forgot to add a certain string into one of the localization folders.
In this case your do_the_fancy_stuff-function has to contain

alert( _ ("Hello")+" "+_ ("world")+"!"); }

without a space between _ and (. I wasn't able to write it that way since Opera is obviously using the same localization function and eliminates the code ^^

Advertisements

Comments on: "Localizing injectedscripts" (3)

  1. This should be added into official documentation.

  2. Anonymous writes:This does not work!JSON object can't parse UTF-8 strings.

  3. Hi there,

    I’m French.
    I’m participating in the translation of turn Off the Lights extension into FR.
    I may also translate you extension into FR because your French translations in the Modern scroll settings come from a translator. So that’s really horrible to understand !!

    I’m use to crowdin to translate into Fr Turn Off the Lights. If you prepare me English texts on this also, I can translate.
    Or the developer sometimes send me a .doc file in English => I translate into Fr > I send back it to him the file => he published the translations fixes in the next version of his app.

    E-mail me back if you are interested in that proposal !

    Regards.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: