WordPress.org

Making WordPress.org

Ticket #3876: 3876.9.diff

File 3876.9.diff, 7.3 KB (added by ocean90, 10 months ago)
  • trunk/wordpress.org/public_html/wp-content/plugins/wporg-gp-customizations/inc/class-plugin.php

     
    277277                WP_CLI::add_command( 'wporg-translate language-pack', __NAMESPACE__ . '\CLI\Language_Pack' );
    278278                WP_CLI::add_command( 'wporg-translate mass-create-sets', __NAMESPACE__ . '\CLI\Mass_Create_Sets' );
    279279                WP_CLI::add_command( 'wporg-translate make-core-pot', __NAMESPACE__ . '\CLI\Make_Core_Pot' );
     280                WP_CLI::add_command( 'wporg-translate export', __NAMESPACE__ . '\CLI\Export' );
    280281        }
    281282
    282283        /**
  • trunk/wordpress.org/public_html/wp-content/plugins/wporg-gp-customizations/inc/cli/class-export.php

     
     1<?php
     2
     3namespace WordPressdotorg\GlotPress\Customizations\CLI;
     4
     5use GP;
     6use GP_Locales;
     7use WP_CLI;
     8use WP_CLI_Command;
     9
     10class Export extends WP_CLI_Command {
     11
     12        /**
     13         * Exports core's translations.
     14         *
     15         * ## OPTIONS
     16         *
     17         * <version>
     18         * : Version to export.
     19         *
     20         * <locale>
     21         * : Locale to export.
     22         *
     23         * <dest>
     24         * : Path to export to.
     25         *
     26         * [--locale-slug]
     27         * : Slug of the locale. Default: 'default'.
     28         */
     29        public function __invoke( $args, $assoc_args ) {
     30                $version = $args[0];
     31                $locale  = $args[1];
     32                $dest    = realpath( $args[2] );
     33
     34                $args = wp_parse_args( $assoc_args, [
     35                        'locale-slug' => 'default',
     36                ] );
     37
     38                // Get WP locale.
     39                $gp_locale = GP_Locales::by_slug( $locale );
     40                if ( ! isset( $gp_locale->wp_locale ) ) {
     41                        WP_CLI::error( "Locale does not exist for $locale." );
     42                }
     43
     44                // Change wp_locale until GlotPress returns the correct wp_locale for variants.
     45                $wp_locale = $gp_locale->wp_locale;
     46                if ( 'default' !== $args['locale-slug'] ) {
     47                        $wp_locale = $wp_locale . '_' . $set->slug;
     48                }
     49
     50                $projects = [
     51                        "wp/$version"               => '',
     52                        "wp/$version/admin"         => 'admin',
     53                        "wp/$version/admin/network" => 'admin-network',
     54                        "wp/$version/cc"            => 'continents-cities',
     55                ];
     56
     57                foreach ( $projects as $path => $context ) {
     58                        $gp_project = GP::$project->by_path( $path );
     59                        if ( ! $gp_project ) {
     60                                WP_CLI::error( "Invalid project path: $path." );
     61                        }
     62
     63                        $translation_set = GP::$translation_set->by_project_id_slug_and_locale( $gp_project->id, $args['locale-slug'], $locale );
     64                        if ( ! $translation_set ) {
     65                                WP_CLI::warning( "No translation set available for $path." );
     66                                continue;
     67                        }
     68
     69                        $entries = GP::$translation->for_export( $gp_project, $translation_set, [ 'status' => 'current' ] );
     70                        if ( ! $entries ) {
     71                                WP_CLI::warning( "No current translations available for {$path}/{$translation_set->locale}/{$translation_set->slug}." );
     72                                continue;
     73                        }
     74
     75                        // Build a mapping based on where the translation entries occur and separate the po entries.
     76                        $mapping    = $this->build_mapping( $entries );
     77                        $po_entries = array_key_exists( 'po', $mapping ) ? $mapping['po'] : array();
     78
     79                        unset( $mapping['po'] );
     80
     81                        // Create JED json files for each JS file.
     82                        $json_file_base = "{$dest}/{$wp_locale}";
     83                        $this->build_json_files( $gp_project, $gp_locale, $translation_set, $mapping, $json_file_base );
     84
     85                        // Create PO file.
     86                        $po_file = "{$wp_locale}.po";
     87                        if ( $context ) {
     88                                $po_file = "$context-{$po_file}";
     89                        }
     90                        $po_file = "{$dest}/{$po_file}";
     91                        $result  = $this->build_po_file( $gp_project, $gp_locale, $translation_set, $po_entries, $po_file );
     92
     93                        if ( ! $result ) {
     94                                WP_CLI::error( "Failure while creating $po_file." );
     95                        }
     96
     97                        // Create MO file.
     98                        $mo_file = "{$wp_locale}.mo";
     99                        if ( $context ) {
     100                                $mo_file = "$context-{$mo_file}";
     101                        }
     102                        $mo_file = "{$dest}/{$mo_file}";
     103                        exec( sprintf(
     104                                'msgfmt %s -o %s 2>&1',
     105                                escapeshellarg( $po_file ),
     106                                escapeshellarg( $mo_file )
     107                        ), $output, $return_var );
     108
     109                        if ( $return_var ) {
     110                                WP_CLI::error( "Failure while creating $mo_file." );
     111                        }
     112                }
     113
     114                WP_CLI::line( 'Done!' );
     115        }
     116
     117        /**
     118         * Build a mapping of JS files to translation entries occurring in those files.
     119         * Translation entries occurring in other files are added to the 'po' key.
     120         *
     121         * @param Translation_Entry[] $entries The translation entries to map.
     122         *
     123         * @return array The mapping of sources to translation entries.
     124         */
     125        private function build_mapping( $entries ) {
     126                $mapping = array();
     127
     128                foreach ( $entries as $entry ) {
     129                        /** @var Translation_Entry $entry */
     130
     131                        // Find all unique sources this translation originates from.
     132                        $sources = array_map( function ( $reference ) {
     133                                $parts = explode( ':', $reference );
     134                                $file  = $parts[0];
     135
     136                                if ( substr( $file, -7 ) === '.min.js' ) {
     137                                        return substr( $file, 0, -7 ) . '.js';
     138                                }
     139
     140                                if ( substr( $file, -3 ) === '.js' ) {
     141                                        return $file;
     142                                }
     143                                return 'po';
     144                        }, $entry->references );
     145
     146                        // Always add all entries to the PO file.
     147                        $sources[] = 'po';
     148
     149                        $sources = array_unique( $sources );
     150
     151                        foreach ( $sources as $source ) {
     152                                $mapping[ $source ][] = $entry;
     153                        }
     154                }
     155
     156                return $mapping;
     157        }
     158
     159        /**
     160         * Builds a mapping of JS file names to translation entries.
     161         *
     162         * @param GP_Project          $gp_project The GlotPress project.
     163         * @param GP_Locale           $gp_locale  The GlotPress locale.
     164         * @param GP_Translation_Set  $set        The translation set.
     165         * @param array               $mapping    A mapping of files to translation entries.
     166         * @param string              $base_dest  Destination file name.
     167         * @return array An array of translation files built, may be empty if no translations in JS files exist.
     168         */
     169        private function build_json_files( $gp_project, $gp_locale, $set, $mapping, $base_dest ) {
     170                // Export translations for each JS file to a separate translation file.
     171                $files  = array();
     172                $format = gp_array_get( GP::$formats, 'jed1x' );
     173                foreach ( $mapping as $file => $entries ) {
     174                        $json_content = $format->print_exported_file( $gp_project, $gp_locale, $set, $entries );
     175
     176                        $hash = md5( $file );
     177                        $dest = "{$base_dest}-{$hash}.json";
     178
     179                        file_put_contents( $dest, $json_content );
     180
     181                        $files[] = $dest;
     182                }
     183
     184                return $files;
     185        }
     186
     187        /**
     188         * Builds a PO file for translations.
     189         *
     190         * @param GP_Project          $gp_project The GlotPress project.
     191         * @param GP_Locale           $gp_locale  The GlotPress locale.
     192         * @param GP_Translation_Set  $set        The translation set.
     193         * @param Translation_Entry[] $entries    The translation entries.
     194         * @param string              $dest       Destination file name.
     195         * @return boolean True on success, false on failure.
     196         */
     197        private function build_po_file( $gp_project, $gp_locale, $set, $entries, $dest ) {
     198                $format     = gp_array_get( GP::$formats, 'po' );
     199                $po_content = $format->print_exported_file( $gp_project, $gp_locale, $set, $entries );
     200
     201                file_put_contents( $dest, $po_content );
     202
     203                return true;
     204        }
     205}