Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor how we define the available locales #1511

Merged
merged 1 commit into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions config/packages/framework.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ framework:
http_method_override: false
handle_all_throwables: true

# this defines the codes of the locales (languages) available in the application
# https://symfony.com/doc/current/reference/configuration/framework.html#enabled-locales
enabled_locales: ['ar', 'bg', 'bn', 'bs', 'ca', 'cs', 'de', 'en', 'es', 'eu', 'fr', 'hr', 'id', 'it', 'ja', 'lt', 'ne', 'nl', 'pl', 'pt_BR', 'ro', 'ru', 'sl', 'sq', 'sr_Cyrl', 'sr_Latn', 'tr', 'uk', 'vi', 'zh_CN']

# Enables session support. Note that the session will ONLY be started if you read or write from it.
# Remove or comment this section to explicitly disable session support.
session:
Expand Down
2 changes: 1 addition & 1 deletion config/packages/security.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ security:
access_control:
# this is a catch-all for the admin area
# additional security lives in the controllers
- { path: '^/(%app_locales%)/admin', roles: ROLE_ADMIN }
- { path: '^/{_locale}/admin', roles: ROLE_ADMIN }

# The ROLE_ADMIN role inherits from the ROLE_USER role
role_hierarchy:
Expand Down
4 changes: 0 additions & 4 deletions config/routes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
homepage:
path: /{_locale}
controller: Symfony\Bundle\FrameworkBundle\Controller\TemplateController::templateAction
requirements:
_locale: '%app_locales%'
defaults:
template: default/homepage.html.twig
_locale: '%locale%'
Expand All @@ -17,7 +15,5 @@ controllers:
namespace: App\Controller
type: attribute
prefix: /{_locale}
requirements:
_locale: '%app_locales%'
defaults:
_locale: '%locale%'
4 changes: 1 addition & 3 deletions config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
parameters:
locale: 'en'
# This parameter defines the codes of the locales (languages) enabled in the application
app_locales: ar|en|fr|de|es|cs|nl|ru|uk|ro|pt_BR|pl|it|ja|id|ca|sl|sq|hr|zh_CN|bg|tr|lt|bs|sr_Cyrl|sr_Latn|eu|ne|bn|vi
app.notifications.email_sender: anonymous@example.com

services:
Expand All @@ -18,7 +16,7 @@ services:
# this allows to define the scalar arguments once and apply them to any services
# defined/created in this file; if some argument is used rarely, instead of defining
# it here you can use the #[Autowire] attribute to inject it manually in the service constructor
string $locales: '%app_locales%'
array $enabledLocales: '%kernel.enabled_locales%'
string $defaultLocale: '%locale%'

# makes classes in src/ available to be used as services
Expand Down
27 changes: 10 additions & 17 deletions src/EventSubscriber/RedirectToPreferredLocaleSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,34 +28,27 @@
*/
final class RedirectToPreferredLocaleSubscriber implements EventSubscriberInterface
{
/**
* @var string[]
*/
private array $locales;
private readonly string $defaultLocale;

public function __construct(
private readonly UrlGeneratorInterface $urlGenerator,
string $locales,
?string $defaultLocale = null
/** @var string[] */
private array $enabledLocales,
private ?string $defaultLocale = null
) {
$this->locales = explode('|', trim($locales));

if (empty($this->locales)) {
if (empty($this->enabledLocales)) {
throw new \UnexpectedValueException('The list of supported locales must not be empty.');
}

$this->defaultLocale = $defaultLocale ?: $this->locales[0];
$this->defaultLocale = $defaultLocale ?: $this->enabledLocales[0];

if (!\in_array($this->defaultLocale, $this->locales, true)) {
throw new \UnexpectedValueException(sprintf('The default locale ("%s") must be one of "%s".', $this->defaultLocale, $locales));
if (!\in_array($this->defaultLocale, $this->enabledLocales, true)) {
throw new \UnexpectedValueException(sprintf('The default locale ("%s") must be one of "%s".', $this->defaultLocale, implode(', ', $this->enabledLocales)));
}

// Add the default locale at the first position of the array,
// because Symfony\HttpFoundation\Request::getPreferredLanguage
// returns the first element when no an appropriate language is found
array_unshift($this->locales, $this->defaultLocale);
$this->locales = array_unique($this->locales);
array_unshift($this->enabledLocales, $this->defaultLocale);
$this->enabledLocales = array_unique($this->enabledLocales);
}

public static function getSubscribedEvents(): array
Expand All @@ -81,7 +74,7 @@ public function onKernelRequest(RequestEvent $event): void
return;
}

$preferredLanguage = $request->getPreferredLanguage($this->locales);
$preferredLanguage = $request->getPreferredLanguage($this->enabledLocales);

if ($preferredLanguage !== $this->defaultLocale) {
$response = new RedirectResponse($this->urlGenerator->generate('homepage', ['_locale' => $preferredLanguage]));
Expand Down
16 changes: 5 additions & 11 deletions src/Twig/AppExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,17 @@
*/
final class AppExtension extends AbstractExtension
{
/**
* @var string[]
*/
private readonly array $localeCodes;

/**
* @var list<array{code: string, name: string}>|null
*/
private ?array $locales = null;

// The $locales argument is injected thanks to the service container.
// See https://symfony.com/doc/current/service_container.html#binding-arguments-by-name-or-type
public function __construct(string $locales)
{
$localeCodes = explode('|', $locales);
sort($localeCodes);
$this->localeCodes = $localeCodes;
public function __construct(
/** @var string[] */
private array $enabledLocales,
) {
}

public function getFunctions(): array
Expand All @@ -65,7 +59,7 @@ public function getLocales(): array

$this->locales = [];

foreach ($this->localeCodes as $localeCode) {
foreach ($this->enabledLocales as $localeCode) {
$this->locales[] = ['code' => $localeCode, 'name' => Locales::getName($localeCode, $localeCode)];
}

Expand Down