vypnutí překladu u options v selectBoxu

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
mirdič
Člen | 41
+
0
-

Zdravím,

Je možné vypnutí překladu pouze u options, které jsou v selextBoxu? Ne celého selectBoxu pomocí:

$form->addSelect('select', 'Select:', array())->setTranslator(NULL);

Ale pouze u options.

Děkuji za rady.

Michal III
Člen | 83
+
0
-

Řeším úplně stejný problém, ale koukám, že ačkoli jsem našel založené téma dřív, než jsem ho založil sám, odpověď jsem se stejně nedozvěděl.

Opravdu nevíte někdo?

jtousek
Člen | 951
+
0
-

Asi leda podědit / upravit SelectBox.

Michal III
Člen | 83
+
0
-

Nedokázal jsem přijít na způsob vhodně podědit, protože jsem nedokázal zavolat metodu předka svého předka, takže než abych dělal paralelní třídu, prostě jsem modifikoval SelectBox.

Nicméně se mi zdá, že by tato funkcionalita měla být implementována už v základu, protože jsou situace, kdy chceme přeložit jen label a prompt, ale nikoliv hodnoty v options (např. pokud jsou jako hodnoty v SelectBoxu jména).

raketoplan2005
Člen | 147
+
0
-

Michal III: Jak jste to tedy vyřešil, prosím?

Michal III
Člen | 83
+
0
-

Modifikoval jsem SelectBox.php následujícím způsobem:

<?php

/**
 * This file is part of the Nette Framework (https://nette.org)
 *
 * Copyright (c) 2004 David Grudl (http://davidgrudl.com)
 *
 * For the full copyright and license information, please view
 * the file license.txt that was distributed with this source code.
 * @package Nette\Forms\Controls
 */



/**
 * Select box control that allows single item selection.
 *
 * @author     David Grudl
 *
 * @property-read mixed $rawValue
 * @property   bool $prompt
 * @property   array $items
 * @property-read string $selectedItem
 * @package Nette\Forms\Controls
 */
class SelectBox extends FormControl
{
	/** @var array */
	private $items = array();

	/** @var array */
	protected $allowed = array();

	/** @var mixed */
	private $prompt = FALSE;

	/** @var bool */
	private $useKeys = TRUE;



	/** @var bool */
	private $translateValues = false;

	/**
	 * Sets Translate Values option
	 * @param  array
	 * @return SelectBox  provides a fluent interface
	 */
	public function setTranslateValues($opt = true)
	{
		$this->translateValues = $opt;

		return $this;
	}

	/**
	 * Are values in options translated?
	 * @return bool
	 */
	public function areValuesTranslated()
	{
		return $this->translateValues;
	}



	/**
	 * @param  string  label
	 * @param  array   items from which to choose
	 * @param  int     number of rows that should be visible
	 */
	public function __construct($label = NULL, array $items = NULL, $size = NULL)
	{
		parent::__construct($label);
		$this->control->setName('select');
		$this->control->size = $size > 1 ? (int) $size : NULL;
		if ($items !== NULL) {
			$this->setItems($items);
		}
	}



	/**
	 * Returns selected item key.
	 * @return mixed
	 */
	public function getValue()
	{
		$allowed = $this->allowed;
		if ($this->prompt) {
			$allowed = array_slice($allowed, 1, count($allowed), TRUE);
		}

		return is_scalar($this->value) && isset($allowed[$this->value]) ? $this->value : NULL;
	}



	/**
	 * Returns selected item key (not checked).
	 * @return mixed
	 */
	public function getRawValue()
	{
		return is_scalar($this->value) ? $this->value : NULL;
	}



	/**
	 * Has been any item selected?
	 * @return bool
	 */
	public function isFilled()
	{
		$value = $this->getValue();
		return is_array($value) ? count($value) > 0 : $value !== NULL;
	}



	/**
	 * Ignores the first item in select box.
	 * @param  string
	 * @return SelectBox  provides a fluent interface
	 */
	public function setPrompt($prompt)
	{
		$this->prompt = $prompt;
		if ($prompt !== NULL && !is_bool($prompt)) {
			$this->items = array('' => $prompt) + $this->items;
			$this->allowed = array('' => '') + $this->allowed;
		}
		return $this;
	}



	/** @deprecated */
	function skipFirst($v = NULL)
	{
		trigger_error(__METHOD__ . '() is deprecated; use setPrompt() instead.', E_USER_WARNING);
		return $this->setPrompt($v);
	}



	/**
	 * Is first item in select box ignored?
	 * @return bool
	 */
	final public function getPrompt()
	{
		return $this->prompt;
	}



	/**
	 * Are the keys used?
	 * @return bool
	 */
	final public function areKeysUsed()
	{
		return $this->useKeys;
	}



	/**
	 * Sets items from which to choose.
	 * @param  array
	 * @return SelectBox  provides a fluent interface
	 */
	public function setItems(array $items, $useKeys = TRUE)
	{
		$this->items = $items;
		if ($this->prompt) {
			$this->items = array('' => is_bool($this->prompt) ? $this->items[''] : $this->prompt) + $this->items;
		}
		$this->allowed = $this->prompt ? array('' => '') : array();
		$this->useKeys = (bool) $useKeys;

		foreach ($items as $key => $value) {
			if (!is_array($value)) {
				$value = array($key => $value);
			}

			foreach ($value as $key2 => $value2) {
				if (!$this->useKeys) {
					if (!is_scalar($value2)) {
						throw new InvalidArgumentException("All items must be scalar.");
					}
					$key2 = $value2;
				}

				if (isset($this->allowed[$key2])) {
					throw new InvalidArgumentException("Items contain duplication for key '$key2'.");
				}

				$this->allowed[$key2] = $value2;
			}
		}
		return $this;
	}



	/**
	 * Returns items from which to choose.
	 * @return array
	 */
	final public function getItems()
	{
		return $this->items;
	}



	/**
	 * Returns selected value.
	 * @return string
	 */
	public function getSelectedItem()
	{
		if (!$this->useKeys) {
			return $this->getValue();

		} else {
			$value = $this->getValue();
			return $value === NULL ? NULL : $this->allowed[$value];
		}
	}



	/**
	 * Generates control's HTML element.
	 * @return Html
	 */
	public function getControl()
	{
		$control = parent::getControl();
		if ($this->prompt) {
			reset($this->items);
			$control->data('nette-empty-value', $this->useKeys ? key($this->items) : current($this->items));
		}
		$selected = $this->getValue();
		$selected = is_array($selected) ? array_flip($selected) : array($selected => TRUE);
		$option = Html::el('option');

		//******
		if($this->prompt && array_key_exists('', $this->items)) $this->items[''] = $this->translate($this->items['']);

		foreach ($this->items as $key => $value) {
			if (!is_array($value)) {
				$value = array($key => $value);
				$dest = $control;

			} else {
				$dest = $control->create('optgroup')->label($this->translate($key));
			}

			foreach ($value as $key2 => $value2) {
				if ($value2 instanceof Html) {
					$dest->add((string) $value2->selected(isset($selected[$key2])));

				} else {
					$key2 = $this->useKeys ? $key2 : $value2;

					//$value2 = $this->translate((string) $value2);
					$value2 = $this->translateValues ? $this->translate((string) $value2) : (string) $value2;

					$dest->add((string) $option->value($key2)
						->selected(isset($selected[$key2]))
						->setText($value2));
				}
			}
		}
		return $control;
	}

}

?>

Přidal jsem tedy proměnnou $translateValues, defaultně je vypnuto, pro změnu stavu se používá metoda setTranslateValues($opt = true).

pawouk
Člen | 172
+
0
-

Určitě bych se vyhnul modifikování kodu třetích stran, to je vždy špatná volba. Je potřeba bud podědit, což jde skoro vždy. Je občas narazim na nějakou vyjímku třeba u metody final. A nabo méně vhodné je třídu zkopírovat a přejmenovat Namespace například na XNette. Určitě ale nikdy needitovat Nette (tedy ani žádnou jinou knihovnu).

Michal III
Člen | 83
+
0
-

Také mě to štve, ale bohužel, jak již jsem říkal, u té třídy SelectBox, kterou bych měl dědit, bych potřeboval přepsat jednu metodu, která nejprve zavolá metodu svého předka a bohužel nelze zavolat parent::parent::metoda();

jtousek
Člen | 951
+
0
-

@pawouk: Dovolil bych si nesouhlasit. :-) Od té doby co je spousta projektů takhle na GitHubu je v podobných případech naopak vhodné knihovnu upravit přímo a poslat pull request.

Má zkušenost je taková, že se nebojím zasahovat do kódu Nette (nebo jiných knihoven) když to potřebuji – časem se většina změn stejně objeví přímo v oficiálním Nette nebo přijdu na jiný způsob. Právě teď sice používám svou upravenou verzi, ale Nette 2.1 všechny ty úpravy bude mít také.

Panda
Člen | 569
+
0
-

Teď jsem to taky potřeboval a zkusil jsem najít, jestli to v současném Nette nejde už nějak zařídit… A pořád je to stejné. SelectBoxu jde předat v poli hodnot místo stringu Html element <option>. Stačí pole sestavit takto (pozor, value musíme optionu specifikovat sami!):

$newItems = array();
foreach ($items as $key => $value) {
	$newItems[$key] = \Nette\Utils\Html::el('option')->value($key)->setText($value);
}

Pole $newItems je pak možné použít jako pole hodnot a texty v objektech Html nejsou překládány.

Editoval Panda (20. 8. 2012 17:35)

SvvimX
Člen | 65
+
+1
-

přišel jsem na to uplně náhodou, nebo se do Nette tato možnost přidala?

Stačí prostě:

$this ->addSelect( "year", __ ( "Year" ), $years )
		->setDefaultValue( date("Y") )
		->setPrompt( __ ( "== Year ==" ) )
		->setTranslator( NULL )
		;

nastavit setTranslator( NULL ) ale pak je potřeba ručně přeložit název a prompt.