translate-maker
Version:
Lightweight translation module. Internationalize your great project.
276 lines (213 loc) • 6.73 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _isPlainObject = _interopRequireDefault(require("lodash/isPlainObject"));
var _get = _interopRequireDefault(require("lodash/get"));
var _reduce = _interopRequireDefault(require("lodash/reduce"));
var _debug = _interopRequireDefault(require("debug"));
var _parser = _interopRequireDefault(require("./parser/parser"));
var _Mode = _interopRequireDefault(require("./constants/Mode"));
var _join = _interopRequireDefault(require("./utils/join"));
const log = (0, _debug.default)('translate-maker');
function resolveVariable(obj, path) {
const value = (0, _get.default)(obj, path);
if (typeof value === 'function') {
const pos = path.indexOf('.');
if (pos === -1) {
return value();
}
const pathBefore = path.substr(0, pos);
const fnName = path.substr(pos + 1);
const parentObj = (0, _get.default)(obj, pathBefore);
return parentObj[fnName]();
}
return value;
}
class Tree {
constructor(translate) {
this.translate = translate;
this.data = {};
}
getOptions() {
return this.translate.getOptions();
}
resolveValue(item = {}, attrs = {}) {
const {
type,
path
} = item;
const {
mode,
references,
variables,
combinations
} = this.getOptions();
if (mode === _Mode.default.ICU) {
// ICU is without combinations
if (references && type === 'variable') {
return this.get(path, attrs);
} else if (variables && type === 'reference') {
return resolveVariable(attrs, path);
}
return undefined;
}
if (references && type === 'reference') {
return this.get(path, attrs);
} else if (variables && type === 'variable') {
return resolveVariable(attrs, path);
} else if (combinations && type === 'combination') {
const referencePath = path[0].path;
const variablePath = path[1].path;
const varToRef = (0, _get.default)(attrs, variablePath);
const refPath = varToRef ? `${referencePath}.${varToRef}` : referencePath;
return this.get(refPath, attrs);
}
return undefined;
}
buildText(obj, attrs, smartValue) {
if (!obj || obj.type !== 'main') {
return undefined;
}
return obj.values.map(part => {
const {
filters
} = part;
if (part.type === 'text') {
return part.value;
}
if (part.type === 'smart') {
return smartValue;
}
const value = this.resolveValue(part, attrs);
if (!filters || !filters.length) {
return value;
}
return (0, _reduce.default)(filters, (reducedValue, filter) => this.applyFilter(reducedValue, part, attrs, filter), value);
});
}
applyFilter(value, part, attrs, filter) {
const filterFn = this.translate.getFilter(filter.type);
const args = filter.args || [];
const filterInput = (0, _join.default)(value);
return filterFn ? filterFn.call(this, filterInput, part, attrs, filter.metadata, ...args) : value;
}
process(value, attrs = {}, path) {
if (!value) {
return value;
}
const {
cache
} = this.getOptions();
if (cache.has(value)) {
const data = cache.get(value);
return this.buildText(data, attrs);
}
try {
const data = _parser.default.parse(value);
cache.set(value, data);
return this.buildText(data, attrs);
} catch (err) {
log(`Problem on path ${path}: ${err.message}`);
this.emit('err', err, path, value, attrs);
return undefined;
}
}
emit(...args) {
this.translate.emit(...args);
}
traverse(data, path, setChild) {
if (!path || !data) {
return data;
}
const isDefault = path[0] === '_';
const currentPath = isDefault ? path.substr(1) : path;
if (isDefault) {
const pos = currentPath.indexOf('.');
const defaultChild = pos !== -1 ? currentPath.substr(0, pos) : currentPath;
if (data.defaultChild && data.defaultChild !== defaultChild) {
throw new Error(`Default children is already set: ${data.defaultChild} ${defaultChild}`);
}
data.defaultChild = defaultChild;
}
const {
children = {}
} = data;
data.children = children;
const {
dotNotation
} = this.getOptions();
const pos = currentPath.indexOf('.');
if (dotNotation && pos !== -1) {
const name = currentPath.substr(0, pos);
const subPath = currentPath.substr(pos + 1);
if (!children[name] && setChild) {
children[name] = {};
}
const child = children[name];
return this.traverse(child, subPath, setChild);
}
if (!children[currentPath] && setChild) {
children[currentPath] = {};
}
return children[currentPath];
}
getDefaultValue(defaultValue, ...args) {
const options = this.getOptions();
const process = typeof defaultValue !== 'undefined' ? defaultValue : options.defaultValue;
return typeof process === 'function' ? process(...args) : process;
}
get(path, attrs, defaultValue) {
// user can skip attrs and use it as defaultValue
if (typeof attrs === 'string') {
return this.get(path, {}, attrs);
}
if (typeof defaultValue === 'undefined') {
this.emit('missingdefault', path, attrs);
}
const {
data
} = this;
let child = this.traverse(data, path); // autoselect defaultChild
while (child && child.defaultChild) {
child = child.children[child.defaultChild];
}
const value = child && child.value;
if (typeof value !== 'undefined') {
return this.process(value, attrs, path);
}
const currentDefaultValue = this.getDefaultValue(defaultValue, path, attrs);
this.emit('missing', path, attrs, currentDefaultValue);
if (typeof currentDefaultValue !== 'undefined') {
return this.process(currentDefaultValue, attrs, path);
}
return undefined;
}
set(path, value) {
if (!path) {
throw new Error('Name is undefined');
}
if ((0, _isPlainObject.default)(path)) {
Object.keys(path).forEach(key => {
this.set(key, path[key]);
});
return this;
}
if ((0, _isPlainObject.default)(value)) {
Object.keys(value).forEach(key => {
this.set(`${path}.${key}`, value[key]);
});
return this;
}
const {
data
} = this;
const child = this.traverse(data, path, true);
child.value = value;
return this;
}
}
exports.default = Tree;
//# sourceMappingURL=Tree.js.map