22 * @since 1.5.0 |
22 * @since 1.5.0 |
23 * |
23 * |
24 * @return string The locale of the blog or from the 'locale' hook. |
24 * @return string The locale of the blog or from the 'locale' hook. |
25 */ |
25 */ |
26 function get_locale() { |
26 function get_locale() { |
27 global $locale; |
27 global $locale, $wp_local_package; |
28 |
28 |
29 if ( isset( $locale ) ) |
29 if ( isset( $locale ) ) { |
30 /** |
30 /** |
31 * Filter WordPress install's locale ID. |
31 * Filter WordPress install's locale ID. |
32 * |
32 * |
33 * @since 1.5.2 |
33 * @since 1.5.0 |
34 * |
34 * |
35 * @param string $locale The locale ID. |
35 * @param string $locale The locale ID. |
36 */ |
36 */ |
37 return apply_filters( 'locale', $locale ); |
37 return apply_filters( 'locale', $locale ); |
38 |
38 } |
39 // WPLANG is defined in wp-config. |
39 |
40 if ( defined( 'WPLANG' ) ) |
40 if ( isset( $wp_local_package ) ) { |
|
41 $locale = $wp_local_package; |
|
42 } |
|
43 |
|
44 // WPLANG was defined in wp-config. |
|
45 if ( defined( 'WPLANG' ) ) { |
41 $locale = WPLANG; |
46 $locale = WPLANG; |
|
47 } |
42 |
48 |
43 // If multisite, check options. |
49 // If multisite, check options. |
44 if ( is_multisite() ) { |
50 if ( is_multisite() ) { |
45 // Don't check blog option when installing. |
51 // Don't check blog option when installing. |
46 if ( defined( 'WP_INSTALLING' ) || ( false === $ms_locale = get_option( 'WPLANG' ) ) ) |
52 if ( defined( 'WP_INSTALLING' ) || ( false === $ms_locale = get_option( 'WPLANG' ) ) ) { |
47 $ms_locale = get_site_option('WPLANG'); |
53 $ms_locale = get_site_option( 'WPLANG' ); |
48 |
54 } |
49 if ( $ms_locale !== false ) |
55 |
|
56 if ( $ms_locale !== false ) { |
50 $locale = $ms_locale; |
57 $locale = $ms_locale; |
51 } |
58 } |
52 |
59 } else { |
53 if ( empty( $locale ) ) |
60 $db_locale = get_option( 'WPLANG' ); |
|
61 if ( $db_locale !== false ) { |
|
62 $locale = $db_locale; |
|
63 } |
|
64 } |
|
65 |
|
66 if ( empty( $locale ) ) { |
54 $locale = 'en_US'; |
67 $locale = 'en_US'; |
55 |
68 } |
56 // duplicate_hook |
69 |
|
70 /** This filter is documented in wp-includes/l10n.php */ |
57 return apply_filters( 'locale', $locale ); |
71 return apply_filters( 'locale', $locale ); |
58 } |
72 } |
59 |
73 |
60 /** |
74 /** |
61 * Retrieve the translation of $text. |
75 * Retrieve the translation of $text. |
62 * |
76 * |
63 * If there is no translation, or the text domain isn't loaded, the original text is returned. |
77 * If there is no translation, or the text domain isn't loaded, the original text is returned. |
64 * |
78 * |
65 * <strong>Note:</strong> Don't use translate() directly, use __() or related functions. |
79 * *Note:* Don't use {@see translate()} directly, use `{@see __()} or related functions. |
66 * |
80 * |
67 * @since 2.2.0 |
81 * @since 2.2.0 |
68 * |
82 * |
69 * @param string $text Text to translate. |
83 * @param string $text Text to translate. |
70 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. |
84 * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. |
71 * @return string Translated text |
85 * @return string Translated text |
72 */ |
86 */ |
73 function translate( $text, $domain = 'default' ) { |
87 function translate( $text, $domain = 'default' ) { |
74 $translations = get_translations_for_domain( $domain ); |
88 $translations = get_translations_for_domain( $domain ); |
75 $translations = $translations->translate( $text ); |
89 $translations = $translations->translate( $text ); |
|
90 |
76 /** |
91 /** |
77 * Filter text with its translation. |
92 * Filter text with its translation. |
78 * |
93 * |
79 * @since 2.0.11 |
94 * @since 2.0.11 |
80 * |
95 * |
348 * |
363 * |
349 * Used when you want to keep structures with translatable plural |
364 * Used when you want to keep structures with translatable plural |
350 * strings and use them later. |
365 * strings and use them later. |
351 * |
366 * |
352 * Example: |
367 * Example: |
353 * <code> |
368 * |
354 * $messages = array( |
369 * $messages = array( |
355 * 'post' => _n_noop('%s post', '%s posts'), |
370 * 'post' => _n_noop( '%s post', '%s posts' ), |
356 * 'page' => _n_noop('%s pages', '%s pages') |
371 * 'page' => _n_noop( '%s pages', '%s pages' ), |
357 * ); |
372 * ); |
358 * ... |
373 * ... |
359 * $message = $messages[$type]; |
374 * $message = $messages[ $type ]; |
360 * $usable_text = sprintf( translate_nooped_plural( $message, $count ), $count ); |
375 * $usable_text = sprintf( translate_nooped_plural( $message, $count ), $count ); |
361 * </code> |
|
362 * |
376 * |
363 * @since 2.5.0 |
377 * @since 2.5.0 |
364 * |
378 * |
365 * @param string $singular Single form to be i18ned. |
379 * @param string $singular Single form to be i18ned. |
366 * @param string $plural Plural form to be i18ned. |
380 * @param string $plural Plural form to be i18ned. |
373 |
387 |
374 /** |
388 /** |
375 * Register plural strings with context in POT file, but don't translate them. |
389 * Register plural strings with context in POT file, but don't translate them. |
376 * |
390 * |
377 * @since 2.8.0 |
391 * @since 2.8.0 |
|
392 * @param string $singular |
|
393 * @param string $plural |
|
394 * @param string $context |
|
395 * @param string|null $domain |
|
396 * @return array |
378 */ |
397 */ |
379 function _nx_noop( $singular, $plural, $context, $domain = null ) { |
398 function _nx_noop( $singular, $plural, $context, $domain = null ) { |
380 return array( 0 => $singular, 1 => $plural, 2 => $context, 'singular' => $singular, 'plural' => $plural, 'context' => $context, 'domain' => $domain ); |
399 return array( 0 => $singular, 1 => $plural, 2 => $context, 'singular' => $singular, 'plural' => $plural, 'context' => $context, 'domain' => $domain ); |
381 } |
400 } |
382 |
401 |
515 * The translated (.mo) file is named based on the locale. |
534 * The translated (.mo) file is named based on the locale. |
516 * |
535 * |
517 * @see load_textdomain() |
536 * @see load_textdomain() |
518 * |
537 * |
519 * @since 1.5.0 |
538 * @since 1.5.0 |
520 */ |
539 * |
521 function load_default_textdomain() { |
540 * @param string $locale Optional. Locale to load. Default is the value of {@see get_locale()}. |
522 $locale = get_locale(); |
541 * @return bool Whether the textdomain was loaded. |
523 |
542 */ |
524 load_textdomain( 'default', WP_LANG_DIR . "/$locale.mo" ); |
543 function load_default_textdomain( $locale = null ) { |
|
544 if ( null === $locale ) { |
|
545 $locale = get_locale(); |
|
546 } |
|
547 |
|
548 // Unload previously loaded strings so we can switch translations. |
|
549 unload_textdomain( 'default' ); |
|
550 |
|
551 $return = load_textdomain( 'default', WP_LANG_DIR . "/$locale.mo" ); |
525 |
552 |
526 if ( ( is_multisite() || ( defined( 'WP_INSTALLING_NETWORK' ) && WP_INSTALLING_NETWORK ) ) && ! file_exists( WP_LANG_DIR . "/admin-$locale.mo" ) ) { |
553 if ( ( is_multisite() || ( defined( 'WP_INSTALLING_NETWORK' ) && WP_INSTALLING_NETWORK ) ) && ! file_exists( WP_LANG_DIR . "/admin-$locale.mo" ) ) { |
527 load_textdomain( 'default', WP_LANG_DIR . "/ms-$locale.mo" ); |
554 load_textdomain( 'default', WP_LANG_DIR . "/ms-$locale.mo" ); |
528 return; |
555 return $return; |
529 } |
556 } |
530 |
557 |
531 if ( is_admin() || ( defined( 'WP_REPAIRING' ) && WP_REPAIRING ) ) |
558 if ( is_admin() || defined( 'WP_INSTALLING' ) || ( defined( 'WP_REPAIRING' ) && WP_REPAIRING ) ) { |
532 load_textdomain( 'default', WP_LANG_DIR . "/admin-$locale.mo" ); |
559 load_textdomain( 'default', WP_LANG_DIR . "/admin-$locale.mo" ); |
|
560 } |
533 |
561 |
534 if ( is_network_admin() || ( defined( 'WP_INSTALLING_NETWORK' ) && WP_INSTALLING_NETWORK ) ) |
562 if ( is_network_admin() || ( defined( 'WP_INSTALLING_NETWORK' ) && WP_INSTALLING_NETWORK ) ) |
535 load_textdomain( 'default', WP_LANG_DIR . "/admin-network-$locale.mo" ); |
563 load_textdomain( 'default', WP_LANG_DIR . "/admin-network-$locale.mo" ); |
536 |
564 |
|
565 return $return; |
537 } |
566 } |
538 |
567 |
539 /** |
568 /** |
540 * Load a plugin's translated strings. |
569 * Load a plugin's translated strings. |
541 * |
570 * |
546 * @since 1.5.0 |
575 * @since 1.5.0 |
547 * |
576 * |
548 * @param string $domain Unique identifier for retrieving translated strings |
577 * @param string $domain Unique identifier for retrieving translated strings |
549 * @param string $deprecated Use the $plugin_rel_path parameter instead. |
578 * @param string $deprecated Use the $plugin_rel_path parameter instead. |
550 * @param string $plugin_rel_path Optional. Relative path to WP_PLUGIN_DIR where the .mo file resides. |
579 * @param string $plugin_rel_path Optional. Relative path to WP_PLUGIN_DIR where the .mo file resides. |
|
580 * Default false. |
|
581 * @return bool True when textdomain is successfully loaded, false otherwise. |
551 */ |
582 */ |
552 function load_plugin_textdomain( $domain, $deprecated = false, $plugin_rel_path = false ) { |
583 function load_plugin_textdomain( $domain, $deprecated = false, $plugin_rel_path = false ) { |
553 $locale = get_locale(); |
584 $locale = get_locale(); |
554 /** |
585 /** |
555 * Filter a plugin's locale. |
586 * Filter a plugin's locale. |
561 */ |
592 */ |
562 $locale = apply_filters( 'plugin_locale', $locale, $domain ); |
593 $locale = apply_filters( 'plugin_locale', $locale, $domain ); |
563 |
594 |
564 if ( false !== $plugin_rel_path ) { |
595 if ( false !== $plugin_rel_path ) { |
565 $path = WP_PLUGIN_DIR . '/' . trim( $plugin_rel_path, '/' ); |
596 $path = WP_PLUGIN_DIR . '/' . trim( $plugin_rel_path, '/' ); |
566 } else if ( false !== $deprecated ) { |
597 } elseif ( false !== $deprecated ) { |
567 _deprecated_argument( __FUNCTION__, '2.7' ); |
598 _deprecated_argument( __FUNCTION__, '2.7' ); |
568 $path = ABSPATH . trim( $deprecated, '/' ); |
599 $path = ABSPATH . trim( $deprecated, '/' ); |
569 } else { |
600 } else { |
570 $path = WP_PLUGIN_DIR; |
601 $path = WP_PLUGIN_DIR; |
571 } |
602 } |
589 * @param string $mu_plugin_rel_path Relative to WPMU_PLUGIN_DIR directory in which the .mo file resides. |
620 * @param string $mu_plugin_rel_path Relative to WPMU_PLUGIN_DIR directory in which the .mo file resides. |
590 * Default empty string. |
621 * Default empty string. |
591 * @return bool True when textdomain is successfully loaded, false otherwise. |
622 * @return bool True when textdomain is successfully loaded, false otherwise. |
592 */ |
623 */ |
593 function load_muplugin_textdomain( $domain, $mu_plugin_rel_path = '' ) { |
624 function load_muplugin_textdomain( $domain, $mu_plugin_rel_path = '' ) { |
594 // duplicate_hook |
625 /** This filter is documented in wp-includes/l10n.php */ |
595 $locale = apply_filters( 'plugin_locale', get_locale(), $domain ); |
626 $locale = apply_filters( 'plugin_locale', get_locale(), $domain ); |
596 $path = trailingslashit( WPMU_PLUGIN_DIR . '/' . ltrim( $mu_plugin_rel_path, '/' ) ); |
627 $path = trailingslashit( WPMU_PLUGIN_DIR . '/' . ltrim( $mu_plugin_rel_path, '/' ) ); |
597 |
628 |
598 // Load the textdomain according to the plugin first |
629 // Load the textdomain according to the plugin first |
599 $mofile = $domain . '-' . $locale . '.mo'; |
630 $mofile = $domain . '-' . $locale . '.mo'; |
765 return array(); |
801 return array(); |
766 |
802 |
767 $language_data = array(); |
803 $language_data = array(); |
768 |
804 |
769 foreach ( $files as $file ) { |
805 foreach ( $files as $file ) { |
770 if ( '.' === $file[0] || is_dir( $file ) ) |
806 if ( '.' === $file[0] || is_dir( $file ) ) { |
771 continue; |
807 continue; |
772 if ( substr( $file, -3 ) !== '.po' ) |
808 } |
|
809 if ( substr( $file, -3 ) !== '.po' ) { |
773 continue; |
810 continue; |
774 if ( ! preg_match( '/(?:(.+)-)?([A-Za-z_]{2,6}).po/', $file, $match ) ) |
811 } |
|
812 if ( ! preg_match( '/(?:(.+)-)?([A-Za-z_]{2,6}).po/', $file, $match ) ) { |
775 continue; |
813 continue; |
|
814 } |
|
815 if ( ! in_array( substr( $file, 0, -3 ) . '.mo', $files ) ) { |
|
816 continue; |
|
817 } |
776 |
818 |
777 list( , $textdomain, $language ) = $match; |
819 list( , $textdomain, $language ) = $match; |
778 if ( '' === $textdomain ) |
820 if ( '' === $textdomain ) { |
779 $textdomain = 'default'; |
821 $textdomain = 'default'; |
|
822 } |
780 $language_data[ $textdomain ][ $language ] = wp_get_pomo_file_data( WP_LANG_DIR . "$dir/$file" ); |
823 $language_data[ $textdomain ][ $language ] = wp_get_pomo_file_data( WP_LANG_DIR . "$dir/$file" ); |
781 } |
824 } |
782 return $language_data; |
825 return $language_data; |
783 } |
826 } |
784 |
827 |
801 // Remove possible contextual '\n' and closing double quote. |
844 // Remove possible contextual '\n' and closing double quote. |
802 $headers[ $header ] = preg_replace( '~(\\\n)?"$~', '', $value ); |
845 $headers[ $header ] = preg_replace( '~(\\\n)?"$~', '', $value ); |
803 } |
846 } |
804 return $headers; |
847 return $headers; |
805 } |
848 } |
|
849 |
|
850 /** |
|
851 * Language selector. |
|
852 * |
|
853 * @since 4.0.0 |
|
854 * |
|
855 * @see get_available_languages() |
|
856 * @see wp_get_available_translations() |
|
857 * |
|
858 * @param string|array $args { |
|
859 * Optional. Array or string of arguments for outputting the language selector. |
|
860 * |
|
861 * @type string $id ID attribute of the select element. Default empty. |
|
862 * @type string $name Name attribute of the select element. Default empty. |
|
863 * @type array $languages List of installed languages, contain only the locales. |
|
864 * Default empty array. |
|
865 * @type array $translations List of available translations. Default result of |
|
866 * {@see wp_get_available_translations()}. |
|
867 * @type string $selected Language which should be selected. Default empty. |
|
868 * @type bool $show_available_translations Whether to show available translations. Default true. |
|
869 * } |
|
870 */ |
|
871 function wp_dropdown_languages( $args = array() ) { |
|
872 |
|
873 $args = wp_parse_args( $args, array( |
|
874 'id' => '', |
|
875 'name' => '', |
|
876 'languages' => array(), |
|
877 'translations' => array(), |
|
878 'selected' => '', |
|
879 'show_available_translations' => true, |
|
880 ) ); |
|
881 |
|
882 $translations = $args['translations']; |
|
883 if ( empty( $translations ) ) { |
|
884 require_once( ABSPATH . 'wp-admin/includes/translation-install.php' ); |
|
885 $translations = wp_get_available_translations(); |
|
886 } |
|
887 |
|
888 /* |
|
889 * $args['languages'] should only contain the locales. Find the locale in |
|
890 * $translations to get the native name. Fall back to locale. |
|
891 */ |
|
892 $languages = array(); |
|
893 foreach ( $args['languages'] as $locale ) { |
|
894 if ( isset( $translations[ $locale ] ) ) { |
|
895 $translation = $translations[ $locale ]; |
|
896 $languages[] = array( |
|
897 'language' => $translation['language'], |
|
898 'native_name' => $translation['native_name'], |
|
899 'lang' => current( $translation['iso'] ), |
|
900 ); |
|
901 |
|
902 // Remove installed language from available translations. |
|
903 unset( $translations[ $locale ] ); |
|
904 } else { |
|
905 $languages[] = array( |
|
906 'language' => $locale, |
|
907 'native_name' => $locale, |
|
908 'lang' => '', |
|
909 ); |
|
910 } |
|
911 } |
|
912 |
|
913 $translations_available = ( ! empty( $translations ) && $args['show_available_translations'] ); |
|
914 |
|
915 printf( '<select name="%s" id="%s">', esc_attr( $args['name'] ), esc_attr( $args['id'] ) ); |
|
916 |
|
917 // Holds the HTML markup. |
|
918 $structure = array(); |
|
919 |
|
920 // List installed languages. |
|
921 if ( $translations_available ) { |
|
922 $structure[] = '<optgroup label="' . esc_attr_x( 'Installed', 'translations' ) . '">'; |
|
923 } |
|
924 $structure[] = '<option value="" lang="en" data-installed="1">English (United States)</option>'; |
|
925 foreach ( $languages as $language ) { |
|
926 $structure[] = sprintf( |
|
927 '<option value="%s" lang="%s"%s data-installed="1">%s</option>', |
|
928 esc_attr( $language['language'] ), |
|
929 esc_attr( $language['lang'] ), |
|
930 selected( $language['language'], $args['selected'], false ), |
|
931 esc_html( $language['native_name'] ) |
|
932 ); |
|
933 } |
|
934 if ( $translations_available ) { |
|
935 $structure[] = '</optgroup>'; |
|
936 } |
|
937 |
|
938 // List available translations. |
|
939 if ( $translations_available ) { |
|
940 $structure[] = '<optgroup label="' . esc_attr_x( 'Available', 'translations' ) . '">'; |
|
941 foreach ( $translations as $translation ) { |
|
942 $structure[] = sprintf( |
|
943 '<option value="%s" lang="%s"%s>%s</option>', |
|
944 esc_attr( $translation['language'] ), |
|
945 esc_attr( current( $translation['iso'] ) ), |
|
946 selected( $translation['language'], $args['selected'], false ), |
|
947 esc_html( $translation['native_name'] ) |
|
948 ); |
|
949 } |
|
950 $structure[] = '</optgroup>'; |
|
951 } |
|
952 |
|
953 echo join( "\n", $structure ); |
|
954 |
|
955 echo '</select>'; |
|
956 } |