Exemplo n.º 1
0
 /**
  * Dumps a given PHP variable to a YAML string.
  *
  * @param mixed $value The PHP variable to convert
  *
  * @return string The YAML string representing the PHP array
  *
  * @throws DumpException When trying to dump PHP resource
  */
 public static function dump($value)
 {
     switch (true) {
         case is_resource($value):
             throw new DumpException(sprintf('Unable to dump PHP resources in a YAML file ("%s").', get_resource_type($value)));
         case is_object($value):
             return '!!php/object:' . serialize($value);
         case is_array($value):
             return self::dumpArray($value);
         case null === $value:
             return 'null';
         case true === $value:
             return 'true';
         case false === $value:
             return 'false';
         case ctype_digit($value):
             return is_string($value) ? "'{$value}'" : (int) $value;
         case is_numeric($value):
             return is_string($value) ? "'{$value}'" : (is_infinite($value) ? str_ireplace('INF', '.Inf', strval($value)) : $value);
         case Escaper::requiresDoubleQuoting($value):
             return Escaper::escapeWithDoubleQuotes($value);
         case Escaper::requiresSingleQuoting($value):
             return Escaper::escapeWithSingleQuotes($value);
         case '' == $value:
             return "''";
         case preg_match(self::getTimestampRegex(), $value):
         case in_array(strtolower($value), array('null', '~', 'true', 'false')):
             return "'{$value}'";
         default:
             return $value;
     }
 }
Exemplo n.º 2
0
 public static function dump($value, $exceptionOnInvalidType = false, $objectSupport = false)
 {
     switch (true) {
         case is_resource($value):
             if ($exceptionOnInvalidType) {
                 throw new DumpException(sprintf('Unable to dump PHP resources in a YAML file ("%s").', get_resource_type($value)));
             }
             return 'null';
         case is_object($value):
             if ($objectSupport) {
                 return '!!php/object:' . serialize($value);
             }
             if ($exceptionOnInvalidType) {
                 throw new DumpException('Object support when dumping a YAML file has been disabled.');
             }
             return 'null';
         case is_array($value):
             return self::dumpArray($value, $exceptionOnInvalidType, $objectSupport);
         case null === $value:
             return 'null';
         case true === $value:
             return 'true';
         case false === $value:
             return 'false';
         case ctype_digit($value):
             return is_string($value) ? "'{$value}'" : (int) $value;
         case is_numeric($value):
             $locale = setlocale(LC_NUMERIC, 0);
             if (false !== $locale) {
                 setlocale(LC_NUMERIC, 'C');
             }
             $repr = is_string($value) ? "'{$value}'" : (is_infinite($value) ? str_ireplace('INF', '.Inf', strval($value)) : strval($value));
             if (false !== $locale) {
                 setlocale(LC_NUMERIC, $locale);
             }
             return $repr;
         case Escaper::requiresDoubleQuoting($value):
             return Escaper::escapeWithDoubleQuotes($value);
         case Escaper::requiresSingleQuoting($value):
             return Escaper::escapeWithSingleQuotes($value);
         case '' == $value:
             return "''";
         case preg_match(self::getTimestampRegex(), $value):
         case in_array(strtolower($value), array('null', '~', 'true', 'false')):
             return "'{$value}'";
         default:
             return $value;
     }
 }
Exemplo n.º 3
0
Arquivo: lib.php Projeto: LeonB/site
/**
 * Find all twig templates and bolt php code, extract translatables
 * strings, merge with existing translations, return
 */
function gatherTranslatableStrings($locale = null, $translated = array())
{
    global $app;
    $isPhp = function ($fname) {
        return pathinfo(strtolower($fname), PATHINFO_EXTENSION) == 'php';
    };
    $isTwig = function ($fname) {
        return pathinfo(strtolower($fname), PATHINFO_EXTENSION) == 'twig';
    };
    $ctypes = $app['config']->get('contenttypes');
    // function that generates a string for each variation of contenttype/contenttypes
    $genContentTypes = function ($txt) use($ctypes) {
        $stypes = array();
        if (strpos($txt, '%contenttypes%') !== false) {
            foreach ($ctypes as $key => $ctype) {
                $stypes[] = str_replace('%contenttypes%', $ctype['name'], $txt);
            }
        }
        if (strpos($txt, '%contenttype%') !== false) {
            foreach ($ctypes as $key => $ctype) {
                $stypes[] = str_replace('%contenttype%', $ctype['singular_name'], $txt);
            }
        }
        return $stypes;
    };
    // Step one: gather all translatable strings
    $finder = new Finder();
    $finder->files()->ignoreVCS(true)->name('*.twig')->name('*.php')->notName('*~')->exclude(array('cache', 'config', 'database', 'resources', 'tests'))->in(dirname($app['paths']['themepath']))->in($app['paths']['apppath']);
    // regex from: stackoverflow.com/questions/5695240/php-regex-to-ignore-escaped-quotes-within-quotes
    $re_dq = '/"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"/s';
    $re_sq = "/'[^'\\\\]*(?:\\\\.[^'\\\\]*)*'/s";
    $nstr = 0;
    $strings = array();
    foreach ($finder as $file) {
        $s = file_get_contents($file);
        // Scan twig templates for  __('...' and __("..."
        if ($isTwig($file)) {
            // __('single_quoted_string'...
            if (preg_match_all("/\\b__\\(\\s*'([^'\\\\]*(?:\\\\.[^'\\\\]*)*)'(?U).*\\)/s", $s, $matches)) {
                //print_r($matches[1]);
                foreach ($matches[1] as $t) {
                    $nstr++;
                    if (!in_array($t, $strings) && strlen($t) > 1) {
                        $strings[] = $t;
                        sort($strings);
                    }
                }
            }
            // __("double_quoted_string"...
            if (preg_match_all('/\\b__\\(\\s*"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"(?U).*\\)/s', $s, $matches)) {
                //print_r($matches[1]);
                foreach ($matches[1] as $t) {
                    $nstr++;
                    if (!in_array($t, $strings) && strlen($t) > 1) {
                        $strings[] = $t;
                        sort($strings);
                    }
                }
            }
        }
        // php :
        /** all translatables strings have to be called with:
         *  __("text", $params=array(), $domain='messages', locale=null) // $app['translator']->trans()
         *  __("text", count, $params=array(), $domain='messages', locale=null) // $app['translator']->transChoice()
         */
        if ($isPhp($file)) {
            $tokens = token_get_all($s);
            $num_tokens = count($tokens);
            for ($x = 0; $x < $num_tokens; $x++) {
                $token = $tokens[$x];
                if (is_array($token) && $token[0] == T_STRING && $token[1] == '__') {
                    $token = $tokens[++$x];
                    if ($x < $num_tokens && is_array($token) && $token[0] == T_WHITESPACE) {
                        $token = $tokens[++$x];
                    }
                    if ($x < $num_tokens && !is_array($token) && $token == '(') {
                        // in our func args...
                        $token = $tokens[++$x];
                        if ($x < $num_tokens && is_array($token) && $token[0] == T_WHITESPACE) {
                            $token = $tokens[++$x];
                        }
                        if (!is_array($token)) {
                            // give up
                            continue;
                        }
                        if ($token[0] == T_CONSTANT_ENCAPSED_STRING) {
                            $t = substr($token[1], 1, strlen($token[1]) - 2);
                            $nstr++;
                            if (!in_array($t, $strings) && strlen($t) > 1) {
                                $strings[] = $t;
                                sort($strings);
                            }
                            // TODO: retrieve domain?
                        }
                    }
                }
            }
            // end for $x
        }
    }
    // Add fields name|label for contenttype (forms)
    foreach ($ctypes as $ckey => $contenttype) {
        foreach ($contenttype['fields'] as $fkey => $field) {
            if (isset($field['label'])) {
                $t = $field['label'];
            } else {
                $t = ucfirst($fkey);
            }
            if (!in_array($t, $strings) && strlen($t) > 1) {
                $strings[] = $t;
            }
        }
        // Relation name|label if exists
        if (array_key_exists('relations', $contenttype)) {
            foreach ($contenttype['relations'] as $fkey => $field) {
                if (isset($field['label'])) {
                    $t = $field['label'];
                } else {
                    $t = ucfirst($fkey);
                }
                if (!in_array($t, $strings) && strlen($t) > 1) {
                    $strings[] = $t;
                }
            }
        }
    }
    // Add name + singular_name for taxonomies
    foreach ($app['config']->get('taxonomy') as $txkey => $value) {
        foreach (array('name', 'singular_name') as $key) {
            $t = $value[$key];
            if (!in_array($t, $strings)) {
                $strings[] = $t;
            }
        }
    }
    // Return the previously translated string if exists,
    // Return an empty string otherwise
    $getTranslated = function ($key) use($app, $translated) {
        if (($trans = $app['translator']->trans($key)) == $key) {
            if (is_array($translated) && array_key_exists($key, $translated) && !empty($translated[$key])) {
                return $translated[$key];
            }
            return '';
        }
        return $trans;
    };
    // Step 2: find already translated strings
    sort($strings);
    if (!$locale) {
        $locale = $app['request']->getLocale();
    }
    $msg_domain = array('translated' => array(), 'not_translated' => array());
    $ctype_domain = array('translated' => array(), 'not_translated' => array());
    foreach ($strings as $idx => $key) {
        $key = stripslashes($key);
        $raw_key = $key;
        $key = Escaper::escapeWithDoubleQuotes($key);
        if (($trans = $getTranslated($raw_key)) == '' && ($trans = $getTranslated($key)) == '') {
            $msg_domain['not_translated'][] = $key;
        } else {
            $trans = Escaper::escapeWithDoubleQuotes($trans);
            $msg_domain['translated'][$key] = $trans;
        }
        // Step 3: generate additionals strings for contenttypes
        if (strpos($raw_key, '%contenttype%') !== false || strpos($raw_key, '%contenttypes%') !== false) {
            foreach ($genContentTypes($raw_key) as $ctypekey) {
                $key = Escaper::escapeWithDoubleQuotes($ctypekey);
                if (($trans = $getTranslated($ctypekey)) == '' && ($trans = $getTranslated($key)) == '') {
                    // Not translated
                    $ctype_domain['not_translated'][] = $key;
                } else {
                    $trans = Escaper::escapeWithDoubleQuotes($trans);
                    $ctype_domain['translated'][$key] = $trans;
                }
            }
        }
    }
    sort($msg_domain['not_translated']);
    ksort($msg_domain['translated']);
    sort($ctype_domain['not_translated']);
    ksort($ctype_domain['translated']);
    return array($msg_domain, $ctype_domain);
}
Exemplo n.º 4
0
 /**
  * Dumps a given PHP variable to a YAML string.
  *
  * @param mixed $value The PHP variable to convert
  * @param int   $flags A bit field of Yaml::DUMP_* constants to customize the dumped YAML string
  *
  * @return string The YAML string representing the PHP array
  *
  * @throws DumpException When trying to dump PHP resource
  */
 public static function dump($value, $flags = 0)
 {
     if (is_bool($flags)) {
         @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED);
         if ($flags) {
             $flags = Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE;
         } else {
             $flags = 0;
         }
     }
     if (func_num_args() >= 3) {
         @trigger_error('Passing a boolean flag to toggle object support is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::DUMP_OBJECT flag instead.', E_USER_DEPRECATED);
         if (func_get_arg(2)) {
             $flags |= Yaml::DUMP_OBJECT;
         }
     }
     switch (true) {
         case is_resource($value):
             if (Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE & $flags) {
                 throw new DumpException(sprintf('Unable to dump PHP resources in a YAML file ("%s").', get_resource_type($value)));
             }
             return 'null';
         case $value instanceof \DateTimeInterface:
             return $value->format('c');
         case is_object($value):
             if (Yaml::DUMP_OBJECT & $flags) {
                 return '!php/object:' . serialize($value);
             }
             if (Yaml::DUMP_OBJECT_AS_MAP & $flags && ($value instanceof \stdClass || $value instanceof \ArrayObject)) {
                 return self::dumpArray((array) $value, $flags);
             }
             if (Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE & $flags) {
                 throw new DumpException('Object support when dumping a YAML file has been disabled.');
             }
             return 'null';
         case is_array($value):
             return self::dumpArray($value, $flags);
         case null === $value:
             return 'null';
         case true === $value:
             return 'true';
         case false === $value:
             return 'false';
         case ctype_digit($value):
             return is_string($value) ? "'{$value}'" : (int) $value;
         case is_numeric($value):
             $locale = setlocale(LC_NUMERIC, 0);
             if (false !== $locale) {
                 setlocale(LC_NUMERIC, 'C');
             }
             if (is_float($value)) {
                 $repr = (string) $value;
                 if (is_infinite($value)) {
                     $repr = str_ireplace('INF', '.Inf', $repr);
                 } elseif (floor($value) == $value && $repr == $value) {
                     // Preserve float data type since storing a whole number will result in integer value.
                     $repr = '!!float ' . $repr;
                 }
             } else {
                 $repr = is_string($value) ? "'{$value}'" : (string) $value;
             }
             if (false !== $locale) {
                 setlocale(LC_NUMERIC, $locale);
             }
             return $repr;
         case '' == $value:
             return "''";
         case self::isBinaryString($value):
             return '!!binary ' . base64_encode($value);
         case Escaper::requiresDoubleQuoting($value):
             return Escaper::escapeWithDoubleQuotes($value);
         case Escaper::requiresSingleQuoting($value):
         case preg_match('{^[0-9]+[_0-9]*$}', $value):
         case preg_match(self::getHexRegex(), $value):
         case preg_match(self::getTimestampRegex(), $value):
             return Escaper::escapeWithSingleQuotes($value);
         default:
             return $value;
     }
 }
Exemplo n.º 5
0
 /**
  * Builds the translations file data with added translations.
  *
  * @param array $newTranslations   New translation data to write
  * @param array $savedTranslations Translation data read from file
  * @param array $hinting           Translation data that can be used as hinting
  *
  * @return string
  */
 private function buildNewContent($newTranslations, $savedTranslations, $hinting = [])
 {
     // Presort
     $unusedTranslations = $savedTranslations;
     $transByType = ['Unused' => [' unused messages', []], 'TodoReal' => [' untranslated messages', []], 'TodoKey' => [' untranslated keyword based messages', []], 'DoneReal' => [' translations', []], 'DoneKey' => [' keyword based translations', []]];
     foreach ($newTranslations as $key => $translation) {
         $set = ['trans' => $translation];
         if (preg_match('%^[a-z0-9-]+\\.[a-z0-9-.]+$%', $key)) {
             $type = 'Key';
             $set['key'] = preg_split('%\\.%', $key);
         } else {
             $type = 'Real';
         }
         $done = $translation === '' ? 'Todo' : 'Done';
         $transByType[$done . $type][1][$key] = $set;
         if (isset($unusedTranslations[$key])) {
             unset($unusedTranslations[$key]);
         }
     }
     foreach ($unusedTranslations as $key => $translation) {
         $transByType['Unused'][1][$key] = ['trans' => $translation];
     }
     // Build List
     $indent = '    ';
     $status = '# ' . $this->relPath . ' – generated on ' . date('Y-m-d H:i:s e') . "\n\n" . '# Warning: Translations are in the process of being moved to a new keyword-based translation' . "\n" . '#          at the moment. This is an ongoing process. Translations currently in the ' . "\n" . '#          repository are automatically mapped to the new scheme. Be aware that there ' . "\n" . '#          can be a race condition between that process and your PR so that it\'s ' . "\n" . '#          eventually necessary to remap your translations. If you\'re planning on ' . "\n" . '#          updating your translations, it\'s best to ask on IRC to time your contribution' . "\n" . '#          in order to prevent merge conflicts.' . "\n\n";
     $content = '';
     // Set this to true to get nested output.
     $nested = false;
     foreach ($transByType as $type => $transData) {
         list($text, $translations) = $transData;
         // Header
         $count = count($translations) > 0 ? sprintf('%3s', count($translations)) : ' no';
         $status .= '# ' . $count . $text . "\n";
         if (count($translations) > 0) {
             $content .= "\n" . '#--- ' . str_pad(ltrim($count) . $text . ' ', 74, '-') . "\n\n";
         }
         // List
         $lastKey = [];
         $linebreak = '';
         // We want an empty line before each 1st level key
         foreach ($translations as $key => $tdata) {
             // Key
             if ($type == 'DoneKey') {
                 if ($nested) {
                     $differs = false;
                     for ($level = 0, $end = count($tdata['key']) - 1; $level < $end; $level++) {
                         if ($differs || $level >= count($lastKey) - 1 || $lastKey[$level] != $tdata['key'][$level]) {
                             $differs = true;
                             if ($level === 0) {
                                 $content .= $linebreak;
                                 $linebreak = "\n";
                             }
                             $content .= str_repeat($indent, $level) . $tdata['key'][$level] . ':' . "\n";
                         }
                     }
                     $lastKey = $tdata['key'];
                     $content .= str_repeat($indent, $level) . $tdata['key'][$level] . ': ';
                 } else {
                     $key2 = $tdata['key'][0] . (isset($tdata['key'][1]) ? '.' . $tdata['key'][1] : '');
                     if ($key2 !== $lastKey) {
                         $content .= $linebreak;
                         $linebreak = "\n";
                         $lastKey = $key2;
                     }
                     $content .= $key . ': ';
                 }
             } else {
                 $content .= Escaper::escapeWithDoubleQuotes($key) . ': ';
             }
             // Value
             if ($tdata['trans'] === '') {
                 $thint = Trans::__($key);
                 if ($thint === $key) {
                     $thint = isset($hinting[$key]) ? $hinting[$key] : '';
                 }
                 $content .= '#' . ($thint ? ' ' . Escaper::escapeWithDoubleQuotes($thint) : '') . "\n";
             } else {
                 $content .= Escaper::escapeWithDoubleQuotes($tdata['trans']) . "\n";
             }
         }
     }
     return $status . $content;
 }
Exemplo n.º 6
0
 /**
  * Dumps a given PHP variable to a YAML string.
  *
  * @param mixed $value                  The PHP variable to convert
  * @param bool  $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise
  * @param bool  $objectSupport          true if object support is enabled, false otherwise
  *
  * @return string The YAML string representing the PHP array
  *
  * @throws DumpException When trying to dump PHP resource
  */
 public static function dump($value, $exceptionOnInvalidType = false, $objectSupport = false)
 {
     switch (true) {
         case is_resource($value):
             if ($exceptionOnInvalidType) {
                 throw new DumpException(sprintf('Unable to dump PHP resources in a YAML file ("%s").', get_resource_type($value)));
             }
             return 'null';
         case is_object($value):
             if ($objectSupport) {
                 return '!php/object:' . serialize($value);
             }
             if ($exceptionOnInvalidType) {
                 throw new DumpException('Object support when dumping a YAML file has been disabled.');
             }
             return 'null';
         case is_array($value):
             return self::dumpArray($value, $exceptionOnInvalidType, $objectSupport);
         case null === $value:
             return 'null';
         case true === $value:
             return 'true';
         case false === $value:
             return 'false';
         case ctype_digit($value):
             return is_string($value) ? "'{$value}'" : (int) $value;
         case is_numeric($value):
             $locale = setlocale(LC_NUMERIC, 0);
             if (false !== $locale) {
                 setlocale(LC_NUMERIC, 'C');
             }
             if (is_float($value)) {
                 $repr = (string) $value;
                 if (is_infinite($value)) {
                     $repr = str_ireplace('INF', '.Inf', $repr);
                 } elseif (floor($value) == $value && $repr == $value) {
                     // Preserve float data type since storing a whole number will result in integer value.
                     $repr = '!!float ' . $repr;
                 }
             } else {
                 $repr = is_string($value) ? "'{$value}'" : (string) $value;
             }
             if (false !== $locale) {
                 setlocale(LC_NUMERIC, $locale);
             }
             return $repr;
         case '' == $value:
             return "''";
         case Escaper::requiresDoubleQuoting($value):
             return Escaper::escapeWithDoubleQuotes($value);
         case Escaper::requiresSingleQuoting($value):
         case preg_match(self::getHexRegex(), $value):
         case preg_match(self::getTimestampRegex(), $value):
             return Escaper::escapeWithSingleQuotes($value);
         default:
             return $value;
     }
 }
Exemplo n.º 7
0
 /**
  * Dumps a given PHP variable to a YAML string.
  *
  * @param mixed $value                  The PHP variable to convert
  * @param bool  $exceptionOnInvalidType true if an exception must be thrown on invalid types (a PHP resource or object), false otherwise
  * @param int   $flags                  A bit field of Yaml::DUMP_* constants to customize the dumped YAML string
  *
  * @return string The YAML string representing the PHP array
  *
  * @throws DumpException When trying to dump PHP resource
  */
 public static function dump($value, $exceptionOnInvalidType = false, $flags = 0)
 {
     if (is_bool($flags)) {
         @trigger_error('Passing a boolean flag to toggle object support is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::DUMP_OBJECT flag instead.', E_USER_DEPRECATED);
         $flags = (int) $flags;
     }
     switch (true) {
         case is_resource($value):
             if ($exceptionOnInvalidType) {
                 throw new DumpException(sprintf('Unable to dump PHP resources in a YAML file ("%s").', get_resource_type($value)));
             }
             return 'null';
         case is_object($value):
             if (Yaml::DUMP_OBJECT & $flags) {
                 return '!php/object:' . serialize($value);
             }
             if ($exceptionOnInvalidType) {
                 throw new DumpException('Object support when dumping a YAML file has been disabled.');
             }
             return 'null';
         case is_array($value):
             return self::dumpArray($value, $exceptionOnInvalidType, $flags);
         case null === $value:
             return 'null';
         case true === $value:
             return 'true';
         case false === $value:
             return 'false';
         case ctype_digit($value):
             return is_string($value) ? "'{$value}'" : (int) $value;
         case is_numeric($value):
             $locale = setlocale(LC_NUMERIC, 0);
             if (false !== $locale) {
                 setlocale(LC_NUMERIC, 'C');
             }
             if (is_float($value)) {
                 $repr = (string) $value;
                 if (is_infinite($value)) {
                     $repr = str_ireplace('INF', '.Inf', $repr);
                 } elseif (floor($value) == $value && $repr == $value) {
                     // Preserve float data type since storing a whole number will result in integer value.
                     $repr = '!!float ' . $repr;
                 }
             } else {
                 $repr = is_string($value) ? "'{$value}'" : (string) $value;
             }
             if (false !== $locale) {
                 setlocale(LC_NUMERIC, $locale);
             }
             return $repr;
         case '' == $value:
             return "''";
         case Escaper::requiresDoubleQuoting($value):
             return Escaper::escapeWithDoubleQuotes($value);
         case Escaper::requiresSingleQuoting($value):
         case preg_match(self::getHexRegex(), $value):
         case preg_match(self::getTimestampRegex(), $value):
             return Escaper::escapeWithSingleQuotes($value);
         default:
             return $value;
     }
 }
Exemplo n.º 8
0
 /**
  * Find all twig templates and bolt php code, extract translatables strings, merge with existing translations
  *
  * @param array $translated
  * @param array $getMessages True returns translation datat for messages, false for contenttypes
  * @return array
  */
 private function gatherTranslatableStrings($translated, $getMessages)
 {
     // Step 1: Gather all translatable strings
     $this->translatables = array();
     $this->scanTwigFiles();
     $this->scanPhpFiles();
     $this->scanContenttypeFields();
     $this->scanContenttypeRelations();
     $this->scanTaxonomies();
     // Build lists
     $msgTranslated = array();
     $msgUntranslated = array();
     foreach ($this->translatables as $key) {
         $keyRaw = stripslashes($key);
         $keyEsc = Escaper::escapeWithDoubleQuotes($keyRaw);
         if ($getMessages) {
             // Step 2: Find already translated strings
             if (($trans = $this->getTranslated($keyRaw, $translated)) == '' && ($trans = $this->getTranslated($keyEsc, $translated)) == '') {
                 $msgUntranslated[] = $keyEsc;
             } else {
                 $trans = Escaper::escapeWithDoubleQuotes($trans);
                 $msgTranslated[$keyEsc] = $trans;
             }
         } else {
             // Step 3: Generate additional strings for contenttypes
             if (strpos($keyRaw, '%contenttype%') !== false || strpos($keyRaw, '%contenttypes%') !== false) {
                 foreach ($this->genContentTypes($keyRaw) as $ctypekey) {
                     $keyEsc = Escaper::escapeWithDoubleQuotes($ctypekey);
                     if (($trans = $this->getTranslated($ctypekey, $translated)) == '' && ($trans = $this->getTranslated($keyEsc, $translated)) == '') {
                         $msgUntranslated[] = $keyEsc;
                         // Not translated
                     } else {
                         $msgTranslated[$keyEsc] = Escaper::escapeWithDoubleQuotes($trans);
                     }
                 }
             }
         }
     }
     sort($msgUntranslated);
     ksort($msgTranslated);
     return array($msgTranslated, $msgUntranslated);
 }