Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Site multilíngue de melhores práticas

Premissa do tópico


Existem três aspectos distintos em um site multilíngue:
  • tradução de interface
  • conteúdo
  • roteamento de URL

Embora todos estejam interconectados de maneiras diferentes, do ponto de vista do CMS, eles são gerenciados usando diferentes elementos de interface do usuário e armazenados de maneira diferente. Você parece estar confiante em sua implementação e compreensão dos dois primeiros. A pergunta era sobre o último aspecto - "Tradução de URL? Devemos fazer isso ou não? e de que maneira?"

De que o URL pode ser feito?


Uma coisa muito importante é, não seja extravagante com IDN . Em vez disso, favoreça a transliteração (também:transcrição e romanização). Embora à primeira vista o IDN pareça uma opção viável para URLs internacionais, na verdade ele não funciona como anunciado por dois motivos:
  • alguns navegadores ativarão os caracteres não ASCII como 'ч' ou 'ž' em '%D1%87' e '%C5%BE'
  • se o usuário tiver temas personalizados, é muito provável que a fonte do tema não tenha símbolos para essas letras

Na verdade, tentei uma abordagem IDN há alguns anos em um projeto baseado em Yii (estrutura horrível, IMHO). Eu encontrei os dois problemas mencionados acima antes de raspar essa solução. Além disso, suspeito que possa ser um vetor de ataque.

Opções disponíveis... como eu as vejo.


Basicamente, você tem duas opções, que podem ser resumidas como:

  • http://site.tld/[:query] :onde [:query] determina a escolha do idioma e do conteúdo

  • http://site.tld/[:language]/[:query] :onde [:language] parte do URL define a escolha do idioma e [:query] é usado apenas para identificar o conteúdo

A consulta é Α e Ω ..


Digamos que você escolha http://site.tld/[:query] .

Nesse caso, você tem uma fonte primária de linguagem:o conteúdo de [:query] segmento; e duas fontes adicionais:
  • valor $_COOKIE['lang'] para esse navegador específico
  • lista de idiomas no cabeçalho HTTP Accept-Language

Primeiro, você precisa corresponder a consulta a um dos padrões de roteamento definidos (se sua escolha for Laravel, então leia aqui ). Na correspondência bem-sucedida do padrão, você precisa encontrar o idioma.

Você teria que passar por todos os segmentos do padrão. Encontre as traduções em potencial para todos esses segmentos e determine qual idioma foi usado. As duas fontes adicionais (cookie e cabeçalho) seriam usadas para resolver conflitos de roteamento, quando (não "se") eles surgissem.

Por exemplo:http://site.tld/blog/novinka .

Essa é a transliteração de "блог, новинка" , que em inglês significa aproximadamente "blog", "latest" .

Como você já pode notar, em russo "блог" será transliterado como "blog". O que significa que para a primeira parte de [:query] você (no melhor cenário ) terminará com ['en', 'ru'] lista de idiomas possíveis. Então você pega o próximo segmento - "novinka". Isso pode ter apenas um idioma na lista de possibilidades:['ru'] .

Quando a lista tem um item, você encontrou o idioma com sucesso.

Mas se você terminar com 2 (exemplo:russo e ucraniano) ou mais possibilidades .. ou 0 possibilidades, conforme o caso. Você terá que usar cookie e/ou cabeçalho para encontrar a opção correta.

E se tudo mais falhar, você escolhe o idioma padrão do site.

Idioma como parâmetro


A alternativa é usar a URL, que pode ser definida como http://site.tld/[:language]/[:query] . Nesse caso, ao traduzir a consulta, você não precisa adivinhar o idioma, pois nesse ponto você já sabe qual usar.

Há também uma fonte secundária de linguagem:o valor do cookie. Mas aqui não faz sentido mexer com o cabeçalho Accept-Language, porque você não está lidando com uma quantidade desconhecida de idiomas possíveis em caso de "início a frio" (quando o usuário abre o site pela primeira vez com uma consulta personalizada).

Em vez disso, você tem 3 opções simples e priorizadas:
  1. if [:language] segmento está definido, use-o
  2. if $_COOKIE['lang'] está definido, use-o
  3. usar idioma padrão

Quando você tem o idioma, você simplesmente tenta traduzir a consulta e, se a tradução falhar, use o "valor padrão" para esse segmento específico (com base nos resultados de roteamento).

Não há uma terceira opção?


Sim, tecnicamente você pode combinar as duas abordagens, mas isso complicaria o processo e acomodaria apenas pessoas que desejam alterar manualmente o URL de http://site.tld/en/news para http://site.tld/de/news e espere que a página de notícias mude para alemão.

Mas mesmo esse caso provavelmente poderia ser mitigado usando o valor do cookie (que conteria informações sobre a escolha anterior do idioma), para implementar com menos mágica e esperança.

Qual ​​abordagem usar?


Como você já deve ter adivinhado, eu recomendaria http://site.tld/[:language]/[:query] como a opção mais sensata.

Também em situação de palavra real, você teria a 3ª parte principal na URL:"título". Como no nome do produto na loja online ou no título do artigo no site de notícias.

Exemplo:http://site.tld/en/news/article/121415/EU-as-global-reserve-currency

Neste caso '/news/article/121415' seria a consulta, e a 'EU-as-global-reserve-currency' é título. Puramente para fins de SEO.

Pode ser feito em Laravel?


Meio, mas não por padrão.

Não estou muito familiarizado com isso, mas pelo que vi, o Laravel usa um mecanismo simples de roteamento baseado em padrões. Para implementar URLs multilíngues, você provavelmente terá que estender a(s) classe(s) principal(s) , pois o roteamento multilíngue precisa acessar diferentes formas de armazenamento (banco de dados, cache e/ou arquivos de configuração).

Está roteado. E agora?


Como resultado de tudo, você teria duas informações valiosas:o idioma atual e os segmentos de consulta traduzidos. Esses valores podem ser usados ​​para despachar para a(s) classe(s) que produzirão o resultado.

Basicamente, o seguinte URL:http://site.tld/ru/blog/novinka (ou a versão sem '/ru' ) se transforma em algo como
$parameters = [
   'language' => 'ru',
   'classname' => 'blog',
   'method' => 'latest',
];

Que você acabou de usar para despachar:
$instance = new {$parameter['classname']};
$instance->{'get'.$parameters['method']}( $parameters );

.. ou alguma variação dela, dependendo da implementação específica.