src/AtechNet/CoreBundle/Helper/Furbify/SeoUrlHelper.php line 275

Open in your IDE?
  1. <?php
  2. namespace App\AtechNet\CoreBundle\Helper\Furbify;
  3. use App\AtechNet\CoreBundle\Entity\Domain;
  4. use App\AtechNet\CoreBundle\Entity\Language;
  5. use App\AtechNet\CoreBundle\Entity\SeoUrl;
  6. use Doctrine\Persistence\ObjectManager;
  7. use Symfony\Component\HttpFoundation\Request;
  8. class SeoUrlHelper
  9. {
  10.     private $entityManager;
  11.     private $request;
  12.     private $domainId;
  13.     private $languageId;
  14.     private $defaultLanguageId;
  15.     private $environment;
  16.     private $scriptName;
  17.     private $locale;
  18.     private $defaultLocale;
  19.     /**
  20.      * @param ObjectManager $entityManager
  21.      * @param Request $request
  22.      * @param string $environment
  23.      */
  24.     public function __construct(ObjectManager $entityManager, Request $request, string $environment)
  25.     {
  26.         $this->entityManager = $entityManager;
  27.         $this->request = $request;
  28.         $this->domainId = $request->getSession()->get('domainId');
  29.         $this->languageId = $request->getSession()->get('languageId');
  30.         $this->defaultLanguageId = $request->getSession()->get('defaultLanguageId');
  31.         $this->environment = $environment;
  32.         $this->locale = $request->getSession()->get('_locale');
  33.         $this->defaultLocale = $request->getSession()->get('defaultLocale');
  34.     }
  35.     /**
  36.      * @param string $route
  37.      * @param array $args
  38.      * @return string
  39.      */
  40.     public function link(string $route, array $args = []): string
  41.     {
  42.         if (in_array($this->domainId, MultiStore::getWholesaleDomainIDs()) && $route !== 'blog') {
  43.             switch ($this->domainId) {
  44.                 case Domain::DOMAIN_ID_WS_SK:
  45.                     $domainId = Domain::DOMAIN_ID_RT_SK;
  46.                     break;
  47.                 case Domain::DOMAIN_ID_WS_HU:
  48.                     $domainId = Domain::DOMAIN_ID_RT_HU;
  49.                     break;
  50.                 case Domain::DOMAIN_ID_WS_CZ:
  51.                     $domainId = Domain::DOMAIN_ID_RT_CZ;
  52.                     break;
  53.                 case Domain::DOMAIN_ID_WS_EU:
  54.                     $domainId = Domain::DOMAIN_ID_RT_EU;
  55.                     break;
  56.             }
  57.         } else {
  58.             $domainId = $this->domainId;
  59.         }
  60.         $domain = $this->entityManager->getRepository(Domain::class)->findOneById($domainId);
  61.         if ($this->environment == 'prod') {
  62.             $url = $domain->getUrl() . $this->getLanguageCode();
  63.         } else {
  64.             $url = $this->request->getSchemeAndHttpHost() . $this->getLanguageCode();
  65.         }
  66.         $path = '';
  67.         $seoUrlRepo = $this->entityManager->getRepository(SeoUrl::class);
  68.         switch ($route) {
  69.             case 'category':
  70.                 if (isset($args['path'])) {
  71.                     if ( isset($args['isBazaar']) ) {
  72.                         if ( $args['isBazaar'] ) {
  73.                             if ( in_array($this->defaultLanguageId, [ Language::LANGUAGE_ID_CZ, Language::LANGUAGE_ID_HU, Language::LANGUAGE_ID_SK ]) ) {
  74.                                 $path .= '/bazar';
  75.                             } else {
  76.                                 $path .= '/bazaar';
  77.                             }
  78.                         }
  79.                         unset($args['isBazaar']);
  80.                     }
  81.                     $categories = explode('_', $args['path']);
  82.                     foreach ($categories as $category) {
  83.                         $seoUrl = $seoUrlRepo->findOneBy([
  84.                             'query' => 'category_id=' . $category,
  85.                             'language' => $this->defaultLanguageId,
  86.                             'domain' => $domainId,
  87.                             'archived' => false,
  88.                         ]);
  89.                         if ($seoUrl) {
  90.                             $path .= '/' . $seoUrl->getKeyword();
  91.                         } else {
  92.                             $path = '/category/' . array_pop($categories);
  93.                             break;
  94.                         }
  95.                     }
  96.                     unset($args['path']);
  97.                 }
  98.                 break;
  99.             case 'product':
  100.                 if (isset($args['product_id'])) {
  101.                     $seoUrl = $seoUrlRepo->findOneBy([
  102.                         'query' => 'product_id=' . $args['product_id'],
  103.                         'language' => $this->defaultLanguageId,
  104.                         'archived' => false,
  105.                     ]);
  106.                     if ( isset($args['isBazaar']) ) {
  107.                         if ( $args['isBazaar'] ) {
  108.                             if ( in_array($this->defaultLanguageId, [ Language::LANGUAGE_ID_CZ, Language::LANGUAGE_ID_HU, Language::LANGUAGE_ID_SK ]) ) {
  109.                                 $path .= '/bazar';
  110.                             } else {
  111.                                 $path .= '/bazaar';
  112.                             }
  113.                         }
  114.                         unset($args['isBazaar']);
  115.                     }
  116.                     if ($seoUrl) {
  117.                         $path .= '/' . $seoUrl->getKeyword();
  118.                     } else {
  119.                         $path = '/product/' . $args['product_id'];
  120.                     }
  121.                     unset($args['product_id']);
  122.                 }
  123.                 break;
  124.             case 'page':
  125.                 if (isset($args['static_id'])) {
  126.                     $seoUrl = $seoUrlRepo->findOneBy([
  127.                         'query' => 'static_id=' . $args['static_id'],
  128.                         'language' => $this->defaultLanguageId,
  129.                         'domain' => $domainId,
  130.                         'archived' => false,
  131.                     ]);
  132.                     if ($seoUrl) {
  133.                         $path .= '/' . $seoUrl->getKeyword();
  134.                     } else {
  135.                         $path = '/page/' . $args['static_id'];
  136.                     }
  137.                     unset($args['static_id']);
  138.                 }
  139.                 break;
  140.             case 'blog':
  141.                 if (isset($args['blog_id'])) {
  142.                     $seoUrl = $seoUrlRepo->findOneBy([
  143.                         'query' => 'blog_id=' . $args['blog_id'],
  144.                         'language' => $this->defaultLanguageId,
  145.                         'domain' => $domainId,
  146.                         'archived' => false,
  147.                     ]);
  148.                     if ($seoUrl) {
  149.                         if (isset($args['blog_category_id'])) {
  150.                             $_seoUrl = $seoUrlRepo->findOneBy([
  151.                                 'query' => 'category_id=' . $args['blog_category_id'],
  152.                                 'language' => $this->defaultLanguageId,
  153.                                 'domain' => $domainId,
  154.                             ]);
  155.                             if ($_seoUrl) {
  156.                                 $path = '/blog/' . $_seoUrl->getKeyword() . '/';
  157.                             } else {
  158.                                 $path = '/blog/';
  159.                             }
  160.                             unset($args['blog_category_id']);
  161.                             $path .= $seoUrl->getKeyword();
  162.                         } else {
  163.                             $path .= '/blog/' . $seoUrl->getKeyword();
  164.                         }
  165.                     } else {
  166.                         $path = '/blog/' . $args['blog_id'];
  167.                     }
  168.                     unset($args['blog_id']);
  169.                 }
  170.                 break;
  171.             case 'blog_category':
  172.                 if (isset($args['blog_category_id'])) {
  173.                     $seoUrl = $seoUrlRepo->findOneBy([
  174.                         'query' => 'category_id=' . $args['blog_category_id'],
  175.                         'language' => $this->defaultLanguageId,
  176.                         'domain' => $domainId,
  177.                         'archived' => false,
  178.                     ]);
  179.                     if ($seoUrl) {
  180.                         if ($seoUrl->getKeyword() == 'blog') {
  181.                             $path = '/' . $seoUrl->getKeyword();
  182.                         } else {
  183.                             $path .= '/blog/' . $seoUrl->getKeyword();
  184.                         }
  185.                     } else {
  186.                         $path = '/blog/' . $args['blog_category_id'] . '/category';
  187.                     }
  188.                     unset($args['blog_category_id']);
  189.                 }
  190.                 break;
  191.             case 'search':
  192.                 $path = '/product-search';
  193.                 break;
  194.             case 'wizard_result':
  195.                 $path = '/wizard/result';
  196.                 break;
  197.         }
  198.         // Add path to URL
  199.         $url .= $path;
  200.         $query = '';
  201.         if ($args) {
  202.             foreach ($args as $key => $value) {
  203.                 $query .= '&' . rawurlencode((string)$key) . '=' . rawurlencode((is_array($value) ? http_build_query($value) : (string)$value));
  204.             }
  205.             if ($query) {
  206.                 $query = '?' . trim($query, '&');
  207.             }
  208.         }
  209.         return $url . $query;
  210.     }
  211.     /**
  212.      * @return string
  213.      */
  214.     private function getLanguageCode()
  215.     {
  216.         $languageCode = '';
  217.         if ($this->defaultLocale !== $this->locale) {
  218.             $languageCode = '/' . $this->locale;
  219.         }
  220.         return $languageCode;
  221.     }
  222.     /**
  223.      * Get URL prefix for localisation settings
  224.      *
  225.      * @param Request $request
  226.      * @return string
  227.      */
  228.     public static function getRoutePrefix(Request $request): string
  229.     {
  230.         if ($request->getSession()->get('defaultLocale') !== $request->getSession()->get('_locale')) {
  231.             return $request->getSession()->get('_locale');
  232.         }
  233.         return '';
  234.     }
  235.     /**
  236.      * @return Request
  237.      */
  238.     public function getRequest(): Request
  239.     {
  240.         return $this->request;
  241.     }
  242.     /**
  243.      * @param string $pageTitle
  244.      * @param string $query
  245.      * @param int $languageId
  246.      * @param int $domainId
  247.      * @return string
  248.      */
  249.     public function createUniqueSlug($pageTitle, $query, $languageId = 1, $domainId = 1)
  250.     {
  251.         return $this->uniqueSlug($this->slug($pageTitle), $query, $languageId, $domainId);
  252.     }
  253.     /**
  254.      * @param string $keyword
  255.      * @param string $query
  256.      * @param int $languageId
  257.      * @param int $domainId
  258.      * @param int $index
  259.      * @return string
  260.      */
  261.     public function uniqueSlug($keyword, $query, $languageId = 1, $domainId = 1, $index = 0)
  262.     {
  263.         $findOneByArray = [
  264.             'language' => $languageId,
  265.             'keyword' => $keyword . ($index > 0 ? '-' . $index : ''),
  266.         ];
  267.         if (strpos($query, 'product_id=') === false) {
  268.             $findOneByArray['domain'] = $domainId;
  269.         }
  270.         $seoUrl = $this->entityManager->getRepository(SeoUrl::class)->findOneBy($findOneByArray);
  271.         if ($seoUrl) {
  272.             if ($seoUrl->getQuery() !== $query) {
  273.                 return $this->uniqueSlug($keyword, $query, $languageId, $domainId, ($index + 1));
  274.             }
  275.         }
  276.         return $keyword . ($index > 0 ? '-' . ($index) : '');
  277.     }
  278.     /**
  279.          * Generate a URL friendly "slug" from a given string.
  280.          *
  281.          * @param  string  $title
  282.          * @param  string  $separator
  283.          * @return string
  284.          */
  285.     public function slug($title, $separator = '-')
  286.     {
  287.         $title = static::ascii($title);
  288.         // Convert all dashes/underscores into separator
  289.         $flip = $separator == '-' ? '_' : '-';
  290.         $title = preg_replace('![' . preg_quote($flip) . ']+!u', $separator, $title);
  291.         // Remove all characters that are not the separator, letters, numbers, or whitespace.
  292.         $title = preg_replace('![^' . preg_quote($separator) . '\pL\pN\s]+!u', '', mb_strtolower($title));
  293.         // Replace all separator characters and whitespace by a single separator
  294.         $title = preg_replace('![' . preg_quote($separator) . '\s]+!u', $separator, $title);
  295.         return trim($title, $separator);
  296.     }
  297.     /**
  298.      * Transliterate a UTF-8 value to ASCII.
  299.      *
  300.      * @param  string  $value
  301.      * @return string
  302.      */
  303.     public static function ascii($value)
  304.     {
  305.         foreach (static::charsArray() as $key => $val) {
  306.             $value = str_replace($val, $key, $value);
  307.         }
  308.         return preg_replace('/[^\x20-\x7E]/u', '', $value);
  309.     }
  310.     /**
  311.      * @return int
  312.      */
  313.     public function getDomainId(): int
  314.     {
  315.         return $this->domainId;
  316.     }
  317.     /**
  318.      * Returns the replacements for the ascii method.
  319.      *
  320.      * Note: Adapted from Stringy\Stringy.
  321.      *
  322.      * @see https://github.com/danielstjules/Stringy/blob/2.3.1/LICENSE.txt
  323.      *
  324.      * @return array
  325.      */
  326.     protected static function charsArray()
  327.     {
  328.         static $charsArray;
  329.         if (isset($charsArray)) {
  330.             return $charsArray;
  331.         }
  332.         return $charsArray = [
  333.             '0' => ['°', '₀', '۰'],
  334.             '1' => ['¹', '₁', '۱'],
  335.             '2' => ['²', '₂', '۲'],
  336.             '3' => ['³', '₃', '۳'],
  337.             '4' => ['⁴', '₄', '۴', '٤'],
  338.             '5' => ['⁵', '₅', '۵', '٥'],
  339.             '6' => ['⁶', '₆', '۶', '٦'],
  340.             '7' => ['⁷', '₇', '۷'],
  341.             '8' => ['⁸', '₈', '۸'],
  342.             '9' => ['⁹', '₉', '۹'],
  343.             'a' => ['à', 'á', 'ả', 'ã', 'ạ', 'ă', 'ắ', 'ằ', 'ẳ', 'ẵ', 'ặ', 'â', 'ấ', 'ầ', 'ẩ', 'ẫ', 'ậ', 'ā', 'ą', 'å', 'α', 'ά', 'ἀ', 'ἁ', 'ἂ', 'ἃ', 'ἄ', 'ἅ', 'ἆ', 'ἇ', 'ᾀ', 'ᾁ', 'ᾂ', 'ᾃ', 'ᾄ', 'ᾅ', 'ᾆ', 'ᾇ', 'ὰ', 'ά', 'ᾰ', 'ᾱ', 'ᾲ', 'ᾳ', 'ᾴ', 'ᾶ', 'ᾷ', 'а', 'أ', 'အ', 'ာ', 'ါ', 'ǻ', 'ǎ', 'ª', 'ა', 'अ', 'ا'],
  344.             'b' => ['б', 'β', 'Ъ', 'Ь', 'ب', 'ဗ', 'ბ'],
  345.             'c' => ['ç', 'ć', 'č', 'ĉ', 'ċ'],
  346.             'd' => ['ď', 'ð', 'đ', 'ƌ', 'ȡ', 'ɖ', 'ɗ', 'ᵭ', 'ᶁ', 'ᶑ', 'д', 'δ', 'د', 'ض', 'ဍ', 'ဒ', 'დ'],
  347.             'e' => ['é', 'è', 'ẻ', 'ẽ', 'ẹ', 'ê', 'ế', 'ề', 'ể', 'ễ', 'ệ', 'ë', 'ē', 'ę', 'ě', 'ĕ', 'ė', 'ε', 'έ', 'ἐ', 'ἑ', 'ἒ', 'ἓ', 'ἔ', 'ἕ', 'ὲ', 'έ', 'е', 'ё', 'э', 'є', 'ə', 'ဧ', 'ေ', 'ဲ', 'ე', 'ए', 'إ', 'ئ'],
  348.             'f' => ['ф', 'φ', 'ف', 'ƒ', 'ფ'],
  349.             'g' => ['ĝ', 'ğ', 'ġ', 'ģ', 'г', 'ґ', 'γ', 'ဂ', 'გ', 'گ'],
  350.             'h' => ['ĥ', 'ħ', 'η', 'ή', 'ح', 'ه', 'ဟ', 'ှ', 'ჰ'],
  351.             'i' => ['í', 'ì', 'ỉ', 'ĩ', 'ị', 'î', 'ï', 'ī', 'ĭ', 'į', 'ı', 'ι', 'ί', 'ϊ', 'ΐ', 'ἰ', 'ἱ', 'ἲ', 'ἳ', 'ἴ', 'ἵ', 'ἶ', 'ἷ', 'ὶ', 'ί', 'ῐ', 'ῑ', 'ῒ', 'ΐ', 'ῖ', 'ῗ', 'і', 'ї', 'и', 'ဣ', 'ိ', 'ီ', 'ည်', 'ǐ', 'ი', 'इ'],
  352.             'j' => ['ĵ', 'ј', 'Ј', 'ჯ', 'ج'],
  353.             'k' => ['ķ', 'ĸ', 'к', 'κ', 'Ķ', 'ق', 'ك', 'က', 'კ', 'ქ', 'ک'],
  354.             'l' => ['ł', 'ľ', 'ĺ', 'ļ', 'ŀ', 'л', 'λ', 'ل', 'လ', 'ლ'],
  355.             'm' => ['м', 'μ', 'م', 'မ', 'მ'],
  356.             'n' => ['ñ', 'ń', 'ň', 'ņ', 'ʼn', 'ŋ', 'ν', 'н', 'ن', 'န', 'ნ'],
  357.             'o' => ['ó', 'ò', 'ỏ', 'õ', 'ọ', 'ô', 'ố', 'ồ', 'ổ', 'ỗ', 'ộ', 'ơ', 'ớ', 'ờ', 'ở', 'ỡ', 'ợ', 'ø', 'ō', 'ő', 'ŏ', 'ο', 'ὀ', 'ὁ', 'ὂ', 'ὃ', 'ὄ', 'ὅ', 'ὸ', 'ό', 'о', 'و', 'θ', 'ို', 'ǒ', 'ǿ', 'º', 'ო', 'ओ'],
  358.             'p' => ['п', 'π', 'ပ', 'პ', 'پ'],
  359.             'q' => ['ყ'],
  360.             'r' => ['ŕ', 'ř', 'ŗ', 'р', 'ρ', 'ر', 'რ'],
  361.             's' => ['ś', 'š', 'ş', 'с', 'σ', 'ș', 'ς', 'س', 'ص', 'စ', 'ſ', 'ს'],
  362.             't' => ['ť', 'ţ', 'т', 'τ', 'ț', 'ت', 'ط', 'ဋ', 'တ', 'ŧ', 'თ', 'ტ'],
  363.             'u' => ['ú', 'ù', 'ủ', 'ũ', 'ụ', 'ư', 'ứ', 'ừ', 'ử', 'ữ', 'ự', 'û', 'ū', 'ů', 'ű', 'ŭ', 'ų', 'µ', 'у', 'ဉ', 'ု', 'ူ', 'ǔ', 'ǖ', 'ǘ', 'ǚ', 'ǜ', 'უ', 'उ'],
  364.             'v' => ['в', 'ვ', 'ϐ'],
  365.             'w' => ['ŵ', 'ω', 'ώ', 'ဝ', 'ွ'],
  366.             'x' => ['χ', 'ξ'],
  367.             'y' => ['ý', 'ỳ', 'ỷ', 'ỹ', 'ỵ', 'ÿ', 'ŷ', 'й', 'ы', 'υ', 'ϋ', 'ύ', 'ΰ', 'ي', 'ယ'],
  368.             'z' => ['ź', 'ž', 'ż', 'з', 'ζ', 'ز', 'ဇ', 'ზ'],
  369.             'aa' => ['ع', 'आ', 'آ'],
  370.             'ae' => ['ä', 'æ', 'ǽ'],
  371.             'ai' => ['ऐ'],
  372.             'at' => ['@'],
  373.             'ch' => ['ч', 'ჩ', 'ჭ', 'چ'],
  374.             'dj' => ['ђ', 'đ'],
  375.             'dz' => ['џ', 'ძ'],
  376.             'ei' => ['ऍ'],
  377.             'gh' => ['غ', 'ღ'],
  378.             'ii' => ['ई'],
  379.             'ij' => ['ij'],
  380.             'kh' => ['х', 'خ', 'ხ'],
  381.             'lj' => ['љ'],
  382.             'nj' => ['њ'],
  383.             'oe' => ['ö', 'œ', 'ؤ'],
  384.             'oi' => ['ऑ'],
  385.             'oii' => ['ऒ'],
  386.             'ps' => ['ψ'],
  387.             'sh' => ['ш', 'შ', 'ش'],
  388.             'shch' => ['щ'],
  389.             'ss' => ['ß'],
  390.             'sx' => ['ŝ'],
  391.             'th' => ['þ', 'ϑ', 'ث', 'ذ', 'ظ'],
  392.             'ts' => ['ц', 'ც', 'წ'],
  393.             'ue' => ['ü'],
  394.             'uu' => ['ऊ'],
  395.             'ya' => ['я'],
  396.             'yu' => ['ю'],
  397.             'zh' => ['ж', 'ჟ', 'ژ'],
  398.             '(c)' => ['©'],
  399.             'A' => ['Á', 'À', 'Ả', 'Ã', 'Ạ', 'Ă', 'Ắ', 'Ằ', 'Ẳ', 'Ẵ', 'Ặ', 'Â', 'Ấ', 'Ầ', 'Ẩ', 'Ẫ', 'Ậ', 'Å', 'Ā', 'Ą', 'Α', 'Ά', 'Ἀ', 'Ἁ', 'Ἂ', 'Ἃ', 'Ἄ', 'Ἅ', 'Ἆ', 'Ἇ', 'ᾈ', 'ᾉ', 'ᾊ', 'ᾋ', 'ᾌ', 'ᾍ', 'ᾎ', 'ᾏ', 'Ᾰ', 'Ᾱ', 'Ὰ', 'Ά', 'ᾼ', 'А', 'Ǻ', 'Ǎ'],
  400.             'B' => ['Б', 'Β', 'ब'],
  401.             'C' => ['Ç', 'Ć', 'Č', 'Ĉ', 'Ċ'],
  402.             'D' => ['Ď', 'Ð', 'Đ', 'Ɖ', 'Ɗ', 'Ƌ', 'ᴅ', 'ᴆ', 'Д', 'Δ'],
  403.             'E' => ['É', 'È', 'Ẻ', 'Ẽ', 'Ẹ', 'Ê', 'Ế', 'Ề', 'Ể', 'Ễ', 'Ệ', 'Ë', 'Ē', 'Ę', 'Ě', 'Ĕ', 'Ė', 'Ε', 'Έ', 'Ἐ', 'Ἑ', 'Ἒ', 'Ἓ', 'Ἔ', 'Ἕ', 'Έ', 'Ὲ', 'Е', 'Ё', 'Э', 'Є', 'Ə'],
  404.             'F' => ['Ф', 'Φ'],
  405.             'G' => ['Ğ', 'Ġ', 'Ģ', 'Г', 'Ґ', 'Γ'],
  406.             'H' => ['Η', 'Ή', 'Ħ'],
  407.             'I' => ['Í', 'Ì', 'Ỉ', 'Ĩ', 'Ị', 'Î', 'Ï', 'Ī', 'Ĭ', 'Į', 'İ', 'Ι', 'Ί', 'Ϊ', 'Ἰ', 'Ἱ', 'Ἳ', 'Ἴ', 'Ἵ', 'Ἶ', 'Ἷ', 'Ῐ', 'Ῑ', 'Ὶ', 'Ί', 'И', 'І', 'Ї', 'Ǐ', 'ϒ'],
  408.             'K' => ['К', 'Κ'],
  409.             'L' => ['Ĺ', 'Ł', 'Л', 'Λ', 'Ļ', 'Ľ', 'Ŀ', 'ल'],
  410.             'M' => ['М', 'Μ'],
  411.             'N' => ['Ń', 'Ñ', 'Ň', 'Ņ', 'Ŋ', 'Н', 'Ν'],
  412.             'O' => ['Ó', 'Ò', 'Ỏ', 'Õ', 'Ọ', 'Ô', 'Ố', 'Ồ', 'Ổ', 'Ỗ', 'Ộ', 'Ơ', 'Ớ', 'Ờ', 'Ở', 'Ỡ', 'Ợ', 'Ø', 'Ō', 'Ő', 'Ŏ', 'Ο', 'Ό', 'Ὀ', 'Ὁ', 'Ὂ', 'Ὃ', 'Ὄ', 'Ὅ', 'Ὸ', 'Ό', 'О', 'Θ', 'Ө', 'Ǒ', 'Ǿ'],
  413.             'P' => ['П', 'Π'],
  414.             'R' => ['Ř', 'Ŕ', 'Р', 'Ρ', 'Ŗ'],
  415.             'S' => ['Ş', 'Ŝ', 'Ș', 'Š', 'Ś', 'С', 'Σ'],
  416.             'T' => ['Ť', 'Ţ', 'Ŧ', 'Ț', 'Т', 'Τ'],
  417.             'U' => ['Ú', 'Ù', 'Ủ', 'Ũ', 'Ụ', 'Ư', 'Ứ', 'Ừ', 'Ử', 'Ữ', 'Ự', 'Û', 'Ū', 'Ů', 'Ű', 'Ŭ', 'Ų', 'У', 'Ǔ', 'Ǖ', 'Ǘ', 'Ǚ', 'Ǜ'],
  418.             'V' => ['В'],
  419.             'W' => ['Ω', 'Ώ', 'Ŵ'],
  420.             'X' => ['Χ', 'Ξ'],
  421.             'Y' => ['Ý', 'Ỳ', 'Ỷ', 'Ỹ', 'Ỵ', 'Ÿ', 'Ῠ', 'Ῡ', 'Ὺ', 'Ύ', 'Ы', 'Й', 'Υ', 'Ϋ', 'Ŷ'],
  422.             'Z' => ['Ź', 'Ž', 'Ż', 'З', 'Ζ'],
  423.             'AE' => ['Ä', 'Æ', 'Ǽ'],
  424.             'CH' => ['Ч'],
  425.             'DJ' => ['Ђ'],
  426.             'DZ' => ['Џ'],
  427.             'GX' => ['Ĝ'],
  428.             'HX' => ['Ĥ'],
  429.             'IJ' => ['IJ'],
  430.             'JX' => ['Ĵ'],
  431.             'KH' => ['Х'],
  432.             'LJ' => ['Љ'],
  433.             'NJ' => ['Њ'],
  434.             'OE' => ['Ö', 'Œ'],
  435.             'PS' => ['Ψ'],
  436.             'SH' => ['Ш'],
  437.             'SHCH' => ['Щ'],
  438.             'SS' => ['ẞ'],
  439.             'TH' => ['Þ'],
  440.             'TS' => ['Ц'],
  441.             'UE' => ['Ü'],
  442.             'YA' => ['Я'],
  443.             'YU' => ['Ю'],
  444.             'ZH' => ['Ж'],
  445.             ' ' => ["\xC2\xA0", "\xE2\x80\x80", "\xE2\x80\x81", "\xE2\x80\x82", "\xE2\x80\x83", "\xE2\x80\x84", "\xE2\x80\x85", "\xE2\x80\x86", "\xE2\x80\x87", "\xE2\x80\x88", "\xE2\x80\x89", "\xE2\x80\x8A", "\xE2\x80\xAF", "\xE2\x81\x9F", "\xE3\x80\x80"],
  446.         ];
  447.     }
  448. }