protected function _compilePattern($pattern)
    {
        if (strpos($pattern, '{') !== false) {
            $tr = [
                '{area}' => '{area:[a-z]\w*}',
                '{controller}' => '{controller:[a-z]\w*}',
                '{action}' => '{action:[a-z]\w*}',
                '{params}' => '{params:.*}',
                '{id}' => '{id:[^/]+}',
                ':int' => ':\d+',
            ];
            $pattern = strtr($pattern, $tr);
        }

        if (strpos($pattern, '{') !== false) {
            $need_restore_token = false;

            if (preg_match('#{\d#', $pattern) === 1) {
                $need_restore_token = true;
                $pattern = (string)preg_replace('#{([\d,]+)}#', '@\1@', $pattern);
            }

            $matches = [];
            if (preg_match_all('#{([A-Z].*)}#Ui', $pattern, $matches, PREG_SET_ORDER) > 0) {
                foreach ($matches as $match) {
                    $parts = explode(':', $match[1], 2);
                    $to = '(?<' . $parts[0] . '>' . (isset($parts[1]) ? $parts[1] : '[\w-]+') . ')';
                    $pattern = (string)str_replace($match[0], $to, $pattern);
                }
            }

            if ($need_restore_token) {
                $pattern = (string)preg_replace('#@([\d,]+)@#', '{\1}', $pattern);
            }

            return '#^' . $pattern . '$#i';
        } else {
            return $pattern;
        }
    }