Returning nested object values based on function arguments

I’m trying to complete an exercise and somethings just not clicking.

Here’s the question: Could you write in JS (or Coffescript or any language that actually makes sense) a method getTranslation(lang, path) –> string that works the following way: You have this global object:

strings = {
    home: {
        intro: {
            en: 'Welcome',
            fr: 'Bienvenue'
        },
        content: {
            explanation: {
                en: 'This is an interesting exercise',
                fr: 'C'est un exercice intéressant',
                de: 'Es ist eine interesante Übung'
            },
            contact: 'Contact',
            goodbye: {
                en: 'Goodbye',
                fr: 'Au revoir',
                es: 'Adios'
            }
        }
    }
}

and

getTranslation('home.intro', 'fr') // => 'Bienvenue'
getTranslation('home.content.contact', 'fr') // => 'Contact'
getTranslation('home.intro', 'es') // => 'Welcome'
getTranslation('home.content.goodbye') // => 'Goodbye'
getTranslation('unvalid.path','en') // => ''

So the first argument is a string that describes the path through the keys separated by a dot (not dots in keys assumed), and the second argument is the language, which falls back to ‘en’ if not provided or nonexistent (we also assume that at the end of every branch, either the ‘en’ keys exists, or it is a single string like in home.content.contact).

Here’s my answer that I’ve come up with so far but I know I’m doing something wrong because nothings being returned.

function getTranslation (path, lang) {

    lang = lang || "en";

    var strings = {
        home: {
            intro: {
                en: 'Welcome',
                fr: 'Bienvenue'
        },
        content: {
            explanation: {
                en: 'This is an interesting exercise',
                fr: 'C'est un exercice intéressant',
                de: 'Es ist eine interesante Übung'
            },
            contact: 'Contact',
            goodbye: {
                en: 'Goodbye',
                fr: 'Au revoir',
                es: 'Adios'
            }
        }
    }

    if (path == 'home.content.contact') {
        return strings.path;
    } else if (path == 'unvalid.path') {
        return '';
    } else {
        return strings.path.lang;
    }
}

getTranslation('home.intro', 'fr'); // => 'Bienvenue'
getTranslation('home.content.contact', 'fr'); // => 'Contact'
getTranslation('home.intro', 'es'); // => 'Welcome'
getTranslation('home.content.goodbye'); // => 'Goodbye'
getTranslation('unvalid.path','en'); // => ''

Thank you to anyone willing to help.

Answer

Not sure if it is the best solution but it satisfies all your needs.

function getTranslation(path, lang) {

    lang = lang || "en";
    strings = {
        home: {
            intro: {
                en: 'Welcome',
                fr: 'Bienvenue'
            },
            content: {
                explanation: {
                    en: 'This is an interesting exercise',
                    fr: 'C'est un exercice intéressant',
                    de: 'Es ist eine interesante Übung'
                },
                contact: 'Contact',
                goodbye: {
                    en: 'Goodbye',
                    fr: 'Au revoir',
                    es: 'Adios'
                }
            }
        }
    }
    path = path.split(".");
    var result = strings;
    for(var i in path){
        result = result[path[i]];
        if(result == undefined){
            return '';
        }
    }
    return (result[lang]==undefined)?"":result[lang];
}

Leave a Reply

Your email address will not be published. Required fields are marked *