~canonical-sysadmins/wordpress/4.7.2

« back to all changes in this revision

Viewing changes to wp-includes/l10n.php

  • Committer: Jacek Nykis
  • Date: 2015-01-05 16:17:05 UTC
  • Revision ID: jacek.nykis@canonical.com-20150105161705-w544l1h5mcg7u4w9
Initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
/**
 
3
 * WordPress Translation API
 
4
 *
 
5
 * @package WordPress
 
6
 * @subpackage i18n
 
7
 */
 
8
 
 
9
/**
 
10
 * Get the current locale.
 
11
 *
 
12
 * If the locale is set, then it will filter the locale in the 'locale' filter
 
13
 * hook and return the value.
 
14
 *
 
15
 * If the locale is not set already, then the WPLANG constant is used if it is
 
16
 * defined. Then it is filtered through the 'locale' filter hook and the value
 
17
 * for the locale global set and the locale is returned.
 
18
 *
 
19
 * The process to get the locale should only be done once, but the locale will
 
20
 * always be filtered using the 'locale' hook.
 
21
 *
 
22
 * @since 1.5.0
 
23
 *
 
24
 * @return string The locale of the blog or from the 'locale' hook.
 
25
 */
 
26
function get_locale() {
 
27
        global $locale, $wp_local_package;
 
28
 
 
29
        if ( isset( $locale ) ) {
 
30
                /**
 
31
                 * Filter WordPress install's locale ID.
 
32
                 *
 
33
                 * @since 1.5.0
 
34
                 *
 
35
                 * @param string $locale The locale ID.
 
36
                 */
 
37
                return apply_filters( 'locale', $locale );
 
38
        }
 
39
 
 
40
        if ( isset( $wp_local_package ) ) {
 
41
                $locale = $wp_local_package;
 
42
        }
 
43
 
 
44
        // WPLANG was defined in wp-config.
 
45
        if ( defined( 'WPLANG' ) ) {
 
46
                $locale = WPLANG;
 
47
        }
 
48
 
 
49
        // If multisite, check options.
 
50
        if ( is_multisite() ) {
 
51
                // Don't check blog option when installing.
 
52
                if ( defined( 'WP_INSTALLING' ) || ( false === $ms_locale = get_option( 'WPLANG' ) ) ) {
 
53
                        $ms_locale = get_site_option( 'WPLANG' );
 
54
                }
 
55
 
 
56
                if ( $ms_locale !== false ) {
 
57
                        $locale = $ms_locale;
 
58
                }
 
59
        } else {
 
60
                $db_locale = get_option( 'WPLANG' );
 
61
                if ( $db_locale !== false ) {
 
62
                        $locale = $db_locale;
 
63
                }
 
64
        }
 
65
 
 
66
        if ( empty( $locale ) ) {
 
67
                $locale = 'en_US';
 
68
        }
 
69
 
 
70
        /** This filter is documented in wp-includes/l10n.php */
 
71
        return apply_filters( 'locale', $locale );
 
72
}
 
73
 
 
74
/**
 
75
 * Retrieve the translation of $text.
 
76
 *
 
77
 * If there is no translation, or the text domain isn't loaded, the original text is returned.
 
78
 *
 
79
 * <strong>Note:</strong> Don't use translate() directly, use __() or related functions.
 
80
 *
 
81
 * @since 2.2.0
 
82
 *
 
83
 * @param string $text   Text to translate.
 
84
 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
 
85
 * @return string Translated text
 
86
 */
 
87
function translate( $text, $domain = 'default' ) {
 
88
        $translations = get_translations_for_domain( $domain );
 
89
        $translations = $translations->translate( $text );
 
90
        /**
 
91
         * Filter text with its translation.
 
92
         *
 
93
         * @since 2.0.11
 
94
         *
 
95
         * @param string $translations Translated text.
 
96
         * @param string $text         Text to translate.
 
97
         * @param string $domain       Text domain. Unique identifier for retrieving translated strings.
 
98
         */
 
99
        return apply_filters( 'gettext', $translations, $text, $domain );
 
100
}
 
101
 
 
102
/**
 
103
 * Remove last item on a pipe-delimited string.
 
104
 *
 
105
 * Meant for removing the last item in a string, such as 'Role name|User role'. The original
 
106
 * string will be returned if no pipe '|' characters are found in the string.
 
107
 *
 
108
 * @since 2.8.0
 
109
 *
 
110
 * @param string $string A pipe-delimited string.
 
111
 * @return string Either $string or everything before the last pipe.
 
112
 */
 
113
function before_last_bar( $string ) {
 
114
        $last_bar = strrpos( $string, '|' );
 
115
        if ( false == $last_bar )
 
116
                return $string;
 
117
        else
 
118
                return substr( $string, 0, $last_bar );
 
119
}
 
120
 
 
121
/**
 
122
 * Retrieve the translation of $text in the context defined in $context.
 
123
 *
 
124
 * If there is no translation, or the text domain isn't loaded the original
 
125
 * text is returned.
 
126
 *
 
127
 * @since 2.8.0
 
128
 *
 
129
 * @param string $text    Text to translate.
 
130
 * @param string $context Context information for the translators.
 
131
 * @param string $domain  Optional. Text domain. Unique identifier for retrieving translated strings.
 
132
 * @return string Translated text on success, original text on failure.
 
133
 */
 
134
function translate_with_gettext_context( $text, $context, $domain = 'default' ) {
 
135
        $translations = get_translations_for_domain( $domain );
 
136
        $translations = $translations->translate( $text, $context );
 
137
        /**
 
138
         * Filter text with its translation based on context information.
 
139
         *
 
140
         * @since 2.8.0
 
141
         *
 
142
         * @param string $translations Translated text.
 
143
         * @param string $text         Text to translate.
 
144
         * @param string $context      Context information for the translators.
 
145
         * @param string $domain       Text domain. Unique identifier for retrieving translated strings.
 
146
         */
 
147
        return apply_filters( 'gettext_with_context', $translations, $text, $context, $domain );
 
148
}
 
149
 
 
150
/**
 
151
 * Retrieve the translation of $text. If there is no translation,
 
152
 * or the text domain isn't loaded, the original text is returned.
 
153
 *
 
154
 * @since 2.1.0
 
155
 *
 
156
 * @param string $text   Text to translate.
 
157
 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
 
158
 * @return string Translated text.
 
159
 */
 
160
function __( $text, $domain = 'default' ) {
 
161
        return translate( $text, $domain );
 
162
}
 
163
 
 
164
/**
 
165
 * Retrieve the translation of $text and escapes it for safe use in an attribute.
 
166
 *
 
167
 * If there is no translation, or the text domain isn't loaded, the original text is returned.
 
168
 *
 
169
 * @since 2.8.0
 
170
 *
 
171
 * @param string $text   Text to translate.
 
172
 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
 
173
 * @return string Translated text on success, original text on failure.
 
174
 */
 
175
function esc_attr__( $text, $domain = 'default' ) {
 
176
        return esc_attr( translate( $text, $domain ) );
 
177
}
 
178
 
 
179
/**
 
180
 * Retrieve the translation of $text and escapes it for safe use in HTML output.
 
181
 *
 
182
 * If there is no translation, or the text domain isn't loaded, the original text is returned.
 
183
 *
 
184
 * @since 2.8.0
 
185
 *
 
186
 * @param string $text   Text to translate.
 
187
 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
 
188
 * @return string Translated text
 
189
 */
 
190
function esc_html__( $text, $domain = 'default' ) {
 
191
        return esc_html( translate( $text, $domain ) );
 
192
}
 
193
 
 
194
/**
 
195
 * Display translated text.
 
196
 *
 
197
 * @since 1.2.0
 
198
 *
 
199
 * @param string $text   Text to translate.
 
200
 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
 
201
 */
 
202
function _e( $text, $domain = 'default' ) {
 
203
        echo translate( $text, $domain );
 
204
}
 
205
 
 
206
/**
 
207
 * Display translated text that has been escaped for safe use in an attribute.
 
208
 *
 
209
 * @since 2.8.0
 
210
 *
 
211
 * @param string $text   Text to translate.
 
212
 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
 
213
 */
 
214
function esc_attr_e( $text, $domain = 'default' ) {
 
215
        echo esc_attr( translate( $text, $domain ) );
 
216
}
 
217
 
 
218
/**
 
219
 * Display translated text that has been escaped for safe use in HTML output.
 
220
 *
 
221
 * @since 2.8.0
 
222
 *
 
223
 * @param string $text   Text to translate.
 
224
 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
 
225
 */
 
226
function esc_html_e( $text, $domain = 'default' ) {
 
227
        echo esc_html( translate( $text, $domain ) );
 
228
}
 
229
 
 
230
/**
 
231
 * Retrieve translated string with gettext context.
 
232
 *
 
233
 * Quite a few times, there will be collisions with similar translatable text
 
234
 * found in more than two places, but with different translated context.
 
235
 *
 
236
 * By including the context in the pot file, translators can translate the two
 
237
 * strings differently.
 
238
 *
 
239
 * @since 2.8.0
 
240
 *
 
241
 * @param string $text    Text to translate.
 
242
 * @param string $context Context information for the translators.
 
243
 * @param string $domain  Optional. Text domain. Unique identifier for retrieving translated strings.
 
244
 * @return string Translated context string without pipe.
 
245
 */
 
246
function _x( $text, $context, $domain = 'default' ) {
 
247
        return translate_with_gettext_context( $text, $context, $domain );
 
248
}
 
249
 
 
250
/**
 
251
 * Display translated string with gettext context.
 
252
 *
 
253
 * @since 3.0.0
 
254
 *
 
255
 * @param string $text    Text to translate.
 
256
 * @param string $context Context information for the translators.
 
257
 * @param string $domain  Optional. Text domain. Unique identifier for retrieving translated strings.
 
258
 * @return string Translated context string without pipe.
 
259
 */
 
260
function _ex( $text, $context, $domain = 'default' ) {
 
261
        echo _x( $text, $context, $domain );
 
262
}
 
263
 
 
264
/**
 
265
 * Translate string with gettext context, and escapes it for safe use in an attribute.
 
266
 *
 
267
 * @since 2.8.0
 
268
 *
 
269
 * @param string $text    Text to translate.
 
270
 * @param string $context Context information for the translators.
 
271
 * @param string $domain  Optional. Text domain. Unique identifier for retrieving translated strings.
 
272
 * @return string Translated text
 
273
 */
 
274
function esc_attr_x( $text, $context, $domain = 'default' ) {
 
275
        return esc_attr( translate_with_gettext_context( $text, $context, $domain ) );
 
276
}
 
277
 
 
278
/**
 
279
 * Translate string with gettext context, and escapes it for safe use in HTML output.
 
280
 *
 
281
 * @since 2.9.0
 
282
 *
 
283
 * @param string $text    Text to translate.
 
284
 * @param string $context Context information for the translators.
 
285
 * @param string $domain  Optional. Text domain. Unique identifier for retrieving translated strings.
 
286
 * @return string Translated text.
 
287
 */
 
288
function esc_html_x( $text, $context, $domain = 'default' ) {
 
289
        return esc_html( translate_with_gettext_context( $text, $context, $domain ) );
 
290
}
 
291
 
 
292
/**
 
293
 * Retrieve the plural or single form based on the supplied amount.
 
294
 *
 
295
 * If the text domain is not set in the $l10n list, then a comparison will be made
 
296
 * and either $plural or $single parameters returned.
 
297
 *
 
298
 * If the text domain does exist, then the parameters $single, $plural, and $number
 
299
 * will first be passed to the text domain's ngettext method. Then it will be passed
 
300
 * to the 'ngettext' filter hook along with the same parameters. The expected
 
301
 * type will be a string.
 
302
 *
 
303
 * @since 2.8.0
 
304
 *
 
305
 * @param string $single The text that will be used if $number is 1.
 
306
 * @param string $plural The text that will be used if $number is not 1.
 
307
 * @param int    $number The number to compare against to use either $single or $plural.
 
308
 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
 
309
 * @return string Either $single or $plural translated text.
 
310
 */
 
311
function _n( $single, $plural, $number, $domain = 'default' ) {
 
312
        $translations = get_translations_for_domain( $domain );
 
313
        $translation = $translations->translate_plural( $single, $plural, $number );
 
314
        /**
 
315
         * Filter text with its translation when plural option is available.
 
316
         *
 
317
         * @since 2.2.0
 
318
         *
 
319
         * @param string $translation Translated text.
 
320
         * @param string $single      The text that will be used if $number is 1.
 
321
         * @param string $plural      The text that will be used if $number is not 1.
 
322
         * @param string $number      The number to compare against to use either $single or $plural.
 
323
         * @param string $domain      Text domain. Unique identifier for retrieving translated strings.
 
324
         */
 
325
        return apply_filters( 'ngettext', $translation, $single, $plural, $number, $domain );
 
326
}
 
327
 
 
328
/**
 
329
 * Retrieve the plural or single form based on the supplied amount with gettext context.
 
330
 *
 
331
 * This is a hybrid of _n() and _x(). It supports contexts and plurals.
 
332
 *
 
333
 * @since 2.8.0
 
334
 *
 
335
 * @param string $single  The text that will be used if $number is 1.
 
336
 * @param string $plural  The text that will be used if $number is not 1.
 
337
 * @param int    $number  The number to compare against to use either $single or $plural.
 
338
 * @param string $context Context information for the translators.
 
339
 * @param string $domain  Optional. Text domain. Unique identifier for retrieving translated strings.
 
340
 * @return string Either $single or $plural translated text with context.
 
341
 */
 
342
function _nx($single, $plural, $number, $context, $domain = 'default') {
 
343
        $translations = get_translations_for_domain( $domain );
 
344
        $translation = $translations->translate_plural( $single, $plural, $number, $context );
 
345
        /**
 
346
         * Filter text with its translation while plural option and context are available.
 
347
         *
 
348
         * @since 2.8.0
 
349
         *
 
350
         * @param string $translation Translated text.
 
351
         * @param string $single      The text that will be used if $number is 1.
 
352
         * @param string $plural      The text that will be used if $number is not 1.
 
353
         * @param string $number      The number to compare against to use either $single or $plural.
 
354
         * @param string $context     Context information for the translators.
 
355
         * @param string $domain      Text domain. Unique identifier for retrieving translated strings.
 
356
         */
 
357
        return apply_filters( 'ngettext_with_context', $translation, $single, $plural, $number, $context, $domain );
 
358
}
 
359
 
 
360
/**
 
361
 * Register plural strings in POT file, but don't translate them.
 
362
 *
 
363
 * Used when you want to keep structures with translatable plural
 
364
 * strings and use them later.
 
365
 *
 
366
 * Example:
 
367
 * <code>
 
368
 * $messages = array(
 
369
 *      'post' => _n_noop('%s post', '%s posts'),
 
370
 *      'page' => _n_noop('%s pages', '%s pages')
 
371
 * );
 
372
 * ...
 
373
 * $message = $messages[$type];
 
374
 * $usable_text = sprintf( translate_nooped_plural( $message, $count ), $count );
 
375
 * </code>
 
376
 *
 
377
 * @since 2.5.0
 
378
 *
 
379
 * @param string $singular Single form to be i18ned.
 
380
 * @param string $plural   Plural form to be i18ned.
 
381
 * @param string $domain   Optional. Text domain. Unique identifier for retrieving translated strings.
 
382
 * @return array array($singular, $plural)
 
383
 */
 
384
function _n_noop( $singular, $plural, $domain = null ) {
 
385
        return array( 0 => $singular, 1 => $plural, 'singular' => $singular, 'plural' => $plural, 'context' => null, 'domain' => $domain );
 
386
}
 
387
 
 
388
/**
 
389
 * Register plural strings with context in POT file, but don't translate them.
 
390
 *
 
391
 * @since 2.8.0
 
392
 */
 
393
function _nx_noop( $singular, $plural, $context, $domain = null ) {
 
394
        return array( 0 => $singular, 1 => $plural, 2 => $context, 'singular' => $singular, 'plural' => $plural, 'context' => $context, 'domain' => $domain );
 
395
}
 
396
 
 
397
/**
 
398
 * Translate the result of _n_noop() or _nx_noop().
 
399
 *
 
400
 * @since 3.1.0
 
401
 *
 
402
 * @param array  $nooped_plural Array with singular, plural and context keys, usually the result of _n_noop() or _nx_noop()
 
403
 * @param int    $count         Number of objects
 
404
 * @param string $domain        Optional. Text domain. Unique identifier for retrieving translated strings. If $nooped_plural contains
 
405
 *                              a text domain passed to _n_noop() or _nx_noop(), it will override this value.
 
406
 * @return string Either $single or $plural translated text.
 
407
 */
 
408
function translate_nooped_plural( $nooped_plural, $count, $domain = 'default' ) {
 
409
        if ( $nooped_plural['domain'] )
 
410
                $domain = $nooped_plural['domain'];
 
411
 
 
412
        if ( $nooped_plural['context'] )
 
413
                return _nx( $nooped_plural['singular'], $nooped_plural['plural'], $count, $nooped_plural['context'], $domain );
 
414
        else
 
415
                return _n( $nooped_plural['singular'], $nooped_plural['plural'], $count, $domain );
 
416
}
 
417
 
 
418
/**
 
419
 * Load a .mo file into the text domain $domain.
 
420
 *
 
421
 * If the text domain already exists, the translations will be merged. If both
 
422
 * sets have the same string, the translation from the original value will be taken.
 
423
 *
 
424
 * On success, the .mo file will be placed in the $l10n global by $domain
 
425
 * and will be a MO object.
 
426
 *
 
427
 * @since 1.5.0
 
428
 *
 
429
 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
 
430
 * @param string $mofile Path to the .mo file.
 
431
 * @return bool True on success, false on failure.
 
432
 */
 
433
function load_textdomain( $domain, $mofile ) {
 
434
        global $l10n;
 
435
 
 
436
        /**
 
437
         * Filter text domain and/or MO file path for loading translations.
 
438
         *
 
439
         * @since 2.9.0
 
440
         *
 
441
         * @param bool   $override Whether to override the text domain. Default false.
 
442
         * @param string $domain   Text domain. Unique identifier for retrieving translated strings.
 
443
         * @param string $mofile   Path to the MO file.
 
444
         */
 
445
        $plugin_override = apply_filters( 'override_load_textdomain', false, $domain, $mofile );
 
446
 
 
447
        if ( true == $plugin_override ) {
 
448
                return true;
 
449
        }
 
450
 
 
451
        /**
 
452
         * Fires before the MO translation file is loaded.
 
453
         *
 
454
         * @since 2.9.0
 
455
         *
 
456
         * @param string $domain Text domain. Unique identifier for retrieving translated strings.
 
457
         * @param string $mofile Path to the .mo file.
 
458
         */
 
459
        do_action( 'load_textdomain', $domain, $mofile );
 
460
 
 
461
        /**
 
462
         * Filter MO file path for loading translations for a specific text domain.
 
463
         *
 
464
         * @since 2.9.0
 
465
         *
 
466
         * @param string $mofile Path to the MO file.
 
467
         * @param string $domain Text domain. Unique identifier for retrieving translated strings.
 
468
         */
 
469
        $mofile = apply_filters( 'load_textdomain_mofile', $mofile, $domain );
 
470
 
 
471
        if ( !is_readable( $mofile ) ) return false;
 
472
 
 
473
        $mo = new MO();
 
474
        if ( !$mo->import_from_file( $mofile ) ) return false;
 
475
 
 
476
        if ( isset( $l10n[$domain] ) )
 
477
                $mo->merge_with( $l10n[$domain] );
 
478
 
 
479
        $l10n[$domain] = &$mo;
 
480
 
 
481
        return true;
 
482
}
 
483
 
 
484
/**
 
485
 * Unload translations for a text domain.
 
486
 *
 
487
 * @since 3.0.0
 
488
 *
 
489
 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
 
490
 * @return bool Whether textdomain was unloaded.
 
491
 */
 
492
function unload_textdomain( $domain ) {
 
493
        global $l10n;
 
494
 
 
495
        /**
 
496
         * Filter the text domain for loading translation.
 
497
         *
 
498
         * @since 3.0.0
 
499
         *
 
500
         * @param bool   $override Whether to override unloading the text domain. Default false.
 
501
         * @param string $domain   Text domain. Unique identifier for retrieving translated strings.
 
502
         */
 
503
        $plugin_override = apply_filters( 'override_unload_textdomain', false, $domain );
 
504
 
 
505
        if ( $plugin_override )
 
506
                return true;
 
507
 
 
508
        /**
 
509
         * Fires before the text domain is unloaded.
 
510
         *
 
511
         * @since 3.0.0
 
512
         *
 
513
         * @param string $domain Text domain. Unique identifier for retrieving translated strings.
 
514
         */
 
515
        do_action( 'unload_textdomain', $domain );
 
516
 
 
517
        if ( isset( $l10n[$domain] ) ) {
 
518
                unset( $l10n[$domain] );
 
519
                return true;
 
520
        }
 
521
 
 
522
        return false;
 
523
}
 
524
 
 
525
/**
 
526
 * Load default translated strings based on locale.
 
527
 *
 
528
 * Loads the .mo file in WP_LANG_DIR constant path from WordPress root.
 
529
 * The translated (.mo) file is named based on the locale.
 
530
 *
 
531
 * @see load_textdomain()
 
532
 *
 
533
 * @since 1.5.0
 
534
 *
 
535
 * @param string $locale Optional. Locale to load. Defaults to get_locale().
 
536
 */
 
537
function load_default_textdomain( $locale = null ) {
 
538
        if ( null === $locale ) {
 
539
                $locale = get_locale();
 
540
        }
 
541
 
 
542
        // Unload previously loaded strings so we can switch translations.
 
543
        unload_textdomain( 'default' );
 
544
 
 
545
        $return = load_textdomain( 'default', WP_LANG_DIR . "/$locale.mo" );
 
546
 
 
547
        if ( ( is_multisite() || ( defined( 'WP_INSTALLING_NETWORK' ) && WP_INSTALLING_NETWORK ) ) && ! file_exists(  WP_LANG_DIR . "/admin-$locale.mo" ) ) {
 
548
                load_textdomain( 'default', WP_LANG_DIR . "/ms-$locale.mo" );
 
549
                return $return;
 
550
        }
 
551
 
 
552
        if ( is_admin() || defined( 'WP_INSTALLING' ) || ( defined( 'WP_REPAIRING' ) && WP_REPAIRING ) ) {
 
553
                load_textdomain( 'default', WP_LANG_DIR . "/admin-$locale.mo" );
 
554
        }
 
555
 
 
556
        if ( is_network_admin() || ( defined( 'WP_INSTALLING_NETWORK' ) && WP_INSTALLING_NETWORK ) )
 
557
                load_textdomain( 'default', WP_LANG_DIR . "/admin-network-$locale.mo" );
 
558
 
 
559
        return $return;
 
560
}
 
561
 
 
562
/**
 
563
 * Load a plugin's translated strings.
 
564
 *
 
565
 * If the path is not given then it will be the root of the plugin directory.
 
566
 *
 
567
 * The .mo file should be named based on the text domain with a dash, and then the locale exactly.
 
568
 *
 
569
 * @since 1.5.0
 
570
 *
 
571
 * @param string $domain          Unique identifier for retrieving translated strings
 
572
 * @param string $deprecated      Use the $plugin_rel_path parameter instead.
 
573
 * @param string $plugin_rel_path Optional. Relative path to WP_PLUGIN_DIR where the .mo file resides.
 
574
 *                                Default false.
 
575
 * @return bool True when textdomain is successfully loaded, false otherwise.
 
576
 */
 
577
function load_plugin_textdomain( $domain, $deprecated = false, $plugin_rel_path = false ) {
 
578
        $locale = get_locale();
 
579
        /**
 
580
         * Filter a plugin's locale.
 
581
         *
 
582
         * @since 3.0.0
 
583
         *
 
584
         * @param string $locale The plugin's current locale.
 
585
         * @param string $domain Text domain. Unique identifier for retrieving translated strings.
 
586
         */
 
587
        $locale = apply_filters( 'plugin_locale', $locale, $domain );
 
588
 
 
589
        if ( false !== $plugin_rel_path ) {
 
590
                $path = WP_PLUGIN_DIR . '/' . trim( $plugin_rel_path, '/' );
 
591
        } else if ( false !== $deprecated ) {
 
592
                _deprecated_argument( __FUNCTION__, '2.7' );
 
593
                $path = ABSPATH . trim( $deprecated, '/' );
 
594
        } else {
 
595
                $path = WP_PLUGIN_DIR;
 
596
        }
 
597
 
 
598
        // Load the textdomain according to the plugin first
 
599
        $mofile = $domain . '-' . $locale . '.mo';
 
600
        if ( $loaded = load_textdomain( $domain, $path . '/'. $mofile ) )
 
601
                return $loaded;
 
602
 
 
603
        // Otherwise, load from the languages directory
 
604
        $mofile = WP_LANG_DIR . '/plugins/' . $mofile;
 
605
        return load_textdomain( $domain, $mofile );
 
606
}
 
607
 
 
608
/**
 
609
 * Load the translated strings for a plugin residing in the mu-plugins directory.
 
610
 *
 
611
 * @since 3.0.0
 
612
 *
 
613
 * @param string $domain             Text domain. Unique identifier for retrieving translated strings.
 
614
 * @param string $mu_plugin_rel_path Relative to WPMU_PLUGIN_DIR directory in which the .mo file resides.
 
615
 *                                   Default empty string.
 
616
 * @return bool True when textdomain is successfully loaded, false otherwise.
 
617
 */
 
618
function load_muplugin_textdomain( $domain, $mu_plugin_rel_path = '' ) {
 
619
        /** This filter is documented in wp-includes/l10n.php */
 
620
        $locale = apply_filters( 'plugin_locale', get_locale(), $domain );
 
621
        $path = trailingslashit( WPMU_PLUGIN_DIR . '/' . ltrim( $mu_plugin_rel_path, '/' ) );
 
622
 
 
623
        // Load the textdomain according to the plugin first
 
624
        $mofile = $domain . '-' . $locale . '.mo';
 
625
        if ( $loaded = load_textdomain( $domain, $path . $mofile ) )
 
626
                return $loaded;
 
627
 
 
628
        // Otherwise, load from the languages directory
 
629
        $mofile = WP_LANG_DIR . '/plugins/' . $mofile;
 
630
        return load_textdomain( $domain, $mofile );
 
631
}
 
632
 
 
633
/**
 
634
 * Load the theme's translated strings.
 
635
 *
 
636
 * If the current locale exists as a .mo file in the theme's root directory, it
 
637
 * will be included in the translated strings by the $domain.
 
638
 *
 
639
 * The .mo files must be named based on the locale exactly.
 
640
 *
 
641
 * @since 1.5.0
 
642
 *
 
643
 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
 
644
 * @param string $path   Optional. Path to the directory containing the .mo file.
 
645
 *                       Default false.
 
646
 * @return bool True when textdomain is successfully loaded, false otherwise.
 
647
 */
 
648
function load_theme_textdomain( $domain, $path = false ) {
 
649
        $locale = get_locale();
 
650
        /**
 
651
         * Filter a theme's locale.
 
652
         *
 
653
         * @since 3.0.0
 
654
         *
 
655
         * @param string $locale The theme's current locale.
 
656
         * @param string $domain Text domain. Unique identifier for retrieving translated strings.
 
657
         */
 
658
        $locale = apply_filters( 'theme_locale', $locale, $domain );
 
659
 
 
660
        if ( ! $path )
 
661
                $path = get_template_directory();
 
662
 
 
663
        // Load the textdomain according to the theme
 
664
        $mofile = "{$path}/{$locale}.mo";
 
665
        if ( $loaded = load_textdomain( $domain, $mofile ) )
 
666
                return $loaded;
 
667
 
 
668
        // Otherwise, load from the languages directory
 
669
        $mofile = WP_LANG_DIR . "/themes/{$domain}-{$locale}.mo";
 
670
        return load_textdomain( $domain, $mofile );
 
671
}
 
672
 
 
673
/**
 
674
 * Load the child themes translated strings.
 
675
 *
 
676
 * If the current locale exists as a .mo file in the child themes
 
677
 * root directory, it will be included in the translated strings by the $domain.
 
678
 *
 
679
 * The .mo files must be named based on the locale exactly.
 
680
 *
 
681
 * @since 2.9.0
 
682
 *
 
683
 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
 
684
 * @param string $path   Optional. Path to the directory containing the .mo file.
 
685
 *                       Default false.
 
686
 * @return bool True when the theme textdomain is successfully loaded, false otherwise.
 
687
 */
 
688
function load_child_theme_textdomain( $domain, $path = false ) {
 
689
        if ( ! $path )
 
690
                $path = get_stylesheet_directory();
 
691
        return load_theme_textdomain( $domain, $path );
 
692
}
 
693
 
 
694
/**
 
695
 * Return the Translations instance for a text domain.
 
696
 *
 
697
 * If there isn't one, returns empty Translations instance.
 
698
 *
 
699
 * @since 2.8.0
 
700
 *
 
701
 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
 
702
 * @return Translations A Translations instance.
 
703
 */
 
704
function get_translations_for_domain( $domain ) {
 
705
        global $l10n;
 
706
        if ( !isset( $l10n[$domain] ) ) {
 
707
                $l10n[$domain] = new NOOP_Translations;
 
708
        }
 
709
        return $l10n[$domain];
 
710
}
 
711
 
 
712
/**
 
713
 * Whether there are translations for the text domain.
 
714
 *
 
715
 * @since 3.0.0
 
716
 *
 
717
 * @param string $domain Text domain. Unique identifier for retrieving translated strings.
 
718
 * @return bool Whether there are translations.
 
719
 */
 
720
function is_textdomain_loaded( $domain ) {
 
721
        global $l10n;
 
722
        return isset( $l10n[$domain] );
 
723
}
 
724
 
 
725
/**
 
726
 * Translates role name.
 
727
 *
 
728
 * Since the role names are in the database and not in the source there
 
729
 * are dummy gettext calls to get them into the POT file and this function
 
730
 * properly translates them back.
 
731
 *
 
732
 * The before_last_bar() call is needed, because older installs keep the roles
 
733
 * using the old context format: 'Role name|User role' and just skipping the
 
734
 * content after the last bar is easier than fixing them in the DB. New installs
 
735
 * won't suffer from that problem.
 
736
 *
 
737
 * @since 2.8.0
 
738
 *
 
739
 * @param string $name The role name.
 
740
 * @return string Translated role name on success, original name on failure.
 
741
 */
 
742
function translate_user_role( $name ) {
 
743
        return translate_with_gettext_context( before_last_bar($name), 'User role' );
 
744
}
 
745
 
 
746
/**
 
747
 * Get all available languages based on the presence of *.mo files in a given directory.
 
748
 *
 
749
 * The default directory is WP_LANG_DIR.
 
750
 *
 
751
 * @since 3.0.0
 
752
 *
 
753
 * @param string $dir A directory to search for language files.
 
754
 *                    Default WP_LANG_DIR.
 
755
 * @return array An array of language codes or an empty array if no languages are present. Language codes are formed by stripping the .mo extension from the language file names.
 
756
 */
 
757
function get_available_languages( $dir = null ) {
 
758
        $languages = array();
 
759
 
 
760
        foreach( (array)glob( ( is_null( $dir) ? WP_LANG_DIR : $dir ) . '/*.mo' ) as $lang_file ) {
 
761
                $lang_file = basename($lang_file, '.mo');
 
762
                if ( 0 !== strpos( $lang_file, 'continents-cities' ) && 0 !== strpos( $lang_file, 'ms-' ) &&
 
763
                        0 !== strpos( $lang_file, 'admin-' ))
 
764
                        $languages[] = $lang_file;
 
765
        }
 
766
 
 
767
        return $languages;
 
768
}
 
769
 
 
770
/**
 
771
 * Get installed translations.
 
772
 *
 
773
 * Looks in the wp-content/languages directory for translations of
 
774
 * plugins or themes.
 
775
 *
 
776
 * @since 3.7.0
 
777
 *
 
778
 * @param string $type What to search for. Accepts 'plugins', 'themes', 'core'.
 
779
 * @return array Array of language data.
 
780
 */
 
781
function wp_get_installed_translations( $type ) {
 
782
        if ( $type !== 'themes' && $type !== 'plugins' && $type !== 'core' )
 
783
                return array();
 
784
 
 
785
        $dir = 'core' === $type ? '' : "/$type";
 
786
 
 
787
        if ( ! is_dir( WP_LANG_DIR ) )
 
788
                return array();
 
789
 
 
790
        if ( $dir && ! is_dir( WP_LANG_DIR . $dir ) )
 
791
                return array();
 
792
 
 
793
        $files = scandir( WP_LANG_DIR . $dir );
 
794
        if ( ! $files )
 
795
                return array();
 
796
 
 
797
        $language_data = array();
 
798
 
 
799
        foreach ( $files as $file ) {
 
800
                if ( '.' === $file[0] || is_dir( $file ) )
 
801
                        continue;
 
802
                if ( substr( $file, -3 ) !== '.po' )
 
803
                        continue;
 
804
                if ( ! preg_match( '/(?:(.+)-)?([A-Za-z_]{2,6}).po/', $file, $match ) )
 
805
                        continue;
 
806
 
 
807
                list( , $textdomain, $language ) = $match;
 
808
                if ( '' === $textdomain )
 
809
                        $textdomain = 'default';
 
810
                $language_data[ $textdomain ][ $language ] = wp_get_pomo_file_data( WP_LANG_DIR . "$dir/$file" );
 
811
        }
 
812
        return $language_data;
 
813
}
 
814
 
 
815
/**
 
816
 * Extract headers from a PO file.
 
817
 *
 
818
 * @since 3.7.0
 
819
 *
 
820
 * @param string $po_file Path to PO file.
 
821
 * @return array PO file headers.
 
822
 */
 
823
function wp_get_pomo_file_data( $po_file ) {
 
824
        $headers = get_file_data( $po_file, array(
 
825
                'POT-Creation-Date'  => '"POT-Creation-Date',
 
826
                'PO-Revision-Date'   => '"PO-Revision-Date',
 
827
                'Project-Id-Version' => '"Project-Id-Version',
 
828
                'X-Generator'        => '"X-Generator',
 
829
        ) );
 
830
        foreach ( $headers as $header => $value ) {
 
831
                // Remove possible contextual '\n' and closing double quote.
 
832
                $headers[ $header ] = preg_replace( '~(\\\n)?"$~', '', $value );
 
833
        }
 
834
        return $headers;
 
835
}
 
836
 
 
837
/**
 
838
 * Language selector.
 
839
 *
 
840
 * @since 4.0.0
 
841
 *
 
842
 * @see get_available_languages()
 
843
 * @see wp_get_available_translations()
 
844
 *
 
845
 * @param array $args Optional arguments. Default empty array.
 
846
 */
 
847
function wp_dropdown_languages( $args = array() ) {
 
848
        require_once( ABSPATH . 'wp-admin/includes/translation-install.php' );
 
849
 
 
850
        $args = wp_parse_args( $args, array(
 
851
                'id'        => '',
 
852
                'name'      => '',
 
853
                'languages' => array(),
 
854
                'selected'  => ''
 
855
        ) );
 
856
 
 
857
        if ( empty( $args['languages'] ) ) {
 
858
                return false;
 
859
        }
 
860
 
 
861
        $translations = wp_get_available_translations();
 
862
 
 
863
        /*
 
864
         * $args['languages'] should only contain the locales. Find the locale in
 
865
         * $translations to get the native name. Fall back to locale.
 
866
         */
 
867
        $languages = array();
 
868
        foreach ( $args['languages'] as $locale ) {
 
869
                if ( isset( $translations[ $locale ] ) ) {
 
870
                        $translation = $translations[ $locale ];
 
871
                        $languages[] = array(
 
872
                                'language'    => $translation['language'],
 
873
                                'native_name' => $translation['native_name'],
 
874
                                'lang'        => $translation['iso'][1],
 
875
                        );
 
876
                } else {
 
877
                        $languages[] = array(
 
878
                                'language'    => $locale,
 
879
                                'native_name' => $locale,
 
880
                                'lang'        => '',
 
881
                        );
 
882
                }
 
883
        }
 
884
 
 
885
        printf( '<select name="%s" id="%s">', esc_attr( $args['name'] ), esc_attr( $args['id'] ) );
 
886
 
 
887
        // List installed languages.
 
888
        echo '<option value="" lang="en">English (United States)</option>';
 
889
        foreach ( $languages as $language ) {
 
890
                $selected = selected( $language['language'], $args['selected'], false );
 
891
                printf(
 
892
                        '<option value="%s" lang="%s"%s>%s</option>',
 
893
                        esc_attr( $language['language'] ),
 
894
                        esc_attr( $language['lang'] ),
 
895
                        $selected,
 
896
                        esc_html( $language['native_name'] )
 
897
                );
 
898
        }
 
899
 
 
900
        echo '</select>';
 
901
}