UNPKG

react-native-i18n-auto

Version:

Auto i18n tool for React Native with full TypeScript support

113 lines (96 loc) 4.52 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = _default; function _default(_ref) { var babelTypes = _ref.types; // Function to convert text to key function parseToKey(text) { return text.trim() // Convert camelCase to underscore (e.g., userName -> user_name) .replace(/([a-z])([A-Z])/g, '$1_$2') // Convert spaces to underscores .replace(/\s+/g, '_') // Remove special characters (keep only alphanumeric and underscore) .replace(/[^A-Za-z0-9_]/g, '') // Convert to uppercase .toUpperCase(); } return { visitor: { Program: { exit: function exit(path, state) { // Check if i18n is actually used if (!state.i18nUsed) return; // Check if there is an i18n import statement var hasI18nImport = path.node.body.some(function (node) { var _node$source, _node$specifiers; return babelTypes.isImportDeclaration(node) && ((_node$source = node.source) === null || _node$source === void 0 ? void 0 : _node$source.value) === 'react-native-i18n-auto' && ((_node$specifiers = node.specifiers) === null || _node$specifiers === void 0 ? void 0 : _node$specifiers.some(function (specifier) { return babelTypes.isImportSpecifier(specifier) && 'name' in specifier.imported && specifier.imported.name === 'i18n'; })); }); // Add import statement if it doesn't exist if (!hasI18nImport) { var importDeclaration = babelTypes.importDeclaration([babelTypes.importSpecifier(babelTypes.identifier('i18n'), babelTypes.identifier('i18n'))], babelTypes.stringLiteral('react-native-i18n-auto')); // Add an empty line for line breaks var emptyStatement = babelTypes.emptyStatement(); path.node.body.unshift(emptyStatement); path.node.body.unshift(importDeclaration); } } }, JSXText: function JSXText(path, state) { var text = path.node.value.trim(); if (!text) return; // Ignore if it contains JSX expressions or dynamic values if (text.includes('{') || text.includes('}')) return; // Check if it's a prop value like title, placeholder, etc. var parent = path.parentPath; if (parent && babelTypes.isJSXAttribute(parent.node)) return; // Ignore if the text is just whitespace or line breaks if (/^[\s\n]*$/.test(text)) return; // Indicate that i18n is used state.i18nUsed = true; // Save extracted text if (state.opts.extractedTexts) { state.opts.extractedTexts.add(text); if (!state.file.metadata.extractedCount) { state.file.metadata.extractedCount = 0; } state.file.metadata.extractedCount++; } // Generate key var key = parseToKey(text); // Convert to i18n.t() call var i18nExpression = babelTypes.jsxExpressionContainer(babelTypes.callExpression(babelTypes.memberExpression(babelTypes.identifier('i18n'), babelTypes.identifier('t')), [babelTypes.stringLiteral(key)])); // Replace original text with the converted expression path.replaceWith(i18nExpression); }, JSXAttribute: function JSXAttribute(path, state) { var node = path.node; // Only process string props like title, placeholder, etc. if (babelTypes.isStringLiteral(node.value) && babelTypes.isJSXIdentifier(node.name) && ['title', 'placeholder', 'label', 'text'].includes(node.name.name)) { var value = node.value.value.trim(); if (!value) return; // Indicate that i18n is used state.i18nUsed = true; // Save extracted text if (state.opts.extractedTexts) { state.opts.extractedTexts.add(value); if (!state.file.metadata.extractedCount) { state.file.metadata.extractedCount = 0; } state.file.metadata.extractedCount++; } // Generate key var key = parseToKey(value); // Convert to i18n.t() call var i18nExpression = babelTypes.jsxExpressionContainer(babelTypes.callExpression(babelTypes.memberExpression(babelTypes.identifier('i18n'), babelTypes.identifier('t')), [babelTypes.stringLiteral(key)])); // Replace prop value with the converted expression node.value = i18nExpression; } } } }; }