i18next-scanner-esm
Version:
Scan your code, extract translation keys/values, and merge them into i18n resource files.
84 lines (69 loc) • 2.46 kB
JavaScript
import _get from 'lodash/get.js';
const isJSXText = (node) => {
if (!node) {
return false;
}
return node.type === 'JSXText';
};
const isNumericLiteral = (node) => {
if (!node) {
return false;
}
return node.type === 'Literal' && typeof node.value === 'number';
};
const isStringLiteral = (node) => {
if (!node) {
return false;
}
return node.type === 'Literal' && typeof node.value === 'string';
};
const isObjectExpression = (node) => {
if (!node) {
return false;
}
return node.type === 'ObjectExpression';
};
const nodesToString = (nodes, code) => {
let memo = '';
let nodeIndex = 0;
nodes.forEach((node, i) => {
if (isJSXText(node) || isStringLiteral(node)) {
const value = node.value
.replace(/^[\r\n]+\s*/g, '') // remove leading spaces containing a leading newline character
.replace(/[\r\n]+\s*$/g, '') // remove trailing spaces containing a leading newline character
.replace(/[\r\n]+\s*/g, ' '); // replace spaces containing a leading newline character with a single space character
if (!value) {
return;
}
memo += value;
} else if (node.type === 'JSXExpressionContainer') {
const { expression = {} } = node;
if (isNumericLiteral(expression)) {
// Numeric literal is ignored in react-i18next
memo += '';
}
if (isStringLiteral(expression)) {
memo += expression.value;
} else if (
isObjectExpression(expression) &&
_get(expression, 'properties[0].type') === 'Property'
) {
memo += `<${nodeIndex}>{{${expression.properties[0].key.name}}}</${nodeIndex}>`;
} else {
console.error(
`Unsupported JSX expression. Only static values or {{interpolation}} blocks are supported. Got ${expression.type}:`
);
console.error(code.slice(node.start, node.end));
console.error(node.expression);
}
} else if (node.children) {
memo += `<${nodeIndex}>${nodesToString(
node.children,
code
)}</${nodeIndex}>`;
}
++nodeIndex;
});
return memo;
};
export default nodesToString;