@rustling-pines/typesafe-locale-generator
Version:
A TypeScript-based tool to generate locale JSON files for i18n frameworks with type safety. It ensures missing translations are caught during development, reducing errors and streamlining localization. Fully customizable input/output paths, compatible wit
148 lines (147 loc) โข 7.22 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.processTranslations = processTranslations;
const ts_node_1 = require("ts-node");
const fs_extra_1 = __importDefault(require("fs-extra"));
const path_1 = __importDefault(require("path"));
function processTranslations(translationInputFile, localesOutputDirectory, tempDir) {
return __awaiter(this, void 0, void 0, function* () {
const tempFileName = path_1.default.basename(translationInputFile, '.ts') + '.js';
try {
console.log(`๐ ๏ธ Starting Translation Processing...`);
console.log(`๐ฅ Input File: ${translationInputFile}`);
console.log(`๐ Output Directory: ${localesOutputDirectory}`);
console.log(`๐ง Temp Directory: ${tempDir}`);
// Ensure the translation input file exists
if (!fs_extra_1.default.existsSync(translationInputFile)) {
throw new Error(`โ Translation file not found: ${translationInputFile}`);
}
// Ensure the output directory exists
fs_extra_1.default.mkdirsSync(localesOutputDirectory);
// Compile the TypeScript file
console.log(`๐ ๏ธ Compiling TypeScript file...`);
require('child_process').execSync(`npx tsc ${translationInputFile} --outDir ${tempDir}`, {
stdio: 'inherit',
});
// Search recursively for the compiled file
console.log(`๐ Searching for the compiled temp file...`);
const compiledFilePath = findCompiledFile(tempDir, tempFileName);
if (!compiledFilePath) {
console.error(`โ Compiled temp file not found.`);
console.log('๐ Debug: Temp directory contents:');
debugTempDirectory(tempDir);
throw new Error(`โ Compiled file could not be located: ${tempFileName}`);
}
console.log(`๐ง Resolved Temp File Path: ${compiledFilePath}`);
// Register ts-node for TypeScript imports
(0, ts_node_1.register)({
project: path_1.default.resolve(process.cwd(), 'tsconfig.json'),
});
// Dynamically import the compiled JavaScript file
console.log(`๐ Loading translation configuration from: ${compiledFilePath}`);
let { locales, translations } = yield Promise.resolve(`${compiledFilePath}`).then(s => __importStar(require(s)));
// Validate locales array
if (!Array.isArray(locales) || locales.length === 0) {
console.warn(`โ ๏ธ Warning: Locales array is empty or invalid. Defaulting to ['en-us'].`);
locales = ['en-us'];
}
// Generate JSON files for each locale
for (const locale of locales) {
const localeFileContent = translations.map((translation) => ({
Key: translation.key,
Value: translation[locale],
}));
const outputFilePath = path_1.default.resolve(localesOutputDirectory, `${locale}.json`);
yield fs_extra_1.default.outputJson(outputFilePath, localeFileContent, { spaces: 2 });
console.log(`โ
Locale file generated: ${outputFilePath}`);
}
console.log(`โ
All locale files generated successfully!`);
}
catch (error) {
console.error(`โ Error during processing:`, error instanceof Error ? error.message : error);
console.log('๐ Debug: Temp directory contents:');
debugTempDirectory(tempDir);
throw error;
}
finally {
console.log(`๐งน Cleaning up temporary files...`);
if (fs_extra_1.default.existsSync(tempDir)) {
fs_extra_1.default.removeSync(tempDir);
console.log(`โ
Temporary files cleaned.`);
}
else {
console.log(`โ ๏ธ Temp directory already cleaned or missing.`);
}
}
});
}
// Helper function to find the compiled file recursively
function findCompiledFile(dir, targetFileName) {
const files = fs_extra_1.default.readdirSync(dir, { withFileTypes: true });
for (const file of files) {
const filePath = path_1.default.resolve(dir, file.name);
if (file.isFile() && file.name === targetFileName) {
return filePath;
}
else if (file.isDirectory()) {
const nestedResult = findCompiledFile(filePath, targetFileName);
if (nestedResult)
return nestedResult;
}
}
return null;
}
// Helper function to log the temp directory contents
function debugTempDirectory(dir) {
const files = fs_extra_1.default.readdirSync(dir, { withFileTypes: true });
files.forEach(file => {
const fullPath = path_1.default.resolve(dir, file.name);
console.log(` - ${fullPath}`);
});
}