UNPKG

i18ntk

Version:

i18n Tool Kit - Zero-dependency internationalization toolkit for setup, scanning, analysis, validation, auto translation, fixing, reporting, and runtime translation loading.

284 lines (229 loc) 8.66 kB
#!/usr/bin/env node /** * i18ntk-go.js - Go Language I18n Management Command * * Supports: * - Standard Go i18n patterns * - go-i18n library * - Custom Go i18n implementations * - Resource file (.json, .toml) management */ const fs = require('fs'); const path = require('path'); const SecurityUtils = require('../utils/security'); const { getConfig, saveConfig } = require('../utils/config-helper'); const I18nHelper = require('../utils/i18n-helper'); const SetupEnforcer = require('../utils/setup-enforcer'); const { program } = require('../utils/mini-commander'); (async () => { try { await SetupEnforcer.checkSetupCompleteAsync(); } catch (error) { console.error('Setup check failed:', error.message); process.exit(1); } })(); class GoI18nManager { constructor() { this.supportedPatterns = [ 'T("key")', 'Localize("key")', 'i18n.T("key")', 'tr("key")', 'message.Printer.Printf', 'i18n.MustLocalize' ]; this.fileExtensions = ['.go', '.mod', '.sum']; this.resourceFormats = ['.json', '.toml', '.yaml', '.yml']; } async detectFramework(sourceDir) { const goModPath = path.join(sourceDir, 'go.mod'); if (SecurityUtils.safeExistsSync(goModPath)) { const content = SecurityUtils.safeReadFileSync(goModPath, sourceDir, 'utf8') || ''; if (content.includes('go-i18n')) return 'go-i18n-v2'; if (/x\/text\b/.test(content)) return 'golang-text'; return 'standard-go'; } // Check for Go files const goFiles = this.findFiles(sourceDir, '.go'); if (goFiles.length > 0) { return 'standard-go'; } return 'generic'; } async extractTranslations(sourceDir, options = {}) { const framework = await this.detectFramework(sourceDir); const translations = new Set(); const goFiles = this.findFiles(sourceDir, '.go'); for (const file of goFiles) { const content = SecurityUtils.safeReadFileSync(file, path.dirname(file), 'utf8') || ''; // Extract Go i18n patterns const patterns = [ /T\("([^"]+)"\)/g, /Localize\("([^"]+)"\)/g, /i18n\.T\("([^"]+)"\)/g, /tr\("([^"]+)"\)/g, /message\.Printer\.Printf\("([^"]+)"/g, /i18n\.MustLocalize\(&i18n\.LocalizeConfig\{MessageID:\s*"([^"]+)"/g ]; for (const pattern of patterns) { let match; while ((match = pattern.exec(content)) !== null) { translations.add(match[1]); } } } return { framework, translations: Array.from(translations), files: goFiles.length, patterns: this.supportedPatterns }; } async createLocaleStructure(outputDir, languages = ['en']) { const localesDir = path.join(outputDir, 'locales'); for (const lang of languages) { const langDir = path.join(localesDir, lang); fs.mkdirSync(langDir, { recursive: true }); // Create Go i18n format files SecurityUtils.safeWriteFileSync(path.join(langDir, 'active.en.toml'), `# Go i18n translations for ${lang} [hello] other = "Hello, World!" [items] one = "{{.Count}} item" other = "{{.Count}} items" `); SecurityUtils.safeWriteFileSync(path.join(langDir, 'active.en.json'), JSON.stringify({ hello: "Hello, World!", items: { one: "{{.Count}} item", other: "{{.Count}} items" } }, null, 2)); } return localesDir; } findFiles(dir, extension) { const files = []; function traverse(currentDir) { const items = fs.readdirSync(currentDir); for (const item of items) { const fullPath = path.join(currentDir, item); const stat = fs.statSync(fullPath); if (stat.isDirectory() && !item.startsWith('.') && item !== 'node_modules') { traverse(fullPath); } else if (stat.isFile() && path.extname(item) === extension) { files.push(fullPath); } } } traverse(dir); return files; } async generateReport(results, outputDir) { const report = { timestamp: new Date().toISOString(), framework: results.framework, totalTranslations: results.translations.length, translations: results.translations, filesProcessed: results.files, patterns: results.patterns, recommendations: this.getRecommendations(results) }; const reportPath = path.join(outputDir, 'i18ntk-go-report.json'); SecurityUtils.safeWriteFileSync(reportPath, JSON.stringify(report, null, 2)); return reportPath; } getRecommendations(results) { const recommendations = []; if (results.translations.length === 0) { recommendations.push('No translations found. Check your Go i18n patterns'); } if (results.files === 0) { recommendations.push('No Go files found in source directory'); } if (results.framework === 'generic') { recommendations.push('Consider using go-i18n library for better i18n support'); } return recommendations; } } // CLI Implementation program .name('i18ntk-go') .description('Go language i18n management tool') .version('1.10.1'); program .command('init') .description('Initialize Go i18n structure') .option('-s, --source-dir <dir>', 'Source directory', './') .option('-o, --output-dir <dir>', 'Output directory', './i18ntk-reports') .option('-l, --languages <langs>', 'Languages (comma-separated)', 'en') .action(async (options) => { try { const manager = new GoI18nManager(); const languages = options.languages.split(','); const localesDir = await manager.createLocaleStructure(options.outputDir, languages); console.log(`✅ Go i18n structure initialized in: ${localesDir}`); console.log(`📊 Languages: ${languages.join(', ')}`); } catch (error) { console.error('❌ Error initializing Go i18n:', error.message); process.exit(1); } }); program .command('analyze') .description('Analyze Go i18n usage') .option('-s, --source-dir <dir>', 'Source directory', './') .option('-o, --output-dir <dir>', 'Output directory', './i18ntk-reports') .option('--dry-run', 'Preview without making changes') .action(async (options) => { try { SecurityUtils.validatePath(options.sourceDir); const manager = new GoI18nManager(); const results = await manager.extractTranslations(options.sourceDir); console.log(`🔍 Framework detected: ${results.framework}`); console.log(`📊 Files processed: ${results.files}`); console.log(`📝 Translations found: ${results.translations.length}`); if (!options.dryRun) { const reportPath = await manager.generateReport(results, options.outputDir); console.log(`📄 Report saved: ${reportPath}`); } } catch (error) { console.error('❌ Error analyzing Go i18n:', error.message); process.exit(1); } }); program .command('extract') .description('Extract Go translations') .option('-s, --source-dir <dir>', 'Source directory', './') .option('-o, --output-dir <dir>', 'Output directory', './locales') .option('-l, --languages <langs>', 'Languages (comma-separated)', 'en') .action(async (options) => { try { SecurityUtils.validatePath(options.sourceDir); const manager = new GoI18nManager(); const results = await manager.extractTranslations(options.sourceDir); await manager.createLocaleStructure(options.outputDir, options.languages.split(',')); console.log(`✅ Extracted ${results.translations.length} translations`); console.log(`📁 Locale structure created in: ${options.outputDir}`); } catch (error) { console.error('❌ Error extracting Go translations:', error.message); process.exit(1); } }); // Handle uncaught errors process.on('uncaughtException', (error) => { console.error('❌ Uncaught exception:', error.message); process.exit(1); }); process.on('unhandledRejection', (reason) => { console.error('❌ Unhandled rejection:', reason); process.exit(1); }); // Export for programmatic use module.exports = { GoI18nManager }; if (require.main === module) { program.parse(); }