Created
August 22, 2025 20:39
-
-
Save jack-arturo/419d0aae732915a3ebbb5b88604a0ec7 to your computer and use it in GitHub Desktop.
Automated deploy process for WP Fusion (local)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const { src, dest, series, parallel } = require( 'gulp' ); | |
| const replace = require( 'gulp-replace' ); | |
| const { exec } = require( 'child_process' ); | |
| const fs = require( 'fs' ); | |
| const replacementPath = { | |
| phpFiles: './**/*.php', | |
| exclude: [ '!./node_modules/**', '!./vendor/**', '!./languages/**' ], | |
| mainPluginFile: './wp-fusion.php', | |
| readmeFile: './readme.txt', | |
| potFile: './languages/wp-fusion.pot', | |
| configDir: './config', | |
| languagesDir: './languages', | |
| }; | |
| // Target languages for translation | |
| const targetLanguages = [ | |
| 'es_ES', // Spanish | |
| 'fr_FR', // French | |
| 'de_DE', // German | |
| 'it_IT', // Italian | |
| 'pt_BR', // Portuguese (Brazil) | |
| 'nl_NL', // Dutch | |
| 'ru_RU', // Russian | |
| 'ja', // Japanese | |
| 'zh_CN', // Chinese (Simplified) | |
| 'ko_KR', // Korean | |
| ]; | |
| function getVersionFromReadme() { | |
| const fs = require( 'fs' ); | |
| const readmeContent = fs.readFileSync( replacementPath.readmeFile, 'utf8' ); | |
| const match = readmeContent.match( /^Stable tag:\s*(.+)$/m ); | |
| if ( ! match ) { | |
| throw new Error( 'Version not found in readme.txt' ); | |
| } | |
| return match[ 1 ].trim(); | |
| } | |
| function updatePHPDocs() { | |
| const version = getVersionFromReadme(); | |
| return src( [ replacementPath.phpFiles, ...replacementPath.exclude ] ) | |
| .pipe( replace( /\bx\.x(?:\.x)?\b/g, version ) ) | |
| .pipe( dest( './' ) ); | |
| } | |
| function updateMainPluginFile() { | |
| const version = getVersionFromReadme(); | |
| return src( replacementPath.mainPluginFile, { base: './' } ) | |
| .pipe( | |
| replace( /^\s*\*\s*Version:\s*.+$/m, ` * Version: ${ version }` ) | |
| ) | |
| .pipe( dest( './' ) ); | |
| } | |
| function updateVersionConstant() { | |
| const version = getVersionFromReadme(); | |
| return src( replacementPath.mainPluginFile, { base: './' } ) | |
| .pipe( | |
| replace( | |
| /(define\(\s*['"]WP_FUSION_VERSION['"],\s*['"]).+?(['"]\s*\);)/, | |
| `$1${ version }$2` | |
| ) | |
| ) | |
| .pipe( dest( './' ) ); | |
| } | |
| function updatePOHeaders() { | |
| const version = getVersionFromReadme(); | |
| const headerFile = `${ replacementPath.configDir }/po-header.json`; | |
| if ( fs.existsSync( headerFile ) ) { | |
| const headers = JSON.parse( fs.readFileSync( headerFile, 'utf8' ) ); | |
| headers[ 'Project-Id-Version' ] = `WP Fusion ${ version }`; | |
| fs.writeFileSync( headerFile, JSON.stringify( headers, null, '\t' ) ); | |
| } | |
| return Promise.resolve(); | |
| } | |
| function generatePotFile( done ) { | |
| // Disable Xdebug in CI environment to prevent infinite loop detection | |
| const xdebugSettings = process.env.CI ? '-d xdebug.mode=off' : ''; | |
| const command = `php ${ xdebugSettings } -d memory_limit=1024M -d error_reporting='E_ALL & ~E_DEPRECATED' -d max_execution_time=300 $(command -v wp) i18n make-pot ./ ./languages/wp-fusion.pot --exclude=node_modules,vendor --allow-root`; | |
| exec( command, ( err, stdout, stderr ) => { | |
| if ( err ) { | |
| const fatalError = stderr | |
| .split( '\n' ) | |
| .filter( ( line ) => ! line.includes( 'Deprecated' ) ) | |
| .join( '\n' ); | |
| if ( fatalError.trim() ) { | |
| console.error( `Error: ${ fatalError }` ); | |
| } else if ( stdout && stdout.includes( 'Fatal error' ) ) { | |
| console.error( `Error: ${ stdout }` ); | |
| } | |
| done( err ); | |
| } else { | |
| console.log( stdout ); | |
| done(); | |
| } | |
| } ); | |
| } | |
| function generateTranslations( done ) { | |
| // Check if POT file exists | |
| if ( ! fs.existsSync( replacementPath.potFile ) ) { | |
| console.error( | |
| 'POT file not found. Please run generatePotFile first.' | |
| ); | |
| done( new Error( 'POT file not found' ) ); | |
| return; | |
| } | |
| // Check if .env file exists | |
| if ( ! fs.existsSync( './.env' ) ) { | |
| console.warn( | |
| 'No .env file found. Please copy env-example.txt to .env and configure your OpenAI API key.' | |
| ); | |
| console.log( 'Skipping automatic translations...' ); | |
| done(); | |
| return; | |
| } | |
| console.log( 'Starting incremental translations with Potomatic...' ); | |
| console.log( `Languages: ${ targetLanguages.join( ', ' ) }` ); | |
| console.log( 'Only new/changed strings will be translated' ); | |
| // Process each language individually to use existing .po files for incremental translation | |
| let languageIndex = 0; | |
| function processNextLanguage() { | |
| if ( languageIndex >= targetLanguages.length ) { | |
| console.log( 'All translations completed successfully!' ); | |
| done(); | |
| return; | |
| } | |
| const language = targetLanguages[ languageIndex ]; | |
| const existingPoFile = `${ replacementPath.languagesDir }/wp-fusion-${ language }.po`; | |
| // Build Potomatic command for this language | |
| let command = | |
| `npx potomatic ` + | |
| `--pot-file-path ${ replacementPath.potFile } ` + | |
| `--target-languages ${ language } ` + | |
| `--output-dir ${ replacementPath.languagesDir } ` + | |
| `--po-file-prefix wp-fusion- ` + | |
| `--locale-format wp_locale ` + | |
| `--use-dictionary ` + | |
| `--dictionary-path ${ replacementPath.configDir }/dictionaries ` + | |
| `--max-retries 3 ` + | |
| `--temperature 0.3 ` + | |
| `--verbose-level 1 ` + | |
| `--timeout 120`; | |
| // Add existing .po file for incremental translation if it exists | |
| if ( fs.existsSync( existingPoFile ) ) { | |
| command += ` --input-po-path ${ existingPoFile }`; | |
| console.log( | |
| `Processing ${ language }: Updating existing translations (incremental)` | |
| ); | |
| } else { | |
| console.log( | |
| `Processing ${ language }: Creating new translation file` | |
| ); | |
| } | |
| exec( command, ( err, stdout, stderr ) => { | |
| if ( err ) { | |
| console.error( | |
| `Translation error for ${ language }: ${ err.message }` | |
| ); | |
| console.error( stderr ); | |
| console.warn( | |
| `Skipping ${ language } and continuing with next language` | |
| ); | |
| } else { | |
| console.log( `${ language } completed successfully` ); | |
| if ( stdout.includes( 'strings translated' ) ) { | |
| // Extract and show translation summary | |
| const summaryMatch = stdout.match( /(\d+) translated/ ); | |
| if ( summaryMatch ) { | |
| console.log( | |
| ` → ${ summaryMatch[ 1 ] } strings translated` | |
| ); | |
| } | |
| } | |
| } | |
| languageIndex++; | |
| processNextLanguage(); | |
| } ); | |
| } | |
| processNextLanguage(); | |
| } | |
| function testTranslationSingle( done ) { | |
| // Check if POT file exists | |
| if ( ! fs.existsSync( replacementPath.potFile ) ) { | |
| console.error( | |
| 'POT file not found. Please run generatePotFile first.' | |
| ); | |
| done( new Error( 'POT file not found' ) ); | |
| return; | |
| } | |
| // Check if .env file exists | |
| if ( ! fs.existsSync( './.env' ) ) { | |
| console.warn( | |
| 'No .env file found. Please copy env-example.txt to .env and configure your OpenAI API key.' | |
| ); | |
| console.log( 'Skipping test translation...' ); | |
| done(); | |
| return; | |
| } | |
| // Test with just German for quick verification | |
| const testLanguage = 'de_DE'; | |
| const existingPoFile = `${ replacementPath.languagesDir }/wp-fusion-${ testLanguage }.po`; | |
| // Potomatic command with test settings - smaller batch, more verbose, cost limit | |
| let command = | |
| `npx potomatic ` + | |
| `--pot-file-path ${ replacementPath.potFile } ` + | |
| `--target-languages ${ testLanguage } ` + | |
| `--output-dir ${ replacementPath.languagesDir } ` + | |
| `--po-file-prefix wp-fusion-test- ` + | |
| `--locale-format wp_locale ` + | |
| `--use-dictionary ` + | |
| `--dictionary-path ${ replacementPath.configDir }/dictionaries ` + | |
| `--batch-size 5 ` + | |
| `--max-strings-per-job 50 ` + | |
| `--max-cost 5 ` + | |
| `--jobs 1 ` + | |
| `--max-retries 2 ` + | |
| `--temperature 0.3 ` + | |
| `--verbose-level 2 ` + | |
| `--timeout 60`; | |
| // Add existing .po file for incremental translation if it exists | |
| if ( fs.existsSync( existingPoFile ) ) { | |
| command += ` --input-po-path ${ existingPoFile }`; | |
| console.log( | |
| 'Using existing German translations as base (incremental)' | |
| ); | |
| } else { | |
| console.log( 'Creating fresh German test translation' ); | |
| } | |
| console.log( 'Starting TEST translation with Potomatic...' ); | |
| console.log( `Test language: German (${ testLanguage })` ); | |
| console.log( 'Limited to 50 strings, $5 max cost' ); | |
| console.log( 'Output file: wp-fusion-test-de_DE.po' ); | |
| exec( command, ( err, stdout, stderr ) => { | |
| if ( err ) { | |
| console.error( `Test translation error: ${ err.message }` ); | |
| console.error( stderr ); | |
| done( err ); | |
| } else { | |
| console.log( 'Test translation completed successfully!' ); | |
| console.log( stdout ); | |
| console.log( | |
| '\n🎉 Test completed! Check languages/wp-fusion-test-de_DE.po for results.' | |
| ); | |
| done(); | |
| } | |
| } ); | |
| } | |
| function createMoFiles( done ) { | |
| // Generate .mo files from .po files | |
| const command = `find ${ replacementPath.languagesDir } -name "*.po" -exec sh -c 'msgfmt "$1" -o "\${1%.po}.mo"' _ {} \\;`; | |
| exec( command, ( err, stdout, stderr ) => { | |
| if ( err ) { | |
| console.warn( | |
| `Warning: Could not generate .mo files: ${ err.message }` | |
| ); | |
| // Don't fail build for .mo generation errors | |
| } else { | |
| console.log( 'Generated .mo files successfully' ); | |
| } | |
| done(); | |
| } ); | |
| } | |
| // Export individual tasks | |
| exports.updatePHPDocs = updatePHPDocs; | |
| exports.updateMainPluginFile = updateMainPluginFile; | |
| exports.updateVersionConstant = updateVersionConstant; | |
| exports.updatePOHeaders = updatePOHeaders; | |
| exports.generatePotFile = generatePotFile; | |
| exports.generateTranslations = generateTranslations; | |
| exports.testTranslationSingle = testTranslationSingle; | |
| exports.createMoFiles = createMoFiles; | |
| // Main build task without translations | |
| exports.build = series( | |
| updatePHPDocs, | |
| updateMainPluginFile, | |
| updateVersionConstant, | |
| updatePOHeaders, | |
| generatePotFile | |
| ); | |
| // Complete release task with translations | |
| exports.release = series( | |
| updatePHPDocs, | |
| updateMainPluginFile, | |
| updateVersionConstant, | |
| updatePOHeaders, | |
| generatePotFile, | |
| generateTranslations, | |
| createMoFiles | |
| ); | |
| // Default task (now includes translations for complete release) | |
| exports.default = series( | |
| updatePHPDocs, | |
| updateMainPluginFile, | |
| updateVersionConstant, | |
| updatePOHeaders, | |
| generatePotFile, | |
| generateTranslations, | |
| createMoFiles | |
| ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment