UNPKG

@akson/cortex-shopify-translations

Version:

Unified Shopify translations management client with product extraction, translation sync, and CLI tools

122 lines (100 loc) 4.02 kB
#!/usr/bin/env node /** * Search for specific translations across all files * Useful for finding and reviewing specific keys or content */ import fs from 'fs/promises'; import path from 'path'; async function searchTranslations(searchTerm, options = {}) { const contentDir = path.join(process.cwd(), 'translations', 'content'); const { language, status, exact } = options; console.log(`\n🔍 Searching for: "${searchTerm}"\n`); try { const files = await fs.readdir(contentDir); const categoryFiles = files.filter(f => f.endsWith('.json')); let totalMatches = 0; const searchLower = searchTerm.toLowerCase(); for (const fileName of categoryFiles) { const filePath = path.join(contentDir, fileName); const data = JSON.parse(await fs.readFile(filePath, 'utf-8')); const matches = []; for (const translation of data.translations) { let isMatch = false; // Check if it matches the search criteria if (exact) { // Exact key match isMatch = translation.key === searchTerm; } else { // Search in key and all language content const keyMatch = translation.key.toLowerCase().includes(searchLower); const frMatch = translation.fr.toLowerCase().includes(searchLower); const deMatch = translation.de && translation.de.toLowerCase().includes(searchLower); const itMatch = translation.it && translation.it.toLowerCase().includes(searchLower); const enMatch = translation.en && translation.en.toLowerCase().includes(searchLower); isMatch = keyMatch || frMatch || deMatch || itMatch || enMatch; } // Filter by status if specified if (isMatch && status && language) { isMatch = translation.status[language] === status; } if (isMatch) { matches.push(translation); } } if (matches.length > 0) { console.log(`📁 ${fileName} (${matches.length} matches)`); console.log('─'.repeat(60)); matches.forEach(t => { console.log(`\nKey: ${t.key}`); console.log(`FR: ${t.fr}`); if (language) { // Show specific language if (t[language]) { console.log(`${language.toUpperCase()}: ${t[language]}`); console.log(`Status: ${t.status[language]}`); } else { console.log(`${language.toUpperCase()}: [${t.status[language]}]`); } } else { // Show all languages with content if (t.de) console.log(`DE: ${t.de} [${t.status.de}]`); if (t.it) console.log(`IT: ${t.it} [${t.status.it}]`); if (t.en) console.log(`EN: ${t.en} [${t.status.en}]`); } }); console.log(); totalMatches += matches.length; } } console.log(`\n✅ Found ${totalMatches} matches\n`); } catch (error) { console.error(`❌ Error: ${error.message}`); process.exit(1); } } // CLI const args = process.argv.slice(2); if (args.length === 0) { console.log('Usage: search-translations.mjs <search-term> [options]'); console.log('\nOptions:'); console.log(' --lang=<de|it|en> Filter by language'); console.log(' --status=<status> Filter by status (pending, completed, reviewed, failed)'); console.log(' --exact Match exact key only'); console.log('\nExamples:'); console.log(' search-translations.mjs badge'); console.log(' search-translations.mjs "ton équipement" --lang=de'); console.log(' search-translations.mjs checkout.payment --exact'); process.exit(0); } const searchTerm = args[0]; const options = {}; args.slice(1).forEach(arg => { if (arg.startsWith('--lang=')) { options.language = arg.split('=')[1]; } else if (arg.startsWith('--status=')) { options.status = arg.split('=')[1]; } else if (arg === '--exact') { options.exact = true; } }); searchTranslations(searchTerm, options);