We're developing an app that utilizes html/css/js, and it uses i18next to display translated strings.
In order to display translations, I embed an attribute within a tag. For example:
利用規約<label for="checkbox2" data-i18n="text_agree">に同意する</label>
In addition to this, the app uses a javascript file to replace strings with translations. For instance, the above code corresponds with:
en: { translation: {
text_agreement: 'Agree to EULA'
} }
This method of translation works for HTML tags. What I don't know is how to translate strings within js code. For instance, how would I display translated strings for this?
element.alert('なまえを記入してください。');
Help would be very much appreciated.
The initialization function gives you a function to translate your strings. ;)
You can 'put' this function to the window object, so you can use it everywhere in your code.
i18n.init(function(t) {
window.t = t("Your string here");
});
// ... more code
// Now you can use window.t to translate
element.alert(window.t('Your string'));
But note that it's asynchronous (!), so it could happen that the console says, that t() is undefined.
So first initialize i18next and then use window.t();
Also have a look at the documentation: http://jamuhl.github.io/i18next/pages/doc_init.html
Related
I'm trying to create a custom template engine in javascript but I'm having trouble getting started as I cannot extract tokens using regex.
Here are the requirements:
Variables are defined like this: $(variable)
Functions: $(name arg1 "this is arg2 but it contains whitespaces.")
Function arguments can contain other variables $(name $(variable) arg2)
Both variables and functions will be rendered async. For example: Get the value for $(variable) from db then replace it.
This is not for rendering an html page but to simply replace a string entered by a user on the backend.
Edit
More information:
Suppose a user enters the following string:
$(id $(lowercase John))
On the backend application must do:
Convert "John" to lowercase.
Get the id for "john" from db.
This is only a simple example to demonstrate how this should work.
Are there any libraries that can help me achieve this? If not, any idea how to implement this?
EDIT 2:
I tried using Mustache and I changed the delimiters to $(), however the function (section) tags do no satisfy the requirements. In Mustache, for functions I must do this: $(#name) $(variable) "this is arg2 but it contains whitespaces."$(/name) also it does not support async rendering.
If not, any idea how to implement this?
You should use an Abstract Syntax Tree, and write a compatible parser. While regex (as Pedro Lima stated) is good for simple templating, if you ever want to extend the parser, you'll need something a bit more robust.
As an example of an Abstract Syntax Tree parser, $(test1 $(test2) test3) lorem ipsum $(test4) would be turned into the following:
(Thanks to Mile Shang's Syntree for the tree generator.)
As for specifically how to write a parser, I think you can figure it out. Just iterate over the string and check for the template delimiter. Reading the source code for a templating library like Handlebars might help.
Here. This regex will identify the templates that can be replaced. Note that it only selects the innermost templates in nested templates.
/\$\((?<FirstTerm>\S+?)(?<OtherTerms>(?:\s+(?:\w+|".*?"))+)?\)/g
So just use a regex replace function with your templating logic recursively until there are no more matches. The inner templates will be replaced and you'll be left with the string with templates replaced.
Other answers on this post are correct, however, I want to share exactly how I managed to implement this:
Create a recursive match function. I used Steven Leviathan's article to implement this.
Create a render function and inside the function call the recursive match function to find and replace variable/function names with appropriate values.
Keep calling the render function recursively until all arguments inside a function have been replaced.
I have a following problem, i am building app that uses data stream from ajax calls, the data that is coming is therefore escaped inside json string.
example: 1°Set
When i insert that data to DOM it is being converted like this: 1°Set
I dont use any libraries like jQuery, pure Javascript.
I tried to store converted name also in another place but i cannot seem to convert it manually, i tried following functions:
var test = function(str) {
console.log(unescape(encodeURIComponent(str)) );
console.log(decodeURIComponent(escape(str)) );
};
test('1°Set');
It stays the same, does anyone have an idea how to convert it to a DOM like version?
I have a following problem, i am building app that uses data stream from ajax calls, the data that is coming is therefore escaped inside json string.
example: 1°Set
Sounds like you're having a problem because your backend serves a JSON that looks like:
{
"something": "1°Set"
}
Instead of a string "1°Set", you're serving HTML source code that amounts to "1°Set". This looks very unnecessary. I cannot see a good reason of using HTML escaping inside JSON, unless you actually want your JSON to actually contain a part of HTML source (with formatting and everything), rather than just a string.
My suggestion: Let's keep it simple and instead serve something like:
{
"something": "1°Set"
}
or equivalently escape it properly using JSON syntax:
{
"something": "1\u00b0Set"
}
Now you'll JavaScript will receive a plain string that can be easily displayed, for example inside element.textContent or element.value or anywhere else. You won't even need any conversions.
I know that I can use i18next to translate languages in html. For example:
<div data-i18n="someKey"></div>
But is there a way to somehow use it in JS. For example if I want to do something like
alert(someKey) ?
It should be alert(t(someKey)) (see http://i18next.com/ at end of page).
Having read the homepage of the project...
i18n.init(function(t) {
// translate nav
$(".nav").i18n();
// programatical access
var appName = t("app.name");
});
That last part is what you're looking for. It's important to note that that t is passed to the init callback as a parameter - you can't just blindly call t() anywhere ;)
How come I can't translate dynamically resp. using a variable with i18next?
For example in my JS-file I got this:
Here I use a variable and assign it to the i18n function and it doesn't work:
//this does not work:
var dynamicTranslation = "myText.toBetranslated";
console.log("translation dynamic ", !{JSON.stringify(t(dynamicTranslation))});
Here I hardcoded the string from above directly into the i18n function and it does work:
//inserted string is the same string as in dynamic translation but this does work:
console.log("translation static ", !{JSON.stringify(t("myText.toBetranslated"))});
As a result I get:
translation dynamic
translation static correct Translation
In order to solve it, I tried to solve it by playing around with setTimeout:
setTimeout(function() {console.log("time out translation: " + !{JSON.stringify(t(dynamicTranslation))})}, 2000);
But it would still show an empty result:
time out translation:
It's jade syntax. The first code didn't work because it is rendered with jade at the back end site. At that point jade doesn't take the JS part into consideration but only renders it and pushes the result (along with the untouched JS code) to the front end. Therefore the part with the variable inside the t()-function is not translated, because it doesn't take the JS code into consideration.
Is there a way of quickly grabbing translated string in javascript?
For example like this:
var s = L20n.get("hello");
I am using 3.5 from npm.
Following does not work:
document.l10n.ready.then(function(context) {
document.l10n.formatValue('myItemKey').then(function(result){
console.log(result);
});
});
It results in printing item key instead of translated value.
If you're using version 3.x, use formatValue:
document.l10n.formatValue('hello').then(console.log);
You can read more about it here: https://github.com/l20n/l20n.js/blob/v3.x/docs/view.md#viewformatvalueid-args. document.l10n is an instance of the View class that is created automatically for you when the page loads.
The method is asynchronous so that you don't have to worry about race conditions related to language files not being loaded yet.