src/ResourceStore.js
import EventEmitter from './EventEmitter.js';
import { getPath, deepFind, setPath, deepExtend, isString } from './utils.js';
class ResourceStore extends EventEmitter {
constructor(data, options = { ns: ['translation'], defaultNS: 'translation' }) {
super();
this.data = data || {};
this.options = options;
if (this.options.keySeparator === undefined) {
this.options.keySeparator = '.';
}
if (this.options.ignoreJSONStructure === undefined) {
this.options.ignoreJSONStructure = true;
}
}
addNamespaces(ns) {
if (this.options.ns.indexOf(ns) < 0) {
this.options.ns.push(ns);
}
}
removeNamespaces(ns) {
const index = this.options.ns.indexOf(ns);
if (index > -1) {
this.options.ns.splice(index, 1);
}
}
getResource(lng, ns, key, options = {}) {
const keySeparator =
options.keySeparator !== undefined ? options.keySeparator : this.options.keySeparator;
const ignoreJSONStructure =
options.ignoreJSONStructure !== undefined
? options.ignoreJSONStructure
: this.options.ignoreJSONStructure;
let path;
if (lng.indexOf('.') > -1) {
path = lng.split('.');
} else {
path = [lng, ns];
if (key) {
if (Array.isArray(key)) {
path.push(...key);
} else if (isString(key) && keySeparator) {
path.push(...key.split(keySeparator));
} else {
path.push(key);
}
}
}
const result = getPath(this.data, path);
if (!result && !ns && !key && lng.indexOf('.') > -1) {
lng = path[0];
ns = path[1];
key = path.slice(2).join('.');
}
if (result || !ignoreJSONStructure || !isString(key)) return result;
return deepFind(this.data?.[lng]?.[ns], key, keySeparator);
}
addResource(lng, ns, key, value, options = { silent: false }) {
const keySeparator =
options.keySeparator !== undefined ? options.keySeparator : this.options.keySeparator;
let path = [lng, ns];
if (key) path = path.concat(keySeparator ? key.split(keySeparator) : key);
if (lng.indexOf('.') > -1) {
path = lng.split('.');
value = ns;
ns = path[1];
}
this.addNamespaces(ns);
setPath(this.data, path, value);
if (!options.silent) this.emit('added', lng, ns, key, value);
}
addResources(lng, ns, resources, options = { silent: false }) {
/* eslint no-restricted-syntax: 0 */
for (const m in resources) {
if (isString(resources[m]) || Array.isArray(resources[m]))
this.addResource(lng, ns, m, resources[m], { silent: true });
}
if (!options.silent) this.emit('added', lng, ns, resources);
}
addResourceBundle(
lng,
ns,
resources,
deep,
overwrite,
options = { silent: false, skipCopy: false },
) {
let path = [lng, ns];
if (lng.indexOf('.') > -1) {
path = lng.split('.');
deep = resources;
resources = ns;
ns = path[1];
}
this.addNamespaces(ns);
let pack = getPath(this.data, path) || {};
if (!options.skipCopy) resources = JSON.parse(JSON.stringify(resources)); // make a copy to fix #2081
if (deep) {
deepExtend(pack, resources, overwrite);
} else {
pack = { ...pack, ...resources };
}
setPath(this.data, path, pack);
if (!options.silent) this.emit('added', lng, ns, resources);
}
removeResourceBundle(lng, ns) {
if (this.hasResourceBundle(lng, ns)) {
delete this.data[lng][ns];
}
this.removeNamespaces(ns);
this.emit('removed', lng, ns);
}
hasResourceBundle(lng, ns) {
return this.getResource(lng, ns) !== undefined;
}
getResourceBundle(lng, ns) {
if (!ns) ns = this.options.defaultNS;
return this.getResource(lng, ns);
}
getDataByLanguage(lng) {
return this.data[lng];
}
hasLanguageSomeTranslations(lng) {
const data = this.getDataByLanguage(lng);
const n = (data && Object.keys(data)) || [];
return !!n.find((v) => data[v] && Object.keys(data[v]).length > 0);
}
toJSON() {
return this.data;
}
}
export default ResourceStore;