Skip to content
This repository was archived by the owner on Jan 30, 2020. It is now read-only.

Commit 21fe3c9

Browse files
committed
Merge pull request #115 from MatthiasKuehneEllerhold/translatable_html_attribute_prefixes
Translatable html attributes
2 parents adbed93 + f495a17 commit 21fe3c9

File tree

4 files changed

+250
-32
lines changed

4 files changed

+250
-32
lines changed

doc/book/helper/abstract-helper.md

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,60 @@ allows setting a translator and text domain.
1212
The following public methods are in addition to the inherited methods of
1313
[Zend\I18n\View\Helper\AbstractTranslatorHelper](http://zendframework.github.io/zend-i18n/view-helpers/#abstract-translator-helper).
1414

15-
Method signature | Description
16-
-------------------------------------- | -----------
17-
`setDoctype(string $doctype) : void` | Sets a doctype to use in the helper.
18-
`getDoctype() : string` | Returns the doctype used in the helper.
19-
`setEncoding(string $encoding) : void` | Set the translation text domain to use in helper when translating.
20-
`getEncoding() : string` | Returns the character encoding used in the helper.
21-
`getId() : string or null` | Returns the element id. If no ID attribute present, attempts to use the name attribute. If name attribute is also not present, returns `null`.
15+
Method signature | Description
16+
-------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------
17+
`setDoctype(string $doctype) : void` | Sets a doctype to use in the helper.
18+
`getDoctype() : string` | Returns the doctype used in the helper.
19+
`setEncoding(string $encoding) : void` | Set the translation text domain to use in helper when translating.
20+
`getEncoding() : string` | Returns the character encoding used in the helper.
21+
`getId() : string or null` | Returns the element id. If no ID attribute present, attempts to use the name attribute. If name attribute is also not present, returns `null`.
22+
`addTranslatableAttribute(string $attribute) : self` | Marks the given HTML attribute as translatable.
23+
`addTranslatableAttributePrefix(string $prefix) : self` | Marks all HTML attributes that start with the given prefix as translatable.
24+
`addTranslatableAttribute(string $attribute) : self` | Marks the given HTML attribute as translatable.
25+
`addTranslatableAttributePrefix(string $prefix) : self` | Marks all HTML attributes that start with the given prefix as translatable.
26+
`addDefaultTranslatableAttribute(string $attribute) : void` | Marks the given HTML attribute as translatable for all view helpers.
27+
`addDefaultTranslatableAttributePrefix(string $prefix) : void` | Marks all HTML attributes that start with the given prefix as translatable for all view helpers.
28+
29+
## Translation
30+
31+
Attaching a translator and setting a text domain (using the formLabel view helper as an example):
32+
33+
```php
34+
// Setting a translator
35+
$this->formLabel()->setTranslator($translator);
36+
37+
// Setting a text domain
38+
$this->formLabel()->setTranslatorTextDomain('my-text-domain');
39+
40+
// Setting both
41+
$this->formLabel()->setTranslator($translator, 'my-text-domain');
42+
```
43+
44+
> ### Enabling translation
45+
>
46+
> If you have a translator in your application container under either the key,
47+
> `translator` or `MvcTranslator`, the view helper plugin manager will
48+
> automatically attach the translator to the view helpers.
49+
50+
### What will be translated?
51+
52+
The specific view helpers are responsible to determine what exactly should be translated
53+
(e. g. the Label in the FormLabel view helper or the "title" HTML attribute).
54+
55+
If you want to have certain HTML attribute values translated you can mark them as "translatable":
56+
```php
57+
// mark one attribute as translatable
58+
$this->formLabel()->addTranslatableAttribute('data-translate-me');
59+
60+
// mark an prefix as translatable
61+
$this->formLabel()->addTranslatableAttributePrefix('data-translatable-');
62+
```
63+
64+
Or you can mark them as translatable for all view helpers (e. g. the title attribute):
65+
```php
66+
// mark one attribute as translatable
67+
\Zend\Form\View\Helper\AbstractHelper->addDefaultTranslatableAttribute('title');
68+
69+
// mark an prefix as translatable
70+
\Zend\Form\View\Helper\AbstractHelper->addDefaultTranslatableAttributePrefix('data-translatable-');
71+
```

doc/book/helper/form-label.md

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -58,24 +58,7 @@ echo $this->formLabel($element);
5858
5959
## Label translation
6060

61-
Attaching a translator and setting a text domain:
62-
63-
```php
64-
// Setting a translator
65-
$this->formLabel()->setTranslator($translator);
66-
67-
// Setting a text domain
68-
$this->formLabel()->setTranslatorTextDomain('my-text-domain');
69-
70-
// Setting both
71-
$this->formLabel()->setTranslator($translator, 'my-text-domain');
72-
```
73-
74-
> ### Enabling translation
75-
>
76-
> If you have a translator in your application container under either the key,
77-
> `translator` or `MvcTranslator`, the view helper plugin manager will
78-
> automatically attach the translator to the `FormLabel` view helper.
61+
See [AbstractHelper Translation](abstract-helper.md#translation).
7962

8063
## Public methods
8164

src/View/Helper/AbstractHelper.php

Lines changed: 107 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,22 @@
2020
*/
2121
abstract class AbstractHelper extends BaseAbstractHelper
2222
{
23+
/**
24+
* The default translatable HTML attributes
25+
*
26+
* @var array
27+
*/
28+
protected static $defaultTranslatableHtmlAttributes = [
29+
'title' => true,
30+
];
31+
32+
/**
33+
* The default translatable HTML attribute prefixes
34+
*
35+
* @var array
36+
*/
37+
protected static $defaultTranslatableHtmlAttributePrefixes = [];
38+
2339
/**
2440
* Standard boolean attributes, with expected values for enabling/disabling
2541
*
@@ -42,9 +58,15 @@ abstract class AbstractHelper extends BaseAbstractHelper
4258
*/
4359
protected $translatableAttributes = [
4460
'placeholder' => true,
45-
'title' => true,
4661
];
4762

63+
/**
64+
* Prefixes of translatable HTML attributes
65+
*
66+
* @var array
67+
*/
68+
protected $translatableAttributePrefixes = [];
69+
4870
/**
4971
* @var Doctype
5072
*/
@@ -219,12 +241,8 @@ public function createAttributesString(array $attributes)
219241
}
220242
}
221243

222-
//check if attribute is translatable
223-
if (isset($this->translatableAttributes[$key]) && !empty($value)) {
224-
if (($translator = $this->getTranslator()) !== null) {
225-
$value = $translator->translate($value, $this->getTranslatorTextDomain());
226-
}
227-
}
244+
//check if attribute is translatable and translate it
245+
$value = $this->translateHtmlAttributeValue($key, $value);
228246

229247
//@TODO Escape event attributes like AbstractHtmlElement view helper does in htmlAttribs ??
230248
$strings[] = sprintf('%s="%s"', $escape($key), $escapeAttr($value));
@@ -397,4 +415,86 @@ protected function prepareBooleanAttributeValue($attribute, $value)
397415
: $this->booleanAttributes[$attribute]['off']
398416
);
399417
}
418+
419+
/**
420+
* Translates the value of the HTML attribute if it should be translated and this view helper has a translator
421+
*
422+
* @param string $key
423+
* @param string $value
424+
*
425+
* @return string
426+
*/
427+
protected function translateHtmlAttributeValue($key, $value)
428+
{
429+
if (empty($value) || ($this->getTranslator() === null)) {
430+
return $value;
431+
}
432+
433+
if (isset($this->translatableAttributes[$key]) || isset(self::$defaultTranslatableHtmlAttributes[$key])) {
434+
return $this->getTranslator()->translate($value, $this->getTranslatorTextDomain());
435+
} else {
436+
foreach ($this->translatableAttributePrefixes as $prefix) {
437+
if (mb_substr($key, 0, mb_strlen($prefix)) === $prefix) {
438+
// prefix matches => return translated $value
439+
return $this->getTranslator()->translate($value, $this->getTranslatorTextDomain());
440+
}
441+
}
442+
foreach (self::$defaultTranslatableHtmlAttributePrefixes as $prefix) {
443+
if (mb_substr($key, 0, mb_strlen($prefix)) === $prefix) {
444+
// default prefix matches => return translated $value
445+
return $this->getTranslator()->translate($value, $this->getTranslatorTextDomain());
446+
}
447+
}
448+
}
449+
450+
return $value;
451+
}
452+
453+
/**
454+
* Adds an HTML attribute to the list of translatable attributes
455+
*
456+
* @param string $attribute
457+
*
458+
* @return AbstractHelper
459+
*/
460+
public function addTranslatableAttribute($attribute)
461+
{
462+
$this->translatableAttributes[$attribute] = true;
463+
464+
return $this;
465+
}
466+
467+
/**
468+
* Adds an HTML attribute to the list of the default translatable attributes
469+
*
470+
* @param string $attribute
471+
*/
472+
public static function addDefaultTranslatableAttribute($attribute)
473+
{
474+
self::$defaultTranslatableHtmlAttributes[$attribute] = true;
475+
}
476+
477+
/**
478+
* Adds an HTML attribute to the list of translatable attributes
479+
*
480+
* @param string $prefix
481+
*
482+
* @return AbstractHelper
483+
*/
484+
public function addTranslatableAttributePrefix($prefix)
485+
{
486+
$this->translatableAttributePrefixes[] = $prefix;
487+
488+
return $this;
489+
}
490+
491+
/**
492+
* Adds an HTML attribute to the list of translatable attributes
493+
*
494+
* @param string $prefix
495+
*/
496+
public static function addDefaultTranslatableAttributePrefix($prefix)
497+
{
498+
self::$defaultTranslatableHtmlAttributePrefixes[] = $prefix;
499+
}
400500
}

test/View/Helper/AbstractHelperTest.php

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
namespace ZendTest\Form\View\Helper;
1111

1212
use Zend\Escaper\Escaper;
13+
use Zend\Form\View\Helper\AbstractHelper;
14+
use Zend\I18n\Translator\Translator;
1315

1416
/**
1517
* Tests for {@see \Zend\Form\View\Helper\AbstractHelper}
@@ -57,4 +59,87 @@ public function testWillNotEncodeValueAttributeValuesCorrectly()
5759
$this->helper->createAttributesString(['data-value' => 'Título'])
5860
);
5961
}
62+
63+
public function testWillTranslateAttributeValuesCorrectly()
64+
{
65+
$translator = self::getMockBuilder(Translator::class)
66+
->disableOriginalConstructor()
67+
->setMethods(['translate'])
68+
->getMock();
69+
70+
$translator
71+
->expects(self::exactly(2))
72+
->method('translate')
73+
->with(
74+
self::equalTo('Welcome'),
75+
self::equalTo('view-helper-text-domain')
76+
)
77+
->willReturn('Willkommen');
78+
79+
$this->helper
80+
->addTranslatableAttribute('data-translate-me')
81+
->addTranslatableAttributePrefix('data-translatable-')
82+
->setTranslatorEnabled(true)
83+
->setTranslator(
84+
$translator,
85+
'view-helper-text-domain'
86+
);
87+
88+
$this->assertSame(
89+
'data-translate-me="Willkommen"',
90+
$this->helper->createAttributesString(['data-translate-me' => 'Welcome'])
91+
);
92+
93+
$this->assertSame(
94+
'data-translatable-welcome="Willkommen"',
95+
$this->helper->createAttributesString(['data-translatable-welcome' => 'Welcome'])
96+
);
97+
98+
$this->assertSame(
99+
'class="Welcome"',
100+
$this->helper->createAttributesString(['class' => 'Welcome'])
101+
);
102+
}
103+
104+
public function testWillTranslateDefaultAttributeValuesCorrectly()
105+
{
106+
$translator = self::getMockBuilder(Translator::class)
107+
->disableOriginalConstructor()
108+
->setMethods(['translate'])
109+
->getMock();
110+
111+
$translator
112+
->expects(self::exactly(2))
113+
->method('translate')
114+
->with(
115+
self::equalTo('Welcome'),
116+
self::equalTo('view-helper-text-domain')
117+
)
118+
->willReturn('Willkommen');
119+
120+
AbstractHelper::addDefaultTranslatableAttribute('data-translate-me');
121+
AbstractHelper::addDefaultTranslatableAttributePrefix('data-translatable-');
122+
123+
$this->helper
124+
->setTranslatorEnabled(true)
125+
->setTranslator(
126+
$translator,
127+
'view-helper-text-domain'
128+
);
129+
130+
$this->assertSame(
131+
'data-translate-me="Willkommen"',
132+
$this->helper->createAttributesString(['data-translate-me' => 'Welcome'])
133+
);
134+
135+
$this->assertSame(
136+
'data-translatable-welcome="Willkommen"',
137+
$this->helper->createAttributesString(['data-translatable-welcome' => 'Welcome'])
138+
);
139+
140+
$this->assertSame(
141+
'class="Welcome"',
142+
$this->helper->createAttributesString(['class' => 'Welcome'])
143+
);
144+
}
60145
}

0 commit comments

Comments
 (0)