WordPress 3.3.2-scripts
[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  * @return array array($singular, $plural)
276  */
277 function _n_noop( $singular, $plural ) {
278         return array( 0 => $singular, 1 => $plural, 'singular' => $singular, 'plural' => $plural, 'context' => null );
279 }
280
281 /**
282  * Register plural strings with context in POT file, but don't translate them.
283  *
284  * @see _n_noop()
285  */
286 function _nx_noop( $singular, $plural, $context ) {
287         return array( 0 => $singular, 1 => $plural, 2 => $context, 'singular' => $singular, 'plural' => $plural, 'context' => $context );
288 }
289
290 /**
291  * Translate the result of _n_noop() or _nx_noop()
292  *
293  * @since 3.1
294  * @param array $nooped_plural Array with singular, plural and context keys, usually the result of _n_noop() or _nx_noop()
295  * @param int $count Number of objects
296  * @param string $domain Optional. The domain identifier the text should be retrieved in
297  */
298 function translate_nooped_plural( $nooped_plural, $count, $domain = 'default' ) {
299         if ( $nooped_plural['context'] )
300                 return _nx( $nooped_plural['singular'], $nooped_plural['plural'], $count, $nooped_plural['context'], $domain );
301         else
302                 return _n( $nooped_plural['singular'], $nooped_plural['plural'], $count, $domain );
303 }
304
305 /**
306  * Loads a MO file into the domain $domain.
307  *
308  * If the domain already exists, the translations will be merged. If both
309  * sets have the same string, the translation from the original value will be taken.
310  *
311  * On success, the .mo file will be placed in the $l10n global by $domain
312  * and will be a MO object.
313  *
314  * @since 1.5.0
315  * @uses $l10n Gets list of domain translated string objects
316  *
317  * @param string $domain Unique identifier for retrieving translated strings
318  * @param string $mofile Path to the .mo file
319  * @return bool True on success, false on failure
320  */
321 function load_textdomain( $domain, $mofile ) {
322         global $l10n;
323
324         $plugin_override = apply_filters( 'override_load_textdomain', false, $domain, $mofile );
325
326         if ( true == $plugin_override ) {
327                 return true;
328         }
329
330         do_action( 'load_textdomain', $domain, $mofile );
331
332         $mofile = apply_filters( 'load_textdomain_mofile', $mofile, $domain );
333
334         if ( !is_readable( $mofile ) ) return false;
335
336         $mo = new MO();
337         if ( !$mo->import_from_file( $mofile ) ) return false;
338
339         if ( isset( $l10n[$domain] ) )
340                 $mo->merge_with( $l10n[$domain] );
341
342         $l10n[$domain] = &$mo;
343
344         return true;
345 }
346
347 /**
348  * Unloads translations for a domain
349  *
350  * @since 3.0.0
351  * @param string $domain Textdomain to be unloaded
352  * @return bool Whether textdomain was unloaded
353  */
354 function unload_textdomain( $domain ) {
355         global $l10n;
356
357         $plugin_override = apply_filters( 'override_unload_textdomain', false, $domain );
358
359         if ( $plugin_override )
360                 return true;
361
362         do_action( 'unload_textdomain', $domain );
363
364         if ( isset( $l10n[$domain] ) ) {
365                 unset( $l10n[$domain] );
366                 return true;
367         }
368
369         return false;
370 }
371
372 /**
373  * Loads default translated strings based on locale.
374  *
375  * Loads the .mo file in WP_LANG_DIR constant path from WordPress root. The
376  * translated (.mo) file is named based on the locale.
377  *
378  * @since 1.5.0
379  */
380 function load_default_textdomain() {
381         $locale = get_locale();
382
383         load_textdomain( 'default', WP_LANG_DIR . "/$locale.mo" );
384
385         if ( is_multisite() || ( defined( 'WP_INSTALLING_NETWORK' ) && WP_INSTALLING_NETWORK ) ) {
386                 load_textdomain( 'default', WP_LANG_DIR . "/ms-$locale.mo" );
387         }
388 }
389
390 /**
391  * Loads the plugin's translated strings.
392  *
393  * If the path is not given then it will be the root of the plugin directory.
394  * The .mo file should be named based on the domain with a dash, and then the locale exactly.
395  *
396  * @since 1.5.0
397  *
398  * @param string $domain Unique identifier for retrieving translated strings
399  * @param string $abs_rel_path Optional. Relative path to ABSPATH of a folder,
400  *      where the .mo file resides. Deprecated, but still functional until 2.7
401  * @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
402  */
403 function load_plugin_textdomain( $domain, $abs_rel_path = false, $plugin_rel_path = false ) {
404         $locale = apply_filters( 'plugin_locale', get_locale(), $domain );
405
406         if ( false !== $plugin_rel_path ) {
407                 $path = WP_PLUGIN_DIR . '/' . trim( $plugin_rel_path, '/' );
408         } else if ( false !== $abs_rel_path ) {
409                 _deprecated_argument( __FUNCTION__, '2.7' );
410                 $path = ABSPATH . trim( $abs_rel_path, '/' );
411         } else {
412                 $path = WP_PLUGIN_DIR;
413         }
414
415         $mofile = $path . '/'. $domain . '-' . $locale . '.mo';
416         return load_textdomain( $domain, $mofile );
417 }
418
419 /**
420  * Load the translated strings for a plugin residing in the mu-plugins dir.
421  *
422  * @since 3.0.0
423  *
424  * @param string $domain Unique identifier for retrieving translated strings
425  * @param string $mu_plugin_rel_path Relative to WPMU_PLUGIN_DIR directory in which
426  * the MO file resides. Defaults to empty string.
427  */
428 function load_muplugin_textdomain( $domain, $mu_plugin_rel_path = '' ) {
429         $locale = apply_filters( 'plugin_locale', get_locale(), $domain );
430         $path = WPMU_PLUGIN_DIR . '/' . ltrim( $mu_plugin_rel_path, '/' );
431         load_textdomain( $domain, trailingslashit( $path ) . "$domain-$locale.mo" );
432 }
433
434 /**
435  * Loads the theme's translated strings.
436  *
437  * If the current locale exists as a .mo file in the theme's root directory, it
438  * will be included in the translated strings by the $domain.
439  *
440  * The .mo files must be named based on the locale exactly.
441  *
442  * @since 1.5.0
443  *
444  * @param string $domain Unique identifier for retrieving translated strings
445  */
446 function load_theme_textdomain( $domain, $path = false ) {
447         $locale = apply_filters( 'theme_locale', get_locale(), $domain );
448
449         $path = ( empty( $path ) ) ? get_template_directory() : $path;
450
451         $mofile = "$path/$locale.mo";
452         return load_textdomain($domain, $mofile);
453 }
454
455 /**
456  * Loads the child themes translated strings.
457  *
458  * If the current locale exists as a .mo file in the child themes root directory, it
459  * will be included in the translated strings by the $domain.
460  *
461  * The .mo files must be named based on the locale exactly.
462  *
463  * @since 2.9.0
464  *
465  * @param string $domain Unique identifier for retrieving translated strings
466  */
467 function load_child_theme_textdomain( $domain, $path = false ) {
468         $locale = apply_filters( 'theme_locale', get_locale(), $domain );
469
470         $path = ( empty( $path ) ) ? get_stylesheet_directory() : $path;
471
472         $mofile = "$path/$locale.mo";
473         return load_textdomain($domain, $mofile);
474 }
475
476 /**
477  * Returns the Translations instance for a domain. If there isn't one,
478  * returns empty Translations instance.
479  *
480  * @param string $domain
481  * @return object A Translation instance
482  */
483 function &get_translations_for_domain( $domain ) {
484         global $l10n;
485         if ( !isset( $l10n[$domain] ) ) {
486                 $l10n[$domain] = new NOOP_Translations;
487         }
488         return $l10n[$domain];
489 }
490
491 /**
492  * Whether there are translations for the domain
493  *
494  * @since 3.0.0
495  * @param string $domain
496  * @return bool Whether there are translations
497  */
498 function is_textdomain_loaded( $domain ) {
499         global $l10n;
500         return isset( $l10n[$domain] );
501 }
502
503 /**
504  * Translates role name. Since the role names are in the database and
505  * not in the source there are dummy gettext calls to get them into the POT
506  * file and this function properly translates them back.
507  *
508  * The before_last_bar() call is needed, because older installs keep the roles
509  * using the old context format: 'Role name|User role' and just skipping the
510  * content after the last bar is easier than fixing them in the DB. New installs
511  * won't suffer from that problem.
512  */
513 function translate_user_role( $name ) {
514         return translate_with_gettext_context( before_last_bar($name), 'User role' );
515 }
516
517 /**
518  * Get all available languages based on the presence of *.mo files in a given directory. The default directory is WP_LANG_DIR.
519  *
520  * @since 3.0.0
521  *
522  * @param string $dir A directory in which to search for language files. The default directory is WP_LANG_DIR.
523  * @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.
524  */
525 function get_available_languages( $dir = null ) {
526         $languages = array();
527
528         foreach( (array)glob( ( is_null( $dir) ? WP_LANG_DIR : $dir ) . '/*.mo' ) as $lang_file ) {
529                 $lang_file = basename($lang_file, '.mo');
530                 if ( 0 !== strpos( $lang_file, 'continents-cities' ) && 0 !== strpos( $lang_file, 'ms-' ) )
531                         $languages[] = $lang_file;
532         }
533
534         return $languages;
535 }