[ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Core Translation API 4 * 5 * @package WordPress 6 * @subpackage i18n 7 * @since 1.2.0 8 */ 9 10 /** 11 * Retrieves the current locale. 12 * 13 * If the locale is set, then it will filter the locale in the {@see 'locale'} 14 * filter hook and return the value. 15 * 16 * If the locale is not set already, then the WPLANG constant is used if it is 17 * defined. Then it is filtered through the {@see 'locale'} filter hook and 18 * the value for the locale global set and the locale is returned. 19 * 20 * The process to get the locale should only be done once, but the locale will 21 * always be filtered using the {@see 'locale'} hook. 22 * 23 * @since 1.5.0 24 * 25 * @global string $locale The current locale. 26 * @global string $wp_local_package Locale code of the package. 27 * 28 * @return string The locale of the blog or from the {@see 'locale'} hook. 29 */ 30 function get_locale() { 31 global $locale, $wp_local_package; 32 33 if ( isset( $locale ) ) { 34 /** This filter is documented in wp-includes/l10n.php */ 35 return apply_filters( 'locale', $locale ); 36 } 37 38 if ( isset( $wp_local_package ) ) { 39 $locale = $wp_local_package; 40 } 41 42 // WPLANG was defined in wp-config. 43 if ( defined( 'WPLANG' ) ) { 44 $locale = WPLANG; 45 } 46 47 // If multisite, check options. 48 if ( is_multisite() ) { 49 // Don't check blog option when installing. 50 if ( wp_installing() ) { 51 $ms_locale = get_site_option( 'WPLANG' ); 52 } else { 53 $ms_locale = get_option( 'WPLANG' ); 54 if ( false === $ms_locale ) { 55 $ms_locale = get_site_option( 'WPLANG' ); 56 } 57 } 58 59 if ( false !== $ms_locale ) { 60 $locale = $ms_locale; 61 } 62 } else { 63 $db_locale = get_option( 'WPLANG' ); 64 if ( false !== $db_locale ) { 65 $locale = $db_locale; 66 } 67 } 68 69 if ( empty( $locale ) ) { 70 $locale = 'en_US'; 71 } 72 73 /** 74 * Filters the locale ID of the WordPress installation. 75 * 76 * @since 1.5.0 77 * 78 * @param string $locale The locale ID. 79 */ 80 return apply_filters( 'locale', $locale ); 81 } 82 83 /** 84 * Retrieves the locale of a user. 85 * 86 * If the user has a locale set to a non-empty string then it will be 87 * returned. Otherwise it returns the locale of get_locale(). 88 * 89 * @since 4.7.0 90 * 91 * @param int|WP_User $user_id User's ID or a WP_User object. Defaults to current user. 92 * @return string The locale of the user. 93 */ 94 function get_user_locale( $user_id = 0 ) { 95 $user = false; 96 if ( 0 === $user_id && function_exists( 'wp_get_current_user' ) ) { 97 $user = wp_get_current_user(); 98 } elseif ( $user_id instanceof WP_User ) { 99 $user = $user_id; 100 } elseif ( $user_id && is_numeric( $user_id ) ) { 101 $user = get_user_by( 'id', $user_id ); 102 } 103 104 if ( ! $user ) { 105 return get_locale(); 106 } 107 108 $locale = $user->locale; 109 return $locale ? $locale : get_locale(); 110 } 111 112 /** 113 * Determines the current locale desired for the request. 114 * 115 * @since 5.0.0 116 * 117 * @global string $pagenow The filename of the current screen. 118 * 119 * @return string The determined locale. 120 */ 121 function determine_locale() { 122 /** 123 * Filters the locale for the current request prior to the default determination process. 124 * 125 * Using this filter allows to override the default logic, effectively short-circuiting the function. 126 * 127 * @since 5.0.0 128 * 129 * @param string|null $locale The locale to return and short-circuit. Default null. 130 */ 131 $determined_locale = apply_filters( 'pre_determine_locale', null ); 132 133 if ( ! empty( $determined_locale ) && is_string( $determined_locale ) ) { 134 return $determined_locale; 135 } 136 137 $determined_locale = get_locale(); 138 139 if ( is_admin() ) { 140 $determined_locale = get_user_locale(); 141 } 142 143 if ( isset( $_GET['_locale'] ) && 'user' === $_GET['_locale'] && wp_is_json_request() ) { 144 $determined_locale = get_user_locale(); 145 } 146 147 $wp_lang = ''; 148 149 if ( ! empty( $_GET['wp_lang'] ) ) { 150 $wp_lang = sanitize_text_field( $_GET['wp_lang'] ); 151 } elseif ( ! empty( $_COOKIE['wp_lang'] ) ) { 152 $wp_lang = sanitize_text_field( $_COOKIE['wp_lang'] ); 153 } 154 155 if ( ! empty( $wp_lang ) && ! empty( $GLOBALS['pagenow'] ) && 'wp-login.php' === $GLOBALS['pagenow'] ) { 156 $determined_locale = $wp_lang; 157 } 158 159 /** 160 * Filters the locale for the current request. 161 * 162 * @since 5.0.0 163 * 164 * @param string $locale The locale. 165 */ 166 return apply_filters( 'determine_locale', $determined_locale ); 167 } 168 169 /** 170 * Retrieves the translation of $text. 171 * 172 * If there is no translation, or the text domain isn't loaded, the original text is returned. 173 * 174 * *Note:* Don't use translate() directly, use __() or related functions. 175 * 176 * @since 2.2.0 177 * @since 5.5.0 Introduced gettext-{$domain} filter. 178 * 179 * @param string $text Text to translate. 180 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. 181 * Default 'default'. 182 * @return string Translated text. 183 */ 184 function translate( $text, $domain = 'default' ) { 185 $translations = get_translations_for_domain( $domain ); 186 $translation = $translations->translate( $text ); 187 188 /** 189 * Filters text with its translation. 190 * 191 * @since 2.0.11 192 * 193 * @param string $translation Translated text. 194 * @param string $text Text to translate. 195 * @param string $domain Text domain. Unique identifier for retrieving translated strings. 196 */ 197 $translation = apply_filters( 'gettext', $translation, $text, $domain ); 198 199 /** 200 * Filters text with its translation for a domain. 201 * 202 * The dynamic portion of the hook name, `$domain`, refers to the text domain. 203 * 204 * @since 5.5.0 205 * 206 * @param string $translation Translated text. 207 * @param string $text Text to translate. 208 * @param string $domain Text domain. Unique identifier for retrieving translated strings. 209 */ 210 $translation = apply_filters( "gettext_{$domain}", $translation, $text, $domain ); 211 212 return $translation; 213 } 214 215 /** 216 * Removes last item on a pipe-delimited string. 217 * 218 * Meant for removing the last item in a string, such as 'Role name|User role'. The original 219 * string will be returned if no pipe '|' characters are found in the string. 220 * 221 * @since 2.8.0 222 * 223 * @param string $string A pipe-delimited string. 224 * @return string Either $string or everything before the last pipe. 225 */ 226 function before_last_bar( $string ) { 227 $last_bar = strrpos( $string, '|' ); 228 if ( false === $last_bar ) { 229 return $string; 230 } else { 231 return substr( $string, 0, $last_bar ); 232 } 233 } 234 235 /** 236 * Retrieves the translation of $text in the context defined in $context. 237 * 238 * If there is no translation, or the text domain isn't loaded, the original text is returned. 239 * 240 * *Note:* Don't use translate_with_gettext_context() directly, use _x() or related functions. 241 * 242 * @since 2.8.0 243 * @since 5.5.0 Introduced gettext_with_context-{$domain} filter. 244 * 245 * @param string $text Text to translate. 246 * @param string $context Context information for the translators. 247 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. 248 * Default 'default'. 249 * @return string Translated text on success, original text on failure. 250 */ 251 function translate_with_gettext_context( $text, $context, $domain = 'default' ) { 252 $translations = get_translations_for_domain( $domain ); 253 $translation = $translations->translate( $text, $context ); 254 255 /** 256 * Filters text with its translation based on context information. 257 * 258 * @since 2.8.0 259 * 260 * @param string $translation Translated text. 261 * @param string $text Text to translate. 262 * @param string $context Context information for the translators. 263 * @param string $domain Text domain. Unique identifier for retrieving translated strings. 264 */ 265 $translation = apply_filters( 'gettext_with_context', $translation, $text, $context, $domain ); 266 267 /** 268 * Filters text with its translation based on context information for a domain. 269 * 270 * The dynamic portion of the hook name, `$domain`, refers to the text domain. 271 * 272 * @since 5.5.0 273 * 274 * @param string $translation Translated text. 275 * @param string $text Text to translate. 276 * @param string $context Context information for the translators. 277 * @param string $domain Text domain. Unique identifier for retrieving translated strings. 278 */ 279 $translation = apply_filters( "gettext_with_context_{$domain}", $translation, $text, $context, $domain ); 280 281 return $translation; 282 } 283 284 /** 285 * Retrieves the translation of $text. 286 * 287 * If there is no translation, or the text domain isn't loaded, the original text is returned. 288 * 289 * @since 2.1.0 290 * 291 * @param string $text Text to translate. 292 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. 293 * Default 'default'. 294 * @return string Translated text. 295 */ 296 function __( $text, $domain = 'default' ) { 297 return translate( $text, $domain ); 298 } 299 300 /** 301 * Retrieves the translation of $text and escapes it for safe use in an attribute. 302 * 303 * If there is no translation, or the text domain isn't loaded, the original text is returned. 304 * 305 * @since 2.8.0 306 * 307 * @param string $text Text to translate. 308 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. 309 * Default 'default'. 310 * @return string Translated text on success, original text on failure. 311 */ 312 function esc_attr__( $text, $domain = 'default' ) { 313 return esc_attr( translate( $text, $domain ) ); 314 } 315 316 /** 317 * Retrieves the translation of $text and escapes it for safe use in HTML output. 318 * 319 * If there is no translation, or the text domain isn't loaded, the original text 320 * is escaped and returned. 321 * 322 * @since 2.8.0 323 * 324 * @param string $text Text to translate. 325 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. 326 * Default 'default'. 327 * @return string Translated text. 328 */ 329 function esc_html__( $text, $domain = 'default' ) { 330 return esc_html( translate( $text, $domain ) ); 331 } 332 333 /** 334 * Displays translated text. 335 * 336 * @since 1.2.0 337 * 338 * @param string $text Text to translate. 339 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. 340 * Default 'default'. 341 */ 342 function _e( $text, $domain = 'default' ) { 343 echo translate( $text, $domain ); 344 } 345 346 /** 347 * Displays translated text that has been escaped for safe use in an attribute. 348 * 349 * Encodes `< > & " '` (less than, greater than, ampersand, double quote, single quote). 350 * Will never double encode entities. 351 * 352 * If you need the value for use in PHP, use esc_attr__(). 353 * 354 * @since 2.8.0 355 * 356 * @param string $text Text to translate. 357 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. 358 * Default 'default'. 359 */ 360 function esc_attr_e( $text, $domain = 'default' ) { 361 echo esc_attr( translate( $text, $domain ) ); 362 } 363 364 /** 365 * Displays translated text that has been escaped for safe use in HTML output. 366 * 367 * If there is no translation, or the text domain isn't loaded, the original text 368 * is escaped and displayed. 369 * 370 * If you need the value for use in PHP, use esc_html__(). 371 * 372 * @since 2.8.0 373 * 374 * @param string $text Text to translate. 375 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. 376 * Default 'default'. 377 */ 378 function esc_html_e( $text, $domain = 'default' ) { 379 echo esc_html( translate( $text, $domain ) ); 380 } 381 382 /** 383 * Retrieves translated string with gettext context. 384 * 385 * Quite a few times, there will be collisions with similar translatable text 386 * found in more than two places, but with different translated context. 387 * 388 * By including the context in the pot file, translators can translate the two 389 * strings differently. 390 * 391 * @since 2.8.0 392 * 393 * @param string $text Text to translate. 394 * @param string $context Context information for the translators. 395 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. 396 * Default 'default'. 397 * @return string Translated context string without pipe. 398 */ 399 function _x( $text, $context, $domain = 'default' ) { 400 return translate_with_gettext_context( $text, $context, $domain ); 401 } 402 403 /** 404 * Displays translated string with gettext context. 405 * 406 * @since 3.0.0 407 * 408 * @param string $text Text to translate. 409 * @param string $context Context information for the translators. 410 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. 411 * Default 'default'. 412 */ 413 function _ex( $text, $context, $domain = 'default' ) { 414 echo _x( $text, $context, $domain ); 415 } 416 417 /** 418 * Translates string with gettext context, and escapes it for safe use in an attribute. 419 * 420 * If there is no translation, or the text domain isn't loaded, the original text 421 * is escaped and returned. 422 * 423 * @since 2.8.0 424 * 425 * @param string $text Text to translate. 426 * @param string $context Context information for the translators. 427 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. 428 * Default 'default'. 429 * @return string Translated text. 430 */ 431 function esc_attr_x( $text, $context, $domain = 'default' ) { 432 return esc_attr( translate_with_gettext_context( $text, $context, $domain ) ); 433 } 434 435 /** 436 * Translates string with gettext context, and escapes it for safe use in HTML output. 437 * 438 * If there is no translation, or the text domain isn't loaded, the original text 439 * is escaped and returned. 440 * 441 * @since 2.9.0 442 * 443 * @param string $text Text to translate. 444 * @param string $context Context information for the translators. 445 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. 446 * Default 'default'. 447 * @return string Translated text. 448 */ 449 function esc_html_x( $text, $context, $domain = 'default' ) { 450 return esc_html( translate_with_gettext_context( $text, $context, $domain ) ); 451 } 452 453 /** 454 * Translates and retrieves the singular or plural form based on the supplied number. 455 * 456 * Used when you want to use the appropriate form of a string based on whether a 457 * number is singular or plural. 458 * 459 * Example: 460 * 461 * printf( _n( '%s person', '%s people', $count, 'text-domain' ), number_format_i18n( $count ) ); 462 * 463 * @since 2.8.0 464 * @since 5.5.0 Introduced ngettext-{$domain} filter. 465 * 466 * @param string $single The text to be used if the number is singular. 467 * @param string $plural The text to be used if the number is plural. 468 * @param int $number The number to compare against to use either the singular or plural form. 469 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. 470 * Default 'default'. 471 * @return string The translated singular or plural form. 472 */ 473 function _n( $single, $plural, $number, $domain = 'default' ) { 474 $translations = get_translations_for_domain( $domain ); 475 $translation = $translations->translate_plural( $single, $plural, $number ); 476 477 /** 478 * Filters the singular or plural form of a string. 479 * 480 * @since 2.2.0 481 * 482 * @param string $translation Translated text. 483 * @param string $single The text to be used if the number is singular. 484 * @param string $plural The text to be used if the number is plural. 485 * @param string $number The number to compare against to use either the singular or plural form. 486 * @param string $domain Text domain. Unique identifier for retrieving translated strings. 487 */ 488 $translation = apply_filters( 'ngettext', $translation, $single, $plural, $number, $domain ); 489 490 /** 491 * Filters the singular or plural form of a string for a domain. 492 * 493 * The dynamic portion of the hook name, `$domain`, refers to the text domain. 494 * 495 * @since 5.5.0 496 * 497 * @param string $translation Translated text. 498 * @param string $single The text to be used if the number is singular. 499 * @param string $plural The text to be used if the number is plural. 500 * @param string $number The number to compare against to use either the singular or plural form. 501 * @param string $domain Text domain. Unique identifier for retrieving translated strings. 502 */ 503 $translation = apply_filters( "ngettext_{$domain}", $translation, $single, $plural, $number, $domain ); 504 505 return $translation; 506 } 507 508 /** 509 * Translates and retrieves the singular or plural form based on the supplied number, with gettext context. 510 * 511 * This is a hybrid of _n() and _x(). It supports context and plurals. 512 * 513 * Used when you want to use the appropriate form of a string with context based on whether a 514 * number is singular or plural. 515 * 516 * Example of a generic phrase which is disambiguated via the context parameter: 517 * 518 * printf( _nx( '%s group', '%s groups', $people, 'group of people', 'text-domain' ), number_format_i18n( $people ) ); 519 * printf( _nx( '%s group', '%s groups', $animals, 'group of animals', 'text-domain' ), number_format_i18n( $animals ) ); 520 * 521 * @since 2.8.0 522 * @since 5.5.0 Introduced ngettext_with_context-{$domain} filter. 523 * 524 * @param string $single The text to be used if the number is singular. 525 * @param string $plural The text to be used if the number is plural. 526 * @param int $number The number to compare against to use either the singular or plural form. 527 * @param string $context Context information for the translators. 528 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. 529 * Default 'default'. 530 * @return string The translated singular or plural form. 531 */ 532 function _nx( $single, $plural, $number, $context, $domain = 'default' ) { 533 $translations = get_translations_for_domain( $domain ); 534 $translation = $translations->translate_plural( $single, $plural, $number, $context ); 535 536 /** 537 * Filters the singular or plural form of a string with gettext context. 538 * 539 * @since 2.8.0 540 * 541 * @param string $translation Translated text. 542 * @param string $single The text to be used if the number is singular. 543 * @param string $plural The text to be used if the number is plural. 544 * @param string $number The number to compare against to use either the singular or plural form. 545 * @param string $context Context information for the translators. 546 * @param string $domain Text domain. Unique identifier for retrieving translated strings. 547 */ 548 $translation = apply_filters( 'ngettext_with_context', $translation, $single, $plural, $number, $context, $domain ); 549 550 /** 551 * Filters the singular or plural form of a string with gettext context for a domain. 552 * 553 * The dynamic portion of the hook name, `$domain`, refers to the text domain. 554 * 555 * @since 5.5.0 556 * 557 * @param string $translation Translated text. 558 * @param string $single The text to be used if the number is singular. 559 * @param string $plural The text to be used if the number is plural. 560 * @param string $number The number to compare against to use either the singular or plural form. 561 * @param string $context Context information for the translators. 562 * @param string $domain Text domain. Unique identifier for retrieving translated strings. 563 */ 564 $translation = apply_filters( "ngettext_with_context_{$domain}", $translation, $single, $plural, $number, $context, $domain ); 565 566 return $translation; 567 } 568 569 /** 570 * Registers plural strings in POT file, but does not translate them. 571 * 572 * Used when you want to keep structures with translatable plural 573 * strings and use them later when the number is known. 574 * 575 * Example: 576 * 577 * $message = _n_noop( '%s post', '%s posts', 'text-domain' ); 578 * ... 579 * printf( translate_nooped_plural( $message, $count, 'text-domain' ), number_format_i18n( $count ) ); 580 * 581 * @since 2.5.0 582 * 583 * @param string $singular Singular form to be localized. 584 * @param string $plural Plural form to be localized. 585 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. 586 * Default null. 587 * @return array { 588 * Array of translation information for the strings. 589 * 590 * @type string $0 Singular form to be localized. No longer used. 591 * @type string $1 Plural form to be localized. No longer used. 592 * @type string $singular Singular form to be localized. 593 * @type string $plural Plural form to be localized. 594 * @type null $context Context information for the translators. 595 * @type string|null $domain Text domain. 596 * } 597 */ 598 function _n_noop( $singular, $plural, $domain = null ) { 599 return array( 600 0 => $singular, 601 1 => $plural, 602 'singular' => $singular, 603 'plural' => $plural, 604 'context' => null, 605 'domain' => $domain, 606 ); 607 } 608 609 /** 610 * Registers plural strings with gettext context in POT file, but does not translate them. 611 * 612 * Used when you want to keep structures with translatable plural 613 * strings and use them later when the number is known. 614 * 615 * Example of a generic phrase which is disambiguated via the context parameter: 616 * 617 * $messages = array( 618 * 'people' => _nx_noop( '%s group', '%s groups', 'people', 'text-domain' ), 619 * 'animals' => _nx_noop( '%s group', '%s groups', 'animals', 'text-domain' ), 620 * ); 621 * ... 622 * $message = $messages[ $type ]; 623 * printf( translate_nooped_plural( $message, $count, 'text-domain' ), number_format_i18n( $count ) ); 624 * 625 * @since 2.8.0 626 * 627 * @param string $singular Singular form to be localized. 628 * @param string $plural Plural form to be localized. 629 * @param string $context Context information for the translators. 630 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. 631 * Default null. 632 * @return array { 633 * Array of translation information for the strings. 634 * 635 * @type string $0 Singular form to be localized. No longer used. 636 * @type string $1 Plural form to be localized. No longer used. 637 * @type string $2 Context information for the translators. No longer used. 638 * @type string $singular Singular form to be localized. 639 * @type string $plural Plural form to be localized. 640 * @type string $context Context information for the translators. 641 * @type string|null $domain Text domain. 642 * } 643 */ 644 function _nx_noop( $singular, $plural, $context, $domain = null ) { 645 return array( 646 0 => $singular, 647 1 => $plural, 648 2 => $context, 649 'singular' => $singular, 650 'plural' => $plural, 651 'context' => $context, 652 'domain' => $domain, 653 ); 654 } 655 656 /** 657 * Translates and returns the singular or plural form of a string that's been registered 658 * with _n_noop() or _nx_noop(). 659 * 660 * Used when you want to use a translatable plural string once the number is known. 661 * 662 * Example: 663 * 664 * $message = _n_noop( '%s post', '%s posts', 'text-domain' ); 665 * ... 666 * printf( translate_nooped_plural( $message, $count, 'text-domain' ), number_format_i18n( $count ) ); 667 * 668 * @since 3.1.0 669 * 670 * @param array $nooped_plural { 671 * Array that is usually a return value from _n_noop() or _nx_noop(). 672 * 673 * @type string $singular Singular form to be localized. 674 * @type string $plural Plural form to be localized. 675 * @type string|null $context Context information for the translators. 676 * @type string|null $domain Text domain. 677 * } 678 * @param int $count Number of objects. 679 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. If $nooped_plural contains 680 * a text domain passed to _n_noop() or _nx_noop(), it will override this value. Default 'default'. 681 * @return string Either $singular or $plural translated text. 682 */ 683 function translate_nooped_plural( $nooped_plural, $count, $domain = 'default' ) { 684 if ( $nooped_plural['domain'] ) { 685 $domain = $nooped_plural['domain']; 686 } 687 688 if ( $nooped_plural['context'] ) { 689 return _nx( $nooped_plural['singular'], $nooped_plural['plural'], $count, $nooped_plural['context'], $domain ); 690 } else { 691 return _n( $nooped_plural['singular'], $nooped_plural['plural'], $count, $domain ); 692 } 693 } 694 695 /** 696 * Loads a .mo file into the text domain $domain. 697 * 698 * If the text domain already exists, the translations will be merged. If both 699 * sets have the same string, the translation from the original value will be taken. 700 * 701 * On success, the .mo file will be placed in the $l10n global by $domain 702 * and will be a MO object. 703 * 704 * @since 1.5.0 705 * 706 * @global MO[] $l10n An array of all currently loaded text domains. 707 * @global MO[] $l10n_unloaded An array of all text domains that have been unloaded again. 708 * 709 * @param string $domain Text domain. Unique identifier for retrieving translated strings. 710 * @param string $mofile Path to the .mo file. 711 * @return bool True on success, false on failure. 712 */ 713 function load_textdomain( $domain, $mofile ) { 714 global $l10n, $l10n_unloaded; 715 716 $l10n_unloaded = (array) $l10n_unloaded; 717 718 /** 719 * Filters whether to override the .mo file loading. 720 * 721 * @since 2.9.0 722 * 723 * @param bool $override Whether to override the .mo file loading. Default false. 724 * @param string $domain Text domain. Unique identifier for retrieving translated strings. 725 * @param string $mofile Path to the MO file. 726 */ 727 $plugin_override = apply_filters( 'override_load_textdomain', false, $domain, $mofile ); 728 729 if ( true === (bool) $plugin_override ) { 730 unset( $l10n_unloaded[ $domain ] ); 731 732 return true; 733 } 734 735 /** 736 * Fires before the MO translation file is loaded. 737 * 738 * @since 2.9.0 739 * 740 * @param string $domain Text domain. Unique identifier for retrieving translated strings. 741 * @param string $mofile Path to the .mo file. 742 */ 743 do_action( 'load_textdomain', $domain, $mofile ); 744 745 /** 746 * Filters MO file path for loading translations for a specific text domain. 747 * 748 * @since 2.9.0 749 * 750 * @param string $mofile Path to the MO file. 751 * @param string $domain Text domain. Unique identifier for retrieving translated strings. 752 */ 753 $mofile = apply_filters( 'load_textdomain_mofile', $mofile, $domain ); 754 755 if ( ! is_readable( $mofile ) ) { 756 return false; 757 } 758 759 $mo = new MO(); 760 if ( ! $mo->import_from_file( $mofile ) ) { 761 return false; 762 } 763 764 if ( isset( $l10n[ $domain ] ) ) { 765 $mo->merge_with( $l10n[ $domain ] ); 766 } 767 768 unset( $l10n_unloaded[ $domain ] ); 769 770 $l10n[ $domain ] = &$mo; 771 772 return true; 773 } 774 775 /** 776 * Unloads translations for a text domain. 777 * 778 * @since 3.0.0 779 * 780 * @global MO[] $l10n An array of all currently loaded text domains. 781 * @global MO[] $l10n_unloaded An array of all text domains that have been unloaded again. 782 * 783 * @param string $domain Text domain. Unique identifier for retrieving translated strings. 784 * @return bool Whether textdomain was unloaded. 785 */ 786 function unload_textdomain( $domain ) { 787 global $l10n, $l10n_unloaded; 788 789 $l10n_unloaded = (array) $l10n_unloaded; 790 791 /** 792 * Filters whether to override the text domain unloading. 793 * 794 * @since 3.0.0 795 * 796 * @param bool $override Whether to override the text domain unloading. Default false. 797 * @param string $domain Text domain. Unique identifier for retrieving translated strings. 798 */ 799 $plugin_override = apply_filters( 'override_unload_textdomain', false, $domain ); 800 801 if ( $plugin_override ) { 802 $l10n_unloaded[ $domain ] = true; 803 804 return true; 805 } 806 807 /** 808 * Fires before the text domain is unloaded. 809 * 810 * @since 3.0.0 811 * 812 * @param string $domain Text domain. Unique identifier for retrieving translated strings. 813 */ 814 do_action( 'unload_textdomain', $domain ); 815 816 if ( isset( $l10n[ $domain ] ) ) { 817 unset( $l10n[ $domain ] ); 818 819 $l10n_unloaded[ $domain ] = true; 820 821 return true; 822 } 823 824 return false; 825 } 826 827 /** 828 * Loads default translated strings based on locale. 829 * 830 * Loads the .mo file in WP_LANG_DIR constant path from WordPress root. 831 * The translated (.mo) file is named based on the locale. 832 * 833 * @see load_textdomain() 834 * 835 * @since 1.5.0 836 * 837 * @param string $locale Optional. Locale to load. Default is the value of get_locale(). 838 * @return bool Whether the textdomain was loaded. 839 */ 840 function load_default_textdomain( $locale = null ) { 841 if ( null === $locale ) { 842 $locale = determine_locale(); 843 } 844 845 // Unload previously loaded strings so we can switch translations. 846 unload_textdomain( 'default' ); 847 848 $return = load_textdomain( 'default', WP_LANG_DIR . "/$locale.mo" ); 849 850 if ( ( is_multisite() || ( defined( 'WP_INSTALLING_NETWORK' ) && WP_INSTALLING_NETWORK ) ) && ! file_exists( WP_LANG_DIR . "/admin-$locale.mo" ) ) { 851 load_textdomain( 'default', WP_LANG_DIR . "/ms-$locale.mo" ); 852 return $return; 853 } 854 855 if ( is_admin() || wp_installing() || ( defined( 'WP_REPAIRING' ) && WP_REPAIRING ) ) { 856 load_textdomain( 'default', WP_LANG_DIR . "/admin-$locale.mo" ); 857 } 858 859 if ( is_network_admin() || ( defined( 'WP_INSTALLING_NETWORK' ) && WP_INSTALLING_NETWORK ) ) { 860 load_textdomain( 'default', WP_LANG_DIR . "/admin-network-$locale.mo" ); 861 } 862 863 return $return; 864 } 865 866 /** 867 * Loads a plugin's translated strings. 868 * 869 * If the path is not given then it will be the root of the plugin directory. 870 * 871 * The .mo file should be named based on the text domain with a dash, and then the locale exactly. 872 * 873 * @since 1.5.0 874 * @since 4.6.0 The function now tries to load the .mo file from the languages directory first. 875 * 876 * @param string $domain Unique identifier for retrieving translated strings 877 * @param string|false $deprecated Optional. Deprecated. Use the $plugin_rel_path parameter instead. 878 * Default false. 879 * @param string|false $plugin_rel_path Optional. Relative path to WP_PLUGIN_DIR where the .mo file resides. 880 * Default false. 881 * @return bool True when textdomain is successfully loaded, false otherwise. 882 */ 883 function load_plugin_textdomain( $domain, $deprecated = false, $plugin_rel_path = false ) { 884 /** 885 * Filters a plugin's locale. 886 * 887 * @since 3.0.0 888 * 889 * @param string $locale The plugin's current locale. 890 * @param string $domain Text domain. Unique identifier for retrieving translated strings. 891 */ 892 $locale = apply_filters( 'plugin_locale', determine_locale(), $domain ); 893 894 $mofile = $domain . '-' . $locale . '.mo'; 895 896 // Try to load from the languages directory first. 897 if ( load_textdomain( $domain, WP_LANG_DIR . '/plugins/' . $mofile ) ) { 898 return true; 899 } 900 901 if ( false !== $plugin_rel_path ) { 902 $path = WP_PLUGIN_DIR . '/' . trim( $plugin_rel_path, '/' ); 903 } elseif ( false !== $deprecated ) { 904 _deprecated_argument( __FUNCTION__, '2.7.0' ); 905 $path = ABSPATH . trim( $deprecated, '/' ); 906 } else { 907 $path = WP_PLUGIN_DIR; 908 } 909 910 return load_textdomain( $domain, $path . '/' . $mofile ); 911 } 912 913 /** 914 * Loads the translated strings for a plugin residing in the mu-plugins directory. 915 * 916 * @since 3.0.0 917 * @since 4.6.0 The function now tries to load the .mo file from the languages directory first. 918 * 919 * @param string $domain Text domain. Unique identifier for retrieving translated strings. 920 * @param string $mu_plugin_rel_path Optional. Relative to `WPMU_PLUGIN_DIR` directory in which the .mo 921 * file resides. Default empty string. 922 * @return bool True when textdomain is successfully loaded, false otherwise. 923 */ 924 function load_muplugin_textdomain( $domain, $mu_plugin_rel_path = '' ) { 925 /** This filter is documented in wp-includes/l10n.php */ 926 $locale = apply_filters( 'plugin_locale', determine_locale(), $domain ); 927 928 $mofile = $domain . '-' . $locale . '.mo'; 929 930 // Try to load from the languages directory first. 931 if ( load_textdomain( $domain, WP_LANG_DIR . '/plugins/' . $mofile ) ) { 932 return true; 933 } 934 935 $path = WPMU_PLUGIN_DIR . '/' . ltrim( $mu_plugin_rel_path, '/' ); 936 937 return load_textdomain( $domain, $path . '/' . $mofile ); 938 } 939 940 /** 941 * Loads the theme's translated strings. 942 * 943 * If the current locale exists as a .mo file in the theme's root directory, it 944 * will be included in the translated strings by the $domain. 945 * 946 * The .mo files must be named based on the locale exactly. 947 * 948 * @since 1.5.0 949 * @since 4.6.0 The function now tries to load the .mo file from the languages directory first. 950 * 951 * @param string $domain Text domain. Unique identifier for retrieving translated strings. 952 * @param string|false $path Optional. Path to the directory containing the .mo file. 953 * Default false. 954 * @return bool True when textdomain is successfully loaded, false otherwise. 955 */ 956 function load_theme_textdomain( $domain, $path = false ) { 957 /** 958 * Filters a theme's locale. 959 * 960 * @since 3.0.0 961 * 962 * @param string $locale The theme's current locale. 963 * @param string $domain Text domain. Unique identifier for retrieving translated strings. 964 */ 965 $locale = apply_filters( 'theme_locale', determine_locale(), $domain ); 966 967 $mofile = $domain . '-' . $locale . '.mo'; 968 969 // Try to load from the languages directory first. 970 if ( load_textdomain( $domain, WP_LANG_DIR . '/themes/' . $mofile ) ) { 971 return true; 972 } 973 974 if ( ! $path ) { 975 $path = get_template_directory(); 976 } 977 978 return load_textdomain( $domain, $path . '/' . $locale . '.mo' ); 979 } 980 981 /** 982 * Loads the child themes translated strings. 983 * 984 * If the current locale exists as a .mo file in the child themes 985 * root directory, it will be included in the translated strings by the $domain. 986 * 987 * The .mo files must be named based on the locale exactly. 988 * 989 * @since 2.9.0 990 * 991 * @param string $domain Text domain. Unique identifier for retrieving translated strings. 992 * @param string|false $path Optional. Path to the directory containing the .mo file. 993 * Default false. 994 * @return bool True when the theme textdomain is successfully loaded, false otherwise. 995 */ 996 function load_child_theme_textdomain( $domain, $path = false ) { 997 if ( ! $path ) { 998 $path = get_stylesheet_directory(); 999 } 1000 return load_theme_textdomain( $domain, $path ); 1001 } 1002 1003 /** 1004 * Loads the script translated strings. 1005 * 1006 * @since 5.0.0 1007 * @since 5.0.2 Uses load_script_translations() to load translation data. 1008 * @since 5.1.0 The `$domain` parameter was made optional. 1009 * 1010 * @see WP_Scripts::set_translations() 1011 * 1012 * @param string $handle Name of the script to register a translation domain to. 1013 * @param string $domain Optional. Text domain. Default 'default'. 1014 * @param string $path Optional. The full file path to the directory containing translation files. 1015 * @return string|false The translated strings in JSON encoding on success, 1016 * false if the script textdomain could not be loaded. 1017 */ 1018 function load_script_textdomain( $handle, $domain = 'default', $path = null ) { 1019 $wp_scripts = wp_scripts(); 1020 1021 if ( ! isset( $wp_scripts->registered[ $handle ] ) ) { 1022 return false; 1023 } 1024 1025 $path = untrailingslashit( $path ); 1026 $locale = determine_locale(); 1027 1028 // If a path was given and the handle file exists simply return it. 1029 $file_base = 'default' === $domain ? $locale : $domain . '-' . $locale; 1030 $handle_filename = $file_base . '-' . $handle . '.json'; 1031 1032 if ( $path ) { 1033 $translations = load_script_translations( $path . '/' . $handle_filename, $handle, $domain ); 1034 1035 if ( $translations ) { 1036 return $translations; 1037 } 1038 } 1039 1040 $src = $wp_scripts->registered[ $handle ]->src; 1041 1042 if ( ! preg_match( '|^(https?:)?//|', $src ) && ! ( $wp_scripts->content_url && 0 === strpos( $src, $wp_scripts->content_url ) ) ) { 1043 $src = $wp_scripts->base_url . $src; 1044 } 1045 1046 $relative = false; 1047 $languages_path = WP_LANG_DIR; 1048 1049 $src_url = wp_parse_url( $src ); 1050 $content_url = wp_parse_url( content_url() ); 1051 $plugins_url = wp_parse_url( plugins_url() ); 1052 $site_url = wp_parse_url( site_url() ); 1053 1054 // If the host is the same or it's a relative URL. 1055 if ( 1056 ( ! isset( $content_url['path'] ) || strpos( $src_url['path'], $content_url['path'] ) === 0 ) && 1057 ( ! isset( $src_url['host'] ) || ! isset( $content_url['host'] ) || $src_url['host'] === $content_url['host'] ) 1058 ) { 1059 // Make the src relative the specific plugin or theme. 1060 if ( isset( $content_url['path'] ) ) { 1061 $relative = substr( $src_url['path'], strlen( $content_url['path'] ) ); 1062 } else { 1063 $relative = $src_url['path']; 1064 } 1065 $relative = trim( $relative, '/' ); 1066 $relative = explode( '/', $relative ); 1067 1068 $languages_path = WP_LANG_DIR . '/' . $relative[0]; 1069 1070 $relative = array_slice( $relative, 2 ); // Remove plugins/<plugin name> or themes/<theme name>. 1071 $relative = implode( '/', $relative ); 1072 } elseif ( 1073 ( ! isset( $plugins_url['path'] ) || strpos( $src_url['path'], $plugins_url['path'] ) === 0 ) && 1074 ( ! isset( $src_url['host'] ) || ! isset( $plugins_url['host'] ) || $src_url['host'] === $plugins_url['host'] ) 1075 ) { 1076 // Make the src relative the specific plugin. 1077 if ( isset( $plugins_url['path'] ) ) { 1078 $relative = substr( $src_url['path'], strlen( $plugins_url['path'] ) ); 1079 } else { 1080 $relative = $src_url['path']; 1081 } 1082 $relative = trim( $relative, '/' ); 1083 $relative = explode( '/', $relative ); 1084 1085 $languages_path = WP_LANG_DIR . '/plugins'; 1086 1087 $relative = array_slice( $relative, 1 ); // Remove <plugin name>. 1088 $relative = implode( '/', $relative ); 1089 } elseif ( ! isset( $src_url['host'] ) || ! isset( $site_url['host'] ) || $src_url['host'] === $site_url['host'] ) { 1090 if ( ! isset( $site_url['path'] ) ) { 1091 $relative = trim( $src_url['path'], '/' ); 1092 } elseif ( ( strpos( $src_url['path'], trailingslashit( $site_url['path'] ) ) === 0 ) ) { 1093 // Make the src relative to the WP root. 1094 $relative = substr( $src_url['path'], strlen( $site_url['path'] ) ); 1095 $relative = trim( $relative, '/' ); 1096 } 1097 } 1098 1099 /** 1100 * Filters the relative path of scripts used for finding translation files. 1101 * 1102 * @since 5.0.2 1103 * 1104 * @param string|false $relative The relative path of the script. False if it could not be determined. 1105 * @param string $src The full source URL of the script. 1106 */ 1107 $relative = apply_filters( 'load_script_textdomain_relative_path', $relative, $src ); 1108 1109 // If the source is not from WP. 1110 if ( false === $relative ) { 1111 return load_script_translations( false, $handle, $domain ); 1112 } 1113 1114 // Translations are always based on the unminified filename. 1115 if ( substr( $relative, -7 ) === '.min.js' ) { 1116 $relative = substr( $relative, 0, -7 ) . '.js'; 1117 } 1118 1119 $md5_filename = $file_base . '-' . md5( $relative ) . '.json'; 1120 1121 if ( $path ) { 1122 $translations = load_script_translations( $path . '/' . $md5_filename, $handle, $domain ); 1123 1124 if ( $translations ) { 1125 return $translations; 1126 } 1127 } 1128 1129 $translations = load_script_translations( $languages_path . '/' . $md5_filename, $handle, $domain ); 1130 1131 if ( $translations ) { 1132 return $translations; 1133 } 1134 1135 return load_script_translations( false, $handle, $domain ); 1136 } 1137 1138 /** 1139 * Loads the translation data for the given script handle and text domain. 1140 * 1141 * @since 5.0.2 1142 * 1143 * @param string|false $file Path to the translation file to load. False if there isn't one. 1144 * @param string $handle Name of the script to register a translation domain to. 1145 * @param string $domain The text domain. 1146 * @return string|false The JSON-encoded translated strings for the given script handle and text domain. 1147 * False if there are none. 1148 */ 1149 function load_script_translations( $file, $handle, $domain ) { 1150 /** 1151 * Pre-filters script translations for the given file, script handle and text domain. 1152 * 1153 * Returning a non-null value allows to override the default logic, effectively short-circuiting the function. 1154 * 1155 * @since 5.0.2 1156 * 1157 * @param string|false|null $translations JSON-encoded translation data. Default null. 1158 * @param string|false $file Path to the translation file to load. False if there isn't one. 1159 * @param string $handle Name of the script to register a translation domain to. 1160 * @param string $domain The text domain. 1161 */ 1162 $translations = apply_filters( 'pre_load_script_translations', null, $file, $handle, $domain ); 1163 1164 if ( null !== $translations ) { 1165 return $translations; 1166 } 1167 1168 /** 1169 * Filters the file path for loading script translations for the given script handle and text domain. 1170 * 1171 * @since 5.0.2 1172 * 1173 * @param string|false $file Path to the translation file to load. False if there isn't one. 1174 * @param string $handle Name of the script to register a translation domain to. 1175 * @param string $domain The text domain. 1176 */ 1177 $file = apply_filters( 'load_script_translation_file', $file, $handle, $domain ); 1178 1179 if ( ! $file || ! is_readable( $file ) ) { 1180 return false; 1181 } 1182 1183 $translations = file_get_contents( $file ); 1184 1185 /** 1186 * Filters script translations for the given file, script handle and text domain. 1187 * 1188 * @since 5.0.2 1189 * 1190 * @param string $translations JSON-encoded translation data. 1191 * @param string $file Path to the translation file that was loaded. 1192 * @param string $handle Name of the script to register a translation domain to. 1193 * @param string $domain The text domain. 1194 */ 1195 return apply_filters( 'load_script_translations', $translations, $file, $handle, $domain ); 1196 } 1197 1198 /** 1199 * Loads plugin and theme textdomains just-in-time. 1200 * 1201 * When a textdomain is encountered for the first time, we try to load 1202 * the translation file from `wp-content/languages`, removing the need 1203 * to call load_plugin_texdomain() or load_theme_texdomain(). 1204 * 1205 * @since 4.6.0 1206 * @access private 1207 * 1208 * @see get_translations_for_domain() 1209 * @global MO[] $l10n_unloaded An array of all text domains that have been unloaded again. 1210 * 1211 * @param string $domain Text domain. Unique identifier for retrieving translated strings. 1212 * @return bool True when the textdomain is successfully loaded, false otherwise. 1213 */ 1214 function _load_textdomain_just_in_time( $domain ) { 1215 global $l10n_unloaded; 1216 1217 $l10n_unloaded = (array) $l10n_unloaded; 1218 1219 // Short-circuit if domain is 'default' which is reserved for core. 1220 if ( 'default' === $domain || isset( $l10n_unloaded[ $domain ] ) ) { 1221 return false; 1222 } 1223 1224 $translation_path = _get_path_to_translation( $domain ); 1225 if ( false === $translation_path ) { 1226 return false; 1227 } 1228 1229 return load_textdomain( $domain, $translation_path ); 1230 } 1231 1232 /** 1233 * Gets the path to a translation file for loading a textdomain just in time. 1234 * 1235 * Caches the retrieved results internally. 1236 * 1237 * @since 4.7.0 1238 * @access private 1239 * 1240 * @see _load_textdomain_just_in_time() 1241 * 1242 * @param string $domain Text domain. Unique identifier for retrieving translated strings. 1243 * @param bool $reset Whether to reset the internal cache. Used by the switch to locale functionality. 1244 * @return string|false The path to the translation file or false if no translation file was found. 1245 */ 1246 function _get_path_to_translation( $domain, $reset = false ) { 1247 static $available_translations = array(); 1248 1249 if ( true === $reset ) { 1250 $available_translations = array(); 1251 } 1252 1253 if ( ! isset( $available_translations[ $domain ] ) ) { 1254 $available_translations[ $domain ] = _get_path_to_translation_from_lang_dir( $domain ); 1255 } 1256 1257 return $available_translations[ $domain ]; 1258 } 1259 1260 /** 1261 * Gets the path to a translation file in the languages directory for the current locale. 1262 * 1263 * Holds a cached list of available .mo files to improve performance. 1264 * 1265 * @since 4.7.0 1266 * @access private 1267 * 1268 * @see _get_path_to_translation() 1269 * 1270 * @param string $domain Text domain. Unique identifier for retrieving translated strings. 1271 * @return string|false The path to the translation file or false if no translation file was found. 1272 */ 1273 function _get_path_to_translation_from_lang_dir( $domain ) { 1274 static $cached_mofiles = null; 1275 1276 if ( null === $cached_mofiles ) { 1277 $cached_mofiles = array(); 1278 1279 $locations = array( 1280 WP_LANG_DIR . '/plugins', 1281 WP_LANG_DIR . '/themes', 1282 ); 1283 1284 foreach ( $locations as $location ) { 1285 $mofiles = glob( $location . '/*.mo' ); 1286 if ( $mofiles ) { 1287 $cached_mofiles = array_merge( $cached_mofiles, $mofiles ); 1288 } 1289 } 1290 } 1291 1292 $locale = determine_locale(); 1293 $mofile = "{$domain}-{$locale}.mo"; 1294 1295 $path = WP_LANG_DIR . '/plugins/' . $mofile; 1296 if ( in_array( $path, $cached_mofiles, true ) ) { 1297 return $path; 1298 } 1299 1300 $path = WP_LANG_DIR . '/themes/' . $mofile; 1301 if ( in_array( $path, $cached_mofiles, true ) ) { 1302 return $path; 1303 } 1304 1305 return false; 1306 } 1307 1308 /** 1309 * Returns the Translations instance for a text domain. 1310 * 1311 * If there isn't one, returns empty Translations instance. 1312 * 1313 * @since 2.8.0 1314 * 1315 * @global MO[] $l10n 1316 * 1317 * @param string $domain Text domain. Unique identifier for retrieving translated strings. 1318 * @return Translations|NOOP_Translations A Translations instance. 1319 */ 1320 function get_translations_for_domain( $domain ) { 1321 global $l10n; 1322 if ( isset( $l10n[ $domain ] ) || ( _load_textdomain_just_in_time( $domain ) && isset( $l10n[ $domain ] ) ) ) { 1323 return $l10n[ $domain ]; 1324 } 1325 1326 static $noop_translations = null; 1327 if ( null === $noop_translations ) { 1328 $noop_translations = new NOOP_Translations; 1329 } 1330 1331 return $noop_translations; 1332 } 1333 1334 /** 1335 * Determines whether there are translations for the text domain. 1336 * 1337 * @since 3.0.0 1338 * 1339 * @global MO[] $l10n 1340 * 1341 * @param string $domain Text domain. Unique identifier for retrieving translated strings. 1342 * @return bool Whether there are translations. 1343 */ 1344 function is_textdomain_loaded( $domain ) { 1345 global $l10n; 1346 return isset( $l10n[ $domain ] ); 1347 } 1348 1349 /** 1350 * Translates role name. 1351 * 1352 * Since the role names are in the database and not in the source there 1353 * are dummy gettext calls to get them into the POT file and this function 1354 * properly translates them back. 1355 * 1356 * The before_last_bar() call is needed, because older installations keep the roles 1357 * using the old context format: 'Role name|User role' and just skipping the 1358 * content after the last bar is easier than fixing them in the DB. New installations 1359 * won't suffer from that problem. 1360 * 1361 * @since 2.8.0 1362 * @since 5.2.0 Added the `$domain` parameter. 1363 * 1364 * @param string $name The role name. 1365 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. 1366 * Default 'default'. 1367 * @return string Translated role name on success, original name on failure. 1368 */ 1369 function translate_user_role( $name, $domain = 'default' ) { 1370 return translate_with_gettext_context( before_last_bar( $name ), 'User role', $domain ); 1371 } 1372 1373 /** 1374 * Gets all available languages based on the presence of *.mo files in a given directory. 1375 * 1376 * The default directory is WP_LANG_DIR. 1377 * 1378 * @since 3.0.0 1379 * @since 4.7.0 The results are now filterable with the {@see 'get_available_languages'} filter. 1380 * 1381 * @param string $dir A directory to search for language files. 1382 * Default WP_LANG_DIR. 1383 * @return string[] 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. 1384 */ 1385 function get_available_languages( $dir = null ) { 1386 $languages = array(); 1387 1388 $lang_files = glob( ( is_null( $dir ) ? WP_LANG_DIR : $dir ) . '/*.mo' ); 1389 if ( $lang_files ) { 1390 foreach ( $lang_files as $lang_file ) { 1391 $lang_file = basename( $lang_file, '.mo' ); 1392 if ( 0 !== strpos( $lang_file, 'continents-cities' ) && 0 !== strpos( $lang_file, 'ms-' ) && 1393 0 !== strpos( $lang_file, 'admin-' ) ) { 1394 $languages[] = $lang_file; 1395 } 1396 } 1397 } 1398 1399 /** 1400 * Filters the list of available language codes. 1401 * 1402 * @since 4.7.0 1403 * 1404 * @param string[] $languages An array of available language codes. 1405 * @param string $dir The directory where the language files were found. 1406 */ 1407 return apply_filters( 'get_available_languages', $languages, $dir ); 1408 } 1409 1410 /** 1411 * Gets installed translations. 1412 * 1413 * Looks in the wp-content/languages directory for translations of 1414 * plugins or themes. 1415 * 1416 * @since 3.7.0 1417 * 1418 * @param string $type What to search for. Accepts 'plugins', 'themes', 'core'. 1419 * @return array Array of language data. 1420 */ 1421 function wp_get_installed_translations( $type ) { 1422 if ( 'themes' !== $type && 'plugins' !== $type && 'core' !== $type ) { 1423 return array(); 1424 } 1425 1426 $dir = 'core' === $type ? '' : "/$type"; 1427 1428 if ( ! is_dir( WP_LANG_DIR ) ) { 1429 return array(); 1430 } 1431 1432 if ( $dir && ! is_dir( WP_LANG_DIR . $dir ) ) { 1433 return array(); 1434 } 1435 1436 $files = scandir( WP_LANG_DIR . $dir ); 1437 if ( ! $files ) { 1438 return array(); 1439 } 1440 1441 $language_data = array(); 1442 1443 foreach ( $files as $file ) { 1444 if ( '.' === $file[0] || is_dir( WP_LANG_DIR . "$dir/$file" ) ) { 1445 continue; 1446 } 1447 if ( substr( $file, -3 ) !== '.po' ) { 1448 continue; 1449 } 1450 if ( ! preg_match( '/(?:(.+)-)?([a-z]{2,3}(?:_[A-Z]{2})?(?:_[a-z0-9]+)?).po/', $file, $match ) ) { 1451 continue; 1452 } 1453 if ( ! in_array( substr( $file, 0, -3 ) . '.mo', $files, true ) ) { 1454 continue; 1455 } 1456 1457 list( , $textdomain, $language ) = $match; 1458 if ( '' === $textdomain ) { 1459 $textdomain = 'default'; 1460 } 1461 $language_data[ $textdomain ][ $language ] = wp_get_pomo_file_data( WP_LANG_DIR . "$dir/$file" ); 1462 } 1463 return $language_data; 1464 } 1465 1466 /** 1467 * Extracts headers from a PO file. 1468 * 1469 * @since 3.7.0 1470 * 1471 * @param string $po_file Path to PO file. 1472 * @return string[] Array of PO file header values keyed by header name. 1473 */ 1474 function wp_get_pomo_file_data( $po_file ) { 1475 $headers = get_file_data( 1476 $po_file, 1477 array( 1478 'POT-Creation-Date' => '"POT-Creation-Date', 1479 'PO-Revision-Date' => '"PO-Revision-Date', 1480 'Project-Id-Version' => '"Project-Id-Version', 1481 'X-Generator' => '"X-Generator', 1482 ) 1483 ); 1484 foreach ( $headers as $header => $value ) { 1485 // Remove possible contextual '\n' and closing double quote. 1486 $headers[ $header ] = preg_replace( '~(\\\n)?"$~', '', $value ); 1487 } 1488 return $headers; 1489 } 1490 1491 /** 1492 * Displays or returns a Language selector. 1493 * 1494 * @since 4.0.0 1495 * @since 4.3.0 Introduced the `echo` argument. 1496 * @since 4.7.0 Introduced the `show_option_site_default` argument. 1497 * @since 5.1.0 Introduced the `show_option_en_us` argument. 1498 * @since 5.9.0 Introduced the `explicit_option_en_us` argument. 1499 * 1500 * @see get_available_languages() 1501 * @see wp_get_available_translations() 1502 * 1503 * @param string|array $args { 1504 * Optional. Array or string of arguments for outputting the language selector. 1505 * 1506 * @type string $id ID attribute of the select element. Default 'locale'. 1507 * @type string $name Name attribute of the select element. Default 'locale'. 1508 * @type array $languages List of installed languages, contain only the locales. 1509 * Default empty array. 1510 * @type array $translations List of available translations. Default result of 1511 * wp_get_available_translations(). 1512 * @type string $selected Language which should be selected. Default empty. 1513 * @type bool|int $echo Whether to echo the generated markup. Accepts 0, 1, or their 1514 * boolean equivalents. Default 1. 1515 * @type bool $show_available_translations Whether to show available translations. Default true. 1516 * @type bool $show_option_site_default Whether to show an option to fall back to the site's locale. Default false. 1517 * @type bool $show_option_en_us Whether to show an option for English (United States). Default true. 1518 * @type bool $explicit_option_en_us Whether the English (United States) option uses an explicit value of en_US 1519 * instead of an empty value. Default false. 1520 * } 1521 * @return string HTML dropdown list of languages. 1522 */ 1523 function wp_dropdown_languages( $args = array() ) { 1524 1525 $parsed_args = wp_parse_args( 1526 $args, 1527 array( 1528 'id' => 'locale', 1529 'name' => 'locale', 1530 'languages' => array(), 1531 'translations' => array(), 1532 'selected' => '', 1533 'echo' => 1, 1534 'show_available_translations' => true, 1535 'show_option_site_default' => false, 1536 'show_option_en_us' => true, 1537 'explicit_option_en_us' => false, 1538 ) 1539 ); 1540 1541 // Bail if no ID or no name. 1542 if ( ! $parsed_args['id'] || ! $parsed_args['name'] ) { 1543 return; 1544 } 1545 1546 // English (United States) uses an empty string for the value attribute. 1547 if ( 'en_US' === $parsed_args['selected'] && ! $parsed_args['explicit_option_en_us'] ) { 1548 $parsed_args['selected'] = ''; 1549 } 1550 1551 $translations = $parsed_args['translations']; 1552 if ( empty( $translations ) ) { 1553 require_once ABSPATH . 'wp-admin/includes/translation-install.php'; 1554 $translations = wp_get_available_translations(); 1555 } 1556 1557 /* 1558 * $parsed_args['languages'] should only contain the locales. Find the locale in 1559 * $translations to get the native name. Fall back to locale. 1560 */ 1561 $languages = array(); 1562 foreach ( $parsed_args['languages'] as $locale ) { 1563 if ( isset( $translations[ $locale ] ) ) { 1564 $translation = $translations[ $locale ]; 1565 $languages[] = array( 1566 'language' => $translation['language'], 1567 'native_name' => $translation['native_name'], 1568 'lang' => current( $translation['iso'] ), 1569 ); 1570 1571 // Remove installed language from available translations. 1572 unset( $translations[ $locale ] ); 1573 } else { 1574 $languages[] = array( 1575 'language' => $locale, 1576 'native_name' => $locale, 1577 'lang' => '', 1578 ); 1579 } 1580 } 1581 1582 $translations_available = ( ! empty( $translations ) && $parsed_args['show_available_translations'] ); 1583 1584 // Holds the HTML markup. 1585 $structure = array(); 1586 1587 // List installed languages. 1588 if ( $translations_available ) { 1589 $structure[] = '<optgroup label="' . esc_attr_x( 'Installed', 'translations' ) . '">'; 1590 } 1591 1592 // Site default. 1593 if ( $parsed_args['show_option_site_default'] ) { 1594 $structure[] = sprintf( 1595 '<option value="site-default" data-installed="1"%s>%s</option>', 1596 selected( 'site-default', $parsed_args['selected'], false ), 1597 _x( 'Site Default', 'default site language' ) 1598 ); 1599 } 1600 1601 if ( $parsed_args['show_option_en_us'] ) { 1602 $value = ( $parsed_args['explicit_option_en_us'] ) ? 'en_US' : ''; 1603 $structure[] = sprintf( 1604 '<option value="%s" lang="en" data-installed="1"%s>English (United States)</option>', 1605 esc_attr( $value ), 1606 selected( '', $parsed_args['selected'], false ) 1607 ); 1608 } 1609 1610 // List installed languages. 1611 foreach ( $languages as $language ) { 1612 $structure[] = sprintf( 1613 '<option value="%s" lang="%s"%s data-installed="1">%s</option>', 1614 esc_attr( $language['language'] ), 1615 esc_attr( $language['lang'] ), 1616 selected( $language['language'], $parsed_args['selected'], false ), 1617 esc_html( $language['native_name'] ) 1618 ); 1619 } 1620 if ( $translations_available ) { 1621 $structure[] = '</optgroup>'; 1622 } 1623 1624 // List available translations. 1625 if ( $translations_available ) { 1626 $structure[] = '<optgroup label="' . esc_attr_x( 'Available', 'translations' ) . '">'; 1627 foreach ( $translations as $translation ) { 1628 $structure[] = sprintf( 1629 '<option value="%s" lang="%s"%s>%s</option>', 1630 esc_attr( $translation['language'] ), 1631 esc_attr( current( $translation['iso'] ) ), 1632 selected( $translation['language'], $parsed_args['selected'], false ), 1633 esc_html( $translation['native_name'] ) 1634 ); 1635 } 1636 $structure[] = '</optgroup>'; 1637 } 1638 1639 // Combine the output string. 1640 $output = sprintf( '<select name="%s" id="%s">', esc_attr( $parsed_args['name'] ), esc_attr( $parsed_args['id'] ) ); 1641 $output .= implode( "\n", $structure ); 1642 $output .= '</select>'; 1643 1644 if ( $parsed_args['echo'] ) { 1645 echo $output; 1646 } 1647 1648 return $output; 1649 } 1650 1651 /** 1652 * Determines whether the current locale is right-to-left (RTL). 1653 * 1654 * For more information on this and similar theme functions, check out 1655 * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ 1656 * Conditional Tags} article in the Theme Developer Handbook. 1657 * 1658 * @since 3.0.0 1659 * 1660 * @global WP_Locale $wp_locale WordPress date and time locale object. 1661 * 1662 * @return bool Whether locale is RTL. 1663 */ 1664 function is_rtl() { 1665 global $wp_locale; 1666 if ( ! ( $wp_locale instanceof WP_Locale ) ) { 1667 return false; 1668 } 1669 return $wp_locale->is_rtl(); 1670 } 1671 1672 /** 1673 * Switches the translations according to the given locale. 1674 * 1675 * @since 4.7.0 1676 * 1677 * @global WP_Locale_Switcher $wp_locale_switcher WordPress locale switcher object. 1678 * 1679 * @param string $locale The locale. 1680 * @return bool True on success, false on failure. 1681 */ 1682 function switch_to_locale( $locale ) { 1683 /* @var WP_Locale_Switcher $wp_locale_switcher */ 1684 global $wp_locale_switcher; 1685 1686 return $wp_locale_switcher->switch_to_locale( $locale ); 1687 } 1688 1689 /** 1690 * Restores the translations according to the previous locale. 1691 * 1692 * @since 4.7.0 1693 * 1694 * @global WP_Locale_Switcher $wp_locale_switcher WordPress locale switcher object. 1695 * 1696 * @return string|false Locale on success, false on error. 1697 */ 1698 function restore_previous_locale() { 1699 /* @var WP_Locale_Switcher $wp_locale_switcher */ 1700 global $wp_locale_switcher; 1701 1702 return $wp_locale_switcher->restore_previous_locale(); 1703 } 1704 1705 /** 1706 * Restores the translations according to the original locale. 1707 * 1708 * @since 4.7.0 1709 * 1710 * @global WP_Locale_Switcher $wp_locale_switcher WordPress locale switcher object. 1711 * 1712 * @return string|false Locale on success, false on error. 1713 */ 1714 function restore_current_locale() { 1715 /* @var WP_Locale_Switcher $wp_locale_switcher */ 1716 global $wp_locale_switcher; 1717 1718 return $wp_locale_switcher->restore_current_locale(); 1719 } 1720 1721 /** 1722 * Determines whether switch_to_locale() is in effect. 1723 * 1724 * @since 4.7.0 1725 * 1726 * @global WP_Locale_Switcher $wp_locale_switcher WordPress locale switcher object. 1727 * 1728 * @return bool True if the locale has been switched, false otherwise. 1729 */ 1730 function is_locale_switched() { 1731 /* @var WP_Locale_Switcher $wp_locale_switcher */ 1732 global $wp_locale_switcher; 1733 1734 return $wp_locale_switcher->is_switched(); 1735 } 1736 1737 /** 1738 * Translates the provided settings value using its i18n schema. 1739 * 1740 * @since 5.9.0 1741 * @access private 1742 * 1743 * @param string|string[]|array[]|object $i18n_schema I18n schema for the setting. 1744 * @param string|string[]|array[] $settings Value for the settings. 1745 * @param string $textdomain Textdomain to use with translations. 1746 * 1747 * @return string|string[]|array[] Translated settings. 1748 */ 1749 function translate_settings_using_i18n_schema( $i18n_schema, $settings, $textdomain ) { 1750 if ( empty( $i18n_schema ) || empty( $settings ) || empty( $textdomain ) ) { 1751 return $settings; 1752 } 1753 1754 if ( is_string( $i18n_schema ) && is_string( $settings ) ) { 1755 return translate_with_gettext_context( $settings, $i18n_schema, $textdomain ); 1756 } 1757 if ( is_array( $i18n_schema ) && is_array( $settings ) ) { 1758 $translated_settings = array(); 1759 foreach ( $settings as $value ) { 1760 $translated_settings[] = translate_settings_using_i18n_schema( $i18n_schema[0], $value, $textdomain ); 1761 } 1762 return $translated_settings; 1763 } 1764 if ( is_object( $i18n_schema ) && is_array( $settings ) ) { 1765 $group_key = '*'; 1766 $translated_settings = array(); 1767 foreach ( $settings as $key => $value ) { 1768 if ( isset( $i18n_schema->$key ) ) { 1769 $translated_settings[ $key ] = translate_settings_using_i18n_schema( $i18n_schema->$key, $value, $textdomain ); 1770 } elseif ( isset( $i18n_schema->$group_key ) ) { 1771 $translated_settings[ $key ] = translate_settings_using_i18n_schema( $i18n_schema->$group_key, $value, $textdomain ); 1772 } else { 1773 $translated_settings[ $key ] = $value; 1774 } 1775 } 1776 return $translated_settings; 1777 } 1778 return $settings; 1779 } 1780 1781 /** 1782 * Retrieves the list item separator based on the locale. 1783 * 1784 * @since 6.0.0 1785 * 1786 * @global WP_Locale $wp_locale WordPress date and time locale object. 1787 * 1788 * @return string Locale-specific list item separator. 1789 */ 1790 function wp_get_list_item_separator() { 1791 global $wp_locale; 1792 1793 return $wp_locale->get_list_item_separator(); 1794 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Tue Jul 5 08:20:01 2022 | Cross-referenced by PHPXref |