/**
  * Converts the special plural syntax to array or ruby style plurals
  *
  * @param string $key Message key prefix
  * @param string $message The plural string
  *
  * @return bool|array
  */
 public function unflattenPlural($key, $message)
 {
     // Quick escape.
     if (strpos($message, '{{PLURAL') === false) {
         return array($key => $message);
     }
     /*
      * Replace all variables with placeholders. Possible source of bugs
      * if other characters that given below are used.
      */
     $regex = '~\\{[a-zA-Z_-]+}~';
     $placeholders = array();
     $match = array();
     while (preg_match($regex, $message, $match)) {
         $uniqkey = TranslateUtils::getPlaceholder();
         $placeholders[$uniqkey] = $match[0];
         $search = preg_quote($match[0], '~');
         $message = preg_replace("~{$search}~", $uniqkey, $message);
     }
     // Then replace (possible multiple) plural instances into placeholders.
     $regex = '~\\{\\{PLURAL\\|(.*?)}}~s';
     $matches = array();
     $match = array();
     while (preg_match($regex, $message, $match)) {
         $uniqkey = TranslateUtils::getPlaceholder();
         $matches[$uniqkey] = $match;
         $message = preg_replace($regex, $uniqkey, $message, 1);
     }
     // No plurals, should not happen.
     if (!count($matches)) {
         return false;
     }
     // The final array of alternative plurals forms.
     $alts = array();
     /*
      * Then loop trough each plural block and replacing the placeholders
      * to construct the alternatives. Produces invalid output if there is
      * multiple plural bocks which don't have the same set of keys.
      */
     $pluralChoice = implode('|', array_keys(self::$pluralWords));
     $regex = "~({$pluralChoice})\\s*=\\s*(.+)~s";
     foreach ($matches as $ph => $plu) {
         $forms = explode('|', $plu[1]);
         foreach ($forms as $form) {
             if ($form === '') {
                 continue;
             }
             $match = array();
             if (preg_match($regex, $form, $match)) {
                 $formWord = "{$key}.{$match[1]}";
                 $value = $match[2];
             } else {
                 $formWord = "{$key}.other";
                 $value = $form;
             }
             if (!isset($alts[$formWord])) {
                 $alts[$formWord] = $message;
             }
             $string = $alts[$formWord];
             $alts[$formWord] = str_replace($ph, $value, $string);
         }
     }
     // Replace other variables.
     foreach ($alts as &$value) {
         $value = str_replace(array_keys($placeholders), array_values($placeholders), $value);
     }
     if (!isset($alts["{$key}.other"])) {
         wfWarn("Other not set for key {$key}");
         return false;
     }
     return $alts;
 }
 /**
  * Splits the content marked with \<translate> tags into sections, which
  * are separated with with two or more newlines. Extra whitespace is captured
  * in the template and not included in the sections.
  * @param array $sections Array of placeholder => TPSection.
  * @param string $text Contents of one pair of \<translate> tags.
  * @return string Template with placeholders for sections, which itself are added to $sections.
  */
 protected function sectionise(&$sections, $text)
 {
     $flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE;
     $parts = preg_split('~(\\s*\\n\\n\\s*|\\s*$)~', $text, -1, $flags);
     $template = '';
     foreach ($parts as $_) {
         if (trim($_) === '') {
             $template .= $_;
         } else {
             $ph = TranslateUtils::getPlaceholder();
             $sections[$ph] = $this->shakeSection($_);
             $template .= $ph;
         }
     }
     return $template;
 }
 protected function splitPlural($text, $forms)
 {
     if ($forms === 1) {
         return $text;
     }
     $placeholder = TranslateUtils::getPlaceholder();
     # |/| is commonly used in KDE to support inflections
     $text = str_replace('|/|', $placeholder, $text);
     $plurals = array();
     $match = preg_match_all('/{{PLURAL:GETTEXT\\|(.*)}}/iUs', $text, $plurals);
     if (!$match) {
         throw new GettextPluralException("Failed to find plural in: {$text}");
     }
     $splitPlurals = array();
     for ($i = 0; $i < $forms; $i++) {
         # Start with the hole string
         $pluralForm = $text;
         # Loop over *each* {{PLURAL}} instance and replace
         # it with the plural form belonging to this index
         foreach ($plurals[0] as $index => $definition) {
             $parsedFormsArray = explode('|', $plurals[1][$index]);
             if (!isset($parsedFormsArray[$i])) {
                 error_log("Too few plural forms in: {$text}");
                 $pluralForm = '';
             } else {
                 $pluralForm = str_replace($pluralForm, $definition, $parsedFormsArray[$i]);
             }
         }
         $pluralForm = str_replace($placeholder, '|/|', $pluralForm);
         $splitPlurals[$i] = $pluralForm;
     }
     return $splitPlurals;
 }
 /**
  * Converts the flattened plural into messages
  *
  * @param string $message
  * @return array
  */
 protected function unflattenPlural($message)
 {
     $regex = '~\\{\\{PLURAL\\|(.*?)}}~s';
     $matches = array();
     $match = array();
     while (preg_match($regex, $message, $match)) {
         $uniqkey = TranslateUtils::getPlaceholder();
         $matches[$uniqkey] = $match;
         $message = preg_replace($regex, $uniqkey, $message, 1);
     }
     // No plurals, should not happen.
     if (!count($matches)) {
         return array();
     }
     // The final array of alternative plurals forms.
     $alts = array();
     /*
      * Then loop trough each plural block and replacing the placeholders
      * to construct the alternatives. Produces invalid output if there is
      * multiple plural bocks which don't have the same set of keys.
      */
     $pluralChoice = implode('|', array_keys(self::$pluralWords));
     $regex = "~({$pluralChoice})\\s*=\\s*(.+)~s";
     foreach ($matches as $ph => $plu) {
         $forms = explode('|', $plu[1]);
         foreach ($forms as $form) {
             if ($form === '') {
                 continue;
             }
             $match = array();
             if (!preg_match($regex, $form, $match)) {
                 // No quantity key was provided
                 continue;
             }
             $formWord = $match[1];
             $value = $match[2];
             if (!isset($alts[$formWord])) {
                 $alts[$formWord] = $message;
             }
             $string = $alts[$formWord];
             $alts[$formWord] = str_replace($ph, $value, $string);
         }
     }
     return $alts;
 }
 public function __construct()
 {
     parent::__construct('SearchTranslations');
     $this->hl = array(TranslateUtils::getPlaceholder(), TranslateUtils::getPlaceholder());
 }