[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/ -> class-wp-textdomain-registry.php (source)

   1  <?php
   2  /**
   3   * Locale API: WP_Textdomain_Registry class.
   4   *
   5   * This file uses rtrim() instead of untrailingslashit() and trailingslashit()
   6   * to avoid formatting.php dependency.
   7   *
   8   * @package WordPress
   9   * @subpackage i18n
  10   * @since 6.1.0
  11   */
  12  
  13  /**
  14   * Core class used for registering text domains.
  15   *
  16   * @since 6.1.0
  17   */
  18  #[AllowDynamicProperties]
  19  class WP_Textdomain_Registry {
  20      /**
  21       * List of domains and all their language directory paths for each locale.
  22       *
  23       * @since 6.1.0
  24       *
  25       * @var array
  26       */
  27      protected $all = array();
  28  
  29      /**
  30       * List of domains and their language directory path for the current (most recent) locale.
  31       *
  32       * @since 6.1.0
  33       *
  34       * @var array
  35       */
  36      protected $current = array();
  37  
  38      /**
  39       * List of domains and their custom language directory paths.
  40       *
  41       * @see load_plugin_textdomain()
  42       * @see load_theme_textdomain()
  43       *
  44       * @since 6.1.0
  45       *
  46       * @var array
  47       */
  48      protected $custom_paths = array();
  49  
  50      /**
  51       * Holds a cached list of available .mo files to improve performance.
  52       *
  53       * @since 6.1.0
  54       * @since 6.5.0 This property is no longer used.
  55       *
  56       * @var array
  57       *
  58       * @deprecated
  59       */
  60      protected $cached_mo_files = array();
  61  
  62      /**
  63       * Holds a cached list of domains with translations to improve performance.
  64       *
  65       * @since 6.2.0
  66       *
  67       * @var string[]
  68       */
  69      protected $domains_with_translations = array();
  70  
  71      /**
  72       * Initializes the registry.
  73       *
  74       * Hooks into the {@see 'upgrader_process_complete'} filter
  75       * to invalidate MO files caches.
  76       *
  77       * @since 6.5.0
  78       */
  79  	public function init() {
  80          add_action( 'upgrader_process_complete', array( $this, 'invalidate_mo_files_cache' ), 10, 2 );
  81      }
  82  
  83      /**
  84       * Returns the languages directory path for a specific domain and locale.
  85       *
  86       * @since 6.1.0
  87       *
  88       * @param string $domain Text domain.
  89       * @param string $locale Locale.
  90       *
  91       * @return string|false MO file path or false if there is none available.
  92       */
  93  	public function get( $domain, $locale ) {
  94          if ( isset( $this->all[ $domain ][ $locale ] ) ) {
  95              return $this->all[ $domain ][ $locale ];
  96          }
  97  
  98          return $this->get_path_from_lang_dir( $domain, $locale );
  99      }
 100  
 101      /**
 102       * Determines whether any MO file paths are available for the domain.
 103       *
 104       * This is the case if a path has been set for the current locale,
 105       * or if there is no information stored yet, in which case
 106       * {@see _load_textdomain_just_in_time()} will fetch the information first.
 107       *
 108       * @since 6.1.0
 109       *
 110       * @param string $domain Text domain.
 111       * @return bool Whether any MO file paths are available for the domain.
 112       */
 113  	public function has( $domain ) {
 114          return (
 115              isset( $this->current[ $domain ] ) ||
 116              empty( $this->all[ $domain ] ) ||
 117              in_array( $domain, $this->domains_with_translations, true )
 118          );
 119      }
 120  
 121      /**
 122       * Sets the language directory path for a specific domain and locale.
 123       *
 124       * Also sets the 'current' property for direct access
 125       * to the path for the current (most recent) locale.
 126       *
 127       * @since 6.1.0
 128       *
 129       * @param string       $domain Text domain.
 130       * @param string       $locale Locale.
 131       * @param string|false $path   Language directory path or false if there is none available.
 132       */
 133  	public function set( $domain, $locale, $path ) {
 134          $this->all[ $domain ][ $locale ] = $path ? rtrim( $path, '/' ) . '/' : false;
 135          $this->current[ $domain ]        = $this->all[ $domain ][ $locale ];
 136      }
 137  
 138      /**
 139       * Sets the custom path to the plugin's/theme's languages directory.
 140       *
 141       * Used by {@see load_plugin_textdomain()} and {@see load_theme_textdomain()}.
 142       *
 143       * @since 6.1.0
 144       *
 145       * @param string $domain Text domain.
 146       * @param string $path   Language directory path.
 147       */
 148  	public function set_custom_path( $domain, $path ) {
 149          $this->custom_paths[ $domain ] = rtrim( $path, '/' );
 150      }
 151  
 152      /**
 153       * Retrieves translation files from the specified path.
 154       *
 155       * Allows early retrieval through the {@see 'pre_get_mo_files_from_path'} filter to optimize
 156       * performance, especially in directories with many files.
 157       *
 158       * @since 6.5.0
 159       *
 160       * @param string $path The directory path to search for translation files.
 161       * @return array Array of translation file paths. Can contain .mo and .l10n.php files.
 162       */
 163  	public function get_language_files_from_path( $path ) {
 164          $path = rtrim( $path, '/' ) . '/';
 165  
 166          /**
 167           * Filters the translation files retrieved from a specified path before the actual lookup.
 168           *
 169           * Returning a non-null value from the filter will effectively short-circuit
 170           * the MO files lookup, returning that value instead.
 171           *
 172           * This can be useful in situations where the directory contains a large number of files
 173           * and the default glob() function becomes expensive in terms of performance.
 174           *
 175           * @since 6.5.0
 176           *
 177           * @param null|array $files List of translation files. Default null.
 178           * @param string $path The path from which translation files are being fetched.
 179           **/
 180          $files = apply_filters( 'pre_get_language_files_from_path', null, $path );
 181  
 182          if ( null !== $files ) {
 183              return $files;
 184          }
 185  
 186          $cache_key = md5( $path );
 187          $files     = wp_cache_get( $cache_key, 'translation_files' );
 188  
 189          if ( false === $files ) {
 190              $files = glob( $path . '*.mo' );
 191              if ( false === $files ) {
 192                  $files = array();
 193              }
 194  
 195              $php_files = glob( $path . '*.l10n.php' );
 196              if ( is_array( $php_files ) ) {
 197                  $files = array_merge( $files, $php_files );
 198              }
 199  
 200              wp_cache_set( $cache_key, $files, 'translation_files', HOUR_IN_SECONDS );
 201          }
 202  
 203          return $files;
 204      }
 205  
 206      /**
 207       * Invalidate the cache for .mo files.
 208       *
 209       * This function deletes the cache entries related to .mo files when triggered
 210       * by specific actions, such as the completion of an upgrade process.
 211       *
 212       * @since 6.5.0
 213       *
 214       * @param WP_Upgrader $upgrader   Unused. WP_Upgrader instance. In other contexts this might be a
 215       *                                Theme_Upgrader, Plugin_Upgrader, Core_Upgrade, or Language_Pack_Upgrader instance.
 216       * @param array       $hook_extra {
 217       *     Array of bulk item update data.
 218       *
 219       *     @type string $action       Type of action. Default 'update'.
 220       *     @type string $type         Type of update process. Accepts 'plugin', 'theme', 'translation', or 'core'.
 221       *     @type bool   $bulk         Whether the update process is a bulk update. Default true.
 222       *     @type array  $plugins      Array of the basename paths of the plugins' main files.
 223       *     @type array  $themes       The theme slugs.
 224       *     @type array  $translations {
 225       *         Array of translations update data.
 226       *
 227       *         @type string $language The locale the translation is for.
 228       *         @type string $type     Type of translation. Accepts 'plugin', 'theme', or 'core'.
 229       *         @type string $slug     Text domain the translation is for. The slug of a theme/plugin or
 230       *                                'default' for core translations.
 231       *         @type string $version  The version of a theme, plugin, or core.
 232       *     }
 233       * }
 234       */
 235  	public function invalidate_mo_files_cache( $upgrader, $hook_extra ) {
 236          if (
 237              ! isset( $hook_extra['type'] ) ||
 238              'translation' !== $hook_extra['type'] ||
 239              array() === $hook_extra['translations']
 240          ) {
 241              return;
 242          }
 243  
 244          $translation_types = array_unique( wp_list_pluck( $hook_extra['translations'], 'type' ) );
 245  
 246          foreach ( $translation_types as $type ) {
 247              switch ( $type ) {
 248                  case 'plugin':
 249                      wp_cache_delete( md5( WP_LANG_DIR . '/plugins/' ), 'translation_files' );
 250                      break;
 251                  case 'theme':
 252                      wp_cache_delete( md5( WP_LANG_DIR . '/themes/' ), 'translation_files' );
 253                      break;
 254                  default:
 255                      wp_cache_delete( md5( WP_LANG_DIR . '/' ), 'translation_files' );
 256                      break;
 257              }
 258          }
 259      }
 260  
 261      /**
 262       * Returns possible language directory paths for a given text domain.
 263       *
 264       * @since 6.2.0
 265       *
 266       * @param string $domain Text domain.
 267       * @return string[] Array of language directory paths.
 268       */
 269  	private function get_paths_for_domain( $domain ) {
 270          $locations = array(
 271              WP_LANG_DIR . '/plugins',
 272              WP_LANG_DIR . '/themes',
 273          );
 274  
 275          if ( isset( $this->custom_paths[ $domain ] ) ) {
 276              $locations[] = $this->custom_paths[ $domain ];
 277          }
 278  
 279          return $locations;
 280      }
 281  
 282      /**
 283       * Gets the path to the language directory for the current domain and locale.
 284       *
 285       * Checks the plugins and themes language directories as well as any
 286       * custom directory set via {@see load_plugin_textdomain()} or {@see load_theme_textdomain()}.
 287       *
 288       * @since 6.1.0
 289       *
 290       * @see _get_path_to_translation_from_lang_dir()
 291       *
 292       * @param string $domain Text domain.
 293       * @param string $locale Locale.
 294       * @return string|false Language directory path or false if there is none available.
 295       */
 296  	private function get_path_from_lang_dir( $domain, $locale ) {
 297          $locations = $this->get_paths_for_domain( $domain );
 298  
 299          $found_location = false;
 300  
 301          foreach ( $locations as $location ) {
 302              $files = $this->get_language_files_from_path( $location );
 303  
 304              $mo_path  = "$location/$domain-$locale.mo";
 305              $php_path = "$location/$domain-$locale.l10n.php";
 306  
 307              foreach ( $files as $file_path ) {
 308                  if (
 309                      ! in_array( $domain, $this->domains_with_translations, true ) &&
 310                      str_starts_with( str_replace( "$location/", '', $file_path ), "$domain-" )
 311                  ) {
 312                      $this->domains_with_translations[] = $domain;
 313                  }
 314  
 315                  if ( $file_path === $mo_path || $file_path === $php_path ) {
 316                      $found_location = rtrim( $location, '/' ) . '/';
 317                      break 2;
 318                  }
 319              }
 320          }
 321  
 322          if ( $found_location ) {
 323              $this->set( $domain, $locale, $found_location );
 324  
 325              return $found_location;
 326          }
 327  
 328          /*
 329           * If no path is found for the given locale and a custom path has been set
 330           * using load_plugin_textdomain/load_theme_textdomain, use that one.
 331           */
 332          if ( 'en_US' !== $locale && isset( $this->custom_paths[ $domain ] ) ) {
 333              $fallback_location = rtrim( $this->custom_paths[ $domain ], '/' ) . '/';
 334              $this->set( $domain, $locale, $fallback_location );
 335              return $fallback_location;
 336          }
 337  
 338          $this->set( $domain, $locale, false );
 339  
 340          return false;
 341      }
 342  }


Generated : Fri Apr 26 08:20:02 2024 Cross-referenced by PHPXref