Automattic /
jetpack
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | |||
| 3 | /* |
||
| 4 | * Exports translations from https://translate.wordpress.org/api/projects/jetpack |
||
| 5 | * |
||
| 6 | * php export-translations.php DIRECTORY SOURCE_URL |
||
| 7 | */ |
||
| 8 | |||
| 9 | require dirname( dirname( __FILE__ ) ) . '/locales.php'; |
||
| 10 | |||
| 11 | /** |
||
| 12 | * Terminates script. Prints help and message to STDERR |
||
| 13 | * |
||
| 14 | * @param string $message |
||
| 15 | */ |
||
| 16 | View Code Duplication | function die_error( $message ) { |
|
| 17 | global $argv; |
||
| 18 | |||
| 19 | fwrite( STDERR, "php $argv[0] DIRECTORY SOURCE_URL\n" ); |
||
| 20 | fwrite( STDERR, "$message\n" ); |
||
| 21 | exit( 1 ); |
||
| 22 | } |
||
| 23 | |||
| 24 | /** |
||
| 25 | * Converts GlotPress URL into a GlotPress API URL. |
||
| 26 | * |
||
| 27 | * @param string $url GlotPres URL. |
||
| 28 | * |
||
| 29 | * @return string $api_url GlotPress API URL. |
||
| 30 | */ |
||
| 31 | View Code Duplication | function apize_url( $url ) { |
|
|
0 ignored issues
–
show
|
|||
| 32 | if ( false !== strpos( $url, '/api' ) ) { |
||
| 33 | return $url; |
||
| 34 | } |
||
| 35 | |||
| 36 | $host = preg_quote( parse_url( $url, PHP_URL_HOST ) ); |
||
| 37 | |||
| 38 | return preg_replace( "#^https?://$host#", '\\0/api', $url ); |
||
| 39 | } |
||
| 40 | |||
| 41 | // Output |
||
| 42 | if ( empty( $argv[1] ) ) { |
||
| 43 | die_error( 'No DIRECTORY' ); |
||
| 44 | } |
||
| 45 | |||
| 46 | $jetpack_directory = rtrim( $argv[1], '/' ); |
||
| 47 | $jetpack_directory = realpath( $jetpack_directory ); |
||
| 48 | if ( !$jetpack_directory || !is_dir( $jetpack_directory ) ) { |
||
| 49 | die_error( 'DIRECTORY must be a valid directory' ); |
||
| 50 | } |
||
| 51 | |||
| 52 | // Input |
||
| 53 | if ( empty( $argv[2] ) ) { |
||
| 54 | die_error( 'No SOURCE_URL' ); |
||
| 55 | } |
||
| 56 | |||
| 57 | // gettext tools required |
||
| 58 | $msgfmt = trim( `which msgfmt` ); |
||
| 59 | if ( empty( $msgfmt ) ) { |
||
| 60 | die_error( 'msgfmt must be installed' ); |
||
| 61 | } |
||
| 62 | |||
| 63 | // Create a temporary directory... hack |
||
| 64 | $temp_file_handle = tmpfile(); // file handle |
||
| 65 | $temp_file_meta = stream_get_meta_data( $temp_file_handle ); // file meta data |
||
| 66 | $temp_file_path = $temp_file_meta['uri']; // file path |
||
| 67 | fclose( $temp_file_handle ); |
||
| 68 | mkdir( $temp_file_path, 0700, true ); |
||
| 69 | register_shutdown_function( function( $temp_file_path ) { |
||
| 70 | exec( sprintf( 'rm -rf %s', escapeshellarg( $temp_file_path ) ) ); |
||
| 71 | }, $temp_file_path ); |
||
| 72 | |||
| 73 | // The current Jetpack translations |
||
| 74 | $current_sets = glob( $jetpack_directory . '/languages/*.mo' ); |
||
| 75 | $current_sets = preg_replace( '/.*-(\w+)\.mo/', '$1', $current_sets ); |
||
| 76 | $keys = array_map( 'strtolower', $current_sets ); |
||
| 77 | $current_sets = array_combine( $keys, $current_sets ); |
||
| 78 | unset( $keys ); |
||
| 79 | |||
| 80 | $source_url = apize_url( rtrim( $argv[2], '/' ) ); |
||
| 81 | $source = file_get_contents( $source_url ); |
||
| 82 | |||
| 83 | $available_sets = json_decode( $source )->translation_sets; |
||
| 84 | // Maps source locale slugs to current Jetpack locales |
||
| 85 | $map = array(); |
||
| 86 | foreach ( $available_sets as $set ) { |
||
| 87 | $s = strtolower( str_replace( '-', '_', $set->locale ) ); |
||
| 88 | |||
| 89 | $suffix = ''; |
||
| 90 | |||
| 91 | if ( 'default' !== $set->slug ) { |
||
| 92 | // Setting up a suffix for locales that have an additional slug, like Informal Deutsch |
||
| 93 | $suffix = '_' . $set->slug; |
||
| 94 | $s .= $suffix; |
||
| 95 | } |
||
| 96 | |||
| 97 | echo PHP_EOL; |
||
| 98 | |||
| 99 | if ( GP_Locales::exists( $set->locale ) ) { |
||
| 100 | $locale = GP_Locales::by_slug( $set->locale ); |
||
| 101 | |||
| 102 | if ( empty( $locale->wp_locale ) ) { |
||
| 103 | echo "Warning: missing wp_locale, using slug {$locale->slug}{$suffix} instead for " |
||
| 104 | . $set->slug . ' ' |
||
| 105 | . $locale->english_name |
||
| 106 | . PHP_EOL; |
||
| 107 | $map[ $set->locale . $suffix ] = $locale->slug . $suffix; |
||
| 108 | } else { |
||
| 109 | echo "Using wp_locale {$locale->wp_locale}{$suffix} for " |
||
| 110 | . $set->slug . ' ' |
||
| 111 | . $locale->english_name |
||
| 112 | . PHP_EOL; |
||
| 113 | $map[ $set->locale . $suffix ] = $locale->wp_locale . $suffix; |
||
| 114 | } |
||
| 115 | continue; |
||
| 116 | } |
||
| 117 | |||
| 118 | echo "Warning: not found locale {$set->slug} {$set->locale}, trying to match current sets..." . PHP_EOL; |
||
| 119 | |||
| 120 | // source's 'ja' matches Jetpack's 'ja' |
||
| 121 | View Code Duplication | if ( isset( $current_sets[$s] ) ) { |
|
| 122 | echo "Found current set: $s\n"; |
||
| 123 | $map[$set->locale] = $current_sets[$s]; |
||
| 124 | unset( $current_sets[$s] ); |
||
| 125 | continue; |
||
| 126 | } |
||
| 127 | |||
| 128 | // source's 'it' matches Jetpack's 'it_IT' |
||
| 129 | foreach ( array_keys( $current_sets ) as $c ) { |
||
| 130 | View Code Duplication | if ( 0 === strpos( $c, $s ) ) { |
|
| 131 | echo "Found partial matched set: $s"; |
||
| 132 | $map[$set->locale] = $current_sets[$c]; |
||
| 133 | unset( $current_sets[$c] ); |
||
| 134 | continue; |
||
| 135 | } |
||
| 136 | } |
||
| 137 | |||
| 138 | echo "No entire or partial match, setting {$set->locale}{$suffix} as new locale." . PHP_EOL; |
||
| 139 | |||
| 140 | // New locale |
||
| 141 | $map[ $set->locale . $suffix ] = $set->locale . $suffix; |
||
| 142 | } |
||
| 143 | |||
| 144 | // Get all the PO files |
||
| 145 | foreach ( $available_sets as $id => $set ) { |
||
| 146 | $full_locale = $set->locale; |
||
| 147 | |||
| 148 | if ( 'default' !== $set->slug ) { |
||
| 149 | $full_locale .= '_' . $set->slug; |
||
| 150 | } |
||
| 151 | |||
| 152 | if ( ! isset ( $map[ $full_locale ] ) ) { |
||
| 153 | echo "UNKNOWN LOCALE: {$full_locale}\n"; |
||
| 154 | continue; |
||
| 155 | } |
||
| 156 | |||
| 157 | $output_file = "{$temp_file_path}/jetpack-{$map[$full_locale]}.po"; |
||
| 158 | $input_url = sprintf( '%s/%s/%s/export-translations/?format=po', $source_url, $set->locale, $set->slug ); |
||
| 159 | $exec = sprintf( 'curl --silent --location --output %s %s', escapeshellarg( $output_file ), escapeshellarg( $input_url ) ); |
||
| 160 | echo "Downloading $input_url to" . PHP_EOL . $output_file . PHP_EOL; |
||
| 161 | exec( $exec ); |
||
| 162 | |||
| 163 | echo "\nSuccessfully downloaded " . $output_file . " with size of " . filesize( $output_file ) . "\n"; |
||
| 164 | } |
||
| 165 | echo "\n"; |
||
| 166 | |||
| 167 | // Convert PO files to MO files |
||
| 168 | foreach( glob( "{$temp_file_path}/*.po" ) as $output_po ) { |
||
| 169 | $file = basename( $output_po ); |
||
| 170 | echo "$file\n"; |
||
| 171 | |||
| 172 | $current_file = "{$jetpack_directory}/languages/$file"; |
||
| 173 | $current_exec = sprintf( '%s --statistics %s -o /dev/null 2>&1', $msgfmt, escapeshellarg( $current_file ) ); |
||
| 174 | $stats = exec( $current_exec ); |
||
| 175 | @list( $translated, $untranslated ) = explode( ',', $stats ); |
||
| 176 | |||
| 177 | $translated = (int) $translated; |
||
| 178 | $untranslated = isset( $untranslated ) ? (int) $untranslated : 0; |
||
| 179 | $current = $translated; |
||
| 180 | $current_total = $translated + $untranslated; |
||
| 181 | |||
| 182 | $output_mo = preg_replace( '/\.po$/', '.mo', $output_po ); |
||
| 183 | $exec = sprintf( '%s --statistics %s -o %s 2>&1', $msgfmt, escapeshellarg( $output_po ), escapeshellarg( $output_mo ) ); |
||
| 184 | $stats = exec( $exec ); |
||
| 185 | @list( $translated, $untranslated ) = explode( ',', $stats ); |
||
| 186 | |||
| 187 | $translated = (int) $translated; |
||
| 188 | $untranslated = isset( $untranslated ) ? (int) $untranslated : 0; |
||
| 189 | $now = $translated; |
||
| 190 | $now_total = $translated + $untranslated; |
||
| 191 | |||
| 192 | echo "NOW: $now/$now_total, CURRENT: $current/$current_total\n"; |
||
| 193 | |||
| 194 | // Ignoring files that add no changes or that have less than 50% translated |
||
| 195 | if ( $translated / $now_total < 0.5 || $now < $current - 1 ) { // some off-by-one error? |
||
| 196 | echo "IGNORING $file\n"; |
||
| 197 | exec( sprintf( 'rm %s', $output_mo ) ); |
||
| 198 | exec( sprintf( 'rm %s', $output_po ) ); |
||
| 199 | } else { |
||
| 200 | echo "MOVING $file\n"; |
||
| 201 | exec( sprintf( 'mv %s %s', $output_mo, "{$jetpack_directory}/languages/" ) ); |
||
| 202 | exec( sprintf( 'mv %s %s', $output_po, "{$jetpack_directory}/languages/" ) ); |
||
| 203 | } |
||
| 204 | |||
| 205 | echo "\n"; |
||
| 206 | } |
||
| 207 | |||
| 208 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.