protected function _renderOptions($options, $disabled, $selected, $templateVars, $escape)
    {
        $out = [];
        foreach ($options as $key => $val) {
            // Option groups
            $arrayVal = (is_array($val) || $val instanceof Traversable);
            if ((!is_int($key) && $arrayVal) ||
                (is_int($key) && $arrayVal && (isset($val['options']) || !isset($val['value'])))
            ) {
                $out[] = $this->_renderOptgroup($key, $val, $disabled, $selected, $templateVars, $escape);
                continue;
            }

            // Basic options
            $optAttrs = [
                'value' => $key,
                'text' => $val,
                'templateVars' => [],
            ];
            if (is_array($val) && isset($val['text'], $val['value'])) {
                $optAttrs = $val;
                $key = $optAttrs['value'];
            }
            if (!isset($optAttrs['templateVars'])) {
                $optAttrs['templateVars'] = [];
            }
            if ($this->_isSelected($key, $selected)) {
                $optAttrs['selected'] = true;
            }
            if ($this->_isDisabled($key, $disabled)) {
                $optAttrs['disabled'] = true;
            }
            if (!empty($templateVars)) {
                $optAttrs['templateVars'] = array_merge($templateVars, $optAttrs['templateVars']);
            }
            $optAttrs['escape'] = $escape;

            $out[] = $this->_templates->format('option', [
                'value' => $escape ? h($optAttrs['value']) : $optAttrs['value'],
                'text' => $escape ? h($optAttrs['text']) : $optAttrs['text'],
                'templateVars' => $optAttrs['templateVars'],
                'attrs' => $this->_templates->formatAttributes($optAttrs, ['text', 'value']),
            ]);
        }

        return $out;
    }