[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/pomo/ -> translations.php (source)

   1  <?php
   2  /**
   3   * Class for a set of entries for translation and their associated headers
   4   *
   5   * @version $Id: translations.php 1157 2015-11-20 04:30:11Z dd32 $
   6   * @package pomo
   7   * @subpackage translations
   8   * @since 2.8.0
   9   */
  10  
  11  require_once  __DIR__ . '/plural-forms.php';
  12  require_once  __DIR__ . '/entry.php';
  13  
  14  if ( ! class_exists( 'Translations', false ) ) :
  15      /**
  16       * Translations class.
  17       *
  18       * @since 2.8.0
  19       */
  20      #[AllowDynamicProperties]
  21      class Translations {
  22          /**
  23           * List of translation entries.
  24           *
  25           * @since 2.8.0
  26           *
  27           * @var Translation_Entry[]
  28           */
  29          public $entries = array();
  30  
  31          /**
  32           * List of translation headers.
  33           *
  34           * @since 2.8.0
  35           *
  36           * @var array<string, string>
  37           */
  38          public $headers = array();
  39  
  40          /**
  41           * Adds an entry to the PO structure.
  42           *
  43           * @since 2.8.0
  44           *
  45           * @param array|Translation_Entry $entry
  46           * @return bool True on success, false if the entry doesn't have a key.
  47           */
  48  		public function add_entry( $entry ) {
  49              if ( is_array( $entry ) ) {
  50                  $entry = new Translation_Entry( $entry );
  51              }
  52              $key = $entry->key();
  53              if ( false === $key ) {
  54                  return false;
  55              }
  56              $this->entries[ $key ] = &$entry;
  57              return true;
  58          }
  59  
  60          /**
  61           * Adds or merges an entry to the PO structure.
  62           *
  63           * @since 2.8.0
  64           *
  65           * @param array|Translation_Entry $entry
  66           * @return bool True on success, false if the entry doesn't have a key.
  67           */
  68  		public function add_entry_or_merge( $entry ) {
  69              if ( is_array( $entry ) ) {
  70                  $entry = new Translation_Entry( $entry );
  71              }
  72              $key = $entry->key();
  73              if ( false === $key ) {
  74                  return false;
  75              }
  76              if ( isset( $this->entries[ $key ] ) ) {
  77                  $this->entries[ $key ]->merge_with( $entry );
  78              } else {
  79                  $this->entries[ $key ] = &$entry;
  80              }
  81              return true;
  82          }
  83  
  84          /**
  85           * Sets $header PO header to $value
  86           *
  87           * If the header already exists, it will be overwritten
  88           *
  89           * TODO: this should be out of this class, it is gettext specific
  90           *
  91           * @since 2.8.0
  92           *
  93           * @param string $header header name, without trailing :
  94           * @param string $value header value, without trailing \n
  95           */
  96  		public function set_header( $header, $value ) {
  97              $this->headers[ $header ] = $value;
  98          }
  99  
 100          /**
 101           * Sets translation headers.
 102           *
 103           * @since 2.8.0
 104           *
 105           * @param array $headers Associative array of headers.
 106           */
 107  		public function set_headers( $headers ) {
 108              foreach ( $headers as $header => $value ) {
 109                  $this->set_header( $header, $value );
 110              }
 111          }
 112  
 113          /**
 114           * Returns a given translation header.
 115           *
 116           * @since 2.8.0
 117           *
 118           * @param string $header
 119           * @return string|false Header if it exists, false otherwise.
 120           */
 121  		public function get_header( $header ) {
 122              return isset( $this->headers[ $header ] ) ? $this->headers[ $header ] : false;
 123          }
 124  
 125          /**
 126           * Returns a given translation entry.
 127           *
 128           * @since 2.8.0
 129           *
 130           * @param Translation_Entry $entry Translation entry.
 131           * @return Translation_Entry|false Translation entry if it exists, false otherwise.
 132           */
 133  		public function translate_entry( &$entry ) {
 134              $key = $entry->key();
 135              return isset( $this->entries[ $key ] ) ? $this->entries[ $key ] : false;
 136          }
 137  
 138          /**
 139           * Translates a singular string.
 140           *
 141           * @since 2.8.0
 142           *
 143           * @param string $singular
 144           * @param string $context
 145           * @return string
 146           */
 147  		public function translate( $singular, $context = null ) {
 148              $entry      = new Translation_Entry(
 149                  array(
 150                      'singular' => $singular,
 151                      'context'  => $context,
 152                  )
 153              );
 154              $translated = $this->translate_entry( $entry );
 155              return ( $translated && ! empty( $translated->translations ) ) ? $translated->translations[0] : $singular;
 156          }
 157  
 158          /**
 159           * Given the number of items, returns the 0-based index of the plural form to use
 160           *
 161           * Here, in the base Translations class, the common logic for English is implemented:
 162           *  0 if there is one element, 1 otherwise
 163           *
 164           * This function should be overridden by the subclasses. For example MO/PO can derive the logic
 165           * from their headers.
 166           *
 167           * @since 2.8.0
 168           *
 169           * @param int $count Number of items.
 170           * @return int Plural form to use.
 171           */
 172  		public function select_plural_form( $count ) {
 173              return 1 === (int) $count ? 0 : 1;
 174          }
 175  
 176          /**
 177           * Returns the plural forms count.
 178           *
 179           * @since 2.8.0
 180           *
 181           * @return int Plural forms count.
 182           */
 183  		public function get_plural_forms_count() {
 184              return 2;
 185          }
 186  
 187          /**
 188           * Translates a plural string.
 189           *
 190           * @since 2.8.0
 191           *
 192           * @param string $singular
 193           * @param string $plural
 194           * @param int    $count
 195           * @param string $context
 196           * @return string
 197           */
 198  		public function translate_plural( $singular, $plural, $count, $context = null ) {
 199              $entry              = new Translation_Entry(
 200                  array(
 201                      'singular' => $singular,
 202                      'plural'   => $plural,
 203                      'context'  => $context,
 204                  )
 205              );
 206              $translated         = $this->translate_entry( $entry );
 207              $index              = $this->select_plural_form( $count );
 208              $total_plural_forms = $this->get_plural_forms_count();
 209              if ( $translated && 0 <= $index && $index < $total_plural_forms &&
 210                  is_array( $translated->translations ) &&
 211                  isset( $translated->translations[ $index ] ) ) {
 212                  return $translated->translations[ $index ];
 213              } else {
 214                  return 1 === (int) $count ? $singular : $plural;
 215              }
 216          }
 217  
 218          /**
 219           * Merges other translations into the current one.
 220           *
 221           * @since 2.8.0
 222           *
 223           * @param Translations $other Another Translation object, whose translations will be merged in this one (passed by reference).
 224           */
 225  		public function merge_with( &$other ) {
 226              foreach ( $other->entries as $entry ) {
 227                  $this->entries[ $entry->key() ] = $entry;
 228              }
 229          }
 230  
 231          /**
 232           * Merges originals with existing entries.
 233           *
 234           * @since 2.8.0
 235           *
 236           * @param Translations $other
 237           */
 238  		public function merge_originals_with( &$other ) {
 239              foreach ( $other->entries as $entry ) {
 240                  if ( ! isset( $this->entries[ $entry->key() ] ) ) {
 241                      $this->entries[ $entry->key() ] = $entry;
 242                  } else {
 243                      $this->entries[ $entry->key() ]->merge_with( $entry );
 244                  }
 245              }
 246          }
 247      }
 248  
 249      /**
 250       * Gettext_Translations class.
 251       *
 252       * @since 2.8.0
 253       */
 254      class Gettext_Translations extends Translations {
 255  
 256          /**
 257           * Number of plural forms.
 258           *
 259           * @var int
 260           *
 261           * @since 2.8.0
 262           */
 263          public $_nplurals;
 264  
 265          /**
 266           * Callback to retrieve the plural form.
 267           *
 268           * @var callable
 269           *
 270           * @since 2.8.0
 271           */
 272          public $_gettext_select_plural_form;
 273  
 274          /**
 275           * The gettext implementation of select_plural_form.
 276           *
 277           * It lives in this class, because there are more than one descendant, which will use it and
 278           * they can't share it effectively.
 279           *
 280           * @since 2.8.0
 281           *
 282           * @param int $count Plural forms count.
 283           * @return int Plural form to use.
 284           */
 285  		public function gettext_select_plural_form( $count ) {
 286              if ( ! isset( $this->_gettext_select_plural_form ) || is_null( $this->_gettext_select_plural_form ) ) {
 287                  list( $nplurals, $expression )     = $this->nplurals_and_expression_from_header( $this->get_header( 'Plural-Forms' ) );
 288                  $this->_nplurals                   = $nplurals;
 289                  $this->_gettext_select_plural_form = $this->make_plural_form_function( $nplurals, $expression );
 290              }
 291              return call_user_func( $this->_gettext_select_plural_form, $count );
 292          }
 293  
 294          /**
 295           * Returns the nplurals and plural forms expression from the Plural-Forms header.
 296           *
 297           * @since 2.8.0
 298           *
 299           * @param string $header
 300           * @return array{0: int, 1: string}
 301           */
 302  		public function nplurals_and_expression_from_header( $header ) {
 303              if ( preg_match( '/^\s*nplurals\s*=\s*(\d+)\s*;\s+plural\s*=\s*(.+)$/', $header, $matches ) ) {
 304                  $nplurals   = (int) $matches[1];
 305                  $expression = trim( $matches[2] );
 306                  return array( $nplurals, $expression );
 307              } else {
 308                  return array( 2, 'n != 1' );
 309              }
 310          }
 311  
 312          /**
 313           * Makes a function, which will return the right translation index, according to the
 314           * plural forms header.
 315           *
 316           * @since 2.8.0
 317           *
 318           * @param int    $nplurals
 319           * @param string $expression
 320           * @return callable
 321           */
 322  		public function make_plural_form_function( $nplurals, $expression ) {
 323              try {
 324                  $handler = new Plural_Forms( rtrim( $expression, ';' ) );
 325                  return array( $handler, 'get' );
 326              } catch ( Exception $e ) {
 327                  // Fall back to default plural-form function.
 328                  return $this->make_plural_form_function( 2, 'n != 1' );
 329              }
 330          }
 331  
 332          /**
 333           * Adds parentheses to the inner parts of ternary operators in
 334           * plural expressions, because PHP evaluates ternary operators from left to right
 335           *
 336           * @since 2.8.0
 337           * @deprecated 6.5.0 Use the Plural_Forms class instead.
 338           *
 339           * @see Plural_Forms
 340           *
 341           * @param string $expression the expression without parentheses
 342           * @return string the expression with parentheses added
 343           */
 344  		public function parenthesize_plural_exression( $expression ) {
 345              $expression .= ';';
 346              $res         = '';
 347              $depth       = 0;
 348              for ( $i = 0; $i < strlen( $expression ); ++$i ) {
 349                  $char = $expression[ $i ];
 350                  switch ( $char ) {
 351                      case '?':
 352                          $res .= ' ? (';
 353                          ++$depth;
 354                          break;
 355                      case ':':
 356                          $res .= ') : (';
 357                          break;
 358                      case ';':
 359                          $res  .= str_repeat( ')', $depth ) . ';';
 360                          $depth = 0;
 361                          break;
 362                      default:
 363                          $res .= $char;
 364                  }
 365              }
 366              return rtrim( $res, ';' );
 367          }
 368  
 369          /**
 370           * Prepare translation headers.
 371           *
 372           * @since 2.8.0
 373           *
 374           * @param string $translation
 375           * @return array<string, string> Translation headers
 376           */
 377  		public function make_headers( $translation ) {
 378              $headers = array();
 379              // Sometimes \n's are used instead of real new lines.
 380              $translation = str_replace( '\n', "\n", $translation );
 381              $lines       = explode( "\n", $translation );
 382              foreach ( $lines as $line ) {
 383                  $parts = explode( ':', $line, 2 );
 384                  if ( ! isset( $parts[1] ) ) {
 385                      continue;
 386                  }
 387                  $headers[ trim( $parts[0] ) ] = trim( $parts[1] );
 388              }
 389              return $headers;
 390          }
 391  
 392          /**
 393           * Sets translation headers.
 394           *
 395           * @since 2.8.0
 396           *
 397           * @param string $header
 398           * @param string $value
 399           */
 400  		public function set_header( $header, $value ) {
 401              parent::set_header( $header, $value );
 402              if ( 'Plural-Forms' === $header ) {
 403                  list( $nplurals, $expression )     = $this->nplurals_and_expression_from_header( $this->get_header( 'Plural-Forms' ) );
 404                  $this->_nplurals                   = $nplurals;
 405                  $this->_gettext_select_plural_form = $this->make_plural_form_function( $nplurals, $expression );
 406              }
 407          }
 408      }
 409  endif;
 410  
 411  if ( ! class_exists( 'NOOP_Translations', false ) ) :
 412      /**
 413       * Provides the same interface as Translations, but doesn't do anything.
 414       *
 415       * @since 2.8.0
 416       */
 417      #[AllowDynamicProperties]
 418      class NOOP_Translations {
 419          /**
 420           * List of translation entries.
 421           *
 422           * @since 2.8.0
 423           *
 424           * @var Translation_Entry[]
 425           */
 426          public $entries = array();
 427  
 428          /**
 429           * List of translation headers.
 430           *
 431           * @since 2.8.0
 432           *
 433           * @var array<string, string>
 434           */
 435          public $headers = array();
 436  
 437  		public function add_entry( $entry ) {
 438              return true;
 439          }
 440  
 441          /**
 442           * Sets a translation header.
 443           *
 444           * @since 2.8.0
 445           *
 446           * @param string $header
 447           * @param string $value
 448           */
 449  		public function set_header( $header, $value ) {
 450          }
 451  
 452          /**
 453           * Sets translation headers.
 454           *
 455           * @since 2.8.0
 456           *
 457           * @param array $headers
 458           */
 459  		public function set_headers( $headers ) {
 460          }
 461  
 462          /**
 463           * Returns a translation header.
 464           *
 465           * @since 2.8.0
 466           *
 467           * @param string $header
 468           * @return false
 469           */
 470  		public function get_header( $header ) {
 471              return false;
 472          }
 473  
 474          /**
 475           * Returns a given translation entry.
 476           *
 477           * @since 2.8.0
 478           *
 479           * @param Translation_Entry $entry
 480           * @return false
 481           */
 482  		public function translate_entry( &$entry ) {
 483              return false;
 484          }
 485  
 486          /**
 487           * Translates a singular string.
 488           *
 489           * @since 2.8.0
 490           *
 491           * @param string $singular
 492           * @param string $context
 493           */
 494  		public function translate( $singular, $context = null ) {
 495              return $singular;
 496          }
 497  
 498          /**
 499           * Returns the plural form to use.
 500           *
 501           * @since 2.8.0
 502           *
 503           * @param int $count
 504           * @return int
 505           */
 506  		public function select_plural_form( $count ) {
 507              return 1 === (int) $count ? 0 : 1;
 508          }
 509  
 510          /**
 511           * Returns the plural forms count.
 512           *
 513           * @since 2.8.0
 514           *
 515           * @return int
 516           */
 517  		public function get_plural_forms_count() {
 518              return 2;
 519          }
 520  
 521          /**
 522           * Translates a plural string.
 523           *
 524           * @since 2.8.0
 525           *
 526           * @param string $singular
 527           * @param string $plural
 528           * @param int    $count
 529           * @param string $context
 530           * @return string
 531           */
 532  		public function translate_plural( $singular, $plural, $count, $context = null ) {
 533              return 1 === (int) $count ? $singular : $plural;
 534          }
 535  
 536          /**
 537           * Merges other translations into the current one.
 538           *
 539           * @since 2.8.0
 540           *
 541           * @param Translations $other
 542           */
 543  		public function merge_with( &$other ) {
 544          }
 545      }
 546  endif;


Generated : Sat Dec 21 08:20:01 2024 Cross-referenced by PHPXref