Reputation: 14866
I'm trying to create an multilingual javascript object. Something like:
function language(lang){
this.error = {
fname : function(lang){
var fname = {
vn : "Tên",
en : "First Name",
};
return fname.lang;
},
};
}
When I attempted to call fname
with this,
var lang = new language("en");
console.log(lang.error.fname);
it turned out
function(lang){var fname = {vn : "Tên",en : "First Name",};return fname.lang;}
instead of First Name
. What's wrong with my code? And how could I get fname
value correctly?
I'm pretty new to JS. I appreciate if somebody helps me figure out this issue.
Upvotes: 2
Views: 105
Reputation: 64526
As a quick fix, you need to use the []
syntax when returning the value, and remove the lang
argument from the fname()
function, so it becomes:
function language(lang){
this.error = {
fname : function(){
var fname = {
vn : "Tên",
en : "First Name",
};
return fname[lang];
},
};
}
language = new language('en');
console.log( language.error.fname() );
This works, but it isn't a very good structure. Look at the syntax for getting a translation, it's very strange looking, why is fname()
a function? Also look at how the translations are defined, they are mixed in with lots of JavaScript functions and logic, this makes it hard to maintain, and impossible for anyone to add translations that aren't familiar with JavaScript.
Let's look at a different structure:
function language(lang){
var translations = {
vn : {
error_fname : "Tên",
},
en : {
error_fname : 'First Name',
error_lname : 'Last Name'
}
};
var currentLang = 'en'; // default
function get(key){
return translations[currentLang][key];
}
// public pointers
this.get = get;
// constructor
if(typeof lang != 'undefined' && translations[lang]){
currentLang = lang;
}
}
var language = new language('en');
console.log( language.get('error_fname') );
First look at how the translations are defined. It's very clear and there is one en
object for all english translations. All of the english translations live in the en
object - makes sense right? There is no JavaScript logic mixed in with the translations, which means you can do things like use a JSON structure that can be read by translators that aren't familiar with JavaScript. You could even give translators a basic .ini
file, and have it transformed into this JavaScript/JSON structure because of its simplicity.
There are other benefits, such as the translations are encapsulated, and aren't directly accessible without going through the get()
method.
Here's a different way of doing it, that uses the .
syntax for getting a translation:
function language(lang){
var translations = {
vn : {
error_fname : "Tên",
},
en : {
error_fname : 'First Name',
error_lname : 'Last Name'
}
};
var currentLang = 'en'; // default
if(typeof lang != 'undefined' && translations[lang]){
currentLang = lang;
}
return translations[currentLang];
}
var language = language('en');
console.log( language.error_fname );
There is no get()
function, which you might or might not prefer. Personally I prefer the other way because of the encapsulation and the OOP style.
Upvotes: 1
Reputation: 10342
The way you have written it is a bit odd:
function language(lang){ // Constructor, that's ok
this.error = { // An attribute that is another object
fname : function(lang){ // this attribute has a function
var fname = { // the function has another object as a local variable with the same name!
vn : "Tên",
en : "First Name",
};
return fname.lang; //the object has vn and en attributes, but no lang
},
};
}
I'll try to define what kind of structure you want and then rewrite that mess from scratch.
Upvotes: 0
Reputation: 2954
You need to call fname
like a function
lang.error.fname()
Also, you should modify your function, because currently you ovveride lang
variable inside fname()
function:
fname : function(){
var fname = {
vn : "Tên",
en : "First Name",
};
return fname[lang];
}
Upvotes: 1