En este articulo os voy a explicar como internacionalizar una aplicacion web redirigiendo al usuario al directorio segun el pais en el que se encuentre.
Os pongo el siguiente ejemplo: Imaginemos que queremos que los usuarios que viven en Mexico solo puedan ver los productos especificos de su pais, ya que estan segmentados por paises. Por lo que un usuario que acceda a la web española debera ser redirigido a la web de Mexico.
Para ello usaremos un bundle para las rutas muy util llamado : JMSi18nRoutingBundle:
1- Añadimos al composer.json
"jms/i18n-routing-bundle": "^2.0"
2- Inicializamos en AppKernel en bundle:
new JMS\I18nRoutingBundle\JMSI18nRoutingBundle(),
3- Configuramos el bundle(Existen mas opciones disponibles en el bundle pero en nuestro caso queremos esta)
jms_i18n_routing: default_locale: es locales: [es, mx] strategy: prefix
4- Instalamos el bundle para Geolocalizar por IP al usuario:
"maxmind/geoip": "~1.0.0",
5- Inicializamos en AppKernel
new \Maxmind\Bundle\GeoipBundle\MaxmindGeoipBundle(),
6- Este bundle necesita descargarse la base de datos interna para localizar la IP del usuario, para ello ejecutamos el siguiente comando:
php app/console maxmind:geoip:update-data
http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
Esto nos descargara un fichero .dat dentro del bundle pero si queremos moverlo para versionarlo o cualquier cosa, creamos esta configuracion de config.yml
maxmind_geoip: data_file_path: "%kernel.root_dir%/../app/GeoLiteCity.dat"
En mi caso lo he ubicado dentro de la carpeta app/
7- Creamos un Listener para capturar los eventos del Kernel y comprobar la IP, de la siguiente forma AppBundle/Listener/LocaleListener.php
<?php namespace AppBundle\Listener; use Maxmind\Bundle\GeoipBundle\Service\GeoipManager; use Symfony\Bundle\FrameworkBundle\Routing\Router; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Authorization\AuthorizationChecker; class LocaleListener implements EventSubscriberInterface { const DEFAULT_LANGUAGE = 'es'; private $avaliableLanguages; /** @var TokenStorageInterface */ private $context; /** @var Router $router */ private $router; /** @var GeoipManager */ private $geoIp; /** @var AuthorizationChecker */ private $authChecker; /** * LocaleListener constructor. * * @param TokenStorageInterface $context * @param Router $router * @param GeoipManager $geoIp * @param AuthorizationChecker $authorizationChecker * @param $languages */ public function __construct(TokenStorageInterface $context, Router $router, GeoipManager $geoIp, AuthorizationChecker $authorizationChecker, $languages) { $this->context = $context; $this->router = $router; $this->geoIp = $geoIp; $this->authChecker = $authorizationChecker; $this->avaliableLanguages = $languages; } /** * @param GetResponseEvent $event */ public function onKernelRequest(GetResponseEvent $event) { /** @var Request $request */ $request = $event->getRequest(); $localeRequest = $request->getLocale(); $clientIp = $request->getClientIp(); $geoip = $this->geoIp->lookup($clientIp); if($geoip){ $geoIpLocale = strtolower($geoip->getCountryCode()); if(in_array($geoIpLocale, $this->avaliableLanguages)){ $request->setLocale($geoIpLocale); }else{ $request->setLocale(self::DEFAULT_LANGUAGE); } }elseif (!in_array($localeRequest, $this->avaliableLanguages)){ $request->setLocale(self::DEFAULT_LANGUAGE); }else{ $request->setLocale($localeRequest); } } public static function getSubscribedEvents() { return array( KernelEvents::REQUEST => array(array('onKernelRequest', 1)) ); } }
8- Añadimos dentro del parameters.yml los idiomas disponibles:
languages: - es - mx
9- Creamos el servicio para que se enganche al subscribe del Kernel dentro del archivo /app/services.yml
service: //.... myapp.locale_listener: class: AppBundle\Listener\LocaleListener arguments: ["@security.token_storage", "@router", "@maxmind.geoip", "@security.authorization_checker" ,"%languages%"] tags: - { name: kernel.event_subscriber }
Con estos cambios ya tendremos practicamente todo montado, ahora si accedemos a cualquier ruta de la web, debera setear el idioma que le toque o si no existe poner el idioma por defecto.
Tambien podemos añadir en el footer de nuestra web, varios enlaces a los idiomas posibles de la siguiente forma:
- <a href=”{{ path(‘homepage’, {‘_locale’: ‘mx’}) }}”>Mexico</a>
- <a href=”{{ path(‘homepage’, {‘_locale’: ‘es’}) }}”>España</a>
Espero que os haya gustado y recordar compartir este articulo.
Saludos ¡¡