WordPress.org

Making WordPress.org

Ticket #3876: 3876.7.diff

File 3876.7.diff, 11.8 KB (added by herregroen, 8 months ago)
  • wordpress.org/public_html/wp-content/plugins/wporg-gp-customizations/inc/cli/class-language-pack.php

    diff --git wordpress.org/public_html/wp-content/plugins/wporg-gp-customizations/inc/cli/class-language-pack.php wordpress.org/public_html/wp-content/plugins/wporg-gp-customizations/inc/cli/class-language-pack.php
    index 0252d9fe7..dca5c716b 100644
    class Language_Pack extends WP_CLI_Command { 
    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;
    class Language_Pack extends WP_CLI_Command { 
    5861                }
    5962        }
    6063
     64        /**
     65         * Generates a language pack for core.
     66         *
     67         * Examples:
     68         *   wp @translate wporg-translate language-pack generate core 5.0
     69         *   wp @translate wporg-translate language-pack generate core 5.0 --locale=de
     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-netwrok',
     79                        "wp/$slug/cc"            => 'continents-cities',
     80                ];
     81
     82                foreach ( $projects as $path => $domain ) {
     83                        $gp_project = GP::$project->by_path( $path );
     84                        if ( ! $gp_project ) {
     85                                WP_CLI::error( "Invalid core path: $path." );
     86                        }
     87
     88                        $translation_sets = GP::$translation_set->by_project_id( $gp_project->id );
     89                        if ( ! $translation_sets ) {
     90                                WP_CLI::error( 'No translation sets available.' );
     91                        }
     92
     93                        /**
     94                         * Filters the arguments passed to the WP-CLI command.
     95                         *
     96                         * @param array  $args CLI arguments.
     97                         * @param string $path Path of the GP Project.
     98                         */
     99                        $args = apply_filters( 'wporg_translate_language_pack_core_args', $args, $path );
     100
     101                        if ( $args['locale'] ) {
     102                                $translation_sets = wp_list_filter( $translation_sets, [
     103                                        'locale' => $args['locale'],
     104                                        'slug'   => $args['locale-slug'],
     105                                ] );
     106                        }
     107
     108                        if ( $domain === 'continents-cities' ) {
     109                                $translation_sets = array_filter( $translation_sets, function ( $set ) {
     110                                        return substr( $set->locale, 0, 3 ) !== 'en_';
     111                                } );
     112                        }
     113
     114                        $svn_command  = $this->get_svn_command();
     115                        $svn_checkout = self::get_temp_directory( $slug );
     116
     117                        $result = $this->execute_command( sprintf(
     118                                '%s checkout --quiet --depth=empty %s %s 2>&1',
     119                                $svn_command,
     120                                escapeshellarg( self::SVN_URL . '/core' ),
     121                                escapeshellarg( $svn_checkout )
     122                        ) );
     123
     124                        if ( is_wp_error( $result ) ) {
     125                                WP_CLI::error_multi_line( $result->get_error_data() );
     126                                WP_CLI::error( 'SVN export failed.' );
     127                        }
     128
     129                        $data                   = new stdClass();
     130                        $data->type             = 'core';
     131                        $data->domain           = $domain;
     132                        $data->version          = $slug;
     133                        $data->translation_sets = $translation_sets;
     134                        $data->gp_project       = $gp_project;
     135                        $data->svn_checkout     = $svn_checkout;
     136                        $this->build_language_packs( $data );
     137                }
     138        }
     139
    61140        /**
    62141         * Generates a language pack for a plugin.
    63142         *
    class Language_Pack extends WP_CLI_Command { 
    374453        }
    375454
    376455        /**
    377          * Builds a PO file for translations.
     456         * Build a mapping of JS files to translation entries occurring in those files.
     457         * Translation entries occurring in other files are added to the 'po' key.
    378458         *
    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.
    383          * @return string|WP_Error Last updated date on success, WP_Error on failure.
     459         * @param Translation_Entry[] $entries The translation entries to map.
     460         *
     461         * @return array The mapping of sources to translation entries.
    384462         */
    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.' );
     463        private function build_mapping( $entries ) {
     464                $mapping = array();
     465                foreach ( $entries as $entry ) {
     466                        /** @var Translation_Entry $entry */
     467
     468                        // Find all unique sources this translation originates from.
     469                        $sources = array_map( function ( $reference ) {
     470                                $parts = explode( ':', $reference );
     471                                $file  = $parts[0];
     472
     473                                if ( substr( $file, -7 ) === '.min.js' ) {
     474                                        return substr( $file, 0, -7 ) . '.js';
     475                                }
     476
     477                                if ( substr( $file, -3 ) === '.js' ) {
     478                                        return $file;
     479                                }
     480                                return 'po';
     481                        }, $entry->references );
     482                        // Always add all entries to the PO file.
     483                        $sources[] = 'po';
     484                        $sources = array_unique( $sources );
     485
     486                        foreach ( $sources as $source ) {
     487                                $mapping[ $source ][] = $entry;
     488                        }
    389489                }
    390490
     491                return $mapping;
     492        }
     493
     494        /**
     495         * Builds a mapping of JS file names to translation entries.
     496         *
     497         * @param GP_Project          $gp_project The GlotPress project.
     498         * @param GP_Locale           $gp_locale  The GlotPress locale.
     499         * @param GP_Translation_Set  $set        The translation set.
     500         * @param array               $mapping    A mapping of files to translation entries.
     501         * @param string              $base_dest  Destination file name.
     502         * @return array An array of translation files built, may be empty if no translations in JS files exist.
     503         */
     504        private function build_json_files(  $gp_project, $gp_locale, $set, $mapping, $base_dest ) {
     505                // Export translations for each JS file to a separate translation file.
     506                $files  = array();
     507                $format = gp_array_get( GP::$formats, 'jed1x' );
     508                foreach ( $mapping as $file => $entries ) {
     509                        $json_content = $format->print_exported_file( $gp_project, $gp_locale, $set, $entries );
     510
     511                        $hash = md5( $file );
     512                        $dest = "{$base_dest}-{$hash}.json";
     513
     514                        file_put_contents( $dest, $json_content );
     515
     516                        $files[] = $dest;
     517                }
     518
     519                return $files;
     520        }
     521
     522        /**
     523         * Builds a PO file for translations.
     524         *
     525         * @param GP_Project          $gp_project The GlotPress project.
     526         * @param GP_Locale           $gp_locale  The GlotPress locale.
     527         * @param GP_Translation_Set  $set        The translation set.
     528         * @param Translation_Entry[] $entries    The translation entries.
     529         * @param string              $dest       Destination file name.
     530         * @return string|WP_Error Last updated date on success, WP_Error on failure.
     531         */
     532        private function build_po_file( $gp_project, $gp_locale, $set, $entries, $dest ) {
    391533                $format     = gp_array_get( GP::$formats, 'po' );
    392534                $po_content = $format->print_exported_file( $gp_project, $gp_locale, $set, $entries );
    393535
    class Language_Pack extends WP_CLI_Command { 
    520662                                }
    521663                        }
    522664
    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";
     665                        $working_directory = $data->type === 'core' ?$data->svn_checkout : "{$data->svn_checkout}/{$data->domain}";
     666                        $export_directory  = "{$working_directory}/{$data->version}/{$wp_locale}";
     667                        $build_directory   = $data->type === 'core'
     668                                ? self::BUILD_DIR . "/core/{$data->version}"
     669                                : self::BUILD_DIR . "/{$data->type}s/{$data->domain}/{$data->version}";
     670
     671                        $filename       = $data->domain === 'default' ? "{$data->domain}-{$wp_locale}" : $wp_locale;
     672                        $json_file_base = "{$export_directory}/{$filename}";
     673                        $po_file        = "{$export_directory}/{$filename}.po";
     674                        $mo_file        = "{$export_directory}/{$filename}.mo";
     675                        $zip_file       = "{$export_directory}/{$filename}.zip";
     676                        $build_zip_file = "{$build_directory}/{$wp_locale}.zip";
    530677
    531678                        // Update/create directories.
    532679                        $this->update_svn_directory( $export_directory );
    533680
     681                        $entries = GP::$translation->for_export( $data->gp_project, $set, [ 'status' => 'current' ] );
     682                        if ( ! $entries ) {
     683                                WP_CLI::warning( "No current translations available for {$wp_locale}." );
     684
     685                                continue;
     686                        }
     687
     688                        // Build a mapping based on where the translation entries occur and separate the po entries.
     689                        $mapping    = $this->build_mapping( $entries );
     690                        $po_entries = array_key_exists( 'po', $mapping ) ? $mapping['po'] : array();
     691
     692                        unset( $mapping['po'] );
     693
     694                        // Create JED json files for each JS file.
     695                        $json_files = $this->build_json_files( $data->gp_project, $gp_locale, $set, $mapping, $json_file_base );
     696
    534697                        // Create PO file.
    535                         $last_modified = $this->build_po_file( $data->gp_project, $gp_locale, $set, $po_file );
     698                        $last_modified = $this->build_po_file( $data->gp_project, $gp_locale, $set, $po_entries, $po_file );
    536699
    537700                        if ( is_wp_error( $last_modified ) ) {
    538701                                WP_CLI::warning( sprintf( "PO generation for {$wp_locale} failed: %s", $last_modified->get_error_message() ) );
    539702
    540703                                // Clean up.
    541                                 $this->execute_command( "rm -rf {$data->svn_checkout}/{$data->domain}" );
     704                                $this->execute_command( "rm -rf {$working_directory}" );
    542705
    543706                                continue;
    544707                        }
    class Language_Pack extends WP_CLI_Command { 
    555718                                WP_CLI::warning( "MO generation for {$wp_locale} failed." );
    556719
    557720                                // Clean up.
    558                                 $this->execute_command( "rm -rf {$data->svn_checkout}/{$data->domain}" );
     721                                $this->execute_command( "rm -rf {$working_directory}" );
    559722
    560723                                continue;
    561724                        }
    562725
    563726                        // Create ZIP file.
    564727                        $result = $this->execute_command( sprintf(
    565                                 'zip -9 -j %s %s %s 2>&1',
     728                                'zip -9 -j %s %s %s %s 2>&1',
    566729                                escapeshellarg( $zip_file ),
    567730                                escapeshellarg( $po_file ),
    568                                 escapeshellarg( $mo_file )
     731                                escapeshellarg( $mo_file ),
     732                                implode( ' ', array_map( 'escapeshellarg', $json_files ) )
    569733                        ) );
    570734
    571735                        if ( is_wp_error( $result ) ) {
    class Language_Pack extends WP_CLI_Command { 
    573737                                WP_CLI::warning( "ZIP generation for {$wp_locale} failed." );
    574738
    575739                                // Clean up.
    576                                 $this->execute_command( "rm -rf {$data->svn_checkout}/{$data->domain}" );
     740                                $this->execute_command( "rm -rf {$working_directory}" );
    577741
    578742                                continue;
    579743                        }
    class Language_Pack extends WP_CLI_Command { 
    589753                                WP_CLI::warning( "Creating build directories for {$wp_locale} failed." );
    590754
    591755                                // Clean up.
    592                                 $this->execute_command( "rm -rf {$data->svn_checkout}/{$data->domain}" );
     756                                $this->execute_command( "rm -rf {$working_directory}" );
    593757
    594758                                continue;
    595759                        }
    class Language_Pack extends WP_CLI_Command { 
    606770                                WP_CLI::warning( "Moving ZIP file for {$wp_locale} failed." );
    607771
    608772                                // Clean up.
    609                                 $this->execute_command( "rm -rf {$data->svn_checkout}/{$data->domain}" );
     773                                $this->execute_command( "rm -rf {$working_directory}" );
    610774
    611775                                continue;
    612776                        }
    class Language_Pack extends WP_CLI_Command { 
    618782                                WP_CLI::warning( sprintf( "Language pack for {$wp_locale} failed: %s", $result->get_error_message() ) );
    619783
    620784                                // Clean up.
    621                                 $this->execute_command( "rm -rf {$data->svn_checkout}/{$data->domain}" );
     785                                $this->execute_command( "rm -rf {$working_directory}" );
    622786
    623787                                continue;
    624788                        }
    class Language_Pack extends WP_CLI_Command { 
    643807                                WP_CLI::warning( "SVN commit for {$wp_locale} failed." );
    644808
    645809                                // Clean up.
    646                                 $this->execute_command( "rm -rf {$data->svn_checkout}/{$data->domain}" );
     810                                $this->execute_command( "rm -rf {$working_directory}" );
    647811
    648812                                continue;
    649813                        }
    650814
    651815                        // Clean up.
    652                         $this->execute_command( "rm -rf {$data->svn_checkout}/{$data->domain}" );
     816                        $this->execute_command( "rm -rf {$working_directory}" );
    653817
    654818                        WP_CLI::success( "Language pack for {$wp_locale} generated." );
    655819                }