<commit_before>/*globals template*/
var parse = function (key, obj) {
    'use strict';
    var ar = key.split('.');

    while (obj && ar.length) {
        obj = obj[ar.shift()];
    }

    return obj;
};

var extend = function (objA, objB) {
    'use strict';
    for (var i in objB) {
        if (objB.hasOwnProperty(i)) {
            if (objA.hasOwnProperty(i) && (typeof objA[i] === typeof objB[i])) {
                objA[i] = extend(objB[i]);
            } else {
                objA[i] = objB[i];
            }
        }
    }
    return objA;
};

var I18n = function () {
    'use strict';
    // PRIVATES
    var localLang = 'en';
    var dico = {};
    var defaults = {};
    var evaluate = /\{\{([\s\S]+?)\}\}/g;
    var interpolate = /\{\{=([\s\S]+?)\}\}/g;
    var escape = /\{\{-([\s\S]+?)\}\}/g;

    this.add = function (lang, ns, locales) {
        var i;
        var obj;

        dico[lang] = dico[lang] || {};

        if (locales === undefined) {
            locales = ns;
            ns = undefined;
            obj = dico[lang];
        } else {
            dico[lang][ns] = dico[lang][ns] || {};
            obj = dico[lang][ns];
        }

        for (i in locales) {
            if (locales.hasOwnProperty(i)) {
                obj[i] = locales[i];
            }
        }
    };

    this.has = function (key, lang) {
        lang = lang || localLang;

        var keyToParse = lang + '.' + key;

        // Check for the lang
        if (dico[key]) {
            return true;
        }

        // Check for the key and lang
        return parse(keyToParse, dico) ? true : false;
    };

    this.listLangs = function () {
        var langs = [];

        for (var i in dico) {
            langs.push(i);
        }

        return langs;
    };

    this.getCurrentLang = function () {
        return localLang;
    };

    this.getDico = function () {
        return dico;
    };

    this.getDefaults = function () {
        return defaults;
    };

    this.setLang = function (lang) {
        localLang = lang;
        return localLang;
    };

    this.setDefaults = function (options) {
        defaults = extend(defaults, options || {});
    };

    this.get = function (key, data, options, lang) {
        var lng = lang || localLang;

        if (lang === undefined) {
            if (typeof data === 'string') {
                lng = data;
                data = undefined;
            } else if (typeof options === 'string') {
                lng = options;
            }
        }

        var obj = parse(lng + '.' + key, dico) ||
            parse(lng + '.' + key, defaults) ||
            parse(key, defaults);
        options = options || {};

        if (typeof obj === 'string' || typeof obj === 'function') {
            return this.templateString(obj, data, options, lng);
        } else if (typeof obj === 'object') {
            return obj;
        }

        return key;
    };

    this.templateString = function (st, data, options, lng) {
        var i;
        options = options || {};
        var settings = {
            evaluate: options.evaluate || evaluate,
            interpolate: options.interpolate || interpolate,
            escape: options.escape || escape
        };
        var newDatas = {};
        var defs = defaults[lng] || defaults;

        for (i in defs) {
            if (defs.hasOwnProperty(i)) {
                newDatas[i] = defs[i];
            }
        }

        for (i in data) {
            if (data.hasOwnProperty(i)) {
                newDatas[i] = data[i];
            }
        }

        if (typeof st !== 'function' && typeof template === 'function') {
            st = template(st, settings);
        }

        return st(newDatas);
    };
};

return new I18n();<commit_msg>refactor: new extend and simpler templating<commit_after>/*globals template*/
var parse = function (key, obj) {
    'use strict';
    var ar = key.split('.');

    while (obj && ar.length) {
        obj = obj[ar.shift()];
    }

    return obj;
};

var extend = function (a, b) {
    'use strict';
    for (var i in b) {
        if (a.hasOwnProperty(i)) {
            var tA = typeof a[i];
            var tB = typeof b[i];
            if (tA === tB) {
                if (tA !== 'object') {
                    a[i] = b[i];
                } else {
                    extend(a[i], b[i]);
                }
            } else {
                a[i] = b[i];
            }
        } else if (b.hasOwnProperty(i)) {
            a[i] = b[i];
        }
    }
    return a;
};

var templateString = function (st, data, options, lng, defaults) {
    'use strict';
    var i;
    var evaluate = /\{\{([\s\S]+?)\}\}/g;
    var interpolate = /\{\{=([\s\S]+?)\}\}/g;
    var escape = /\{\{-([\s\S]+?)\}\}/g;
    options = options || {};
    var settings = {
        evaluate: options.evaluate || evaluate,
        interpolate: options.interpolate || interpolate,
        escape: options.escape || escape
    };
    var newDatas = extend(extend(defaults, defaults[lng]), data) ||
        defaults || {};

    if (typeof st !== 'function' && typeof template === 'function') {
        st = template(st, settings);
    }

    return st(newDatas);
};

var I18n = function () {
    'use strict';
    // PRIVATES
    var localLang = 'en';
    var dico = {};
    var defaults = {};

    this.add = function (lang, ns, locales) {
        var i;
        var obj;

        dico[lang] = dico[lang] || {};

        if (locales === undefined) {
            locales = ns;
            ns = undefined;
            obj = dico[lang];
        } else {
            dico[lang][ns] = dico[lang][ns] || {};
            obj = dico[lang][ns];
        }
        obj = extend(obj, locales);
    };

    this.has = function (key, lang) {
        lang = lang || localLang;

        var keyToParse = lang + '.' + key;

        // Check for the lang
        if (dico[key]) {
            return true;
        }

        // Check for the key and lang
        return parse(keyToParse, dico) ? true : false;
    };

    this.listLangs = function () {
        var langs = [];

        for (var i in dico) {
            langs.push(i);
        }

        return langs;
    };

    this.getCurrentLang = function () {
        return localLang;
    };

    this.getDico = function () {
        return dico;
    };

    this.getDefaults = function () {
        return defaults;
    };

    this.setLang = function (lang) {
        localLang = lang;
        return localLang;
    };

    this.setDefaults = function (options) {
        defaults = extend(defaults, options || {});
    };

    this.get = function (key, data, options, lang) {
        var lng = lang || localLang;

        if (lang === undefined) {
            if (typeof data === 'string') {
                lng = data;
                data = undefined;
            } else if (typeof options === 'string') {
                lng = options;
            }
        }
        var obj = parse(lng + '.' + key, dico) ||
            parse(lng + '.' + key, defaults) ||
            parse(key, defaults);
        options = options || {};
        var toReturn = key;

        if (typeof obj === 'string' || typeof obj === 'function') {
            toReturn = templateString(obj, data, options, lng, defaults);
        } else if (typeof obj === 'object') {
            toReturn = obj;
        }

        return toReturn;
    };
};

return new I18n();
{'fraction_non_alphanumeric': 0.15510039078291335, 'fraction_numerical': 0.0010780218299420562, 'mean_word_length': 1.4657807308970099, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1716134', 'n_tokens_mistral': 2329, 'n_tokens_neox': 2254, 'n_words': 581}