Lewis
Lewis

Reputation: 14866

Call a method inside an object

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

Answers (3)

MrCode
MrCode

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:

Fiddle

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:

Fiddle

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:

Fiddle

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

Pablo Lozano
Pablo Lozano

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

Artem Petrosian
Artem Petrosian

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];
    }

FIDDLE

Upvotes: 1

Related Questions