-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathformat_srt.php
More file actions
237 lines (200 loc) · 7.11 KB
/
format_srt.php
File metadata and controls
237 lines (200 loc) · 7.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
<?php
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
/**
* GP Format SRT class
*
* @package GlotPress
* @since 2.1.0
*/
/**
* Format class used to support SRT file format.
*
* @since 2.1.0
*/
class GP_Format_SRT extends GP_Format {
/**
* Name of file format, used in file format dropdowns.
*
* @since 2.1.0
*
* @var string
*/
public $name = 'SubRip Text File (.srt)';
/**
* File Extension of file format, used to autodetect formats and when creating the output file names.
*
* @since 2.1.0
*
* @var string
*/
public $extension = 'srt';
/**
* Generates a string the contains the $entries to export in the Properties file format.
*
* @since 2.1.0
*
* @param GP_Project $project The project the strings are being exported for, not used
* in this format but part of the scaffold of the parent object.
* @param GP_Locale $locale The locale object the strings are being exported for. not used
* in this format but part of the scaffold of the parent object.
* @param GP_Translation_Set $translation_set The locale object the strings are being
* exported for. not used in this format but part
* of the scaffold of the parent object.
* @param GP_Translation $entries The entries to export.
*
* @return string
*/
public function print_exported_file( $project, $locale, $translation_set, $entries ) {
$result = '';
// Sort the entries based on the context timestamp string.
$sorted_entries = $entries;
usort( $sorted_entries, array( 'GP_Format_SRT', 'sort_entries' ) );
// Since SRT files use an increase, 1 based, indicator for each translation block, set it up now.
$i = 1;
// Loop through all the entries to export.
foreach ( $sorted_entries as $entry ) {
// Internally GP uses just \n, but SRT files always use the windows standard \r\n so convert them now.
$translation = str_replace( "\n", "\r\n", $entry->translations[0] );
$result .= "{$i}\r\n{$entry->context}\r\n{$translation}\r\n\r\n";
$i++;
}
// Make sure we only have one \r\n at the end of the file.
$result = trim( $result, "\r\n" );
$result .= "\r\n";
return $result;
}
/**
* Reads a set of original strings from an SRT file.
*
* @since 2.1.0
*
* @param string $file_name The filename of the uploaded SRT file.
*
* @return Translations|bool
*/
public function read_originals_from_file( $file_name ) {
$entries = new Translations;
$file = file_get_contents( $file_name );
if ( false === $file ) {
return false;
}
$context = $comment = $text = null;
$this_entry = 0;
// Note, SRT files use the Windows line ending standard.
$lines = explode( "\r\n", $file );
// Loop through each line, translation "blocks" are separated by blank lines.
foreach ( $lines as $line ) {
switch ( $this_entry ) {
case 0: // This is the first line of a new SRT block, just discard it.
$this_entry++;
break;
case 1: // This is the timestamp line, save it to the context.
$context = trim( $line, " \r\n" );
$this_entry++;
break;
default: // This is the text.
// A blank line means we're done with the block and we should save it.
if ( '' === $line ) {
$entry = new Translation_Entry();
$entry->context = $context;
$entry->singular = trim( $text, "\r\n" );
$entry->translations = array();
$entries->add_entry( $entry );
$this_entry = 0;
$text = '';
$context = '';
} else {
$text .= trim( $line, " \r\n" ) . "\n";
$this_entry++;
}
break;
}
}
return $entries;
}
/**
* Reads a set of translations from an SRT file.
*
* @since 2.1.0
*
* @param string $file_name The filename of the uploaded properties file.
* @param GP_Project $project The project object to read the translations in to.
*
* @return Translations|bool
*/
public function read_translations_from_file( $file_name, $project = null ) {
// Use the read_oroginals_from_file code to read the file.
$translations = $this->read_originals_from_file( $file_name );
// Get the originals for this project since they are not contained in the SRT file.
$originals = GP::$original->by_project_id( $project->id );
$new_translations = new Translations;
// Loop through each of the translations read from the SRT file.
foreach ( $translations->entries as $key => $entry ) {
// Since we used the read_originals_from_file, we need to swap the singular to the translation.
$entry->translations = array( $entry->singular );
$entry->singular = null;
// Now find the original string based on the context timestamp line.
foreach ( $originals as $original ) {
if ( $original->context === $entry->context ) {
$entry->singular = $original->singular;
$new_translations->add_entry( $entry );
break;
}
}
}
return $new_translations;
}
/**
* Splits a time info line (stored in the context property ) in two.
*
* @since 2.1.0
*
* @param string $context The line to split.
*
* @return array Returns an array containing the start and stop timestamp in strings.
*/
private function split_context_time_info( $context ) {
// Since the millisecond field uses the french separator, convert it to the north american standard.
$context = str_replace( ',', '.', $context );
// Since the timestamps are zero padded we can just replace the colons with blanks and get a valid number to compare against.
$context = str_replace( ':', '', $context );
// Split the start/end sections.
$parts = explode( '-->', $context );
$start = floatval( $parts[0] );
// If for some reason we didn't parse an end time, set the end to be the same as the start.
if ( count( $parts ) > 1 ) {
$end = floatval( $parts[1] );
} else {
$end = $start;
}
return array( $start, $end );
}
/**
* The callback to sort the entries by, used above in print_exported_file().
*
* @since 2.1.0
*
* @param Translations $a The first translation to compare.
* @param Translations $b The second translation to compare.
*
* @return int
*/
private function sort_entries( $a, $b ) {
/*
* Since SRT files are ordered by their time stamp, split the two context
* strings (which contain the start/stop timestamps).
*
* Convert them to floating point numbers so we can compare against the
* millisecond.
*/
list( $start_a, $end_a ) = $this->split_context_time_info( $a->context );
list( $start_b, $end_b ) = $this->split_context_time_info( $b->context );
// Check if we're starting at the same time.
if ( $start_a === $start_b ) {
return 0;
}
// Otherwise return if they're greater or less than each other.
return ( $start_a > $start_b ) ? 1 : -1;
}
}
GP::$formats['srt'] = new GP_Format_SRT;