+/**
+ * Loads plugin and theme textdomains just-in-time.
+ *
+ * When a textdomain is encountered for the first time, we try to load
+ * the translation file from `wp-content/languages`, removing the need
+ * to call load_plugin_texdomain() or load_theme_texdomain().
+ *
+ * @since 4.6.0
+ * @access private
+ *
+ * @see get_translations_for_domain()
+ * @global array $l10n_unloaded An array of all text domains that have been unloaded again.
+ *
+ * @param string $domain Text domain. Unique identifier for retrieving translated strings.
+ * @return bool True when the textdomain is successfully loaded, false otherwise.
+ */
+function _load_textdomain_just_in_time( $domain ) {
+ global $l10n_unloaded;
+
+ $l10n_unloaded = (array) $l10n_unloaded;
+
+ // Short-circuit if domain is 'default' which is reserved for core.
+ if ( 'default' === $domain || isset( $l10n_unloaded[ $domain ] ) ) {
+ return false;
+ }
+
+ $translation_path = _get_path_to_translation( $domain );
+ if ( false === $translation_path ) {
+ return false;
+ }
+
+ return load_textdomain( $domain, $translation_path );
+}
+
+/**
+ * Gets the path to a translation file for loading a textdomain just in time.
+ *
+ * Caches the retrieved results internally.
+ *
+ * @since 4.7.0
+ * @access private
+ *
+ * @see _load_textdomain_just_in_time()
+ *
+ * @param string $domain Text domain. Unique identifier for retrieving translated strings.
+ * @param bool $reset Whether to reset the internal cache. Used by the switch to locale functionality.
+ * @return string|false The path to the translation file or false if no translation file was found.
+ */
+function _get_path_to_translation( $domain, $reset = false ) {
+ static $available_translations = array();
+
+ if ( true === $reset ) {
+ $available_translations = array();
+ }
+
+ if ( ! isset( $available_translations[ $domain ] ) ) {
+ $available_translations[ $domain ] = _get_path_to_translation_from_lang_dir( $domain );
+ }
+
+ return $available_translations[ $domain ];
+}
+
+/**
+ * Gets the path to a translation file in the languages directory for the current locale.
+ *
+ * Holds a cached list of available .mo files to improve performance.
+ *
+ * @since 4.7.0
+ * @access private
+ *
+ * @see _get_path_to_translation()
+ *
+ * @param string $domain Text domain. Unique identifier for retrieving translated strings.
+ * @return string|false The path to the translation file or false if no translation file was found.
+ */
+function _get_path_to_translation_from_lang_dir( $domain ) {
+ static $cached_mofiles = null;
+
+ if ( null === $cached_mofiles ) {
+ $cached_mofiles = array();
+
+ $locations = array(
+ WP_LANG_DIR . '/plugins',
+ WP_LANG_DIR . '/themes',
+ );
+
+ foreach ( $locations as $location ) {
+ $mofiles = glob( $location . '/*.mo' );
+ if ( $mofiles ) {
+ $cached_mofiles = array_merge( $cached_mofiles, $mofiles );
+ }
+ }
+ }
+
+ $locale = is_admin() ? get_user_locale() : get_locale();
+ $mofile = "{$domain}-{$locale}.mo";
+
+ $path = WP_LANG_DIR . '/plugins/' . $mofile;
+ if ( in_array( $path, $cached_mofiles ) ) {
+ return $path;
+ }
+
+ $path = WP_LANG_DIR . '/themes/' . $mofile;
+ if ( in_array( $path, $cached_mofiles ) ) {
+ return $path;
+ }
+
+ return false;
+}
+