-
-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #12 from kdambekalns/translatable-forms
!!! FEATURE: Translatable forms This change allows for forms to be translated using XLIFF as elsewhere in Flow. Form element labels, placeholders, option labels and more can be translated. Instructions are included in a new documentation chapter. This is marked as breaking: if you changed the "translationPackage" earlier to customize validation error messages, you will need to use the new "validationErrorTranslationPackage" setting for that now. A code migration to adjust that is included, run: ./flow flow:core:migrate --version 20160601101500 --package-key ...
- Loading branch information
Showing
25 changed files
with
424 additions
and
28 deletions.
There are no files selected for viewing
74 changes: 74 additions & 0 deletions
74
Classes/TYPO3/Form/ViewHelpers/TranslateElementPropertyViewHelper.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
<?php | ||
namespace TYPO3\Form\ViewHelpers; | ||
|
||
/* | ||
* This file is part of the TYPO3.Form package. | ||
* | ||
* (c) Contributors of the Neos Project - www.neos.io | ||
* | ||
* This package is Open Source Software. For the full copyright and license | ||
* information, please view the LICENSE file which was distributed with this | ||
* source code. | ||
*/ | ||
|
||
use TYPO3\Flow\Annotations as Flow; | ||
use TYPO3\Flow\I18n\Translator; | ||
use TYPO3\Flow\Resource\Exception as ResourceException; | ||
use TYPO3\Fluid\Core\ViewHelper\AbstractViewHelper; | ||
use TYPO3\Fluid\Core\ViewHelper\Exception as ViewHelperException; | ||
use TYPO3\Form\Core\Model\FormElementInterface; | ||
|
||
/** | ||
* ViewHelper to translate the property of a given form element based on its rendering options | ||
* | ||
* = Examples = | ||
* | ||
* <code> | ||
* {element -> form:translateElementProperty(property: 'placeholder')} | ||
* </code> | ||
* <output> | ||
* the translated placeholder, or the actual "placeholder" property if no translation was found | ||
* </output> | ||
* | ||
*/ | ||
class TranslateElementPropertyViewHelper extends AbstractViewHelper | ||
{ | ||
/** | ||
* @Flow\Inject | ||
* @var Translator | ||
*/ | ||
protected $translator; | ||
|
||
/** | ||
* @var bool | ||
*/ | ||
protected $escapeChildren = false; | ||
|
||
/** | ||
* @param string $property | ||
* @param FormElementInterface $element | ||
* @return string the rendered form head | ||
*/ | ||
public function render($property, FormElementInterface $element = null) | ||
{ | ||
if ($element === null) { | ||
$element = $this->renderChildren(); | ||
} | ||
if ($property === 'label') { | ||
$defaultValue = $element->getLabel(); | ||
} else { | ||
$defaultValue = isset($element->getProperties()[$property]) ? (string)$element->getProperties()[$property] : ''; | ||
} | ||
$renderingOptions = $element->getRenderingOptions(); | ||
if (!isset($renderingOptions['translationPackage'])) { | ||
return $defaultValue; | ||
} | ||
$translationId = sprintf('forms.elements.%s.%s', $element->getIdentifier(), $property); | ||
try { | ||
$translation = $this->translator->translateById($translationId, [], null, null, 'Main', $renderingOptions['translationPackage']); | ||
} catch (ResourceException $exception) { | ||
return $defaultValue; | ||
} | ||
return $translation === null ? $defaultValue : $translation; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,204 @@ | ||
.. _translating-forms: | ||
|
||
Translating Forms | ||
================= | ||
|
||
If a form has been set up, all elements will use the labels, placeholders and so forth as configured. | ||
To have the form translated depending on the current locale, you need to configure a package to load | ||
the translations from and add the translations as XLIFF files. | ||
|
||
Configuration | ||
------------- | ||
|
||
The package to load the translations from is configured in the form preset being used. The simplest | ||
way to configure it is this: | ||
|
||
.. code-block:: yaml | ||
TYPO3: | ||
Form: | ||
presets: | ||
default: | ||
formElementTypes: | ||
'TYPO3.Form:Base': | ||
renderingOptions: | ||
translationPackage: 'AcmeCom.SomePackage' | ||
Of course it can be set in a custom preset in the same way. | ||
|
||
The translation of validation error messages uses the TYPO3.Flow package by default, to avoid having to | ||
copy the validation errors message catalog to all packages used for form translation. If you want to | ||
adjust those error messages as well, copy ``ValidationErrors.xlf`` to your package and set the option | ||
``validationErrorTranslationPackage`` to your package key. | ||
|
||
XLIFF files | ||
----------- | ||
|
||
The XLIFF files follow the usual rules, the ``Main`` catalog is used. The Form package comes with the following | ||
catalog (``Main.xlf``): | ||
|
||
.. code-block:: xml | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> | ||
<file original="" product-name="TYPO3.Form" source-language="en" datatype="plaintext"> | ||
<body> | ||
<trans-unit id="forms.navigation.previousPage" xml:space="preserve"> | ||
<source>Previous page</source> | ||
</trans-unit> | ||
<trans-unit id="forms.navigation.nextPage" xml:space="preserve"> | ||
<source>Next page</source> | ||
</trans-unit> | ||
<trans-unit id="forms.navigation.submit" xml:space="preserve"> | ||
<source>Submit</source> | ||
</trans-unit> | ||
</body> | ||
</file> | ||
</xliff> | ||
It should be copied to make sure the three expected units are available and can then be amended by your own | ||
units. | ||
|
||
For most reliable translations, the units should be given id properties based on the form configuration. | ||
The schema is as follows: | ||
|
||
forms.navigation.nextPage | ||
In multi-page forms this is used for the navigation. | ||
forms.navigation.previousPage | ||
In multi-page forms this is used for the navigation. | ||
forms.navigation.submitButton | ||
In forms this is used for the submit button. | ||
|
||
Forms and sections can have their labels translated using this, where where ``{identifier}`` is the identifier | ||
of the page or section itself: | ||
|
||
forms.pages.{identifier}.label | ||
The label used for a form page. | ||
forms.sections.{identifier}.label | ||
The label used for a form section. | ||
|
||
The actual elements of a form have their id constructed by appending one of the following to | ||
``forms.elements.{identifier}.``, where ``{identifier}`` is the identifier of the form element | ||
itself: | ||
|
||
label | ||
The label for an element. | ||
placeholder | ||
The placeholder for an element, if applicable. | ||
description | ||
dkjsadhsajk | ||
text | ||
The text of a ``StaticText`` element. | ||
confirmationLabel | ||
Used in the ``PasswordWithConfirmation`` element. | ||
passwordDescription | ||
Used in the ``PasswordWithConfirmation`` element. | ||
|
||
The labels of radio buttons and select field options can be translated using the following schema, | ||
where ``{identifier}`` is the identifier of the form element itself and ``value`` is the value assigned | ||
to the option: | ||
|
||
forms.elements.{identifier}.options.{value} | ||
Used to translate labels of radio buttons and select field entries. | ||
|
||
Complete example | ||
---------------- | ||
|
||
This is the example form used elsewhere in this documentation: | ||
|
||
* Contact Form *(Form)* | ||
* Page 01 *(Page)* | ||
* Name *(Single-line Text)* | ||
* Email *(Single-line Text)* | ||
* Message *(Multi-line Text)* | ||
|
||
Assume it is configured like this using YAML: | ||
|
||
.. code-block:: yaml | ||
type: 'TYPO3.Form:Form' | ||
identifier: 'contact' | ||
label: 'Contact form' | ||
renderables: | ||
- | ||
type: 'TYPO3.Form:Page' | ||
identifier: 'page-one' | ||
renderables: | ||
- | ||
type: 'TYPO3.Form:SingleLineText' | ||
identifier: name | ||
label: 'Name' | ||
validators: | ||
- identifier: 'TYPO3.Flow:NotEmpty' | ||
properties: | ||
placeholder: 'Please enter your full name' | ||
- | ||
type: 'TYPO3.Form:SingleLineText' | ||
identifier: email | ||
label: 'Email' | ||
validators: | ||
- identifier: 'TYPO3.Flow:NotEmpty' | ||
- identifier: 'TYPO3.Flow:EmailAddress' | ||
properties: | ||
placeholder: 'Enter a valid email address' | ||
- | ||
type: 'TYPO3.Form:MultiLineText' | ||
identifier: message | ||
label: 'Message' | ||
validators: | ||
- identifier: 'TYPO3.Flow:NotEmpty' | ||
properties: | ||
placeholder: 'Enter your message here' | ||
.. note:: You may leave out ``label`` and ``placeholder`` if you use id-based matching for the translation. | ||
Be aware though, that you will get empty labels and placeholders in case the translation fails or is not | ||
available. | ||
|
||
The following XLIFF would allow to translate the form: | ||
|
||
.. code-block:: xml | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> | ||
<file original="" product-name="TYPO3.Form" source-language="en" datatype="plaintext"> | ||
<body> | ||
<trans-unit id="forms.navigation.previousPage" xml:space="preserve"> | ||
<source>Previous page</source> | ||
</trans-unit> | ||
<trans-unit id="forms.navigation.nextPage" xml:space="preserve"> | ||
<source>Next page</source> | ||
</trans-unit> | ||
<trans-unit id="forms.navigation.submit" xml:space="preserve"> | ||
<source>Submit</source> | ||
</trans-unit> | ||
<trans-unit id="forms.pages.page-one" xml:space="preserve"> | ||
<source>Submit</source> | ||
</trans-unit> | ||
<trans-unit id="forms.elements.name.label" xml:space="preserve"> | ||
<source>Name</source> | ||
</trans-unit> | ||
<trans-unit id="forms.elements.name.placeholder" xml:space="preserve"> | ||
<source>Please enter your full name</source> | ||
</trans-unit> | ||
<trans-unit id="forms.elements.email.label" xml:space="preserve"> | ||
<source>Email</source> | ||
</trans-unit> | ||
<trans-unit id="forms.elements.email.placeholder" xml:space="preserve"> | ||
<source>Enter a valid email address</source> | ||
</trans-unit> | ||
<trans-unit id="forms.elements.message.label" xml:space="preserve"> | ||
<source>Message</source> | ||
</trans-unit> | ||
<trans-unit id="forms.elements.message.placeholder" xml:space="preserve"> | ||
<source>Enter your message here</source> | ||
</trans-unit> | ||
</body> | ||
</file> | ||
</xliff> | ||
Copy it to your target language and add the ``target-language`` attribute as well as the needed | ||
``<target>…</target>`` entries. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
<?php | ||
namespace TYPO3\Flow\Core\Migrations; | ||
|
||
/* | ||
* This file is part of the TYPO3.Flow package. | ||
* | ||
* (c) Contributors of the Neos Project - www.neos.io | ||
* | ||
* This package is Open Source Software. For the full copyright and license | ||
* information, please view the LICENSE file which was distributed with this | ||
* source code. | ||
*/ | ||
|
||
use TYPO3\Flow\Configuration\ConfigurationManager; | ||
|
||
/** | ||
* Adjust "Settings.yaml" to use validationErrorTranslationPackage instead of translationPackage | ||
*/ | ||
class Version20160601101500 extends AbstractMigration | ||
{ | ||
|
||
/** | ||
* @return void | ||
*/ | ||
public function up() | ||
{ | ||
$this->processConfiguration(ConfigurationManager::CONFIGURATION_TYPE_SETTINGS, | ||
function (array &$configuration) { | ||
$presetsConfiguration = \TYPO3\Flow\Reflection\ObjectAccess::getPropertyPath($configuration, 'TYPO3.Form.presets'); | ||
if (!is_array($presetsConfiguration)) { | ||
return; | ||
} | ||
|
||
$presetsConfiguration = $this->renameTranslationPackage($presetsConfiguration); | ||
|
||
$configuration['TYPO3']['Form']['presets'] = $presetsConfiguration; | ||
}, | ||
true | ||
); | ||
} | ||
|
||
/** | ||
* Recurse into the given preset and rename translationPackage to validationErrorTranslationPackage | ||
* | ||
* @param array $preset | ||
* @return array | ||
*/ | ||
public function renameTranslationPackage(array &$preset) | ||
{ | ||
foreach ($preset as $key => $value) { | ||
if (is_array($value)) { | ||
if (isset($value['renderingOptions']['translationPackage'])) { | ||
$value['renderingOptions']['validationErrorTranslationPackage'] = $value['renderingOptions']['translationPackage']; | ||
unset($value['renderingOptions']['translationPackage']); | ||
} | ||
$preset[$key] = $this->renameTranslationPackage($value); | ||
} | ||
} | ||
|
||
return $preset; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.