UNPKG

@akson/cortex-shopify-translations

Version:

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

187 lines (161 loc) 6.39 kB
#!/usr/bin/env node /** * Split large translation file into manageable category-based files * Adds status tracking for each translation */ import fs from 'fs/promises'; import path from 'path'; async function splitTranslations() { console.log('🧠 Splitting translations into category files...'); try { // Read the main translation file const mainFile = path.join(process.cwd(), 'translations-to-edit.json'); const data = JSON.parse(await fs.readFile(mainFile, 'utf-8')); // Initialize groups const groups = { checkout: [], customer: [], products: [], myarmy: [], navigation: [], forms: [], errors: [], other: [] }; // Stats tracking const stats = { total: data.translations.length, byCategory: {} }; // Categorize translations console.log(`📊 Processing ${data.translations.length} translations...`); data.translations.forEach(translation => { const key = translation.key.toLowerCase(); const frenchText = translation.fr_original.toLowerCase(); // Transform to new structure with status const item = { key: translation.key, fr: translation.fr_original, de: translation.de_current || '', it: translation.it_current || '', en: translation.en_current || '', status: { de: translation.de_current ? 'completed' : 'pending', it: translation.it_current ? 'completed' : 'pending', en: translation.en_current ? 'completed' : 'pending' }, resourceId: translation.resourceId, digest: translation.digest }; // Categorize based on key patterns if (key.includes('checkout') || key.includes('payment') || key.includes('shipping') || key.includes('billing') || key.includes('cart') || key.includes('order')) { groups.checkout.push(item); } else if (key.includes('customer') || key.includes('account') || key.includes('login') || key.includes('register') || key.includes('profile')) { groups.customer.push(item); } else if (key.includes('product') || key.includes('collection') || key.includes('variant') || key.includes('inventory') || key.includes('catalog')) { groups.products.push(item); } else if (key.includes('badge') || key.includes('section') || key.includes('pull') || key.includes('slide') || frenchText.includes('badge') || frenchText.includes('section') || frenchText.includes('équipement') || frenchText.includes('pull')) { groups.myarmy.push(item); } else if (key.includes('navigation') || key.includes('menu') || key.includes('header') || key.includes('footer') || key.includes('breadcrumb')) { groups.navigation.push(item); } else if (key.includes('form') || key.includes('input') || key.includes('field') || key.includes('button') || key.includes('submit')) { groups.forms.push(item); } else if (key.includes('error') || key.includes('invalid') || key.includes('required') || key.includes('failed') || key.includes('missing')) { groups.errors.push(item); } else { groups.other.push(item); } }); // Save each group to its own file const contentDir = path.join(process.cwd(), 'translations', 'content'); // Create content directory if it doesn't exist await fs.mkdir(contentDir, { recursive: true }); for (const [category, translations] of Object.entries(groups)) { const filePath = path.join(contentDir, `${category}.json`); // Calculate stats for this category const categoryStats = { total: translations.length, de: { pending: 0, completed: 0 }, it: { pending: 0, completed: 0 }, en: { pending: 0, completed: 0 } }; translations.forEach(t => { ['de', 'it', 'en'].forEach(lang => { categoryStats[lang][t.status[lang]]++; }); }); // Save file with metadata const fileData = { metadata: { category, total: translations.length, stats: categoryStats, created: new Date().toISOString() }, translations }; await fs.writeFile(filePath, JSON.stringify(fileData, null, 2), 'utf-8'); stats.byCategory[category] = categoryStats; console.log(`✅ ${category}.json: ${translations.length} translations`); console.log(` DE: ${categoryStats.de.completed} completed, ${categoryStats.de.pending} pending`); console.log(` IT: ${categoryStats.it.completed} completed, ${categoryStats.it.pending} pending`); console.log(` EN: ${categoryStats.en.completed} completed, ${categoryStats.en.pending} pending`); } // Create initial status file const statusPath = path.join(process.cwd(), 'translations', 'status.json'); const statusData = { summary: { total_keys: data.translations.length, created_at: new Date().toISOString(), last_update: new Date().toISOString(), source_language: 'fr', target_languages: ['de', 'it', 'en'] }, progress: calculateProgress(stats.byCategory), files: stats.byCategory }; await fs.writeFile(statusPath, JSON.stringify(statusData, null, 2), 'utf-8'); console.log('\n📊 Summary:'); console.log(`Total translations: ${stats.total}`); console.log('Files created:'); Object.entries(stats.byCategory).forEach(([cat, data]) => { console.log(` - ${cat}: ${data.total} items`); }); console.log('\n✅ Split completed successfully!'); console.log('📁 Files saved in: translations/content/'); } catch (error) { console.error('❌ Error splitting translations:', error.message); process.exit(1); } } function calculateProgress(categoryStats) { const progress = { de: { pending: 0, completed: 0 }, it: { pending: 0, completed: 0 }, en: { pending: 0, completed: 0 } }; Object.values(categoryStats).forEach(cat => { ['de', 'it', 'en'].forEach(lang => { progress[lang].pending += cat[lang].pending; progress[lang].completed += cat[lang].completed; }); }); return progress; } // Run the script splitTranslations();