Symfony 3 Rediriger Toutes Les Voies De Paramètres Régionaux En Cours De Version
Je suis en train de travailler sur une application symfony où mon objectif est de n'importe quelle page l'utilisateur est sur il sera accédez à la version locale de la page.
Par exemple, si l'utilisateur accède à "/" de la page d'accueil, il vous redirigera vers "/fr/"
Si ils sont sur le "/admin" de la page, il va rediriger vers "/fr/admin", de telle manière que la _locale
propriété est définie à partir de la route.
Aussi il doit déterminer les paramètres régionaux s'ils visitent /admin à partir du navigateur d'utilisateurs depuis aucune locale a été déterminé de manière à ce qu'il sache page de redirection.
Actuellement mon contrôleur par défaut ressemble à ci-dessous depuis que je suis en essais. Je suis en utilisant le dev mode & profiler pour tester que les traductions sont de travail correcte.
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class DefaultController extends Controller
{
/**
* @Route("/", name="homepage")
* @Route("/{_locale}/", name="homepage_locale")
*/
public function indexAction(Request $request)
{
$translated = $this->get('translator')->trans('Symfony is great');
//replace this example code with whatever you need
return $this->render('default/index.html.twig', [
'base_dir' => realpath($this->container->getParameter('kernel.root_dir').'/..'),
'translated' => $translated
]);
}
}
Cette méthode permettra de garder l'utilisateur au "/" si ils passent par là, mais je veux l'avoir rediriger vers "/en/". Cela devrait fonctionner pour d'autres pages, comme /admin, ou /chemin/pathagain/article1 (/fr/admin /fr/chemin/pathagain/article1)
Comment puis-je faire?
Les références que j'ai lu cela n'a pas aidé:
Symfony2 paramètres régionaux par défaut dans le service de routage
::Mise jour::
Je n'ai pas résolu mon problème mais j'ai réussi à proximité ainsi que appris quelques astuces pour être plus efficace.
DefaultController.php
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class DefaultController extends Controller
{
/**
* @Route("/", name="home", defaults={"_locale"="en"}, requirements={"_locale" = "%app.locales%"})
* @Route("/{_locale}/", name="home_locale", requirements={"_locale" = "%app.locales%"})
*/
public function indexAction(Request $request)
{
$translated = $this->get('translator')->trans('Symfony is great');
//replace this example code with whatever you need
return $this->render('default/index.html.twig', [
'base_dir' => realpath($this->container->getParameter('kernel.root_dir').'/..'),
'translated' => $translated
]);
}
/**
* @Route("/admin", name="admin", defaults={"_locale"="en"}, requirements={"_locale" = "%app.locales%"})
* @Route("/{_locale}/admin", name="admin_locale", requirements={"_locale" = "%app.locales%"})
*/
public function adminAction(Request $request)
{
$translated = $this->get('translator')->trans('Symfony is great');
//replace this example code with whatever you need
return $this->render('default/index.html.twig', [
'base_dir' => realpath($this->container->getParameter('kernel.root_dir').'/..'),
'translated' => $translated
]);
}
}
?>
Config.yml
imports:
- { resource: parameters.yml }
- { resource: security.yml }
- { resource: services.yml }
# Put parameters here that don't need to change on each machine where the app is deployed
# http://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
locale: en
app.locales: en|es|zh
framework:
#esi: ~
translator: { fallbacks: ["%locale%"] }
secret: "%secret%"
router:
resource: "%kernel.root_dir%/config/routing.yml"
strict_requirements: ~
form: ~
csrf_protection: ~
validation: { enable_annotations: true }
#serializer: { enable_annotations: true }
templating:
engines: ['twig']
#assets_version: SomeVersionScheme
default_locale: "%locale%"
trusted_hosts: ~
trusted_proxies: ~
session:
# handler_id set to null will use default session handler from php.ini
handler_id: ~
save_path: "%kernel.root_dir%/../var/sessions/%kernel.environment%"
fragments: ~
http_method_override: true
assets: ~
# Twig Configuration
twig:
debug: "%kernel.debug%"
strict_variables: "%kernel.debug%"
# Doctrine Configuration
doctrine:
dbal:
driver: pdo_mysql
host: "%database_host%"
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
charset: UTF8
# if using pdo_sqlite as your database driver:
# 1. add the path in parameters.yml
# e.g. database_path: "%kernel.root_dir%/data/data.db3"
# 2. Uncomment database_path in parameters.yml.dist
# 3. Uncomment next line:
# path: "%database_path%"
orm:
auto_generate_proxy_classes: "%kernel.debug%"
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: true
# Swiftmailer Configuration
swiftmailer:
transport: "%mailer_transport%"
host: "%mailer_host%"
username: "%mailer_user%"
password: "%mailer_password%"
spool: { type: memory }
Avis en vertu de l'paramètres de la valeur app.locales: en|es|zh
. C'est maintenant une valeur que je peut faire référence à chaque fois que je créer mes itinéraires si j'ai l'intention de soutenir plus de jeux dans l'avenir que je fais. Ces itinéraires sont l'anglais, l'espagnol, le chinois, dans l'ordre, pour les curieux. Dans le DefaultController dans les annotations de la "%app.locales%"
est la partie qui fait référence à la configuration de paramètre.
Le problème avec ma méthode actuelle est d'aller à /admin par exemple ne pas rediriger l'utilisateur vers /{navigateurs locale}/admin, ce qui serait la solution la plus élégante de garder tout organisé... mais au moins, les itinéraires de travail. Toujours à la recherche de la meilleure solution.
****Mise à jour****
Je crois que j'ai peut-être trouvé la réponse ici comme la bas réponse donnée (Ajouter les paramètres régionaux et les exigences de tous les itinéraires - Symfony2), la réponse par Athlan. Juste ne sais pas comment l'implémenter dans symfony 3 que ses instructions n'ont pas été assez clair pour moi.
Je pense que cet article peut aider aussi (http://symfony.com/doc/current/components/event_dispatcher/introduction.html)
OriginalL'auteur Joseph Astrahan | 2016-01-10
Vous devez vous connecter pour publier un commentaire.
Après 12 heures de recherche dans ce que j'ai finalement trouvé une solution acceptable. Veuillez publier des versions révisées de cette solution si vous pouvez la rendre plus efficace.
Des choses à noter, ma solution est particulier à mon besoin. Ce qu'il fait, c'est la force de n'importe quelle URL pour accéder à une version localisée, si elle existe.
Cela nécessite certaines conventions à suivre lorsque vous créez des itinéraires.
DefaultController.php
D'avis que les deux routes de toujours commencer par "/{_locale}/". Pour que cela fonctionne, chaque route dans votre projet doit avoir cette. Vous venez de mettre le vrai nom de la route par la suite. Pour moi, j'étais d'accord avec ce scénario. Vous pouvez modifier ma solution adaptée à vos besoins assez facilement.
La première étape consiste à créer l'écouter sur httpKernal d'intercepter les demandes avant d'aller pour les routeurs de rendre leur.
LocaleRewriteListener.php
Enfin, vous définissez les services.yml pour démarrer l'auditeur.
Services.yml
Aussi dans la config.yml vous souhaitez ajouter les informations suivantes sous paramètres:
config.yml
Je voulais n'être qu'un seul endroit où vous définissez les paramètres régionaux, mais j'ai fini par avoir à faire 2...mais au moins ils sont dans le même endroit, donc facile à changer.
app.locales est utilisé dans le contrôleur par défaut
(requirements={"_locale" = "%app.locales%"})
et locale_supported est utilisé dans le LocaleRewriteListener. S'il détecte une locale qui n'est pas dans la liste, il se replie sur les paramètres régionaux par défaut, qui dans ce cas est la valeur de paramètres régionaux:fr.app.locales est gentil avec les exigences de commande car cela risque de provoquer une erreur 404 pour tous les paramètres régionaux qui ne correspondent pas.
Si vous utilisez des formulaires et d'avoir une connexion, vous devez faire ce qui suit pour votre sécurité.yml
De sécurité.yml
Le changement important à noter ici est que
(.*?)/login
permettra de s'authentifier de manière anonyme afin que vos utilisateurs puissent toujours vous connecter. Cela signifie que les routes, comme..dogdoghere/login pourrait déclencher, mais les exigences, je vais vous montrer prochainement sur les routes de connexion de prévenir cette situation et va lancer des erreurs 404. J'aime cette solution avec le(.*?)
contre[a-z]{2}
au cas où vous vouliez l'utiliser en_US type de paramètres régionaux.SecurityController.php
Noter que même ces chemins utiliser {_locale} en face. J'aime ceci, cependant, afin que je puisse donner personnalisée connexions pour les différents paramètres régionaux. Il suffit de garder cela à l'esprit. La seule voie qui n'a pas besoin de la locale est de déconnexion qui fonctionne très bien depuis son en réalité qu'une seule interception de route pour la sécurité du système. Notez également qu'il se fonde sur les prescriptions qui est définie à partir de la config.yml, de sorte que vous n'avez qu'à éditer dans un seul endroit pour tous les itinéraires dans tous vos projets.
Espère que cela aide quelqu'un qui essaie de faire ce que je faisais!
REMARQUE: Pour tester facilement j'utilise le plus Rapide de la Langue Switcher' extension pour Google Chrome, qui modifie l'-tête accept-language sur toutes les demandes.
@Route
annotation ainsi, juste avant l'ouvertureclass {}
. Vous pouvez essayer de mettre votre_locale
là-bas et voir si cela fonctionne, de sorte que vous n'aurez pas à le répéter dans chaque action.bonne idée, je vais essayer cela.
artamiel votre idée a fonctionné partout à l'exception du contrôleur de sécurité parce que la déconnexion de l'itinéraire se modifie, mais si j'ai donné la déconnexion de l'itinéraire d'un nom, il serait probablement travailler. Je vais essayer cela et si la mise à jour de ma réponse, donc, les choses sont un peu plus propre.
Heureux de l'entendre. En tout cas, vous avez 2 autres routes pour définir -
logout
etlogin
, de sorte que même si elles ne sont pas automatiquement le préfixe, ce n'est pas une grosse affaire, si le repos de vos itinéraires sont configurés correctement.Oui, vous avez raison c'est une option aussi, à faire de déconnexion dans son propre domaine, ou depuis son seulement 2 dans le routeur, de toute façon tout faire de ces exceptions.
OriginalL'auteur Joseph Astrahan
Je n'ai pas assez de réputation pour ajouter un commentaire pour la bonne solution. Donc, je vais ajouter une nouvelle réponse
Vous pouvez ajouter un préfixe: /{_locale}" dans app/config/routing.yml comme ceci:
De sorte que vous n'avez pas besoin de l'ajouter à chaque route, à chaque action. Pour les étapes suivantes. Merci beaucoup c'est parfait.
OriginalL'auteur Susana Santos
fonction finale smallResumeOfResearching($localeRewrite, $avis = 'mon humble avis') 🙂
La méthode, fournies par le monsieur. Joseph génial de travailler avec des voies comme /{route_name} ou /, mais pas avec de tels axes /article/slug/autres.
Si nous utilisons modifié monsieur.Joseph méthode, fournis par https://stackoverflow.com/a/37168304/9451542, nous avons perdu profiler et le débogueur en dev mode.
Si nous voulons solution plus flexible, onKernelRequest méthode peut être modifiée comme ceci (merci à monsieur. Joseph, grâce à https://stackoverflow.com/a/37168304/9451542):
note: $this->profilerRoutes = array('_profiler', '_wdt', '_error');
OriginalL'auteur Vitalijus Trainys
Petite amélioration pour Symfony 3.4:
Être sûr, que les getSubscribedEvents() va enregistrer LocaleRewriteListener AVANT RouterListener::onKernelRequest et AVANT LocaleListener::onKernelRequest. Entier 17 doit être supérieure à RouterListener::onKernelRequest la priorité. Sinon, vous aurez obtenu 404.
bin/console de debug:événement-répartiteur
Définition de Service dans les services.yml doit être (dépend de la configuration de Symfony):
AppBundle\EventListener\LocaleRewriteListener:
arguments: ['@routeur', '%noyau.paramètre default_locale%', '%locale_supported%']
tags:
- { name: kernel.event_subscriber, de l'événement: le noyau.demande }
OriginalL'auteur Vitalijus Trainys