Making WordPress.org

Ticket #3876: 3876.8.diff

File 3876.8.diff, 11.8 KB (added by ocean90, 6 years ago)
  • trunk/wordpress.org/public_html/wp-content/plugins/wporg-gp-customizations/inc/cli/class-language-pack.php

     
    4747                ] );
    4848
    4949                switch ( $type ) {
     50                        case 'core':
     51                                $this->generate_core( $slug, $args );
     52                                break;
    5053                        case 'plugin' :
    5154                                $this->generate_plugin( $slug, $args );
    5255                                break;
     
    5962        }
    6063
    6164        /**
     65         * Generates a language pack for core.
     66         *
     67         * Examples:
     68         *   wp @translate wporg-translate language-pack generate core dev --version=5.0-beta
     69         *   wp @translate wporg-translate language-pack generate core 4.9.x --locale=de --version=4.9.8
     70         *
     71         * @param string $slug Slug of the core version.
     72         * @param array  $args Extra arguments.
     73         */
     74        private function generate_core( $slug, $args ) {
     75                $projects = [
     76                        "wp/$slug"               => 'default',
     77                        "wp/$slug/admin"         => 'admin',
     78                        "wp/$slug/admin/network" => 'admin-network',
     79                        "wp/$slug/cc"            => 'continents-cities',
     80                ];
     81
     82                $version = $args['version'];
     83                if ( ! $version ) {
     84                        WP_CLI::error( 'Missing version.' );
     85                }
     86
     87                foreach ( $projects as $path => $domain ) {
     88                        $gp_project = GP::$project->by_path( $path );
     89                        if ( ! $gp_project ) {
     90                                WP_CLI::error( "Invalid core path: $path." );
     91                        }
     92
     93                        $translation_sets = GP::$translation_set->by_project_id( $gp_project->id );
     94                        if ( ! $translation_sets ) {
     95                                WP_CLI::error( 'No translation sets available.' );
     96                        }
     97
     98                        /**
     99                         * Filters the arguments passed to the WP-CLI command.
     100                         *
     101                         * @param array  $args CLI arguments.
     102                         * @param string $path Path of the GP Project.
     103                         */
     104                        $args = apply_filters( 'wporg_translate_language_pack_core_args', $args, $path );
     105
     106                        if ( $args['locale'] ) {
     107                                $translation_sets = wp_list_filter( $translation_sets, [
     108                                        'locale' => $args['locale'],
     109                                        'slug'   => $args['locale-slug'],
     110                                ] );
     111                        }
     112
     113                        if ( 'continents-cities' === $domain ) {
     114                                $translation_sets = array_filter( $translation_sets, function ( $set ) {
     115                                        return substr( $set->locale, 0, 3 ) !== 'en_';
     116                                } );
     117                        }
     118
     119                        $svn_command  = $this->get_svn_command();
     120                        $svn_checkout = self::get_temp_directory( $slug );
     121
     122                        $result = $this->execute_command( sprintf(
     123                                '%s checkout --quiet --depth=empty %s %s 2>&1',
     124                                $svn_command,
     125                                escapeshellarg( self::SVN_URL . '/core' ),
     126                                escapeshellarg( $svn_checkout )
     127                        ) );
     128
     129                        if ( is_wp_error( $result ) ) {
     130                                WP_CLI::error_multi_line( $result->get_error_data() );
     131                                WP_CLI::error( 'SVN export failed.' );
     132                        }
     133
     134                        $data                   = new stdClass();
     135                        $data->type             = 'core';
     136                        $data->domain           = 'default';
     137                        $data->version          = $args['version'];
     138                        $data->translation_sets = $translation_sets;
     139                        $data->gp_project       = $gp_project;
     140                        $data->svn_checkout     = $svn_checkout;
     141                        $this->build_language_packs( $data );
     142                }
     143        }
     144
     145        /**
    62146         * Generates a language pack for a plugin.
    63147         *
    64148         * Examples:
     
    374458        }
    375459
    376460        /**
     461         * Build a mapping of JS files to translation entries occurring in those files.
     462         * Translation entries occurring in other files are added to the 'po' key.
     463         *
     464         * @param Translation_Entry[] $entries The translation entries to map.
     465         *
     466         * @return array The mapping of sources to translation entries.
     467         */
     468        private function build_mapping( $entries ) {
     469                $mapping = array();
     470                foreach ( $entries as $entry ) {
     471                        /** @var Translation_Entry $entry */
     472
     473                        // Find all unique sources this translation originates from.
     474                        $sources = array_map( function ( $reference ) {
     475                                $parts = explode( ':', $reference );
     476                                $file  = $parts[0];
     477
     478                                if ( substr( $file, -7 ) === '.min.js' ) {
     479                                        return substr( $file, 0, -7 ) . '.js';
     480                                }
     481
     482                                if ( substr( $file, -3 ) === '.js' ) {
     483                                        return $file;
     484                                }
     485                                return 'po';
     486                        }, $entry->references );
     487                        // Always add all entries to the PO file.
     488                        $sources[] = 'po';
     489                        $sources = array_unique( $sources );
     490
     491                        foreach ( $sources as $source ) {
     492                                $mapping[ $source ][] = $entry;
     493                        }
     494                }
     495
     496                return $mapping;
     497        }
     498
     499        /**
     500         * Builds a mapping of JS file names to translation entries.
     501         *
     502         * @param GP_Project          $gp_project The GlotPress project.
     503         * @param GP_Locale           $gp_locale  The GlotPress locale.
     504         * @param GP_Translation_Set  $set        The translation set.
     505         * @param array               $mapping    A mapping of files to translation entries.
     506         * @param string              $base_dest  Destination file name.
     507         * @return array An array of translation files built, may be empty if no translations in JS files exist.
     508         */
     509        private function build_json_files( $gp_project, $gp_locale, $set, $mapping, $base_dest ) {
     510                // Export translations for each JS file to a separate translation file.
     511                $files  = array();
     512                $format = gp_array_get( GP::$formats, 'jed1x' );
     513                foreach ( $mapping as $file => $entries ) {
     514                        $json_content = $format->print_exported_file( $gp_project, $gp_locale, $set, $entries );
     515
     516                        $hash = md5( $file );
     517                        $dest = "{$base_dest}-{$hash}.json";
     518
     519                        file_put_contents( $dest, $json_content );
     520
     521                        $files[] = $dest;
     522                }
     523
     524                return $files;
     525        }
     526
     527        /**
    377528         * Builds a PO file for translations.
    378529         *
    379          * @param GP_Project         $gp_project The GlotPress project.
    380          * @param GP_Locale          $gp_locale  The GlotPress locale.
    381          * @param GP_Translation_Set $set        The translation set.
    382          * @param string             $dest       Destination file name.
     530         * @param GP_Project          $gp_project The GlotPress project.
     531         * @param GP_Locale           $gp_locale  The GlotPress locale.
     532         * @param GP_Translation_Set  $set        The translation set.
     533         * @param Translation_Entry[] $entries    The translation entries.
     534         * @param string              $dest       Destination file name.
    383535         * @return string|WP_Error Last updated date on success, WP_Error on failure.
    384536         */
    385         private function build_po_file( $gp_project, $gp_locale, $set, $dest ) {
    386                 $entries = GP::$translation->for_export( $gp_project, $set, [ 'status' => 'current' ] );
    387                 if ( ! $entries ) {
    388                         return new WP_Error( 'no_translations', 'No current translations available.' );
    389                 }
    390 
     537        private function build_po_file( $gp_project, $gp_locale, $set, $entries, $dest ) {
    391538                $format     = gp_array_get( GP::$formats, 'po' );
    392539                $po_content = $format->print_exported_file( $gp_project, $gp_locale, $set, $entries );
    393540
     
    423570         * Inserts a language pack into database.
    424571         *
    425572         * @param string $type     Type of the language pack.
    426          * @param string $domain   Slug of the theme/plugin.
     573         * @param string $domain   Slug of the theme/plugin/core.
    427574         * @param string $language Language the language pack is for.
    428575         * @param string $version  Version of the theme/plugin.
    429576         * @param string $updated  Last updated.
     
    520667                                }
    521668                        }
    522669
    523                         $export_directory = "{$data->svn_checkout}/{$data->domain}/{$data->version}/{$wp_locale}";
    524                         $build_directory  = self::BUILD_DIR . "/{$data->type}s/{$data->domain}/{$data->version}";
    525                         $filename         = "{$data->domain}-{$wp_locale}";
    526                         $po_file          = "{$export_directory}/{$filename}.po";
    527                         $mo_file          = "{$export_directory}/{$filename}.mo";
    528                         $zip_file         = "{$export_directory}/{$filename}.zip";
    529                         $build_zip_file   = "{$build_directory}/{$wp_locale}.zip";
     670                        $working_directory = 'core' === $data->type ? $data->svn_checkout : "{$data->svn_checkout}/{$data->domain}";
     671                        $export_directory  = "{$working_directory}/{$data->version}/{$wp_locale}";
     672                        $build_directory   = 'core' === $data->type
     673                                ? self::BUILD_DIR . "/core/{$data->version}"
     674                                : self::BUILD_DIR . "/{$data->type}s/{$data->domain}/{$data->version}";
    530675
     676                        $filename       = 'default' !== $data->domain ? "{$data->domain}-{$wp_locale}" : $wp_locale;
     677                        $json_file_base = "{$export_directory}/{$filename}";
     678                        $po_file        = "{$export_directory}/{$filename}.po";
     679                        $mo_file        = "{$export_directory}/{$filename}.mo";
     680                        $zip_file       = "{$export_directory}/{$filename}.zip";
     681                        $build_zip_file = "{$build_directory}/{$wp_locale}.zip";
     682
    531683                        // Update/create directories.
    532684                        $this->update_svn_directory( $export_directory );
    533685
     686                        $entries = GP::$translation->for_export( $data->gp_project, $set, [ 'status' => 'current' ] );
     687                        if ( ! $entries ) {
     688                                WP_CLI::warning( "No current translations available for {$wp_locale}." );
     689
     690                                continue;
     691                        }
     692
     693                        // Build a mapping based on where the translation entries occur and separate the po entries.
     694                        $mapping    = $this->build_mapping( $entries );
     695                        $po_entries = array_key_exists( 'po', $mapping ) ? $mapping['po'] : array();
     696
     697                        unset( $mapping['po'] );
     698
     699                        // Create JED json files for each JS file.
     700                        $json_files = $this->build_json_files( $data->gp_project, $gp_locale, $set, $mapping, $json_file_base );
     701
    534702                        // Create PO file.
    535                         $last_modified = $this->build_po_file( $data->gp_project, $gp_locale, $set, $po_file );
     703                        $last_modified = $this->build_po_file( $data->gp_project, $gp_locale, $set, $po_entries, $po_file );
    536704
    537705                        if ( is_wp_error( $last_modified ) ) {
    538706                                WP_CLI::warning( sprintf( "PO generation for {$wp_locale} failed: %s", $last_modified->get_error_message() ) );
    539707
    540708                                // Clean up.
    541                                 $this->execute_command( "rm -rf {$data->svn_checkout}/{$data->domain}" );
     709                                $this->execute_command( "rm -rf {$working_directory}" );
    542710
    543711                                continue;
    544712                        }
     
    555723                                WP_CLI::warning( "MO generation for {$wp_locale} failed." );
    556724
    557725                                // Clean up.
    558                                 $this->execute_command( "rm -rf {$data->svn_checkout}/{$data->domain}" );
     726                                $this->execute_command( "rm -rf {$working_directory}" );
    559727
    560728                                continue;
    561729                        }
     
    562730
    563731                        // Create ZIP file.
    564732                        $result = $this->execute_command( sprintf(
    565                                 'zip -9 -j %s %s %s 2>&1',
     733                                'zip -9 -j %s %s %s %s 2>&1',
    566734                                escapeshellarg( $zip_file ),
    567735                                escapeshellarg( $po_file ),
    568                                 escapeshellarg( $mo_file )
     736                                escapeshellarg( $mo_file ),
     737                                implode( ' ', array_map( 'escapeshellarg', $json_files ) )
    569738                        ) );
    570739
    571740                        if ( is_wp_error( $result ) ) {
     
    573742                                WP_CLI::warning( "ZIP generation for {$wp_locale} failed." );
    574743
    575744                                // Clean up.
    576                                 $this->execute_command( "rm -rf {$data->svn_checkout}/{$data->domain}" );
     745                                $this->execute_command( "rm -rf {$working_directory}" );
    577746
    578747                                continue;
    579748                        }
     
    589758                                WP_CLI::warning( "Creating build directories for {$wp_locale} failed." );
    590759
    591760                                // Clean up.
    592                                 $this->execute_command( "rm -rf {$data->svn_checkout}/{$data->domain}" );
     761                                $this->execute_command( "rm -rf {$working_directory}" );
    593762
    594763                                continue;
    595764                        }
     
    606775                                WP_CLI::warning( "Moving ZIP file for {$wp_locale} failed." );
    607776
    608777                                // Clean up.
    609                                 $this->execute_command( "rm -rf {$data->svn_checkout}/{$data->domain}" );
     778                                $this->execute_command( "rm -rf {$working_directory}" );
    610779
    611780                                continue;
    612781                        }
     
    618787                                WP_CLI::warning( sprintf( "Language pack for {$wp_locale} failed: %s", $result->get_error_message() ) );
    619788
    620789                                // Clean up.
    621                                 $this->execute_command( "rm -rf {$data->svn_checkout}/{$data->domain}" );
     790                                $this->execute_command( "rm -rf {$working_directory}" );
    622791
    623792                                continue;
    624793                        }
     
    643812                                WP_CLI::warning( "SVN commit for {$wp_locale} failed." );
    644813
    645814                                // Clean up.
    646                                 $this->execute_command( "rm -rf {$data->svn_checkout}/{$data->domain}" );
     815                                $this->execute_command( "rm -rf {$working_directory}" );
    647816
    648817                                continue;
    649818                        }
    650819
    651820                        // Clean up.
    652                         $this->execute_command( "rm -rf {$data->svn_checkout}/{$data->domain}" );
     821                        $this->execute_command( "rm -rf {$working_directory}" );
    653822
    654823                        WP_CLI::success( "Language pack for {$wp_locale} generated." );
    655824                }