WordPress 3.4.1
[autoinstalls/wordpress.git] / wp-includes / l10n.php
1 <?php
2 /**
3  * WordPress Translation API
4  *
5  * @package WordPress
6  * @subpackage i18n
7  */
8
9 /**
10  * Gets 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  * @uses apply_filters() Calls 'locale' hook on locale value.
24  * @uses $locale Gets the locale stored in the global.
25  *
26  * @return string The locale of the blog or from the 'locale' hook.
27  */
28 function get_locale() {
29         global $locale;
30
31         if ( isset( $locale ) )
32                 return apply_filters( 'locale', $locale );
33
34         // WPLANG is defined in wp-config.
35         if ( defined( 'WPLANG' ) )
36                 $locale = WPLANG;
37
38         // If multisite, check options.
39         if ( is_multisite() ) {
40                 // Don't check blog option when installing.
41                 if ( defined( 'WP_INSTALLING' ) || ( false === $ms_locale = get_option( 'WPLANG' ) ) )
42                         $ms_locale = get_site_option('WPLANG');
43
44                 if ( $ms_locale !== false )
45                         $locale = $ms_locale;
46         }
47
48         if ( empty( $locale ) )
49                 $locale = 'en_US';
50
51         return apply_filters( 'locale', $locale );
52 }
53
54 /**
55  * Retrieves the translation of $text. If there is no translation, or
56  * the domain isn't loaded, the original text is returned.
57  *
58  * @see __() Don't use translate() directly, use __()
59  * @since 2.2.0
60  * @uses apply_filters() Calls 'gettext' on domain translated text
61  *              with the untranslated text as second parameter.
62  *
63  * @param string $text Text to translate.
64  * @param string $domain Domain to retrieve the translated text.
65  * @return string Translated text
66  */
67 function translate( $text, $domain = 'default' ) {
68         $translations = &get_translations_for_domain( $domain );
69         return apply_filters( 'gettext', $translations->translate( $text ), $text, $domain );
70 }
71
72 function before_last_bar( $string ) {
73         $last_bar = strrpos( $string, '|' );
74         if ( false == $last_bar )
75                 return $string;
76         else
77                 return substr( $string, 0, $last_bar );
78 }
79
80 function translate_with_gettext_context( $text, $context, $domain = 'default' ) {
81         $translations = &get_translations_for_domain( $domain );
82         return apply_filters( 'gettext_with_context', $translations->translate( $text, $context ), $text, $context, $domain );
83 }
84
85 /**
86  * Retrieves the translation of $text. If there is no translation, or
87  * the domain isn't loaded, the original text is returned.
88  *
89  * @see translate() An alias of translate()
90  * @since 2.1.0
91  *
92  * @param string $text Text to translate
93  * @param string $domain Optional. Domain to retrieve the translated text
94  * @return string Translated text
95  */
96 function __( $text, $domain = 'default' ) {
97         return translate( $text, $domain );
98 }
99
100 /**
101  * Retrieves the translation of $text and escapes it for safe use in an attribute.
102  * If there is no translation, or the domain isn't loaded, the original text is returned.
103  *
104  * @see translate() An alias of translate()
105  * @see esc_attr()
106  * @since 2.8.0
107  *
108  * @param string $text Text to translate
109  * @param string $domain Optional. Domain to retrieve the translated text
110  * @return string Translated text
111  */
112 function esc_attr__( $text, $domain = 'default' ) {
113         return esc_attr( translate( $text, $domain ) );
114 }
115
116 /**
117  * Retrieves the translation of $text and escapes it for safe use in HTML output.
118  * If there is no translation, or the domain isn't loaded, the original text is returned.
119  *
120  * @see translate() An alias of translate()
121  * @see esc_html()
122  * @since 2.8.0
123  *
124  * @param string $text Text to translate
125  * @param string $domain Optional. Domain to retrieve the translated text
126  * @return string Translated text
127  */
128 function esc_html__( $text, $domain = 'default' ) {
129         return esc_html( translate( $text, $domain ) );
130 }
131
132 /**
133  * Displays the returned translated text from translate().
134  *
135  * @see translate() Echoes returned translate() string
136  * @since 1.2.0
137  *
138  * @param string $text Text to translate
139  * @param string $domain Optional. Domain to retrieve the translated text
140  */
141 function _e( $text, $domain = 'default' ) {
142         echo translate( $text, $domain );
143 }
144
145 /**
146  * Displays translated text that has been escaped for safe use in an attribute.
147  *
148  * @see translate() Echoes returned translate() string
149  * @see esc_attr()
150  * @since 2.8.0
151  *
152  * @param string $text Text to translate
153  * @param string $domain Optional. Domain to retrieve the translated text
154  */
155 function esc_attr_e( $text, $domain = 'default' ) {
156         echo esc_attr( translate( $text, $domain ) );
157 }
158
159 /**
160  * Displays translated text that has been escaped for safe use in HTML output.
161  *
162  * @see translate() Echoes returned translate() string
163  * @see esc_html()
164  * @since 2.8.0
165  *
166  * @param string $text Text to translate
167  * @param string $domain Optional. Domain to retrieve the translated text
168  */
169 function esc_html_e( $text, $domain = 'default' ) {
170         echo esc_html( translate( $text, $domain ) );
171 }
172
173 /**
174  * Retrieve translated string with gettext context
175  *
176  * Quite a few times, there will be collisions with similar translatable text
177  * found in more than two places but with different translated context.
178  *
179  * By including the context in the pot file translators can translate the two
180  * strings differently.
181  *
182  * @since 2.8.0
183  *
184  * @param string $text Text to translate
185  * @param string $context Context information for the translators
186  * @param string $domain Optional. Domain to retrieve the translated text
187  * @return string Translated context string without pipe
188  */
189 function _x( $text, $context, $domain = 'default' ) {
190         return translate_with_gettext_context( $text, $context, $domain );
191 }
192
193 /**
194  * Displays translated string with gettext context
195  *
196  * @see _x
197  * @since 3.0.0
198  *
199  * @param string $text Text to translate
200  * @param string $context Context information for the translators
201  * @param string $domain Optional. Domain to retrieve the translated text
202  * @return string Translated context string without pipe
203  */
204 function _ex( $text, $context, $domain = 'default' ) {
205         echo _x( $text, $context, $domain );
206 }
207
208 function esc_attr_x( $single, $context, $domain = 'default' ) {
209         return esc_attr( translate_with_gettext_context( $single, $context, $domain ) );
210 }
211
212 function esc_html_x( $single, $context, $domain = 'default' ) {
213         return esc_html( translate_with_gettext_context( $single, $context, $domain ) );
214 }
215
216 /**
217  * Retrieve the plural or single form based on the amount.
218  *
219  * If the domain is not set in the $l10n list, then a comparison will be made
220  * and either $plural or $single parameters returned.
221  *
222  * If the domain does exist, then the parameters $single, $plural, and $number
223  * will first be passed to the domain's ngettext method. Then it will be passed
224  * to the 'ngettext' filter hook along with the same parameters. The expected
225  * type will be a string.
226  *
227  * @since 2.8.0
228  * @uses $l10n Gets list of domain translated string (gettext_reader) objects
229  * @uses apply_filters() Calls 'ngettext' hook on domains text returned,
230  *              along with $single, $plural, and $number parameters. Expected to return string.
231  *
232  * @param string $single The text that will be used if $number is 1
233  * @param string $plural The text that will be used if $number is not 1
234  * @param int $number The number to compare against to use either $single or $plural
235  * @param string $domain Optional. The domain identifier the text should be retrieved in
236  * @return string Either $single or $plural translated text
237  */
238 function _n( $single, $plural, $number, $domain = 'default' ) {
239         $translations = &get_translations_for_domain( $domain );
240         $translation = $translations->translate_plural( $single, $plural, $number );
241         return apply_filters( 'ngettext', $translation, $single, $plural, $number, $domain );
242 }
243
244 /**
245  * A hybrid of _n() and _x(). It supports contexts and plurals.
246  *
247  * @see _n()
248  * @see _x()
249  *
250  */
251 function _nx($single, $plural, $number, $context, $domain = 'default') {
252         $translations = &get_translations_for_domain( $domain );
253         $translation = $translations->translate_plural( $single, $plural, $number, $context );
254         return apply_filters( 'ngettext_with_context', $translation, $single, $plural, $number, $context, $domain );
255 }
256
257 /**
258  * Register plural strings in POT file, but don't translate them.
259  *
260  * Used when you want to keep structures with translatable plural strings and
261  * use them later.
262  *
263  * Example:
264  *  $messages = array(
265  *      'post' => _n_noop('%s post', '%s posts'),
266  *      'page' => _n_noop('%s pages', '%s pages')
267  *  );
268  *  ...
269  *  $message = $messages[$type];
270  *  $usable_text = sprintf( translate_nooped_plural( $message, $count ), $count );
271  *
272  * @since 2.5
273  * @param string $singular Single form to be i18ned
274  * @param string $plural Plural form to be i18ned
275  * @param string $domain Optional. The domain identifier the text will be retrieved in
276  * @return array array($singular, $plural)
277  */
278 function _n_noop( $singular, $plural, $domain = null ) {
279         return array( 0 => $singular, 1 => $plural, 'singular' => $singular, 'plural' => $plural, 'context' => null, 'domain' => $domain );
280 }
281
282 /**
283  * Register plural strings with context in POT file, but don't translate them.
284  *
285  * @see _n_noop()
286  */
287 function _nx_noop( $singular, $plural, $context, $domain = null ) {
288         return array( 0 => $singular, 1 => $plural, 2 => $context, 'singular' => $singular, 'plural' => $plural, 'context' => $context, 'domain' => $domain );
289 }
290
291 /**
292  * Translate the result of _n_noop() or _nx_noop()
293  *
294  * @since 3.1
295  * @param array $nooped_plural Array with singular, plural and context keys, usually the result of _n_noop() or _nx_noop()
296  * @param int $count Number of objects
297  * @param string $domain Optional. The domain identifier the text should be retrieved in. If $nooped_plural contains
298  *      a domain passed to _n_noop() or _nx_noop(), it will override this value.
299  */
300 function translate_nooped_plural( $nooped_plural, $count, $domain = 'default' ) {
301         if ( $nooped_plural['domain'] )
302                 $domain = $nooped_plural['domain'];
303
304         if ( $nooped_plural['context'] )
305                 return _nx( $nooped_plural['singular'], $nooped_plural['plural'], $count, $nooped_plural['context'], $domain );
306         else
307                 return _n( $nooped_plural['singular'], $nooped_plural['plural'], $count, $domain );
308 }
309
310 /**
311  * Loads a MO file into the domain $domain.
312  *
313  * If the domain already exists, the translations will be merged. If both
314  * sets have the same string, the translation from the original value will be taken.
315  *
316  * On success, the .mo file will be placed in the $l10n global by $domain
317  * and will be a MO object.
318  *
319  * @since 1.5.0
320  * @uses $l10n Gets list of domain translated string objects
321  *
322  * @param string $domain Unique identifier for retrieving translated strings
323  * @param string $mofile Path to the .mo file
324  * @return bool True on success, false on failure
325  */
326 function load_textdomain( $domain, $mofile ) {
327         global $l10n;
328
329         $plugin_override = apply_filters( 'override_load_textdomain', false, $domain, $mofile );
330
331         if ( true == $plugin_override ) {
332                 return true;
333         }
334
335         do_action( 'load_textdomain', $domain, $mofile );
336
337         $mofile = apply_filters( 'load_textdomain_mofile', $mofile, $domain );
338
339         if ( !is_readable( $mofile ) ) return false;
340
341         $mo = new MO();
342         if ( !$mo->import_from_file( $mofile ) ) return false;
343
344         if ( isset( $l10n[$domain] ) )
345                 $mo->merge_with( $l10n[$domain] );
346
347         $l10n[$domain] = &$mo;
348
349         return true;
350 }
351
352 /**
353  * Unloads translations for a domain
354  *
355  * @since 3.0.0
356  * @param string $domain Textdomain to be unloaded
357  * @return bool Whether textdomain was unloaded
358  */
359 function unload_textdomain( $domain ) {
360         global $l10n;
361
362         $plugin_override = apply_filters( 'override_unload_textdomain', false, $domain );
363
364         if ( $plugin_override )
365                 return true;
366
367         do_action( 'unload_textdomain', $domain );
368
369         if ( isset( $l10n[$domain] ) ) {
370                 unset( $l10n[$domain] );
371                 return true;
372         }
373
374         return false;
375 }
376
377 /**
378  * Loads default translated strings based on locale.
379  *
380  * Loads the .mo file in WP_LANG_DIR constant path from WordPress root. The
381  * translated (.mo) file is named based on the locale.
382  *
383  * @since 1.5.0
384  */
385 function load_default_textdomain() {
386         $locale = get_locale();
387
388         load_textdomain( 'default', WP_LANG_DIR . "/$locale.mo" );
389
390         if ( ( is_multisite() || ( defined( 'WP_INSTALLING_NETWORK' ) && WP_INSTALLING_NETWORK ) ) && ! file_exists(  WP_LANG_DIR . "/admin-$locale.mo" ) ) {
391                 load_textdomain( 'default', WP_LANG_DIR . "/ms-$locale.mo" );
392                 return;
393         }
394
395         if ( is_admin() || ( defined( 'WP_REPAIRING' ) && WP_REPAIRING ) )
396                 load_textdomain( 'default', WP_LANG_DIR . "/admin-$locale.mo" );
397
398         if ( is_network_admin() || ( defined( 'WP_INSTALLING_NETWORK' ) && WP_INSTALLING_NETWORK ) )
399                 load_textdomain( 'default', WP_LANG_DIR . "/admin-network-$locale.mo" );
400
401 }
402
403 /**
404  * Loads the plugin's translated strings.
405  *
406  * If the path is not given then it will be the root of the plugin directory.
407  * The .mo file should be named based on the domain with a dash, and then the locale exactly.
408  *
409  * @since 1.5.0
410  *
411  * @param string $domain Unique identifier for retrieving translated strings
412  * @param string $abs_rel_path Optional. Relative path to ABSPATH of a folder,
413  *      where the .mo file resides. Deprecated, but still functional until 2.7
414  * @param string $plugin_rel_path Optional. Relative path to WP_PLUGIN_DIR. This is the preferred argument to use. It takes precedence over $abs_rel_path
415  */
416 function load_plugin_textdomain( $domain, $abs_rel_path = false, $plugin_rel_path = false ) {
417         $locale = apply_filters( 'plugin_locale', get_locale(), $domain );
418
419         if ( false !== $plugin_rel_path ) {
420                 $path = WP_PLUGIN_DIR . '/' . trim( $plugin_rel_path, '/' );
421         } else if ( false !== $abs_rel_path ) {
422                 _deprecated_argument( __FUNCTION__, '2.7' );
423                 $path = ABSPATH . trim( $abs_rel_path, '/' );
424         } else {
425                 $path = WP_PLUGIN_DIR;
426         }
427
428         $mofile = $path . '/'. $domain . '-' . $locale . '.mo';
429         return load_textdomain( $domain, $mofile );
430 }
431
432 /**
433  * Load the translated strings for a plugin residing in the mu-plugins dir.
434  *
435  * @since 3.0.0
436  *
437  * @param string $domain Unique identifier for retrieving translated strings
438  * @param string $mu_plugin_rel_path Relative to WPMU_PLUGIN_DIR directory in which
439  * the MO file resides. Defaults to empty string.
440  */
441 function load_muplugin_textdomain( $domain, $mu_plugin_rel_path = '' ) {
442         $locale = apply_filters( 'plugin_locale', get_locale(), $domain );
443         $path = WPMU_PLUGIN_DIR . '/' . ltrim( $mu_plugin_rel_path, '/' );
444         load_textdomain( $domain, trailingslashit( $path ) . "$domain-$locale.mo" );
445 }
446
447 /**
448  * Loads the theme's translated strings.
449  *
450  * If the current locale exists as a .mo file in the theme's root directory, it
451  * will be included in the translated strings by the $domain.
452  *
453  * The .mo files must be named based on the locale exactly.
454  *
455  * @since 1.5.0
456  *
457  * @param string $domain Unique identifier for retrieving translated strings
458  */
459 function load_theme_textdomain( $domain, $path = false ) {
460         $locale = apply_filters( 'theme_locale', get_locale(), $domain );
461
462         $path = ( empty( $path ) ) ? get_template_directory() : $path;
463
464         $mofile = "$path/$locale.mo";
465         return load_textdomain($domain, $mofile);
466 }
467
468 /**
469  * Loads the child themes translated strings.
470  *
471  * If the current locale exists as a .mo file in the child themes root directory, it
472  * will be included in the translated strings by the $domain.
473  *
474  * The .mo files must be named based on the locale exactly.
475  *
476  * @since 2.9.0
477  *
478  * @param string $domain Unique identifier for retrieving translated strings
479  */
480 function load_child_theme_textdomain( $domain, $path = false ) {
481         $locale = apply_filters( 'theme_locale', get_locale(), $domain );
482
483         $path = ( empty( $path ) ) ? get_stylesheet_directory() : $path;
484
485         $mofile = "$path/$locale.mo";
486         return load_textdomain($domain, $mofile);
487 }
488
489 /**
490  * Returns the Translations instance for a domain. If there isn't one,
491  * returns empty Translations instance.
492  *
493  * @param string $domain
494  * @return object A Translation instance
495  */
496 function &get_translations_for_domain( $domain ) {
497         global $l10n;
498         if ( !isset( $l10n[$domain] ) ) {
499                 $l10n[$domain] = new NOOP_Translations;
500         }
501         return $l10n[$domain];
502 }
503
504 /**
505  * Whether there are translations for the domain
506  *
507  * @since 3.0.0
508  * @param string $domain
509  * @return bool Whether there are translations
510  */
511 function is_textdomain_loaded( $domain ) {
512         global $l10n;
513         return isset( $l10n[$domain] );
514 }
515
516 /**
517  * Translates role name. Since the role names are in the database and
518  * not in the source there are dummy gettext calls to get them into the POT
519  * file and this function properly translates them back.
520  *
521  * The before_last_bar() call is needed, because older installs keep the roles
522  * using the old context format: 'Role name|User role' and just skipping the
523  * content after the last bar is easier than fixing them in the DB. New installs
524  * won't suffer from that problem.
525  */
526 function translate_user_role( $name ) {
527         return translate_with_gettext_context( before_last_bar($name), 'User role' );
528 }
529
530 /**
531  * Get all available languages based on the presence of *.mo files in a given directory. The default directory is WP_LANG_DIR.
532  *
533  * @since 3.0.0
534  *
535  * @param string $dir A directory in which to search for language files. The default directory is WP_LANG_DIR.
536  * @return array 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.
537  */
538 function get_available_languages( $dir = null ) {
539         $languages = array();
540
541         foreach( (array)glob( ( is_null( $dir) ? WP_LANG_DIR : $dir ) . '/*.mo' ) as $lang_file ) {
542                 $lang_file = basename($lang_file, '.mo');
543                 if ( 0 !== strpos( $lang_file, 'continents-cities' ) && 0 !== strpos( $lang_file, 'ms-' ) &&
544                         0 !== strpos( $lang_file, 'admin-' ))
545                         $languages[] = $lang_file;
546         }
547
548         return $languages;
549 }