-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwpl10n-feature.php
225 lines (194 loc) · 7.25 KB
/
wpl10n-feature.php
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
<?php
/**
* Plugin Name: WP L10n Feature
*/
/**
* The main plugin class.
*/
class WPL10n_Feature {
/**
* An array of domains and their translations.
*
* @var array
*/
private $translations = array();
/**
* Class constructor.
*/
public function __construct() {
add_filter( 'override_load_textdomain', array( $this, 'override_load_textdomain' ), 10, 4);
add_filter( 'gettext', array( $this, 'override_gettext' ), 10, 3 );
add_filter( 'gettext_with_context', array( $this, 'override_gettext_with_context' ), 10, 4 );
// TODO: Handle using the $plural expression.
add_filter( 'ngettext', array( $this, 'override_ngettext' ), 10, 5 );
}
/**
* Get translations from a JSON file.
* This function does the following:
* - If the file doesn't exist, create it from the .mo file.
* - If the .mo file is newer than the .json file, regenerate the .json file.
* - If the .json file exists, return the translations.
* - If the .json file cannot be created, return false.
*
* @param string $domain Text domain. Unique identifier for retrieving translated strings.
* @param string $mofile Path to the MO file.
* @param string $locale The locale of the file.
*
* @return array|bool Array of translations or false if the JSON file cannot be created.
*/
public function get_translations_from_file( $domain, $mofile, $locale ) {
// TODO: If the file exists, check the date. If the date is older than the .mo file, regenerate the .json file.
$json_path = str_replace( '.mo', '.json', $mofile );
// Just init an empty array to avoid errors down the line.
$translations = array();
if ( ! file_exists( $json_path ) ) {
global $wp_filesystem;
if ( ! $wp_filesystem ) {
require_once ABSPATH . '/wp-admin/includes/file.php';
WP_Filesystem();
}
$mo = new \Mo();
$mo->import_from_file( $mofile );
// Get the Plural Forms header from the MO file.
$plural = 'nplurals=2; plural=n != 1;';
if ( isset( $mo->headers['Plural-Forms'] ) ) {
$plural = $mo->headers['Plural-Forms'];
}
// Build the JSON file structure.
$json_content = array(
'translation-revision-date' => filemtime( $mofile ),
'generator' => 'WordPress',
'domain' => 'messages',
'locale_data' => array(
'messages' => array(
'' => array(
'domain' => 'messages',
'plural-forms' => $plural,
'lang' => $locale,
),
),
)
);
// Add translations to the JSON file.
foreach ( $mo->entries as $key => $entry ) {
$json_content['locale_data']['messages'][ $key ] = $entry->translations;
}
// Try to write the JSON file. If it fails, return false to fallback to the .mo file.
// @TODO: Remove the JSON_PRETTY_PRINT flag to generate minified JSON files.
if ( ! $wp_filesystem->put_contents( $json_path, json_encode( $json_content, JSON_PRETTY_PRINT ) ) ) {
return false;
}
return $json_content['locale_data']['messages'][ $key ];
}
// Read the JSON file and save translations in the $translations variable.
$json_content = json_decode( file_get_contents( $json_path ), true );
// If the .mo file is newer than the .json file, delete the .json file
// so it can be re-generated on the next pageload.
if ( filemtime( $mofile ) > (int) $json_content['translation-revision-date'] ) {
$wp_filesystem->delete( $json_path );
return false;
}
return $json_content['locale_data']['messages'];
}
/**
* Hooks in the `override_load_textdomain` filter to load translations from a JSON file.
*
* @param bool $override Whether to override the textdomain load. Default false.
* @param string $domain Text domain. Unique identifier for retrieving translated strings.
* @param string $mofile Path to the MO file.
* @param string $locale The locale of the file.
*
* @return bool True if the translations were loaded from the JSON file, false otherwise.
*/
public function override_load_textdomain( $override, $domain, $mofile, $locale ) {
/**
* Filters MO file path for loading translations for a specific text domain.
*
* @since 2.9.0
*
* @param string $mofile Path to the MO file.
* @param string $domain Text domain. Unique identifier for retrieving translated strings.
*/
$mofile = apply_filters( 'load_textdomain_mofile', $mofile, $domain );
/**
* Fires before the MO translation file is loaded.
*
* @since 2.9.0
*
* @param string $domain Text domain. Unique identifier for retrieving translated strings.
* @param string $mofile Path to the .mo file.
*/
do_action( 'load_textdomain', $domain, $mofile );
$translations = $this->get_translations_from_file( $domain, $mofile, $locale );
if ( ! $translations ) {
return false;
}
$this->translations[ $domain ] = isset( $this->translations[ $domain ] )
? $this->translations[ $domain ]
: array();
$this->translations[ $domain ] = array_merge(
$this->translations[ $domain ],
$this->get_translations_from_file( $domain, $mofile, $locale )
);
return true;
}
/**
* Hooks in the `gettext` filter to load translations from a JSON file.
*
* @param string $translation Translated text.
* @param string $text Text to translate.
* @param string $domain Text domain. Unique identifier for retrieving translated strings.
*
* @return string Translated text.
*/
public function override_gettext( $translation, $text, $domain ) {
if ( ! isset( $this->translations[ $domain ] ) ) {
return $translation;
}
if ( ! empty( $this->translations[ $domain ][ $text ] ) ) {
return $this->translations[ $domain ][ $text ][0];
}
return $translation;
}
/**
* Hooks in the `gettext_with_context` filter to load translations from a JSON file.
*
* @param string $translation Translated text.
* @param string $text Text to translate.
* @param string $context Context information for the translators.
* @param string $domain Text domain. Unique identifier for retrieving translated strings.
*
* @return string Translated text.
*/
public function override_gettext_with_context( $translation, $text, $context, $domain ) {
if ( ! isset( $this->translations[ $domain ] ) ) {
return $translation;
}
if ( ! empty( $this->translations[ $domain ][ "$context$text" ] ) ) {
return $this->translations[ $domain ][ "$context$text" ][0];
}
return $translation;
}
/**
* Hooks in the `ngettext` filter to load translations from a JSON file.
*
* @param string $translation Translated text.
* @param string $single The text to be translated.
* @param string $plural The plural form of the text to be translated.
* @param int $number The number to use to find the translation for the
* respective plural form.
* @param string $domain Text domain. Unique identifier for retrieving translated strings.
*
* @return string Translated text.
*/
public function override_ngettext( $translation, $single, $plural, $number, $domain ) {
if ( ! isset( $this->translations[ $domain ] ) ) {
return $translation;
}
if ( ! empty( $this->translations[ $domain ][ $single ] ) ) {
return $this->translations[ $domain ][ $single ][ $number == 1 ? 0 : 1 ];
}
return $translation;
}
}
new WPL10n_Feature();