961 if ( ( is_multisite() || ( defined( 'WP_INSTALLING_NETWORK' ) && WP_INSTALLING_NETWORK ) ) && ! file_exists( WP_LANG_DIR . "/admin-$locale.mo" ) ) { |
962 if ( ( is_multisite() || ( defined( 'WP_INSTALLING_NETWORK' ) && WP_INSTALLING_NETWORK ) ) && ! file_exists( WP_LANG_DIR . "/admin-$locale.mo" ) ) { |
962 load_textdomain( 'default', WP_LANG_DIR . "/ms-$locale.mo", $locale ); |
963 load_textdomain( 'default', WP_LANG_DIR . "/ms-$locale.mo", $locale ); |
963 return $return; |
964 return $return; |
964 } |
965 } |
965 |
966 |
966 if ( is_admin() || wp_installing() || ( defined( 'WP_REPAIRING' ) && WP_REPAIRING ) ) { |
967 if ( is_admin() || wp_installing() || ( defined( 'WP_REPAIRING' ) && WP_REPAIRING ) || doing_action( 'wp_maybe_auto_update' ) ) { |
967 load_textdomain( 'default', WP_LANG_DIR . "/admin-$locale.mo", $locale ); |
968 load_textdomain( 'default', WP_LANG_DIR . "/admin-$locale.mo", $locale ); |
968 } |
969 } |
969 |
970 |
970 if ( is_network_admin() || ( defined( 'WP_INSTALLING_NETWORK' ) && WP_INSTALLING_NETWORK ) ) { |
971 if ( is_network_admin() || ( defined( 'WP_INSTALLING_NETWORK' ) && WP_INSTALLING_NETWORK ) ) { |
971 load_textdomain( 'default', WP_LANG_DIR . "/admin-network-$locale.mo", $locale ); |
972 load_textdomain( 'default', WP_LANG_DIR . "/admin-network-$locale.mo", $locale ); |
981 * |
982 * |
982 * The .mo file should be named based on the text domain with a dash, and then the locale exactly. |
983 * The .mo file should be named based on the text domain with a dash, and then the locale exactly. |
983 * |
984 * |
984 * @since 1.5.0 |
985 * @since 1.5.0 |
985 * @since 4.6.0 The function now tries to load the .mo file from the languages directory first. |
986 * @since 4.6.0 The function now tries to load the .mo file from the languages directory first. |
|
987 * @since 6.7.0 Translations are no longer immediately loaded, but handed off to the just-in-time loading mechanism. |
|
988 * |
|
989 * @global WP_Textdomain_Registry $wp_textdomain_registry WordPress Textdomain Registry. |
|
990 * @global array<string, WP_Translations|NOOP_Translations> $l10n An array of all currently loaded text domains. |
986 * |
991 * |
987 * @param string $domain Unique identifier for retrieving translated strings |
992 * @param string $domain Unique identifier for retrieving translated strings |
988 * @param string|false $deprecated Optional. Deprecated. Use the $plugin_rel_path parameter instead. |
993 * @param string|false $deprecated Optional. Deprecated. Use the $plugin_rel_path parameter instead. |
989 * Default false. |
994 * Default false. |
990 * @param string|false $plugin_rel_path Optional. Relative path to WP_PLUGIN_DIR where the .mo file resides. |
995 * @param string|false $plugin_rel_path Optional. Relative path to WP_PLUGIN_DIR where the .mo file resides. |
991 * Default false. |
996 * Default false. |
992 * @return bool True when textdomain is successfully loaded, false otherwise. |
997 * @return bool True when textdomain is successfully loaded, false otherwise. |
993 */ |
998 */ |
994 function load_plugin_textdomain( $domain, $deprecated = false, $plugin_rel_path = false ) { |
999 function load_plugin_textdomain( $domain, $deprecated = false, $plugin_rel_path = false ) { |
995 /** @var WP_Textdomain_Registry $wp_textdomain_registry */ |
1000 /** @var WP_Textdomain_Registry $wp_textdomain_registry */ |
996 global $wp_textdomain_registry; |
1001 /** @var array<string, WP_Translations|NOOP_Translations> $l10n */ |
|
1002 global $wp_textdomain_registry, $l10n; |
997 |
1003 |
998 if ( ! is_string( $domain ) ) { |
1004 if ( ! is_string( $domain ) ) { |
999 return false; |
1005 return false; |
1000 } |
|
1001 |
|
1002 /** |
|
1003 * Filters a plugin's locale. |
|
1004 * |
|
1005 * @since 3.0.0 |
|
1006 * |
|
1007 * @param string $locale The plugin's current locale. |
|
1008 * @param string $domain Text domain. Unique identifier for retrieving translated strings. |
|
1009 */ |
|
1010 $locale = apply_filters( 'plugin_locale', determine_locale(), $domain ); |
|
1011 |
|
1012 $mofile = $domain . '-' . $locale . '.mo'; |
|
1013 |
|
1014 // Try to load from the languages directory first. |
|
1015 if ( load_textdomain( $domain, WP_LANG_DIR . '/plugins/' . $mofile, $locale ) ) { |
|
1016 return true; |
|
1017 } |
1006 } |
1018 |
1007 |
1019 if ( false !== $plugin_rel_path ) { |
1008 if ( false !== $plugin_rel_path ) { |
1020 $path = WP_PLUGIN_DIR . '/' . trim( $plugin_rel_path, '/' ); |
1009 $path = WP_PLUGIN_DIR . '/' . trim( $plugin_rel_path, '/' ); |
1021 } elseif ( false !== $deprecated ) { |
1010 } elseif ( false !== $deprecated ) { |
1025 $path = WP_PLUGIN_DIR; |
1014 $path = WP_PLUGIN_DIR; |
1026 } |
1015 } |
1027 |
1016 |
1028 $wp_textdomain_registry->set_custom_path( $domain, $path ); |
1017 $wp_textdomain_registry->set_custom_path( $domain, $path ); |
1029 |
1018 |
1030 return load_textdomain( $domain, $path . '/' . $mofile, $locale ); |
1019 // If just-in-time loading was triggered before, reset the entry so it can be tried again. |
|
1020 if ( isset( $l10n[ $domain ] ) && $l10n[ $domain ] instanceof NOOP_Translations ) { |
|
1021 unset( $l10n[ $domain ] ); |
|
1022 } |
|
1023 |
|
1024 return true; |
1031 } |
1025 } |
1032 |
1026 |
1033 /** |
1027 /** |
1034 * Loads the translated strings for a plugin residing in the mu-plugins directory. |
1028 * Loads the translated strings for a plugin residing in the mu-plugins directory. |
1035 * |
1029 * |
1036 * @since 3.0.0 |
1030 * @since 3.0.0 |
1037 * @since 4.6.0 The function now tries to load the .mo file from the languages directory first. |
1031 * @since 4.6.0 The function now tries to load the .mo file from the languages directory first. |
|
1032 * @since 6.7.0 Translations are no longer immediately loaded, but handed off to the just-in-time loading mechanism. |
1038 * |
1033 * |
1039 * @global WP_Textdomain_Registry $wp_textdomain_registry WordPress Textdomain Registry. |
1034 * @global WP_Textdomain_Registry $wp_textdomain_registry WordPress Textdomain Registry. |
|
1035 * @global array<string, WP_Translations|NOOP_Translations> $l10n An array of all currently loaded text domains. |
1040 * |
1036 * |
1041 * @param string $domain Text domain. Unique identifier for retrieving translated strings. |
1037 * @param string $domain Text domain. Unique identifier for retrieving translated strings. |
1042 * @param string $mu_plugin_rel_path Optional. Relative to `WPMU_PLUGIN_DIR` directory in which the .mo |
1038 * @param string $mu_plugin_rel_path Optional. Relative to `WPMU_PLUGIN_DIR` directory in which the .mo |
1043 * file resides. Default empty string. |
1039 * file resides. Default empty string. |
1044 * @return bool True when textdomain is successfully loaded, false otherwise. |
1040 * @return bool True when textdomain is successfully loaded, false otherwise. |
1045 */ |
1041 */ |
1046 function load_muplugin_textdomain( $domain, $mu_plugin_rel_path = '' ) { |
1042 function load_muplugin_textdomain( $domain, $mu_plugin_rel_path = '' ) { |
1047 /** @var WP_Textdomain_Registry $wp_textdomain_registry */ |
1043 /** @var WP_Textdomain_Registry $wp_textdomain_registry */ |
1048 global $wp_textdomain_registry; |
1044 /** @var array<string, WP_Translations|NOOP_Translations> $l10n */ |
|
1045 global $wp_textdomain_registry, $l10n; |
1049 |
1046 |
1050 if ( ! is_string( $domain ) ) { |
1047 if ( ! is_string( $domain ) ) { |
1051 return false; |
1048 return false; |
1052 } |
1049 } |
1053 |
1050 |
1054 /** This filter is documented in wp-includes/l10n.php */ |
|
1055 $locale = apply_filters( 'plugin_locale', determine_locale(), $domain ); |
|
1056 |
|
1057 $mofile = $domain . '-' . $locale . '.mo'; |
|
1058 |
|
1059 // Try to load from the languages directory first. |
|
1060 if ( load_textdomain( $domain, WP_LANG_DIR . '/plugins/' . $mofile, $locale ) ) { |
|
1061 return true; |
|
1062 } |
|
1063 |
|
1064 $path = WPMU_PLUGIN_DIR . '/' . ltrim( $mu_plugin_rel_path, '/' ); |
1051 $path = WPMU_PLUGIN_DIR . '/' . ltrim( $mu_plugin_rel_path, '/' ); |
1065 |
1052 |
1066 $wp_textdomain_registry->set_custom_path( $domain, $path ); |
1053 $wp_textdomain_registry->set_custom_path( $domain, $path ); |
1067 |
1054 |
1068 return load_textdomain( $domain, $path . '/' . $mofile, $locale ); |
1055 // If just-in-time loading was triggered before, reset the entry so it can be tried again. |
|
1056 if ( isset( $l10n[ $domain ] ) && $l10n[ $domain ] instanceof NOOP_Translations ) { |
|
1057 unset( $l10n[ $domain ] ); |
|
1058 } |
|
1059 |
|
1060 return true; |
1069 } |
1061 } |
1070 |
1062 |
1071 /** |
1063 /** |
1072 * Loads the theme's translated strings. |
1064 * Loads the theme's translated strings. |
1073 * |
1065 * |
1076 * |
1068 * |
1077 * The .mo files must be named based on the locale exactly. |
1069 * The .mo files must be named based on the locale exactly. |
1078 * |
1070 * |
1079 * @since 1.5.0 |
1071 * @since 1.5.0 |
1080 * @since 4.6.0 The function now tries to load the .mo file from the languages directory first. |
1072 * @since 4.6.0 The function now tries to load the .mo file from the languages directory first. |
|
1073 * @since 6.7.0 Translations are no longer immediately loaded, but handed off to the just-in-time loading mechanism. |
1081 * |
1074 * |
1082 * @global WP_Textdomain_Registry $wp_textdomain_registry WordPress Textdomain Registry. |
1075 * @global WP_Textdomain_Registry $wp_textdomain_registry WordPress Textdomain Registry. |
|
1076 * @global array<string, WP_Translations|NOOP_Translations> $l10n An array of all currently loaded text domains. |
1083 * |
1077 * |
1084 * @param string $domain Text domain. Unique identifier for retrieving translated strings. |
1078 * @param string $domain Text domain. Unique identifier for retrieving translated strings. |
1085 * @param string|false $path Optional. Path to the directory containing the .mo file. |
1079 * @param string|false $path Optional. Path to the directory containing the .mo file. |
1086 * Default false. |
1080 * Default false. |
1087 * @return bool True when textdomain is successfully loaded, false otherwise. |
1081 * @return bool True when textdomain is successfully loaded, false otherwise. |
1088 */ |
1082 */ |
1089 function load_theme_textdomain( $domain, $path = false ) { |
1083 function load_theme_textdomain( $domain, $path = false ) { |
1090 /** @var WP_Textdomain_Registry $wp_textdomain_registry */ |
1084 /** @var WP_Textdomain_Registry $wp_textdomain_registry */ |
1091 global $wp_textdomain_registry; |
1085 /** @var array<string, WP_Translations|NOOP_Translations> $l10n */ |
|
1086 global $wp_textdomain_registry, $l10n; |
1092 |
1087 |
1093 if ( ! is_string( $domain ) ) { |
1088 if ( ! is_string( $domain ) ) { |
1094 return false; |
1089 return false; |
1095 } |
1090 } |
1096 |
1091 |
1097 /** |
|
1098 * Filters a theme's locale. |
|
1099 * |
|
1100 * @since 3.0.0 |
|
1101 * |
|
1102 * @param string $locale The theme's current locale. |
|
1103 * @param string $domain Text domain. Unique identifier for retrieving translated strings. |
|
1104 */ |
|
1105 $locale = apply_filters( 'theme_locale', determine_locale(), $domain ); |
|
1106 |
|
1107 $mofile = $domain . '-' . $locale . '.mo'; |
|
1108 |
|
1109 // Try to load from the languages directory first. |
|
1110 if ( load_textdomain( $domain, WP_LANG_DIR . '/themes/' . $mofile, $locale ) ) { |
|
1111 return true; |
|
1112 } |
|
1113 |
|
1114 if ( ! $path ) { |
1092 if ( ! $path ) { |
1115 $path = get_template_directory(); |
1093 $path = get_template_directory(); |
1116 } |
1094 } |
1117 |
1095 |
1118 $wp_textdomain_registry->set_custom_path( $domain, $path ); |
1096 $wp_textdomain_registry->set_custom_path( $domain, $path ); |
1119 |
1097 |
1120 return load_textdomain( $domain, $path . '/' . $locale . '.mo', $locale ); |
1098 // If just-in-time loading was triggered before, reset the entry so it can be tried again. |
|
1099 if ( isset( $l10n[ $domain ] ) && $l10n[ $domain ] instanceof NOOP_Translations ) { |
|
1100 unset( $l10n[ $domain ] ); |
|
1101 } |
|
1102 |
|
1103 return true; |
1121 } |
1104 } |
1122 |
1105 |
1123 /** |
1106 /** |
1124 * Loads the child theme's translated strings. |
1107 * Loads the child theme's translated strings. |
1125 * |
1108 * |
1190 |
1173 |
1191 $src_url = wp_parse_url( $src ); |
1174 $src_url = wp_parse_url( $src ); |
1192 $content_url = wp_parse_url( content_url() ); |
1175 $content_url = wp_parse_url( content_url() ); |
1193 $plugins_url = wp_parse_url( plugins_url() ); |
1176 $plugins_url = wp_parse_url( plugins_url() ); |
1194 $site_url = wp_parse_url( site_url() ); |
1177 $site_url = wp_parse_url( site_url() ); |
|
1178 $theme_root = get_theme_root(); |
1195 |
1179 |
1196 // If the host is the same or it's a relative URL. |
1180 // If the host is the same or it's a relative URL. |
1197 if ( |
1181 if ( |
1198 ( ! isset( $content_url['path'] ) || str_starts_with( $src_url['path'], $content_url['path'] ) ) && |
1182 ( ! isset( $content_url['path'] ) || str_starts_with( $src_url['path'], $content_url['path'] ) ) && |
1199 ( ! isset( $src_url['host'] ) || ! isset( $content_url['host'] ) || $src_url['host'] === $content_url['host'] ) |
1183 ( ! isset( $src_url['host'] ) || ! isset( $content_url['host'] ) || $src_url['host'] === $content_url['host'] ) |
1205 $relative = $src_url['path']; |
1189 $relative = $src_url['path']; |
1206 } |
1190 } |
1207 $relative = trim( $relative, '/' ); |
1191 $relative = trim( $relative, '/' ); |
1208 $relative = explode( '/', $relative ); |
1192 $relative = explode( '/', $relative ); |
1209 |
1193 |
1210 $languages_path = WP_LANG_DIR . '/plugins'; |
1194 /* |
|
1195 * Ensure correct languages path when using a custom `WP_PLUGIN_DIR` / `WP_PLUGIN_URL` configuration, |
|
1196 * a custom theme root, and/or using Multisite with subdirectories. |
|
1197 * See https://core.trac.wordpress.org/ticket/60891 and https://core.trac.wordpress.org/ticket/62016. |
|
1198 */ |
|
1199 |
|
1200 $theme_dir = array_slice( explode( '/', $theme_root ), -1 ); |
|
1201 $dirname = $theme_dir[0] === $relative[0] ? 'themes' : 'plugins'; |
|
1202 |
|
1203 $languages_path = WP_LANG_DIR . '/' . $dirname; |
1211 |
1204 |
1212 $relative = array_slice( $relative, 2 ); // Remove plugins/<plugin name> or themes/<theme name>. |
1205 $relative = array_slice( $relative, 2 ); // Remove plugins/<plugin name> or themes/<theme name>. |
1213 $relative = implode( '/', $relative ); |
1206 $relative = implode( '/', $relative ); |
1214 } elseif ( |
1207 } elseif ( |
1215 ( ! isset( $plugins_url['path'] ) || str_starts_with( $src_url['path'], $plugins_url['path'] ) ) && |
1208 ( ! isset( $plugins_url['path'] ) || str_starts_with( $src_url['path'], $plugins_url['path'] ) ) && |
1371 $locale = determine_locale(); |
1364 $locale = determine_locale(); |
1372 $path = $wp_textdomain_registry->get( $domain, $locale ); |
1365 $path = $wp_textdomain_registry->get( $domain, $locale ); |
1373 if ( ! $path ) { |
1366 if ( ! $path ) { |
1374 return false; |
1367 return false; |
1375 } |
1368 } |
|
1369 |
|
1370 if ( ! doing_action( 'after_setup_theme' ) && ! did_action( 'after_setup_theme' ) ) { |
|
1371 _doing_it_wrong( |
|
1372 __FUNCTION__, |
|
1373 sprintf( |
|
1374 /* translators: 1: The text domain. 2: 'init'. */ |
|
1375 __( 'Translation loading for the %1$s domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the %2$s action or later.' ), |
|
1376 '<code>' . $domain . '</code>', |
|
1377 '<code>init</code>' |
|
1378 ), |
|
1379 '6.7.0' |
|
1380 ); |
|
1381 } |
|
1382 |
1376 // Themes with their language directory outside of WP_LANG_DIR have a different file name. |
1383 // Themes with their language directory outside of WP_LANG_DIR have a different file name. |
1377 $template_directory = trailingslashit( get_template_directory() ); |
1384 $template_directory = trailingslashit( get_template_directory() ); |
1378 $stylesheet_directory = trailingslashit( get_stylesheet_directory() ); |
1385 $stylesheet_directory = trailingslashit( get_stylesheet_directory() ); |
1379 if ( str_starts_with( $path, $template_directory ) || str_starts_with( $path, $stylesheet_directory ) ) { |
1386 if ( str_starts_with( $path, $template_directory ) || str_starts_with( $path, $stylesheet_directory ) ) { |
1380 $mofile = "{$path}{$locale}.mo"; |
1387 $mofile = "{$path}{$locale}.mo"; |