UNPKG

@akson/cortex-shopify-translations

Version:

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

140 lines (117 loc) • 4.78 kB
#!/usr/bin/env node /** * Merge split translation files back to Shopify format * Creates a file ready for publish-translations.mjs */ import fs from 'fs/promises'; import path from 'path'; async function mergeBack(outputFile = 'translations-to-edit.json') { console.log('šŸ”€ Merging translations back to publishable format...\n'); const contentDir = path.join(process.cwd(), 'translations', 'content'); const outputPath = path.join(process.cwd(), outputFile); try { // Get all category files const files = await fs.readdir(contentDir); const categoryFiles = files.filter(f => f.endsWith('.json')); const mergedData = { metadata: { createdAt: new Date().toISOString(), resourceType: 'ONLINE_STORE_THEME', resourceCount: 1, totalTranslations: 0, sourceLanguage: 'fr', targetLanguages: ['de', 'it', 'en'], note: 'fr_original contains the source language content for translations', instructions: { howToEdit: "Edit the '*_fixed' fields with proper translations FROM the fr_original field.", workflow: [ '1. Look at fr_original (this is the source text)', '2. Fix the *_fixed fields for target languages: de, it, en', '3. Save your changes', '4. Run: node publish-translations.mjs online_store_theme --force' ] }, categories_merged: [] }, translations: [] }; const stats = { total: 0, by_status: { de: { pending: 0, completed: 0, reviewed: 0, failed: 0 }, it: { pending: 0, completed: 0, reviewed: 0, failed: 0 }, en: { pending: 0, completed: 0, reviewed: 0, failed: 0 } } }; // Process each category file for (const fileName of categoryFiles) { const filePath = path.join(contentDir, fileName); const data = JSON.parse(await fs.readFile(filePath, 'utf-8')); console.log(`šŸ“ Processing ${fileName}: ${data.translations.length} translations`); mergedData.metadata.categories_merged.push(fileName.replace('.json', '')); // Convert back to publish format (with _fixed fields for editing) data.translations.forEach(t => { const shopifyFormat = { key: t.key, resourceId: t.resourceId || 'gid://shopify/OnlineStoreTheme/185946079581', fr_original: t.fr, digest: t.digest, de_current: t.de || '', de_fixed: t.de || '', // Use current value as starting point it_current: t.it || '', it_fixed: t.it || '', // Use current value as starting point en_current: t.en || '', en_fixed: t.en || '' // Use current value as starting point }; // Include all translations for complete file mergedData.translations.push(shopifyFormat); // Update stats ['de', 'it', 'en'].forEach(lang => { const status = t.status[lang] || 'pending'; if (stats.by_status[lang][status] !== undefined) { stats.by_status[lang][status]++; } }); stats.total++; }); } // Update metadata with final counts mergedData.metadata.totalTranslations = mergedData.translations.length; // Add summary stats mergedData.metadata.stats = { total_keys: stats.total, merged_keys: mergedData.translations.length, by_language: {} }; ['de', 'it', 'en'].forEach(lang => { const completed = stats.by_status[lang].completed + stats.by_status[lang].reviewed; mergedData.metadata.stats.by_language[lang] = { translated: completed, percentage: Math.round((completed / stats.total) * 100) }; }); // Write merged file await fs.writeFile(outputPath, JSON.stringify(mergedData, null, 2)); console.log('\nāœ… Merge complete!'); console.log(`šŸ“Š Total translations: ${stats.total}`); console.log(`šŸ“ Translated entries: ${mergedData.translations.length}`); console.log('\nšŸŒ Language completion:'); ['de', 'it', 'en'].forEach(lang => { const langStats = mergedData.metadata.stats.by_language[lang]; console.log(` ${lang.toUpperCase()}: ${langStats.translated} (${langStats.percentage}%)`); }); console.log(`\nšŸ’¾ Output saved to: ${outputFile}`); // Show publish command if ready if (mergedData.translations.length > 0) { console.log('\nšŸ“¤ Ready to publish to Shopify:'); console.log(` node publish-translations.mjs ${outputFile}`); } } catch (error) { console.error(`āŒ Error: ${error.message}`); process.exit(1); } } // CLI const args = process.argv.slice(2); const outputFile = args[0] || 'translations-to-edit.json'; mergeBack(outputFile);