Completed
Push — update/add_release_post_to_upd... ( 716ce6...83935e )
by
unknown
70:54 queued 60:39
created

tools/export-translations.php (1 issue)

Upgrade to new PHP Analysis Engine

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
This function seems to be duplicated in your project.

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.

Loading history...
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