Symfony: alguma maneira de definir automaticamente a localidade dentro da função de ramificação path ()?

Criado em 15 jul. 2011  ·  31Comentários  ·  Fonte: symfony/symfony

Pessoalmente, acho que deve ser suportado por padrão, apenas tendo que especificar a localidade para substituir.

Por exemplo, se eu tiver rotas:

/contato
/cerca de

/ fr / contact
/ fr / sobre

em / fr / sobre eu tenho um caminho:

{{caminho ('contato')}}

Por que isso criaria um caminho para / contact por padrão em vez de / fr / contact?

Pelo que entendi, para criar o que deveria ser um comportamento padrão por link, devo:

{{path ('address', {'_locale': app.request.attributes.get ('_ locale')})}}

Algum plano para alterar isso?

Routing

Comentários muito úteis

Alguém encontrou uma solução para o primeiro problema do @ damien-roche?
Tenho exatamente o mesmo problema e não consigo encontrar uma solução limpa

Todos 31 comentários

A localidade é definida automaticamente, no entanto, apenas sob certas condições quando você a define antes que o objeto Routercontext seja criado pelo Routing Listener.

@Fabien : Isso me lembra que devemos fazer do Locale um objeto com __toString () para que você possa alterá-lo sem ter que hax0r o RouterContext também.

Em Qui, 14 de julho de 2011 23:57:58 -0700
ivrock [email protected] escreveu:

Pessoalmente, acho que deve ser suportado por padrão, apenas tendo que especificar a localidade para substituir.

Por exemplo, se eu tiver rotas:

/contato
/cerca de

/ fr / contact
/ fr / sobre

em / fr / sobre eu tenho um caminho:

{{caminho ('contato')}}

Por que isso criaria um caminho para / contact por padrão em vez de / fr / contact?

Pelo que entendi, para criar o que deveria ser um comportamento padrão por link, devo:

{{path ('address', {'_locale': app.request.attributes.get ('_ locale')})}}

Algum plano para alterar isso?

Responda a este e-mail diretamente ou visualize-o no GitHub:
https://github.com/symfony/symfony/issues/1700

Hmm..

Que tal esta situação? Temos um aplicativo padrão em inglês e, portanto, nenhum prefixo / en /. Todas as rotas têm o prefixo / en / inserido automaticamente, o que está causando inconsistências com a estrutura do url. Existe alguma maneira de contornar isso de forma que, se o local padrão estiver ativo, nenhum prefixo será usado nas rotas?

@ivrock : Este é exatamente o comportamento que também estou procurando - fazer com que a URL para rotas com localidade padrão não contenha o parâmetro local. Isso permitiria até que um aplicativo fosse inicialmente estendido com suporte para localidades sem quebrar todos os URLs antigos em notificações de e-mail, favoritos, etc. Embora ao perguntar sobre isso no IRC, fui informado que isso não seria possível (e ainda estou perguntando por quê).

@beberlei : Você quer dizer @fabpot , certo? ;)

@craue : As únicas soluções viáveis ​​que posso ver nesse meio tempo são:

  1. use rotas locais desde o início
  2. use a sessão local em vez disso

Eles deram algum motivo pelo qual isso não é possível?

@ivrock : Sim, alguém deu um exemplo. Não se trata explicitamente de localidades, mas de ocultar parâmetros com valores padrão da URL. O restante deste comentário está citando http://pastebin.com/gavYkF0C :

foo:
  pattern: /foo/{bar}/{car}
  defaults:
    bar: barValue
    car: carValue

Gere uma rota em um controlador:

$this->get('router')->generate('foo', array('bar' => 'barValue', 'car' => 'somethingElse');

Em seu cenário onde um valor padrão está oculto do url, 'barValue' NÃO seria adicionado ao url porque corresponde ao valor padrão, então o url gerado seria: / foo / somethingElse

Agora, se alguém clicou nesse link e solicitou / foo / somethingElse e aconteceu de corresponder à rota foo, seria o equivalente a / foo / somethingElse / carValue

O bar e o param do carro foram confundidos.

Obrigado, isso deve ajudar!

Embora isso seja apenas a metade. Que tal fazer o mesmo nos modelos de galho? (veja a mensagem original). Parece que tenho que estender a função path () para incluir automaticamente a localidade padrão se essa for a localidade atual.

@ivrock : Claro que é possível (consulte https://github.com/craue/TwigExtensionsBundle/blob/92ef57f757a24493314c0029d3e21c6ee5563d05/Twig/Extension/ChangeLanguageExtension.php#L223);), mas não se parece com _a solução para mim.

@ivrock : Com base na sua descrição inicial, você está definindo todas as rotas duas vezes? Aqueles sem prefixo de localidade (para o local padrão) por um lado e aqueles com prefixo local por outro lado? Tentei fazer isso importando o arquivo de configuração de roteamento duas vezes, o que resultou em nomes de rota definidos duplicados, é claro. Qual seria uma _boa_ solução?

Oi. Não, é isso que estou tentando evitar. Se eu tiver 10 idiomas, de repente terei centenas de rotas, onde 10 seriam suficientes.

Embora pareça uma ideia decente, se eu tiver apenas alguns idiomas.

Atualmente tenho:

app.com/fr/contact
app.com/en/contact

onde / en / é a localidade padrão para o aplicativo. Então eu quero a rota

app.com/contact

Para funcionar como / en / automaticamente. No momento, eu tenho que criar outra rota que não contenha locale, e quando você estiver nesta localidade padrão, todas as rotas path () geradas para o modelo twig incluem essa localidade.

Uma solução para isso seria ótimo.

Devo esclarecer exatamente qual saída estou procurando.

Eu tenho:

padrão: / {locale} / contato

Eu quero as rotas:

app.com/contact (localidade padrão definida no arquivo de configuração)
app.com/fr/contact

Agora, quando estou visualizando app.com/contact, quero que o caminho () no twig não inclua / {locale} / pagename porque todas as minhas rotas devem ser padronizadas como / pagename.

Os 2 obstáculos para isso são:

  1. ao usar o padrão: / {locale} / contact, / contact does not exist
  2. path () sempre inclui {locale}

Se eu usar mais de 1 caminho para criar / contatar também, terei um problema ainda maior: o caminho () requer o parâmetro de caminho, mas agora tenho 2, dependendo do local.

caminho ('contato')
caminho ('contactIN')

Tudo parece muito confuso. Mesmo se eu estender o twig para remover a localidade se a localidade padrão for selecionada no caminho (), ainda tenho problemas com as rotas que não funcionam. Agradeço qualquer ideia, embora eu suspeite que isso não seja possível como agora.

@ivrock : Você deve usar o (tipo de) parâmetro "mágico" {_locale} vez de {locale} que significa que você teria que definir todas as rotas exatamente duas vezes como mencionei, não um branch para cada localidade . Mas o problema que você descreveu persiste e também duvido que haja uma solução limpa para isso atualmente.

Desculpe, eu não sabia que havia diferença. Eu uso {_locale}, usei apenas {locale} como exemplo e, sim, infelizmente, o problema ainda persiste.

Oi,

Estou usando o parâmetro {_locale} com padrões para este parâmetro para conseguir o que você deseja. Estou usando anotações, mas não vejo por que isso não funcionaria usando um arquivo de roteamento YAML. Aqui estão algumas informações.

Digamos que eu tenha os seguintes caminhos que desejo apoiar:

app.com/ => (deve estar em inglês)
app.com/en => (deve estar em inglês)
app.com/fr => (deve ser em francês)

Eu consigo isso com as seguintes anotações em meu controlador:

/**
 * @Route("/{_locale}", name = "index", defaults = {"_locale" = "en"})
 */

Não defini nenhum requisito porque, por enquanto, não é possível usar parâmetros na definição de roteamento, portanto, adicionar uma nova localidade significaria alterar várias cláusulas de requisitos. Isso também é verdadeiro para a cláusula defaults , mas alterar a localidade padrão é menos provável de acontecer do que adicionar uma nova localidade. De qualquer forma, por enquanto, tentar carregar app.com/es irá gerar a página em inglês, que é minha localidade padrão.

No Twig, eu faço {{ path('index') }} e o url app.com/ será produzido se o {_locale} atual for en e app.com/fr será gerado se o {_locale} atual for fr . Este evento de trabalho para rotas sem um conjunto padrão. Por exemplo, com esta rota:

/**
 * @Route("/{_locale}/event/create", name = "event_create")
 */

Se você fizer isso no Twig, {{ path('event_create') }} , a saída mudará em relação ao valor atual do parâmetro {_locale} .

Em en => app.com/en/event/create
Em fr => app.com/fr/event/create

Sem eu ter que especificar o local em qualquer lugar.

Espero que isto ajude.

Cumprimentos,
Matt

Também enfrentei alguns problemas com isso, e você pode encontrar minha solução aqui:
http://github.com/schmittjoh/JMSI18nRoutingBundle

Basicamente, você pode começar sem nenhuma rota localizada e, em seguida, adicionar traduções para suas rotas ou apenas para algumas delas, conforme necessário.

Deixe-me saber o que você pensa e talvez possamos incluir algumas de suas funcionalidades no Symfony 2.1.

@schmittjoh : Thx, isso parece realmente interessante. Vou dar uma olhada nisso nos próximos dias e dar meu feedback sobre isso.

Obrigado pelo seu trabalho neste pacote e no Symfony.

Cumprimentos,
Matt

Olá, talvez este link ajude:
http://stackoverflow.com/questions/5800675/symfony2-locale-in-route/5803144#5803144

{{ path('address', {'_locale': app.request.attributes.get('_locale')}) }}

No master, o problema descrito por @beberlei foi corrigido (mas não é possível fazer o backport dessa correção para 2.0). Portanto, o argumento _locale agora está sempre disponível e você não precisa passá-lo explicitamente ao gerar uma rota para o local atual.

No momento, é possível (e eficiente fazer isso):

PTCIdentialsBundle:
    resource: "@PTCIdentialsBundle/Controller/"
    type: annotation
    prefix: /{_locale}

Mas não é possível adicionar um parâmetro defaults: { _locale: en } aqui. Só é possível ao definir as rotas para um controlador, assim:

contact:
    pattern:   /{_locale}/contact
    defaults:  { _controller: AcmeDemoBundle:Contact:index, _locale: en }
    requirements:
        _locale: en|fr|de

Então para não ter problemas ao acessar a raiz do site, preciso criar um redirecionamento assim:

root:
    pattern: /
    defaults:
        _controller: FrameworkBundle:Redirect:redirect
        route: homepage
        permanent: true # this is for 301

E para todas as minhas rotas, sempre tenho a localidade, mesmo para a localidade padrão:

Em en => http://my-app.com/en (localidade padrão)
Em fr => http://my-app.com/fr

Seria mais interessante ter o mesmo comportamento como se eu tivesse adicionado o {_locale} diretamente em um controlador específico:

/**
 * @Route("/{_locale}", name = "homepage", defaults = {"_locale" = "en"})
 */

@ raziel057 É possível padronizar ao importar quando você está usando Sf 2.2

Eu uso a última versão do Symfony (v 2.2.1), mas defaults não tem efeito quando escrevo:

PTCIdentialsBundle:
    resource: "@PTCIdentialsBundle/Controller/"
    type: annotation
    prefix: /{_locale}
    defaults: { _locale: en }

Não consigo acessar http://my-app.com/

Na verdade, para ser preciso, defaults é levado em consideração, como podemos ver com o comando router:debug

> php app/console router:debug welcome_index
[router] Route "welcome_index"
Name         welcome_index
Path         /{_locale}/
Host         ANY
Scheme       ANY
Method       ANY
Class        Symfony\Component\Routing\Route
Defaults     _controller: PTC\IdentialsBundle\Controller\WelcomeController::indexAction
             _locale: en
Requirements _locale: en|fr
Options      compiler_class: Symfony\Component\Routing\RouteCompiler
Path-Regex   #^/(?P<_locale>en|fr)/$#s

Mas se eu tentar acessar http://my-app.com/ , obtenho uma "NotFoundHttpException".

@ raziel057 eu tentaria remover o traling "/" e ver se funciona.

@henrikbjorn já tentei mas não deu certo.

Além disso, se eu tiver uma outra rota como esta:

> php app/console router:debug login
[router] Route "login"
Name         login
Path         /{_locale}/secured/login
Host         ANY
Scheme       ANY
Method       ANY
Class        Symfony\Component\Routing\Route
Defaults     _controller: PTC\IdentialsBundle\Controller\AuthenticationController::indexAction
Requirements _locale: en|fr
Options      compiler_class: Symfony\Component\Routing\RouteCompiler
Path-Regex   #^/(?P<_locale>en|fr)/secured/login$#s

{_locale}/ ser substituído por uma string vazia ao acessar o idioma padrão para ter:
http://my-app.com/secured/login em en
http://my-app.com/fr/secured/login em fr

@ raziel057 você está atingindo # 4322 ao importar uma rota. O local não é opcional para /{_locale}/ mesmo com um padrão. Portanto, / não corresponde. Você pode ver isso com a ajuda do regex.

{_locale} / deve ser substituído por uma string vazia ao acessar no idioma padrão para ter:
http://my-app.com/secured/login em en
http://my-app.com/fr/secured/login em fr

Pelo mesmo motivo: não é possível ter marcadores de posição opcionais no meio. # 7051 resolveria isso.

@Tobion Ok. Obrigado por suas explicações. Achei que era possível ao ler o comentário de @maoueh.

Você sabe o que é usado para exibir a documentação oficial do Symfony?
http://symfony.com/doc/current/book/forms.html <- conteúdo em "en"
http://symfony.com/fr/doc/current/book/forms.html <- conteúdo em "fr"

É este pacote? http://github.com/schmittjoh/JMSI18nRoutingBundle

Não sei. Mas, como solução alternativa, você pode definir duas rotas: uma com o local e outra sem. Você só precisa escolher o apropriado ao gerar uma rota.

Quando eu uso http://github.com/schmittjoh/JMSI18nRoutingBundle com esta configuração:

jms_i18n_routing:
    default_locale: en
    locales: [en, fr]
    strategy: prefix_except_default

Eu tenho as seguintes rotas quando executo php app/console router:debug :

en__RG__welcome_index                  ANY    ANY    ANY  /
fr__RG__welcome_index                  ANY    ANY    ANY  /fr/
en__RG__view_about                     ANY    ANY    ANY  /about
fr__RG__view_about                     ANY    ANY    ANY  /fr/about
en__RG__view_contact                   ANY    ANY    ANY  /contact
fr__RG__view_contact                   ANY    ANY    ANY  /fr/contact
...

Portanto, podemos ver que as rotas estão bem duplicadas. Mas quando tento acessar http://my-app.com/ , recebo o seguinte erro:

FatalErrorException: Erro: Nível máximo de aninhamento de função de '100' atingido, interrompendo! em /home/lallement/workspace/Identials/vendor/symfony/symfony/src/Symfony/Component/Routing/Matcher/Dumper/DumperCollection.php linha 54

in /home/lallement/workspace/Identials/vendor/symfony/symfony/src/Symfony/Component/Routing/Matcher/Dumper/DumperCollection.php line 54
at ErrorHandler??handleFatal() in /home/lallement/workspace/Identials/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Debug/ErrorHandler.php line 0
at DumperCollection??add() in /home/lallement/workspace/Identials/vendor/symfony/symfony/src/Symfony/Component/Routing/Matcher/Dumper/DumperPrefixCollection.php line 70
at DumperPrefixCollection??addPrefixRoute() in /home/lallement/workspace/Identials/vendor/symfony/symfony/src/Symfony/Component/Routing/Matcher/Dumper/DumperPrefixCollection.php line 72

Use a pesquisa, por favor.

@Tobion Sim, desculpe;). O max_nesting_level de xdebug estava muito baixo.

Alguém encontrou uma solução para o primeiro problema do @ damien-roche?
Tenho exatamente o mesmo problema e não consigo encontrar uma solução limpa

Não tenho certeza se é isso que você está procurando e depois de tantos anos pode não ser tão útil ... mas aqui está o que fiz para resolver o meu problema que parece ser bastante semelhante à situação descrita por @ damien-roche.

Em primeiro lugar, estou trabalhando com a versão 5.1.2 do Symfony.

Aqui está meu arquivo translation.yaml :

framework:
    default_locale: fr
    translator:
        default_path: '%kernel.project_dir%/translations'
        fallbacks:
            - en
        enabled_locales: ['fr', 'en']

Eu defini os locais suportados e defini FR como o padrão com um fallback para EN . Esta configuração não faz parte da sua pergunta de roteamento, mas como o gerenciamento de traduções também faz parte da minha solução para gerenciar um site multilíngue, também a compartilho.

Mudei a configuração de minhas rotas para que todas as anotações definidas não precisem ser alteradas para suporte a vários idiomas, simplesmente defini um prefixo para cada idioma compatível em routes/annotations.yaml :

controllers:
    resource: ../../src/Controller/
    type: annotation
    defaults:
        _locale: '%kernel.default_locale%'
    requirements:
        _locale: fr|en
    prefix:
        fr: ''
        en: '/en'

Então aqui está o que eu configurei em security.yaml para que todas as minhas rotas funcionem conforme o esperado:

    access_control:
        - { path: ^/(_|en/)login, roles: IS_AUTHENTICATED_ANONYMOUSLY}
        - { path: ^/(_|en/)/admin, roles: ROLE_ADMIN}
        - { path: ^/(_|en/)/, roles: IS_AUTHENTICATED_ANONYMOUSLY}

Esta configuração me permite usar todas as rotas existentes para meu idioma padrão ( / , /login ...) e as rotas para a versão em inglês com o prefixo en definido ( /en , /en/login ...).

Agora, quando executo php bin/console debug:router , tenho todas as rotas que posso usar a partir de meus modelos de galho:

image

Isso significa que quando eu simplesmente preciso definir a navegação em meu site sem me preocupar com a localidade atual, posso usar minhas rotas normalmente:

<a href="{{ path('app_login') }}">{% trans %}action.menu.member.access{% endtrans %}</a>

E quando preciso usar especificamente uma das minhas rotas "localizadas" (por exemplo, para os links para mudar o site da França para a EN), simplesmente uso a rota apropriada, incluindo a localidade desejada:

            {% if app.request.locale != 'en' %}
                <a href="{{ path('app_home_index.en') }}">EN</a>
            {% endif %}
            {% if app.request.locale != 'fr' %}
                <a href="{{ path('app_home_index.fr') }}">FR</a>
            {% endif %}

Espero que isso ajude.

Cumprimentos,

Esta página foi útil?
0 / 5 - 0 avaliações