|
| 1 | +#!/usr/bin/env node |
| 2 | +/* eslint-disable no-console */ |
| 3 | + |
| 4 | +const fs = require('fs'); |
| 5 | +const path = require('path'); |
| 6 | + |
| 7 | +const TRANSLATIONS_FILE = path.resolve(__dirname, '../app/translations.js'); |
| 8 | +const PRINT_WIDTH = 80; |
| 9 | +const VALID_FLAGS = new Set(['--check', '--fix']); |
| 10 | + |
| 11 | +function needsQuoting(key) { |
| 12 | + return !/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key); |
| 13 | +} |
| 14 | + |
| 15 | +function formatKey(key) { |
| 16 | + return needsQuoting(key) ? `'${key}'` : key; |
| 17 | +} |
| 18 | + |
| 19 | +function formatValue(value) { |
| 20 | + const escaped = value |
| 21 | + .replace(/\\/g, '\\\\') |
| 22 | + .replace(/\n/g, '\\n') |
| 23 | + .replace(/\r/g, '\\r') |
| 24 | + .replace(/\t/g, '\\t'); |
| 25 | + // Use double quotes when value contains a single quote to avoid escaping |
| 26 | + if (escaped.includes("'")) { |
| 27 | + return `"${escaped.replace(/"/g, '\\"')}"`; |
| 28 | + } |
| 29 | + return `'${escaped}'`; |
| 30 | +} |
| 31 | + |
| 32 | +function sortedTranslationsFileContent(translations) { |
| 33 | + const lines = []; |
| 34 | + lines.push('/* eslint sort-keys: "error" */'); |
| 35 | + lines.push('const translations = {'); |
| 36 | + |
| 37 | + const sortedLangs = Object.keys(translations).sort(); |
| 38 | + for (let i = 0; i < sortedLangs.length; i++) { |
| 39 | + const lang = sortedLangs[i]; |
| 40 | + lines.push(` ${formatKey(lang)}: {`); |
| 41 | + |
| 42 | + const keys = Object.keys(translations[lang]).sort(); |
| 43 | + for (let j = 0; j < keys.length; j++) { |
| 44 | + const key = keys[j]; |
| 45 | + const formattedKey = formatKey(key); |
| 46 | + const formattedValue = formatValue(translations[lang][key]); |
| 47 | + const singleLine = ` ${formattedKey}: ${formattedValue},`; |
| 48 | + if (singleLine.length <= PRINT_WIDTH) { |
| 49 | + lines.push(singleLine); |
| 50 | + } else { |
| 51 | + lines.push(` ${formattedKey}:`); |
| 52 | + lines.push(` ${formattedValue},`); |
| 53 | + } |
| 54 | + } |
| 55 | + lines.push(' },'); |
| 56 | + } |
| 57 | + |
| 58 | + lines.push('};'); |
| 59 | + lines.push(''); |
| 60 | + lines.push('export default translations;'); |
| 61 | + lines.push(''); |
| 62 | + |
| 63 | + return lines.join('\n'); |
| 64 | +} |
| 65 | + |
| 66 | +async function main() { |
| 67 | + try { |
| 68 | + console.log('---------- Running sort-translations.js script ----------'); |
| 69 | + const flag = process.argv[2]; |
| 70 | + if (!VALID_FLAGS.has(flag)) { |
| 71 | + console.error( |
| 72 | + 'Missing or invalid mode. Use --check to verify sorting or --fix to write sorted translations.', |
| 73 | + ); |
| 74 | + process.exitCode = 1; |
| 75 | + return; |
| 76 | + } |
| 77 | + |
| 78 | + const translations = (await import(TRANSLATIONS_FILE)).default; |
| 79 | + const current = fs.readFileSync(TRANSLATIONS_FILE, 'utf-8'); |
| 80 | + const sorted = sortedTranslationsFileContent(translations); |
| 81 | + |
| 82 | + if (flag === '--check') { |
| 83 | + if (current === sorted) { |
| 84 | + console.log('CHECK mode - Translations are sorted:', TRANSLATIONS_FILE); |
| 85 | + } else { |
| 86 | + console.error( |
| 87 | + 'CHECK mode - Translations are not sorted:', |
| 88 | + TRANSLATIONS_FILE, |
| 89 | + ); |
| 90 | + process.exitCode = 1; |
| 91 | + } |
| 92 | + return; |
| 93 | + } |
| 94 | + |
| 95 | + try { |
| 96 | + fs.writeFileSync(TRANSLATIONS_FILE, sorted, 'utf-8'); |
| 97 | + console.log( |
| 98 | + 'FIX mode - Sorted translations written to', |
| 99 | + TRANSLATIONS_FILE, |
| 100 | + ); |
| 101 | + } catch (error) { |
| 102 | + const message = error instanceof Error ? error.message : String(error); |
| 103 | + console.error( |
| 104 | + `FIX - Failed to write sorted translations to ${TRANSLATIONS_FILE}: ${message}`, |
| 105 | + ); |
| 106 | + process.exitCode = 1; |
| 107 | + } |
| 108 | + } catch (error) { |
| 109 | + const message = error instanceof Error ? error.message : String(error); |
| 110 | + console.error(`Failed to process translations: ${message}`); |
| 111 | + process.exitCode = 1; |
| 112 | + } |
| 113 | +} |
| 114 | + |
| 115 | +main(); |
0 commit comments