2011-10-26 8 views
26

मुझे रूटिंग और सिम्फनी 2 के साथ बनाई गई मेरी साइट के अंतर्राष्ट्रीयकरण में समस्या है।
अगर मैं routing.yml फ़ाइल में मार्गों को परिभाषित, इस तरह:रूफिंग में सिम्फनी 2 डिफ़ॉल्ट लोकेल

example: 
    pattern: /{_locale}/example 
    defaults: { _controller: ExampleBundle:Example:index, _locale: fr } 

ऐसा लगता है कि यूआरएल के साथ ठीक काम करता है:

mysite.com/en/example 
mysite.com/fr/example 

लेकिन साथ काम नहीं करता

mysite.com/example 

क्या यह हो सकता है कि वैकल्पिक प्लेसहोल्डर्स को केवल यूआरएल के अंत में ही अनुमति दी जाए?
यदि हाँ, क्या की तरह एक यूआरएल प्रदर्शित करने के लिए एक संभव समाधान हो सकता है: एक डिफ़ॉल्ट भाषा में

mysite.com/example 

या करने के लिए उपयोगकर्ता पुनः निर्देशित:

mysite.com/defaultlanguage/example 

जब वह दौरा:

mysite.com/example. ? 

मैं इसे समझने की कोशिश कर रहा हूं लेकिन सफलता के बिना अब तक।

धन्यवाद।

+0

आप इस का समाधान कर सकता है? –

+0

मैंने अभी तक अपनी वेबसाइट में डिफ़ॉल्ट स्थानीय के संबंध में कोई समाधान लागू नहीं किया है। मुझे जल्द ही ऐसा करना पड़ सकता है क्योंकि हम अंतरराष्ट्रीय जा रहे हैं, मैं उस समाधान की रिपोर्ट करूंगा जो हम यहां लागू करेंगे। मैंने अभी जवाब पढ़े हैं और @mattexx एक सबसे अच्छा/क्लीनर लगता है। मुझे नहीं पता था कि आप एक नियंत्रक के लिए एकाधिक मार्ग परिभाषित कर सकते हैं। –

उत्तर

-3

मैं आप बस इस तरह एक मार्ग जोड़ सकता है लगता है:

example: 
pattern: /example 
defaults: { _controller: ExampleBundle:Example:index } 

इस तरह, लोकेल पिछले लोकेल उपयोगकर्ता द्वारा चयनित, या डिफ़ॉल्ट स्थान हो सकता है अगर उपयोगकर्ता का स्थान सेट नहीं किया गया।

example: 
pattern: /example 
defaults: { _controller: ExampleBundle:Example:index, _locale: fr } 

मैं वहाँ यह करने के लिए एक बेहतर तरीका है पता नहीं है: आप यह भी आप एक विशिष्ट स्थान के लिए/उदाहरण स्थापित करना चाहते हैं तो "चूक" अपने मार्ग config में करने के लिए "_locale" पैरामीटर जोड़ सकते हैं ।

+0

क्या आपने इस समाधान की कोशिश की है? यहां पैटर्न में कोई लोकेल शामिल नहीं है और मुझे लगता है कि यह काम नहीं करेगा। –

0

मैं एनोटेशन का उपयोग, और मैं

/** 
* @Route("/{_locale}/example", defaults={"_locale"=""}) 
* @Route("/example", defaults={"_locale"="en"}, , requirements = {"_locale" = "fr|en|uk"}) 
*/ 

करेंगे लेकिन YML रास्ता के लिए, कुछ बराबर की कोशिश ...

+1

जानकारी के लिए, लोकेल के बारे में कुछ बदलाव v2.1 के लिए आ रहे हैं। लोकेल केवल अनुरोध में होगा, सत्र में https://github.com/symfony/symfony/commit/74bc699b2701icies70b1de6ece47c726f5df8bd41 – webda2l

+1

मैं एक ही यूआरएल का उपयोग कई अलग-अलग भाषाओं में संसाधन प्रदर्शित करने के लिए नहीं करना चाहता उपयोगकर्ता का लोकेल मैं वेबसाइट डिफ़ॉल्ट भाषा में संसाधन प्रदर्शित करने के लिए एक डिफ़ॉल्ट यूआरएल का उपयोग करना चाहता हूं। उदाहरण के लिए, ऐप्पल अपनी वेबसाइट पर यही करता है: http://apple.com => यूएस "डिफ़ॉल्ट" संस्करण; http://apple.com/uk: यूके संस्करण; http://apple.com/fr: फ्रेंच संस्करण, आदि –

11

आप इसी प्रकार अनेक पैटर्न परिभाषित कर सकते हैं: आप

example_default: 
    pattern: /example 
    defaults: { _controller: ExampleBundle:Example:index, _locale: fr } 

example: 
    pattern: /{_locale}/example 
    defaults: { _controller: ExampleBundle:Example:index} 
    requirements: 
     _locale: fr|en 

एनोटेशन के साथ एक ही तरह की चीज प्राप्त करने में सक्षम होना चाहिए:

/** 
* @Route("/example", defaults={"_locale"="fr"}) 
* @Route("/{_locale}/example", requirements={"_locale" = "fr|en"}) 
*/ 

आशा है कि मदद करता है!

+1

यह मदद करता है। हालांकि, एनोटेशन के साथ, कम, मेरे लिए काम नहीं करता है। क्यूं कर? – mario

+1

क्या आप 'सेंसियो \ बंडल \ फ्रेमवर्क एक्स्ट्राबंडल \ कॉन्फ़िगरेशन \ रूट का उपयोग कर सकते हैं; ' – Jhonne

+0

सुनिश्चित करें कि आप उनके लिए अलग-अलग रूट नामों का उपयोग करें – amiroff

6

यह मैं क्या स्वचालित स्थान का पता लगाने और पुनर्निर्देशन के लिए उपयोग है, यह अच्छी तरह से काम करता है और लंबा मार्ग एनोटेशन की आवश्यकता नहीं है:

routing.yml

locale मार्ग वेबसाइट के रूट और फिर हैंडल हर दूसरे नियंत्रक कार्रवाई लोकेल के साथ तैयार की जाती है।

locale: 
    path:/
    defaults: { _controller: AppCoreBundle:Core:locale } 

main: 
    resource: "@AppCoreBundle/Controller" 
    prefix: /{_locale} 
    type: annotation 
    requirements: 
    _locale: en|fr 

CoreController.php

इस उपयोगकर्ता की भाषा का पता लगाता है और अपनी पसंद के मार्ग पर रीडायरेक्ट। मैं घर को डिफॉल्ट के रूप में उपयोग करता हूं क्योंकि यह सबसे आम मामला है।

public function localeAction($route = 'home', $parameters = array()) 
{ 
    $this->getRequest()->setLocale($this->getRequest()->getPreferredLanguage(array('en', 'fr'))); 

    return $this->redirect($this->generateUrl($route, $parameters)); 
} 

फिर, मार्ग एनोटेशन बस हो सकता है:

/** 
* @Route("/", name="home") 
*/ 
public function indexAction(Request $request) 
{ 
    // Do stuff 
} 

टहनी

localeAction उपयोगकर्ता वर्तमान पृष्ठ से दूर नेविगेट बिना स्थान बदलना अनुमति देने के लिए इस्तेमाल किया जा सकता :

<a href="{{ path(app.request.get('_route'), app.request.get('_route_params')|merge({'_locale': targetLocale })) }}">{{ targetLanguage }}</a> 

साफ & सरल!

+0

लेकिन इस तरह से स्वचालित रूप से स्थान के साथ लिंक पर पुनः निर्देशित: www.example.com/en www.example.com/fr लेकिन www.example।कॉम प्रदर्शित नहीं है। क्या हम क्या करने की कोशिश कर रहे वास्तव में चल रहा है के रूप में ही है www.symfony.com साइट: अगर मैं www.example.com के लिए जाना डिफ़ॉल्ट स्थान प्रयोग किया जाता है अगर मैं www.example.com/fr करने के लिए जाना फ्रैंक लोकल यदि मैं www.example.com/en पर जाता हूं तो लोकेल एन सिम्फनी वेबसाइट को देख रहा है, और दस्तावेज अध्याय मार्गों में भी निर्दिष्ट है, अगर मैं www.example.com पर जाता हूं और सभी अन्य मार्गों को निर्दिष्ट किए बिना वह यूआरएल को बदलने के बिना डिफ़ॉल्ट लोकेल का उपयोग करता है! – Lughino

+1

पर्याप्त मेला। यह विधि इसे बनाता है ताकि लोकेल हमेशा यूआरएल में रहता है, जिसे मैं व्यक्तिगत रूप से नहीं मानता। विशेष रूप से यह लोकल सेटिंग्स से सरल और पूरी तरह से decotpled एनोटेशन रखता है। –

+0

लेकिन समस्या को हल नहीं करता .. हालांकि इष्टतम समाधान! – Lughino

2

मेरा समाधान है, यह इस प्रक्रिया को तेज़ी से बनाता है!

नियंत्रक:

/** 
* @Route("/change/locale/{current}/{locale}/", name="locale_change") 
*/ 
public function setLocaleAction($current, $locale) 
{ 
    $this->get('request')->setLocale($locale); 
    $referer = str_replace($current,$locale,$this->getRequest()->headers->get('referer')); 

    return $this->redirect($referer); 
} 

टहनी:

<li {% if app.request.locale == language.locale %} class="selected" {% endif %}> 
    <a href="{{ path('locale_change', { 'current' : app.request.locale, 'locale' : language.locale }) }}"> {{ language.locale }}</a> 
</li> 
18

किसी में, मैं अन्य बंडलों का उपयोग किए बिना मेरी routing.yml पर एक उपसर्ग डाल करने के लिए सफल रुचि है।

तो अब, thoses यूआरएल काम:

www.example.com/ 
www.example.com//home/ 
www.example.com/fr/home/ 
www.example.com/en/home/ 

संपादित अपने app/config/routing.yml:

ex_example: 
    resource: "@ExExampleBundle/Resources/config/routing.yml" 
    prefix: /{_locale} 
    requirements: 
     _locale: |fr|en # put a pipe "|" first 

उसके बाद, आप app/config/parameters.yml में, आप एक स्थान

parameters: 
    locale: en 

स्थापित करने के लिए के साथ है यह, लोग एक विशिष्ट लोकेल दर्ज किए बिना आपकी वेबसाइट तक पहुंच सकते हैं।

+7

के लिए एक नया प्रश्न बनाना चाहिए दुर्भाग्यवश यह काम नहीं करता है: www.example.com//home/ url www.example.com/home/ होना चाहिए और यह इस तरह से काम नहीं करेगा। – amiroff

1

मेरे पास इसका पूरा समाधान है जिसे मैंने कुछ शोध के बाद खोजा। मेरा समाधान मानता है कि आप चाहते हैं कि हर मार्ग में इसके सामने एक लोकेल हो, यहां तक ​​कि लॉगिन भी करें। इसे सिम्फनी 3 का समर्थन करने के लिए संशोधित किया गया है, लेकिन मेरा मानना ​​है कि यह अभी भी 2 में काम करेगा।

यह संस्करण यह भी मानता है कि आप ब्राउजर लोकेल को डिफ़ॉल्ट लोकेल के रूप में उपयोग करना चाहते हैं यदि वे रूट/व्यवस्थापक जैसे मार्ग पर जाते हैं, लेकिन यदि वे/en/admin पर जाएं यह लोकेल का उपयोग करने के लिए पता चलेगा। उदाहरण के लिए यह नीचे # 2 मामला है।

उदाहरण के लिए

तो:

1. User Navigates To -> "/"   -> (redirects) -> "/en/" 
2. User Navigates To -> "/admin" -> (redirects) -> "/en/admin" 
3. User Navigates To -> "/en/admin" -> (no redirects) -> "/en/admin" 

सभी स्थितियों स्थान सही ढंग से स्थापित किया जाएगा कि कैसे आप इसे अपने कार्यक्रम के दौरान इस्तेमाल के लिए चाहते हैं।

पूर्ण समाधान देख सकते हैं जो इसे लॉगिन और सुरक्षा के साथ काम करने के लिए कैसे, नहीं तो कम संस्करण शायद आप के लिए काम करेंगे शामिल नीचे:

Full Version

Symfony 3 Redirect All Routes To Current Locale Version

लघु संस्करण

ऐसा करने के लिए ताकि मेरे उदाहरणों में मामला # 2 संभव हो का उपयोग कर एक httpKernal listner

LocaleRewriteListener.php

<?php 
//src/AppBundle/EventListener/LocaleRewriteListener.php 
namespace AppBundle\EventListener; 

use Symfony\Component\HttpFoundation\RedirectResponse; 

use Symfony\Component\Routing\RouterInterface; 
use Symfony\Component\HttpKernel\Event\GetResponseEvent; 
use Symfony\Component\HttpKernel\KernelEvents; 
use Symfony\Component\EventDispatcher\EventSubscriberInterface; 
use Symfony\Component\HttpFoundation\Session\Session; 
use Symfony\Component\Routing\RouteCollection; 

class LocaleRewriteListener implements EventSubscriberInterface 
{ 
    /** 
    * @var Symfony\Component\Routing\RouterInterface 
    */ 
    private $router; 

    /** 
    * @var routeCollection \Symfony\Component\Routing\RouteCollection 
    */ 
    private $routeCollection; 

    /** 
    * @var string 
    */ 
    private $defaultLocale; 

    /** 
    * @var array 
    */ 
    private $supportedLocales; 

    /** 
    * @var string 
    */ 
    private $localeRouteParam; 

    public function __construct(RouterInterface $router, $defaultLocale = 'en', array $supportedLocales = array('en'), $localeRouteParam = '_locale') 
    { 
     $this->router = $router; 
     $this->routeCollection = $router->getRouteCollection(); 
     $this->defaultLocale = $defaultLocale; 
     $this->supportedLocales = $supportedLocales; 
     $this->localeRouteParam = $localeRouteParam; 
    } 

    public function isLocaleSupported($locale) 
    { 
     return in_array($locale, $this->supportedLocales); 
    } 

    public function onKernelRequest(GetResponseEvent $event) 
    { 
     //GOAL: 
     // Redirect all incoming requests to their /locale/route equivlent as long as the route will exists when we do so. 
     // Do nothing if it already has /locale/ in the route to prevent redirect loops 

     $request = $event->getRequest(); 
     $path = $request->getPathInfo(); 

     $route_exists = false; //by default assume route does not exist. 

     foreach($this->routeCollection as $routeObject){ 
      $routePath = $routeObject->getPath(); 
      if($routePath == "/{_locale}".$path){ 
       $route_exists = true; 
       break; 
      } 
     } 

     //If the route does indeed exist then lets redirect there. 
     if($route_exists == true){ 
      //Get the locale from the users browser. 
      $locale = $request->getPreferredLanguage(); 

      //If no locale from browser or locale not in list of known locales supported then set to defaultLocale set in config.yml 
      if($locale=="" || $this->isLocaleSupported($locale)==false){ 
       $locale = $request->getDefaultLocale(); 
      } 

      $event->setResponse(new RedirectResponse("/".$locale.$path)); 
     } 

     //Otherwise do nothing and continue on~ 
    } 

    public static function getSubscribedEvents() 
    { 
     return array(
      // must be registered before the default Locale listener 
      KernelEvents::REQUEST => array(array('onKernelRequest', 17)), 
     ); 
    } 
} 

को समझने के लिए कि कैसे सिम्फोनी प्रलेखन पर घटना ग्राहक इंटरफ़ेस को देखने के काम कर रहा है ऐसा करने के लिए की जरूरत है।

listner आप इसे अपने services.yml में स्थापित करने की जरूरत है सक्रिय करने के लिए

services.yml

# Learn more about services, parameters and containers at 
# http://symfony.com/doc/current/book/service_container.html 
parameters: 
# parameter_name: value 

services: 
# service_name: 
#  class: AppBundle\Directory\ClassName 
#  arguments: ["@another_service_name", "plain_value", "%parameter_name%"] 
    appBundle.eventListeners.localeRewriteListener: 
      class: AppBundle\EventListener\LocaleRewriteListener 
      arguments: ["@router", "%kernel.default_locale%", "%locale_supported%"] 
      tags: 
      - { name: kernel.event_subscriber } 

अंत में इस चर अपने config.yml में परिभाषित करने की आवश्यकता है को संदर्भित करता है

config.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 
    locale_supported: ['en','es','zh'] 

अंत में, आपको यह सुनिश्चित करना होगा कि आपके सभी मार्ग अब के लिए/{locale} से शुरू हो जाएं। इस का एक नमूना मेरा डिफ़ॉल्ट controller.php

<?php 

namespace AppBundle\Controller; 

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; 
use Symfony\Bundle\FrameworkBundle\Controller\Controller; 
use Symfony\Component\HttpFoundation\Request; 

/** 
* @Route("/{_locale}", requirements={"_locale" = "%app.locales%"}) 
*/ 
class DefaultController extends Controller 
{ 

    /** 
    * @Route("/", name="home") 
    */ 
    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") 
    */ 
    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 
     ]); 
    } 
} 
?> 

नोट आवश्यकताओं requirements={"_locale" = "%app.locales%"}, इस config.yml फ़ाइल संदर्भित कर रहा है ताकि आप केवल सभी मार्गों के लिए एक ही स्थान पर उन आवश्यकताओं को परिभाषित करने के लिए है में नीचे है।

आशा इस मदद करता है किसी को :)

2

LocalRewriteListener यूसुफ astrahan के समाधान $routePath == "/{_locale}".$path)

पूर्व की वजह से पैरामीटर वाला मार्ग को छोड़कर काम करता है: $routePath = "/{_locale}/my/route/{foo}"$path = "/{_locale}/my/route/bar"

की अलग है मैं UrlMatcher का इस्तेमाल किया था (यूआरएल के साथ वास्तविक मार्ग से मेल खाने के लिए सिम्फनी 2.7 एपीआई डॉक्टर से लिंक करें।

मैं ब्राउज़र स्थानीय कोड (उदा: fr -> fr_FR) का उपयोग करने के लिए isLocale समर्थित बदलता हूं। मैं कुंजीपटल के रूप में ब्राउज़र लोकेल और मार्ग लोकेल का उपयोग करता हूं। यदि स्थानीय अनुरोध में दी गई

  • चेक suported है: मैं इस array(['fr_FR'] => ['fr'], ['en_GB'] => 'en'...) की तरह एक सरणी

    परिवर्तन (मापदंडों में अधिक जानकारी के लिए नीचे दिए गए फ़ाइल देखें)। यदि नहीं, तो डिफ़ॉल्ट लोकेल का उपयोग करें।

  • ऐप रूट संग्रह के साथ पथ से मिलान करने का प्रयास करें।यदि कुछ भी नहीं है (यदि रूट मौजूद नहीं है तो ऐप 404 फेंक देगा)। यदि हां, मार्ग परम में दाएं लोकेल के साथ रीडायरेक्ट करें।

यहां मेरा कोड है। बिना किसी पैरा के साथ या बिना किसी मार्ग के लिए काम करता है। यह केवल लोकेल को जोड़ता है जब {_local} मार्ग में सेट होता है।

रूटिंग फ़ाइल (मेरे मामले में, अनुप्रयोग/config में एक)

app: 
    resource: "@AppBundle/Resources/config/routing.yml" 
    prefix: /{_locale}/ 
    requirements: 
     _locale: '%app.locales%' 
    defaults: { _locale: %locale%} 

एप्लिकेशन/config/parameters.yml फ़ाइल

locale: fr 
app.locales: fr|gb|it|es 
locale_supported: 
    fr_FR: fr 
    en_GB: gb 
    it_IT: it 
    es_ES: es 

सेवाओं में पैरामीटर। yml

app.eventListeners.localeRewriteListener: 
    class: AppBundle\EventListener\LocaleRewriteListener 
    arguments: ["@router", "%kernel.default_locale%", "%locale_supported%"] 
    tags: 
     - { name: kernel.event_subscriber } 

LocaleRewriteListener.php

<?php 
namespace AppBundle\EventListener; 

use Symfony\Component\HttpFoundation\RedirectResponse; 

use Symfony\Component\Routing\RouterInterface; 
use Symfony\Component\HttpKernel\Event\GetResponseEvent; 
use Symfony\Component\HttpKernel\KernelEvents; 
use Symfony\Component\EventDispatcher\EventSubscriberInterface; 
use Symfony\Component\HttpFoundation\Session\Session; 
use Symfony\Component\Routing\RouteCollection; 
use Symfony\Component\Routing\Matcher\UrlMatcher; 
use Symfony\Component\Routing\RequestContext; 

class LocaleRewriteListener implements EventSubscriberInterface 
{ 
    /** 
    * @var Symfony\Component\Routing\RouterInterface 
    */ 
    private $router; 

    /** 
    * @var routeCollection \Symfony\Component\Routing\RouteCollection 
    */ 
    private $routeCollection; 

    /** 
    * @var urlMatcher \Symfony\Component\Routing\Matcher\UrlMatcher; 
    */ 
    private $urlMatcher; 

    /** 
    * @var string 
    */ 
    private $defaultLocale; 

    /** 
    * @var array 
    */ 
    private $supportedLocales; 

    /** 
    * @var string 
    */ 
    private $localeRouteParam; 

    public function __construct(RouterInterface $router, $defaultLocale = 'fr', array $supportedLocales, $localeRouteParam = '_locale') 
    { 
     $this->router = $router; 
     $this->routeCollection = $router->getRouteCollection(); 
     $this->defaultLocale = $defaultLocale; 
     $this->supportedLocales = $supportedLocales; 
     $this->localeRouteParam = $localeRouteParam; 
     $context = new RequestContext("/"); 
     $this->matcher = new UrlMatcher($this->routeCollection, $context); 
    } 

    public function isLocaleSupported($locale) 
    { 
     return array_key_exists($locale, $this->supportedLocales); 
    } 

    public function onKernelRequest(GetResponseEvent $event) 
    { 
     //GOAL: 
     // Redirect all incoming requests to their /locale/route equivalent when exists. 
     // Do nothing if it already has /locale/ in the route to prevent redirect loops 
     // Do nothing if the route requested has no locale param 

     $request = $event->getRequest(); 
     $baseUrl = $request->getBaseUrl(); 
     $path = $request->getPathInfo(); 

     //Get the locale from the users browser. 
     $locale = $request->getPreferredLanguage(); 

     if ($this->isLocaleSupported($locale)) { 
      $locale = $this->supportedLocales[$locale]; 
     } else if ($locale == ""){ 
      $locale = $request->getDefaultLocale(); 
     } 

     $pathLocale = "/".$locale.$path; 

     //We have to catch the ResourceNotFoundException 
     try { 
      //Try to match the path with the local prefix 
      $this->matcher->match($pathLocale); 
      $event->setResponse(new RedirectResponse($baseUrl.$pathLocale)); 
     } catch (\Symfony\Component\Routing\Exception\ResourceNotFoundException $e) { 

     } catch (\Symfony\Component\Routing\Exception\MethodNotAllowedException $e) { 

     } 
    } 

    public static function getSubscribedEvents() 
    { 
     return array(
      // must be registered before the default Locale listener 
      KernelEvents::REQUEST => array(array('onKernelRequest', 17)), 
     ); 
    } 
} 
0

शायद मैं एक यथोचित सरल तरीके से इस हल:

example: 
    path:  '/{_locale}{_S}example' 
    defaults: { _controller: 'AppBundle:Example:index' , _locale="de" , _S: "/" } 
    requirements: 
     _S: "/?" 
     _locale: '|de|en|fr' 

आलोचकों के फैसले के बारे में उत्सुक ... शुभकामनाएं, ग्रेग

2

सिम्फनी 3

app: 
resource: "@AppBundle/Controller/" 
type:  annotation 
prefix: /{_locale} 
requirements: 
    _locale: en|bg| # put a pipe "|" last 
+0

यह केवल 'domain.com // test' की अनुमति देगा, लेकिन 'domain.com/test' नहीं। –