"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.Trans = Trans; exports.nodesToString = nodesToString; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _react = _interopRequireWildcard(require("react")); var _htmlParseStringify = _interopRequireDefault(require("html-parse-stringify")); var _utils = require("./utils.js"); var _defaults = require("./defaults.js"); var _i18nInstance = require("./i18nInstance.js"); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function hasChildren(node, checkLength) { if (!node) return false; const base = node.props ? node.props.children : node.children; if (checkLength) return base.length > 0; return !!base; } function getChildren(node) { if (!node) return []; const children = node.props ? node.props.children : node.children; return node.props && node.props.i18nIsDynamicList ? getAsArray(children) : children; } function hasValidReactChildren(children) { if (Object.prototype.toString.call(children) !== '[object Array]') return false; return children.every(child => (0, _react.isValidElement)(child)); } function getAsArray(data) { return Array.isArray(data) ? data : [data]; } function mergeProps(source, target) { const newTarget = { ...target }; newTarget.props = Object.assign(source.props, target.props); return newTarget; } function nodesToString(children, i18nOptions) { if (!children) return ''; let stringNode = ''; const childrenArray = getAsArray(children); const keepArray = i18nOptions.transSupportBasicHtmlNodes && i18nOptions.transKeepBasicHtmlNodesFor ? i18nOptions.transKeepBasicHtmlNodesFor : []; childrenArray.forEach((child, childIndex) => { if (typeof child === 'string') { stringNode += `${child}`; } else if ((0, _react.isValidElement)(child)) { const childPropsCount = Object.keys(child.props).length; const shouldKeepChild = keepArray.indexOf(child.type) > -1; const childChildren = child.props.children; if (!childChildren && shouldKeepChild && childPropsCount === 0) { stringNode += `<${child.type}/>`; } else if (!childChildren && (!shouldKeepChild || childPropsCount !== 0)) { stringNode += `<${childIndex}>`; } else if (child.props.i18nIsDynamicList) { stringNode += `<${childIndex}>`; } else if (shouldKeepChild && childPropsCount === 1 && typeof childChildren === 'string') { stringNode += `<${child.type}>${childChildren}`; } else { const content = nodesToString(childChildren, i18nOptions); stringNode += `<${childIndex}>${content}`; } } else if (child === null) { (0, _utils.warn)(`Trans: the passed in value is invalid - seems you passed in a null child.`); } else if (typeof child === 'object') { const { format, ...clone } = child; const keys = Object.keys(clone); if (keys.length === 1) { const value = format ? `${keys[0]}, ${format}` : keys[0]; stringNode += `{{${value}}}`; } else { (0, _utils.warn)(`react-i18next: the passed in object contained more than one variable - the object should look like {{ value, format }} where format is optional.`, child); } } else { (0, _utils.warn)(`Trans: the passed in value is invalid - seems you passed in a variable like {number} - please pass in variables for interpolation as full objects like {{number}}.`, child); } }); return stringNode; } function renderNodes(children, targetString, i18n, i18nOptions, combinedTOpts, shouldUnescape) { if (targetString === '') return []; const keepArray = i18nOptions.transKeepBasicHtmlNodesFor || []; const emptyChildrenButNeedsHandling = targetString && new RegExp(keepArray.map(keep => `<${keep}`).join('|')).test(targetString); if (!children && !emptyChildrenButNeedsHandling && !shouldUnescape) return [targetString]; const data = {}; function getData(childs) { const childrenArray = getAsArray(childs); childrenArray.forEach(child => { if (typeof child === 'string') return; if (hasChildren(child)) getData(getChildren(child));else if (typeof child === 'object' && !(0, _react.isValidElement)(child)) Object.assign(data, child); }); } getData(children); const ast = _htmlParseStringify.default.parse(`<0>${targetString}`); const opts = { ...data, ...combinedTOpts }; function renderInner(child, node, rootReactNode) { const childs = getChildren(child); const mappedChildren = mapAST(childs, node.children, rootReactNode); return hasValidReactChildren(childs) && mappedChildren.length === 0 || child.props && child.props.i18nIsDynamicList ? childs : mappedChildren; } function pushTranslatedJSX(child, inner, mem, i, isVoid) { if (child.dummy) { child.children = inner; mem.push((0, _react.cloneElement)(child, { key: i }, isVoid ? undefined : inner)); } else { mem.push(..._react.Children.map([child], c => { const props = { ...c.props }; delete props.i18nIsDynamicList; return _react.default.createElement(c.type, (0, _extends2.default)({}, props, { key: i, ref: c.ref }, isVoid ? {} : { children: inner })); })); } } function mapAST(reactNode, astNode, rootReactNode) { const reactNodes = getAsArray(reactNode); const astNodes = getAsArray(astNode); return astNodes.reduce((mem, node, i) => { const translationContent = node.children && node.children[0] && node.children[0].content && i18n.services.interpolator.interpolate(node.children[0].content, opts, i18n.language); if (node.type === 'tag') { let tmp = reactNodes[parseInt(node.name, 10)]; if (rootReactNode.length === 1 && !tmp) tmp = rootReactNode[0][node.name]; if (!tmp) tmp = {}; const child = Object.keys(node.attrs).length !== 0 ? mergeProps({ props: node.attrs }, tmp) : tmp; const isElement = (0, _react.isValidElement)(child); const isValidTranslationWithChildren = isElement && hasChildren(node, true) && !node.voidElement; const isEmptyTransWithHTML = emptyChildrenButNeedsHandling && typeof child === 'object' && child.dummy && !isElement; const isKnownComponent = typeof children === 'object' && children !== null && Object.hasOwnProperty.call(children, node.name); if (typeof child === 'string') { const value = i18n.services.interpolator.interpolate(child, opts, i18n.language); mem.push(value); } else if (hasChildren(child) || isValidTranslationWithChildren) { const inner = renderInner(child, node, rootReactNode); pushTranslatedJSX(child, inner, mem, i); } else if (isEmptyTransWithHTML) { const inner = mapAST(reactNodes, node.children, rootReactNode); pushTranslatedJSX(child, inner, mem, i); } else if (Number.isNaN(parseFloat(node.name))) { if (isKnownComponent) { const inner = renderInner(child, node, rootReactNode); pushTranslatedJSX(child, inner, mem, i, node.voidElement); } else if (i18nOptions.transSupportBasicHtmlNodes && keepArray.indexOf(node.name) > -1) { if (node.voidElement) { mem.push((0, _react.createElement)(node.name, { key: `${node.name}-${i}` })); } else { const inner = mapAST(reactNodes, node.children, rootReactNode); mem.push((0, _react.createElement)(node.name, { key: `${node.name}-${i}` }, inner)); } } else if (node.voidElement) { mem.push(`<${node.name} />`); } else { const inner = mapAST(reactNodes, node.children, rootReactNode); mem.push(`<${node.name}>${inner}`); } } else if (typeof child === 'object' && !isElement) { const content = node.children[0] ? translationContent : null; if (content) mem.push(content); } else { pushTranslatedJSX(child, translationContent, mem, i, node.children.length !== 1 || !translationContent); } } else if (node.type === 'text') { const wrapTextNodes = i18nOptions.transWrapTextNodes; const content = shouldUnescape ? i18nOptions.unescape(i18n.services.interpolator.interpolate(node.content, opts, i18n.language)) : i18n.services.interpolator.interpolate(node.content, opts, i18n.language); if (wrapTextNodes) { mem.push((0, _react.createElement)(wrapTextNodes, { key: `${node.name}-${i}` }, content)); } else { mem.push(content); } } return mem; }, []); } const result = mapAST([{ dummy: true, children: children || [] }], ast, getAsArray(children || [])); return getChildren(result[0]); } function Trans(_ref) { let { children, count, parent, i18nKey, context, tOptions = {}, values, defaults, components, ns, i18n: i18nFromProps, t: tFromProps, shouldUnescape, ...additionalProps } = _ref; const i18n = i18nFromProps || (0, _i18nInstance.getI18n)(); if (!i18n) { (0, _utils.warnOnce)('You will need to pass in an i18next instance by using i18nextReactModule'); return children; } const t = tFromProps || i18n.t.bind(i18n) || (k => k); if (context) tOptions.context = context; const reactI18nextOptions = { ...(0, _defaults.getDefaults)(), ...(i18n.options && i18n.options.react) }; let namespaces = ns || t.ns || i18n.options && i18n.options.defaultNS; namespaces = typeof namespaces === 'string' ? [namespaces] : namespaces || ['translation']; const nodeAsString = nodesToString(children, reactI18nextOptions); const defaultValue = defaults || nodeAsString || reactI18nextOptions.transEmptyNodeValue || i18nKey; const { hashTransKey } = reactI18nextOptions; const key = i18nKey || (hashTransKey ? hashTransKey(nodeAsString || defaultValue) : nodeAsString || defaultValue); if (i18n.options && i18n.options.interpolation && i18n.options.interpolation.defaultVariables) { values = values && Object.keys(values).length > 0 ? { ...values, ...i18n.options.interpolation.defaultVariables } : { ...i18n.options.interpolation.defaultVariables }; } const interpolationOverride = values ? tOptions.interpolation : { interpolation: { ...tOptions.interpolation, prefix: '#$?', suffix: '?$#' } }; const combinedTOpts = { ...tOptions, count, ...values, ...interpolationOverride, defaultValue, ns: namespaces }; const translation = key ? t(key, combinedTOpts) : defaultValue; if (components) { Object.keys(components).forEach(c => { const comp = components[c]; if (typeof comp.type === 'function' || !comp.props || !comp.props.children || translation.indexOf(`${c}/>`) < 0 && translation.indexOf(`${c} />`) < 0) return; function Componentized() { return _react.default.createElement(_react.default.Fragment, null, comp); } components[c] = _react.default.createElement(Componentized, null); }); } const content = renderNodes(components || children, translation, i18n, reactI18nextOptions, combinedTOpts, shouldUnescape); const useAsParent = parent !== undefined ? parent : reactI18nextOptions.defaultTransParent; return useAsParent ? (0, _react.createElement)(useAsParent, additionalProps, content) : content; }