feature #32388 [Form] Allow to translate each language into its language in LanguageType (javiereguiluz)
This PR was squashed before being merged into the 5.1-dev branch (closes #32388).
Discussion
----------
[Form] Allow to translate each language into its language in LanguageType
| Q | A
| ------------- | ---
| Branch? | 4.4
| Bug fix? | no
| New feature? | yes
| BC breaks? | no <!-- see https://symfony.com/bc -->
| Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tests pass? | yes <!-- please add some, will be required by reviewers -->
| Fixed tickets | #31562
| License | MIT
| Doc PR | I'll do it if this is approved
This would allow to set this option:
```php
->add('language', LanguageType::class, [
'choice_self_translation' => true,
])
```
To display each language translated into its own language:
![image](https://user-images.githubusercontent.com/73419/60709908-cdf29b80-9f11-11e9-83c8-8ee939c0de3a.png)
@ro0NL if this proposal is approved, could you please tell me why I must `try ... catch` with `\Exception`?
* First, I need the try..catch because of a special language with the code "root" which triggers exceptions (*The resource bundle "symfony-code/src/Symfony/Component/Intl/Resources/data/languages/root.json" does not exist*)
* Second, I must catch \Exception because when I try to catch the exact exception (`Symfony\Component\Intl\Exception\ResourceBundleNotFoundException`) the exception is not caught. Why?
Commits
-------
138200cd88
[Form] Allow to translate each language into its language in LanguageType
This commit is contained in:
commit
9097230b6e
@ -13,6 +13,8 @@ namespace Symfony\Component\Form\Extension\Core\Type;
|
|||||||
|
|
||||||
use Symfony\Component\Form\AbstractType;
|
use Symfony\Component\Form\AbstractType;
|
||||||
use Symfony\Component\Form\ChoiceList\Loader\IntlCallbackChoiceLoader;
|
use Symfony\Component\Form\ChoiceList\Loader\IntlCallbackChoiceLoader;
|
||||||
|
use Symfony\Component\Form\Exception\LogicException;
|
||||||
|
use Symfony\Component\Intl\Exception\MissingResourceException;
|
||||||
use Symfony\Component\Intl\Languages;
|
use Symfony\Component\Intl\Languages;
|
||||||
use Symfony\Component\OptionsResolver\Options;
|
use Symfony\Component\OptionsResolver\Options;
|
||||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
@ -27,19 +29,43 @@ class LanguageType extends AbstractType
|
|||||||
$resolver->setDefaults([
|
$resolver->setDefaults([
|
||||||
'choice_loader' => function (Options $options) {
|
'choice_loader' => function (Options $options) {
|
||||||
$choiceTranslationLocale = $options['choice_translation_locale'];
|
$choiceTranslationLocale = $options['choice_translation_locale'];
|
||||||
$alpha3 = $options['alpha3'];
|
$useAlpha3Codes = $options['alpha3'];
|
||||||
|
$choiceSelfTranslation = $options['choice_self_translation'];
|
||||||
|
|
||||||
return new IntlCallbackChoiceLoader(function () use ($choiceTranslationLocale, $alpha3) {
|
return new IntlCallbackChoiceLoader(function () use ($choiceTranslationLocale, $useAlpha3Codes, $choiceSelfTranslation) {
|
||||||
return array_flip($alpha3 ? Languages::getAlpha3Names($choiceTranslationLocale) : Languages::getNames($choiceTranslationLocale));
|
if (true === $choiceSelfTranslation) {
|
||||||
|
foreach (Languages::getLanguageCodes() as $alpha2Code) {
|
||||||
|
try {
|
||||||
|
$languageCode = $useAlpha3Codes ? Languages::getAlpha3Code($alpha2Code) : $alpha2Code;
|
||||||
|
$languagesList[$languageCode] = Languages::getName($alpha2Code, $alpha2Code);
|
||||||
|
} catch (MissingResourceException $e) {
|
||||||
|
// ignore errors like "Couldn't read the indices for the locale 'meta'"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$languagesList = $useAlpha3Codes ? Languages::getAlpha3Names($choiceTranslationLocale) : Languages::getNames($choiceTranslationLocale);
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_flip($languagesList);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
'choice_translation_domain' => false,
|
'choice_translation_domain' => false,
|
||||||
'choice_translation_locale' => null,
|
'choice_translation_locale' => null,
|
||||||
'alpha3' => false,
|
'alpha3' => false,
|
||||||
|
'choice_self_translation' => false,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$resolver->setAllowedTypes('choice_self_translation', ['bool']);
|
||||||
$resolver->setAllowedTypes('choice_translation_locale', ['null', 'string']);
|
$resolver->setAllowedTypes('choice_translation_locale', ['null', 'string']);
|
||||||
$resolver->setAllowedTypes('alpha3', 'bool');
|
$resolver->setAllowedTypes('alpha3', 'bool');
|
||||||
|
|
||||||
|
$resolver->setNormalizer('choice_self_translation', function (Options $options, $value) {
|
||||||
|
if (true === $value && $options['choice_translation_locale']) {
|
||||||
|
throw new LogicException('Cannot use the "choice_self_translation" and "choice_translation_locale" options at the same time. Remove one of them.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
|
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
|
||||||
|
|
||||||
use Symfony\Component\Form\ChoiceList\View\ChoiceView;
|
use Symfony\Component\Form\ChoiceList\View\ChoiceView;
|
||||||
|
use Symfony\Component\Form\Exception\LogicException;
|
||||||
use Symfony\Component\Intl\Util\IntlTestHelper;
|
use Symfony\Component\Intl\Util\IntlTestHelper;
|
||||||
|
|
||||||
class LanguageTypeTest extends BaseTypeTest
|
class LanguageTypeTest extends BaseTypeTest
|
||||||
@ -86,6 +87,52 @@ class LanguageTypeTest extends BaseTypeTest
|
|||||||
$this->assertNotContainsEquals(new ChoiceView('my', 'my', 'бірманська'), $choices);
|
$this->assertNotContainsEquals(new ChoiceView('my', 'my', 'бірманська'), $choices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @requires extension intl
|
||||||
|
*/
|
||||||
|
public function testChoiceSelfTranslationOption()
|
||||||
|
{
|
||||||
|
$choices = $this->factory
|
||||||
|
->create(static::TESTED_TYPE, null, [
|
||||||
|
'choice_self_translation' => true,
|
||||||
|
])
|
||||||
|
->createView()->vars['choices'];
|
||||||
|
|
||||||
|
$this->assertContainsEquals(new ChoiceView('cs', 'cs', 'čeština'), $choices);
|
||||||
|
$this->assertContainsEquals(new ChoiceView('es', 'es', 'español'), $choices);
|
||||||
|
$this->assertContainsEquals(new ChoiceView('fr', 'fr', 'français'), $choices);
|
||||||
|
$this->assertContainsEquals(new ChoiceView('ta', 'ta', 'தமிழ்'), $choices);
|
||||||
|
$this->assertContainsEquals(new ChoiceView('uk', 'uk', 'українська'), $choices);
|
||||||
|
$this->assertContainsEquals(new ChoiceView('yi', 'yi', 'ייִדיש'), $choices);
|
||||||
|
$this->assertContainsEquals(new ChoiceView('zh', 'zh', '中文'), $choices);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @requires extension intl
|
||||||
|
*/
|
||||||
|
public function testChoiceSelfTranslationAndAlpha3Options()
|
||||||
|
{
|
||||||
|
$choices = $this->factory
|
||||||
|
->create(static::TESTED_TYPE, null, [
|
||||||
|
'alpha3' => true,
|
||||||
|
'choice_self_translation' => true,
|
||||||
|
])
|
||||||
|
->createView()->vars['choices'];
|
||||||
|
|
||||||
|
$this->assertContainsEquals(new ChoiceView('spa', 'spa', 'español'), $choices, '', false, false);
|
||||||
|
$this->assertContainsEquals(new ChoiceView('yid', 'yid', 'ייִדיש'), $choices, '', false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSelfTranslationNotAllowedWithChoiceTranslation()
|
||||||
|
{
|
||||||
|
$this->expectException(LogicException::class);
|
||||||
|
|
||||||
|
$this->factory->create(static::TESTED_TYPE, null, [
|
||||||
|
'choice_translation_locale' => 'es',
|
||||||
|
'choice_self_translation' => true,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
public function testMultipleLanguagesIsNotIncluded()
|
public function testMultipleLanguagesIsNotIncluded()
|
||||||
{
|
{
|
||||||
$choices = $this->factory->create(static::TESTED_TYPE, 'language')
|
$choices = $this->factory->create(static::TESTED_TYPE, 'language')
|
||||||
|
Reference in New Issue
Block a user