Estou lutando com essa questão há alguns meses, mas não estava em uma situação em que precisava explorar todas as opções possíveis antes. No momento, sinto que é hora de conhecer as possibilidades e criar minha própria preferência pessoal para usar nos meus próximos projetos.
Deixe-me primeiro esboçar a situação que estou procurando
Estou prestes a atualizar / reconstruir um sistema de gerenciamento de conteúdo que já uso há bastante tempo. No entanto, sinto que a linguagem multilíngue é uma grande melhoria para este sistema. Antes eu não usava nenhuma estrutura, mas vou usar o Laraval4 para o próximo projeto. O Laravel parece ser a melhor escolha de uma maneira mais limpa de codificar PHP. Sidenote: Laraval4 should be no factor in your answer
. Estou procurando maneiras gerais de tradução que sejam independentes de plataforma / estrutura.
O que deve ser traduzido
Como o sistema que estou procurando precisa ser o mais amigável possível, o método de gerenciamento da tradução deve estar dentro do CMS. Não deve haver necessidade de iniciar uma conexão FTP para modificar arquivos de tradução ou quaisquer modelos analisados em html / php.
Além disso, estou procurando a maneira mais fácil de traduzir várias tabelas de banco de dados, talvez sem a necessidade de criar tabelas adicionais.
O que eu vim comigo mesmo
Como eu tenho procurado, lendo e experimentando as coisas já. Existem algumas opções que tenho. Mas ainda não sinto que cheguei a um método de melhores práticas para o que realmente estou procurando. No momento, é isso que eu criei, mas esse método também tem efeitos colaterais.
- Modelos Analisados em PHP: o sistema de modelos deve ser analisado pelo PHP. Dessa forma, sou capaz de inserir os parâmetros traduzidos no HTML sem precisar abrir os modelos e modificá-los. Além disso, os modelos analisados pelo PHP me dão a capacidade de ter 1 modelo para o site completo, em vez de ter uma subpasta para cada idioma (que eu já tinha antes). O método para atingir esse objetivo pode ser Smarty, TemplatePower, Laravel's Blade ou qualquer outro analisador de modelos. Como eu disse, isso deve ser independente da solução escrita.
- Orientado a banco de dados : talvez eu não precise mencionar isso novamente. Mas a solução deve ser orientada por banco de dados. O CMS tem como objetivo ser orientado a objetos e MVC, então eu precisaria pensar em uma estrutura de dados lógica para as strings. Como meus modelos seria estruturada: templates / Controller / view.php talvez esta estrutura faria mais sentido:
Controller.View.parameter
. A tabela do banco de dados teria esses campos por muito tempo com umvalue
campo. Dentro dos modelos, poderíamos usar algum método de classificação comoecho __('Controller.View.welcome', array('name', 'Joshua'))
e o parâmetro contémWelcome, :name
. Assim sendo o resultadoWelcome, Joshua
. Essa parece ser uma boa maneira de fazer isso, porque os parâmetros como: name são fáceis de entender pelo editor. - Baixa carga de banco de dados : é claro que o sistema acima causaria cargas de banco de dados se essas cadeias estivessem sendo carregadas em movimento. Portanto, eu precisaria de um sistema de cache que renderize novamente os arquivos de idioma assim que forem editados / salvos no ambiente de administração. Como os arquivos são gerados, também é necessário um bom layout do sistema de arquivos. Acho que podemos ir com
languages/en_EN/Controller/View.php
ou .ini, o que melhor lhe convier. Talvez um .ini seja analisado mais rapidamente no final. Isso deve conter os dados no arquivoformat parameter=value;
. Eu acho que essa é a melhor maneira de fazer isso, pois cada View renderizada pode incluir seu próprio arquivo de idioma, se existir. Os parâmetros de idioma devem ser carregados em uma visualização específica e não em um escopo global para impedir que os parâmetros se substituam. - Tradução da tabela de banco de dados : é com isso que estou mais preocupado. Estou procurando uma maneira de criar traduções de Notícias / Páginas / etc. o mais rápido possível. Ter duas tabelas para cada módulo (por exemplo
News
eNews_translations
) é uma opção, mas parece muito trabalho para obter um bom sistema. Uma das coisas que eu vim com é baseado em umdata versioning
sistema de I escreveu: existe um nome de tabela de banco de dadosTranslations
, esta tabela tem uma combinação única delanguage
,tablename
eprimarykey
. Por exemplo: en_En / News / 1 (referindo-se à versão em inglês do item de Notícias com ID = 1). Mas existem duas grandes desvantagens nesse método: primeiro, essa tabela tende a ficar bastante longa com muitos dados no banco de dados e, em segundo lugar, seria um trabalho muito bom usar essa configuração para pesquisar na tabela. Por exemplo, pesquisar a lesma de SEO do item seria uma pesquisa de texto completo, o que é bastante idiota. Mas, por outro lado: é uma maneira rápida de criar conteúdo traduzível em todas as tabelas muito rapidamente, mas não acredito que esse profissional supere os contras. - Trabalho de front-end : também o front-end precisaria de algumas reflexões. É claro que armazenaríamos os idiomas disponíveis em um banco de dados e (de) ativamos os que precisamos. Dessa forma, o script pode gerar uma lista suspensa para selecionar um idioma e o back-end pode decidir automaticamente quais traduções podem ser feitas usando o CMS. O idioma escolhido (por exemplo, en_EN) seria usado ao obter o arquivo de idioma para uma visualização ou obter a tradução correta para um item de conteúdo no site.
Então, lá estão eles. Minhas idéias até agora. Eles ainda nem incluem opções de localização para datas, etc., mas como meu servidor suporta PHP5.3.2 +, a melhor opção é usar a extensão intl conforme explicado aqui: http://devzone.zend.com/1500/internationalization-in -php-53 / - mas isso seria útil em qualquer estádio de desenvolvimento posterior. Por enquanto, a questão principal é como ter as melhores práticas de tradução do conteúdo em um site.
Além de tudo que expliquei aqui, ainda tenho outra coisa que ainda não decidi, parece uma pergunta simples, mas na verdade está me dando dores de cabeça:
Tradução de URL? Devemos fazer isso ou não? e de que maneira?
Então .. se eu tiver esse URL: http://www.domain.com/about-us
e inglês é o meu idioma padrão. Esse URL deve ser traduzido para http://www.domain.com/over-ons
quando eu escolher o holandês como meu idioma? Ou devemos seguir o caminho mais fácil e simplesmente alterar o conteúdo da página visível em /about
. A última coisa que parece não ser uma opção válida, porque isso geraria várias versões do mesmo URL; a indexação do conteúdo falhará da maneira correta.
Outra opção está sendo usada http://www.domain.com/nl/about-us
. Isso gera pelo menos um URL exclusivo para cada conteúdo. Também seria mais fácil ir para outro idioma, por exemplo, http://www.domain.com/en/about-us
e o URL fornecido é mais fácil de entender para os visitantes do Google e Humanos. Usando esta opção, o que fazemos com os idiomas padrão? O idioma padrão deve remover o idioma selecionado por padrão? Então, redirecionando http://www.domain.com/en/about-us
para http://www.domain.com/about-us
... A meu ver, essa é a melhor solução, porque quando o CMS é configurado para apenas um idioma, não é necessário ter essa identificação no URL.
E uma terceira opção é uma combinação das duas opções: usar o "idioma-identificação-menos" -URL ( http://www.domain.com/about-us
) para o idioma principal. E use um URL com uma lesma de SEO traduzida para sub-idiomas: http://www.domain.com/nl/over-ons
&http://www.domain.com/de/uber-uns
Espero que minha pergunta faça sua cabeça rachar, eles racharam a minha com certeza! Já me ajudou a resolver as coisas como uma pergunta aqui. Deu-me a possibilidade de revisar os métodos que usei antes e a idéia que estou tendo para o meu próximo CMS.
Eu gostaria de agradecer a você por ler esse monte de texto!
// Edit #1
:
Esqueci de mencionar: a função __ () é um alias para traduzir uma determinada string. Nesse método, obviamente deve haver algum tipo de método de fallback em que o texto padrão é carregado quando ainda não há traduções disponíveis. Se a tradução estiver ausente, ela deve ser inserida ou o arquivo de tradução deve ser regenerado.
fonte
Respostas:
Premissa do tópico
Existem três aspectos distintos em um site multilíngue:
Embora todos estejam interconectados de maneiras diferentes, do ponto de vista do CMS, eles são gerenciados usando diferentes elementos da interface do usuário e armazenados de maneira diferente. Você parece confiante em sua implementação e compreensão dos dois primeiros. A pergunta era sobre o último aspecto - "Tradução da URL? Devemos fazer isso ou não? E de que maneira?"
Do que o URL pode ser feito?
Uma coisa muito importante é que não se apaixone pelo IDN . Em vez disso, favorecer 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 não funciona como anunciado por dois motivos:
'ч'
ou'ž'
em'%D1%87'
e'%C5%BE'
Na verdade, tentei abordar os IDNs alguns anos atrás em um projeto baseado no Yii (quadro horrível, IMHO). Encontrei os dois problemas acima mencionados antes de raspar a 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 abstraídas como:
http://site.tld/[:query]
: onde[:query]
determina a escolha do idioma e do conteúdohttp://site.tld/[:language]/[:query]
: onde[:language]
parte do URL define a escolha do idioma e[:query]
é usada apenas para identificar o conteúdoA consulta é Α e Ω ..
Vamos dizer que você escolhe
http://site.tld/[:query]
.Nesse caso, você tem uma fonte primária de idioma: o conteúdo do
[:query]
segmento; e duas fontes adicionais:$_COOKIE['lang']
para esse navegador específicoPrimeiro, você precisa corresponder a consulta a um dos padrões de roteamento definidos (se você escolher Laravel, leia aqui ). Na correspondência bem-sucedida de padrão, você precisará encontrar o idioma.
Você precisaria 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") surgirem.
Tomemos por exemplo:
http://site.tld/blog/novinka
.Isso é transliteração
"блог, новинка"
, que em inglês significa aproximadamente"blog", "latest"
.Como você já pode notar, em russo "блог" será transliterado como "blog". O que significa que, na primeira parte de
[:query]
você (na melhor das hipóteses ), a['en', 'ru']
lista de idiomas possíveis será finalizada . Então você toma o próximo segmento - "novinka". Isso pode ter apenas um idioma na lista de possibilidades:['ru']
.Quando a lista possui 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ê precisará usar cookies 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 URL, que pode ser definido como
http://site.tld/[:language]/[:query]
. Nesse caso, ao traduzir a consulta, você não precisa adivinhar o idioma, porque nesse momento 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 no cabeçalho Accept-Language, porque você não está lidando com uma quantidade desconhecida de idiomas possíveis em caso de "partida a frio" (quando o usuário abre o site pela primeira vez com uma consulta personalizada).
Em vez disso, você tem três opções simples e priorizadas:
[:language]
segmento estiver definido, use-o$_COOKIE['lang']
estiver definido, use-oQuando você possui 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 do roteamento).
Aqui não é uma terceira opção?
Sim, tecnicamente você pode combinar ambas as abordagens, mas isso iria complicar o processo e só acomodar as pessoas que querem URL alterar manualmente de
http://site.tld/en/news
parahttp://site.tld/de/news
e esperar que a página de notícias para a mudança para Alemão.Mas mesmo esse caso pode 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ções reais, você teria a terceira parte principal no URL: "title". 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
Nesse caso,
'/news/article/121415'
seria a consulta e o'EU-as-global-reserve-currency'
é title. Puramente para fins de SEO.Isso pode ser feito no Laravel?
Meio, mas não por padrão.
Não estou muito familiarizado com isso, mas pelo que vi, o Laravel usa um mecanismo de roteamento baseado em padrões simples. Para implementar URLs multilíngues, você provavelmente precisará estender as classes principais , porque 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, você terminaria com duas informações valiosas: idioma atual e segmentos de consulta traduzidos. Esses valores podem ser usados para despachar para as classes que produzirão o resultado.
Basicamente, o seguinte URL:
http://site.tld/ru/blog/novinka
(ou a versão sem'/ru'
) é transformado em algo comoQue você apenas usa para despachar:
.. ou alguma variação, dependendo da implementação específica.
fonte
Implementando o i18n sem o desempenho atingido usando um pré-processador, conforme sugerido por Thomas Bley
No trabalho, recentemente implementamos o i18n em algumas de nossas propriedades, e uma das coisas com as quais continuamos lutando foi o impacto no desempenho de lidar com traduções on-the-fly, então descobri este ótimo post de Thomas Bley que inspirou a maneira como usamos o i18n para lidar com grandes cargas de tráfego com problemas mínimos de desempenho.
Em vez de chamar funções para todas as operações de tradução, que, como sabemos no PHP, são caras, definimos nossos arquivos de base com espaços reservados e usamos um pré-processador para armazenar em cache esses arquivos (armazenamos o tempo de modificação do arquivo para garantir que estamos servindo o conteúdo mais recente em todos os momentos).
Tags de tradução
Thomas usa
{tr}
e{/tr}
tags para definir onde as traduções começam e terminam. Devido ao fato de que estamos usando GALHO, não queremos usar{
para evitar confusão por isso usamos[%tr%]
e[%/tr%]
em vez disso. Basicamente, isso se parece com isso:Observe que Thomas sugere usar o inglês base no arquivo. Não fazemos isso porque não queremos modificar todos os arquivos de tradução se alterarmos o valor em inglês.
Os arquivos INI
Em seguida, criamos um arquivo INI para cada idioma, no formato
placeholder = translated
:Seria trivial para permitir que um usuário para modificar estes dentro do CMS, é só pegar os pares de chaves por um
preg_split
on\n
ou=
e fazendo o CMS apto a reescrever os arquivos INI.O componente pré-processador
Essencialmente, Thomas sugere o uso de uma função de 'compilador' just-in-time (embora, na verdade, seja um pré-processador) como essa para pegar seus arquivos de tradução e criar arquivos PHP estáticos no disco. Dessa forma, nós armazenamos nossos arquivos traduzidos em cache, em vez de chamar uma função de tradução para cada sequência do arquivo:
Nota: Não verifiquei se o regex funciona, não o copiei do servidor da empresa, mas você pode ver como a operação funciona.
Como chamá-lo
Novamente, este exemplo é de Thomas Bley, não de mim:
Armazenamos o idioma em um cookie (ou variável de sessão, se não conseguimos obter um cookie) e, em seguida, recuperamos em cada solicitação. Você pode combinar isso com um opcional
$_GET
parâmetro para substituir o idioma, mas não sugiro subdomínio por idioma ou página por idioma, porque isso tornará mais difícil ver quais páginas são populares e reduzirá o valor de entrada links, pois você dificilmente os espalhará.Por que usar esse método?
Gostamos deste método de pré-processamento por três razões:
Obtendo o conteúdo traduzido do banco de dados
Nós apenas adicionamos uma coluna para o conteúdo em nosso banco de dados chamado
language
, então usamos um método acessador para aLANG
constante que definimos anteriormente, para que nossas chamadas SQL (usando ZF1, infelizmente) sejam assim:Nossos artigos têm uma chave primária composta
id
e,language
portanto, o artigo54
pode existir em todos os idiomas. NossosLANG
padrões sãoen_US
se não especificado.Tradução de URL Slug
Eu combinaria duas coisas aqui, uma é uma função no seu bootstrap que aceita um
$_GET
parâmetro para o idioma e substitui a variável de cookie, e outra é o roteamento que aceita várias lesmas. Então você pode fazer algo assim no seu roteamento:Eles podem ser armazenados em um arquivo simples que pode ser facilmente gravado no seu painel de administração. JSON ou XML pode fornecer uma boa estrutura para suportá-los.
Notas sobre algumas outras opções
Tradução On-The-Fly baseada em PHP
Não vejo que eles oferecem alguma vantagem sobre as traduções pré-processadas.
Traduções baseadas em front-end
Há muito tempo acho isso interessante, mas há algumas ressalvas. Por exemplo, você deve disponibilizar ao usuário toda a lista de frases em seu site que você planeja traduzir; isso pode ser problemático se houver áreas do site que você está mantendo oculto ou que não lhes permitiram acesso.
Você também deve assumir que todos os seus usuários estão dispostos e podem usar o Javascript em seu site, mas, pelas minhas estatísticas, cerca de 2,5% de nossos usuários estão executando sem ele (ou usando o Noscript para impedir que nossos sites o usem) .
Traduções Orientadas a Banco de Dados
As velocidades de conectividade do banco de dados do PHP não são nada sobre o que escrever, e isso aumenta a já alta sobrecarga de chamar uma função em cada frase para traduzir. Os problemas de desempenho e escalabilidade parecem impressionantes com essa abordagem.
fonte
Why?
: Simples .. Eu quero não quero ser incomoda por pequenas mudanças no texto, os usuários devem ser capazes de fazê-lo themselfs sem usar um editor de código e / ou ftp programm :).INI
arquivos com uma tabela de banco de 3 colunas complaceholder
,replacement
,language
. Tecla composta ativadaplaceholder
elanguage
. Depois, tenha mais 2-col comtempfile
(caminho para o modelo) emodified
(DATETIME).Sugiro que você não invente uma roda e use a lista de abreviações de linguagens gettext e ISO. Você viu como o i18n / l10n foi implementado em CMSes ou estruturas populares?
Usando gettext, você terá uma ferramenta poderosa na qual muitos casos já estão implementados, como formas plurais de números. Em inglês, você tem apenas 2 opções: singular e plural. Mas em russo, por exemplo, existem três formas e não é tão simples quanto no inglês.
Muitos tradutores também já têm experiência para trabalhar com o gettext.
Dê uma olhada no CakePHP ou Drupal . Ambos multilíngues habilitados. CakePHP como exemplo de localização de interface e Drupal como exemplo de tradução de conteúdo.
Para l10n, usar banco de dados não é o caso. Serão toneladas de consultas. A abordagem padrão é obter todos os dados da l10n na memória no estágio inicial (ou durante a primeira chamada para a função i10n, se você preferir carregamento lento). Pode ler do arquivo .po ou do DB todos os dados de uma só vez. E do que apenas ler as strings solicitadas da matriz.
Se você precisar implementar uma ferramenta online para traduzir a interface, poderá ter todos esses dados no banco de dados, mas ainda assim salvar todos os dados no arquivo para trabalhar com ele. Para reduzir a quantidade de dados na memória, você pode dividir todas as suas mensagens / strings traduzidas em grupos e carregar apenas os grupos necessários, se for possível.
Então você está totalmente certo no seu # 3. Com uma exceção: geralmente é um arquivo grande e não um arquivo por controlador. Porque é melhor para o desempenho abrir um arquivo. Você provavelmente sabe que alguns aplicativos da Web carregados compilam todo o código PHP em um arquivo para evitar operações de arquivo ao incluir / exigir a chamada.
Sobre URLs. O Google sugere indiretamente o uso da tradução:
Também acho que você precisa redirecionar o usuário para o prefixo do idioma padrão, por exemplo, http://examlpe.com/about-us será redirecionado para http://examlpe.com/en/about-us Mas se o seu site usar apenas um idioma, você não precisa de prefixos.
Confira: http://www.audiomicro.com/trailer-hit-impact-psychodrama-sound-effects-836925 http://nl.audiomicro.com/aanhangwagen-hit-effect-psychodrama-geluidseffecten-836925 http: / /de.audiomicro.com/anhanger-hit-auswirkungen-psychodrama-sound-effekte-836925
Traduzir conteúdo é uma tarefa mais difícil. Eu acho que haverá algumas diferenças com diferentes tipos de conteúdo, por exemplo, artigos, itens de menu etc. Mas na quarta posição você está no caminho certo. Dê uma olhada no Drupal para ter mais idéias. Ele possui um esquema de banco de dados suficientemente claro e uma interface suficientemente boa para a tradução. Como você criando um artigo e selecionando o idioma para ele. E depois você pode traduzi-lo para outros idiomas.
Eu acho que não é problema com lesmas de URL. Você pode apenas criar uma tabela separada para lesmas e será a decisão certa. Também usando índices corretos, não é problema consultar a tabela, mesmo com grande quantidade de dados. E não foi a pesquisa de texto completo, mas a correspondência de string se usará o tipo de dados varchar para slug e você também poderá ter um índice nesse campo.
PS Desculpe, meu inglês está longe de ser perfeito.
fonte
Depende da quantidade de conteúdo que seu site possui. No começo, usei um banco de dados como todas as outras pessoas aqui, mas pode levar muito tempo para criar scripts para todo o funcionamento de um banco de dados. Não digo que esse seja um método ideal e, especialmente, se você tiver muito texto, mas se quiser fazê-lo rapidamente sem usar um banco de dados, esse método poderá funcionar, no entanto, você não poderá permitir que os usuários insiram dados que será usado como arquivos de tradução. Mas se você adicionar as traduções, ele funcionará:
Digamos que você tenha este texto:
Você pode inserir isso em um banco de dados com traduções, mas também pode fazer isso:
Agora, se o seu site usa um cookie, você tem isso, por exemplo:
Para facilitar, vamos transformá-lo em um código que pode ser facilmente usado:
Se o seu idioma de cookies for galês e você tiver este código:
O resultado disso será:
Se você precisar adicionar muitas traduções ao seu site e um banco de dados estiver consumindo muito, o uso de uma matriz pode ser a solução ideal.
fonte
lang.en.php
que será incluído e usar o$lang['welcome']
que é declarado em cada arquivo.Vou sugerir que você não dependa realmente do banco de dados para tradução. Isso pode ser uma tarefa muito complicada e um problema extremo no caso de codificação de dados.
Eu tive um problema semelhante há um tempo atrás e escrevi a seguinte aula para resolver meu problema
Objeto: Localidade \ Localidade
Uso
Como funciona
{a:1}
é substituído pelo 1º argumento passado ao métodoLocale::translate('key_name','arg1')
{a:2}
é substituído pelo 2º argumento passado ao métodoLocale::translate('key_name','arg1','arg2')
Como funciona a detecção
geoip
estiver instalado, ele retornará o código do paísgeoip_country_code_by_name
e, se o geoip não estiver instalado, o fallback para oHTTP_ACCEPT_LANGUAGE
cabeçalhofonte
utf8_general_ci
agrupamento é a maneira apropriada de fazê-lo.Apenas uma sub-resposta: use absolutamente os URLs traduzidos com um identificador de idioma à sua frente: http://www.domain.com/nl/over-ons As
soluções Hybride tendem a ficar complicadas, então eu continuaria com ele. Por quê? Porque o URL é essencial para o SEO.
Sobre a tradução do banco de dados: o número de idiomas é mais ou menos fixo? Ou melhor, imprevisível e dinâmico? Se for corrigido, eu adicionaria apenas novas colunas, caso contrário, usaria várias tabelas.
Mas geralmente, por que não usar Drupal? Eu sei que todo mundo quer criar seu próprio CMS porque é mais rápido, mais enxuto, etc. etc. Mas isso é realmente uma péssima ideia!
fonte
Não vou tentar refinar as respostas já dadas. Em vez disso, vou falar sobre como minha própria estrutura PHP OOP lida com traduções.
Internamente, minha estrutura usa códigos como en, fr, es, cn e assim por diante. Um array contém os idiomas suportados pelo site: array ('en', 'fr', 'es', 'cn') O código do idioma é passado através de $ _GET (lang = fr) e, se não for passado ou não for válido, é definido como o primeiro idioma da matriz. Portanto, a qualquer momento durante a execução do programa e desde o início, o idioma atual é conhecido.
É útil entender o tipo de conteúdo que precisa ser traduzido em um aplicativo típico:
1) mensagens de erro de classes (ou código processual) 2) mensagens sem erro de classes (ou código processual) 3) conteúdo da página (geralmente armazenado em um banco de dados) 4) seqüências de caracteres em todo o site (como o nome do site) 5) script- seqüências específicas
O primeiro tipo é simples de entender. Basicamente, estamos falando de mensagens como "não foi possível conectar ao banco de dados ...". Essas mensagens precisam ser carregadas apenas quando ocorrer um erro. Minha classe de gerente recebe uma chamada das outras classes e, usando as informações passadas como parâmetros, simplesmente vai para a pasta da classe e recupera o arquivo de erro.
O segundo tipo de mensagem de erro é mais parecido com as mensagens recebidas quando a validação de um formulário deu errado. ("Você não pode deixar ... em branco" ou "escolha uma senha com mais de 5 caracteres"). As seqüências de caracteres precisam ser carregadas antes da execução da classe.
Para o conteúdo da página real, eu uso uma tabela por idioma, cada tabela prefixada pelo código do idioma. Então en_content é a tabela com conteúdo em inglês, es_content é para a espanha, cn_content para a China e fr_content é o material francês.
O quarto tipo de string é relevante em todo o site. Isso é carregado por meio de um arquivo de configuração nomeado usando o código do idioma, ou seja, en_lang.php, es_lang.php e assim por diante. No arquivo de idioma global, você precisará carregar os idiomas traduzidos, como matriz ('inglês', 'chinês', 'espanhol', 'francês') no arquivo global e matriz em inglês ('Anglais', 'Chinois', ' Espagnol ',' Francais ') no arquivo francês. Portanto, quando você preenche um menu suspenso para seleção de idioma, ele está no idioma correto;)
Finalmente, você tem as seqüências específicas do script. Portanto, se você escrever um aplicativo de culinária, pode ser "O forno não estava quente o suficiente".
No meu ciclo de aplicação, o arquivo de idioma global é carregado primeiro. Lá você encontrará não apenas strings globais (como o "site de Jack"), mas também configurações para algumas das classes. Basicamente, qualquer coisa que depende da língua ou da cultura. Algumas das seqüências de caracteres incluem máscaras para datas (MMDDYYYY ou DDMMYYYY) ou códigos de idioma ISO. No arquivo de idioma principal, eu incluo strings para classes individuais, pois são poucas.
O segundo e último arquivo de idioma que é lido do disco é o arquivo de idioma do script. lang_en_home_welcome.php é o arquivo de idioma para o script home / welcome. Um script é definido por um modo (home) e uma ação (bem-vindo). Cada script possui sua própria pasta com arquivos de configuração e lang.
O script extrai o conteúdo do banco de dados nomeando a tabela de conteúdo, conforme explicado acima.
Se algo der errado, o gerente sabe onde obter o arquivo de erro dependente do idioma. Esse arquivo é carregado apenas em caso de erro.
Portanto, a conclusão é óbvia. Pense nos problemas de tradução antes de começar a desenvolver um aplicativo ou estrutura. Você também precisa de um fluxo de trabalho de desenvolvimento que incorpore traduções. Com minha estrutura, desenvolvo o site inteiro em inglês e depois traduzo todos os arquivos relevantes.
Apenas uma palavra final rápida sobre como as seqüências de tradução são implementadas. Minha estrutura possui um único global, o $ manager, que executa serviços disponíveis para qualquer outro serviço. Assim, por exemplo, o serviço de formulário obtém o serviço html e o usa para escrever o html. Um dos serviços no meu sistema é o serviço de tradutor. $ translator-> set ($ service, $ code, $ string) define uma string para o idioma atual. O arquivo de idioma é uma lista dessas declarações. O $ translator-> get ($ service, $ code) recupera uma string de tradução. O código $ pode ser numérico como 1 ou uma sequência como 'no_connection'. Não pode haver conflito entre serviços, porque cada um tem seu próprio espaço para nome na área de dados do tradutor.
Coloco isso aqui na esperança de que alguém salve a tarefa de reinventar a roda, como tive que fazer alguns anos atrás.
fonte
Eu tive o mesmo problema há um tempo atrás, antes de começar a usar o framework Symfony .
Basta usar uma função __ () que possua os parâmetros pageId (ou objectId, objectTable descritos em # 2), idioma de destino e um parâmetro opcional do idioma de fallback (padrão). O idioma padrão pode ser definido em algumas configurações globais para ter uma maneira mais fácil de alterá-lo posteriormente.
Para armazenar o conteúdo no banco de dados, usei a seguinte estrutura: (ID da página, idioma, conteúdo, variáveis).
O pageId seria um FK para a sua página que você deseja traduzir. se você tiver outros objetos, como notícias, galerias ou qualquer outra coisa, divida-o em 2 campos objectId, objectTable.
idioma - obviamente, ele armazenaria a string de idioma ISO EN_en, LT_lt, EN_us etc.
conteúdo - o texto que você deseja traduzir junto com os curingas para substituição de variável. Exemplo "Olá Sr. %% name %%. O saldo da sua conta é %% balance %%."
variáveis - as variáveis codificadas pelo json. O PHP fornece funções para analisá-las rapidamente. Exemplo "nome: Laurynas, saldo: 15,23".
você mencionou também campo lesma. você pode adicioná-lo livremente a esta tabela apenas para ter uma maneira rápida de procurá-lo.
Suas chamadas ao banco de dados devem ser reduzidas ao mínimo com o cache das traduções. Ele deve ser armazenado na matriz PHP, porque é a estrutura mais rápida da linguagem PHP. Como você fará esse cache é com você. Pela minha experiência, você deve ter uma pasta para cada idioma suportado e uma matriz para cada pageId. O cache deve ser reconstruído após a atualização da tradução. SOMENTE a matriz alterada deve ser regenerada.
acho que respondi isso em # 2
sua ideia é perfeitamente lógica. este é bem simples e acho que não causará nenhum problema.
Os URLs devem ser traduzidos usando as lesmas armazenadas na tabela de tradução.
Palavras finais
é sempre bom pesquisar as melhores práticas, mas não reinvente a roda. basta pegar e usar os componentes de estruturas conhecidas e usá-los.
dê uma olhada no componente de tradução Symfony . Pode ser uma boa base de código para você.
fonte
Fiz perguntas repetidas vezes a mim mesmo, depois me perdi em idiomas formais ... mas, para ajudar um pouco, gostaria de compartilhar algumas descobertas:
Eu recomendo dar uma olhada no CMS avançado
Typo3
paraPHP
(eu sei que há muitas coisas, mas essa é a que eu acho mais madura)Plone
noPython
Se você descobrir que a web em 2013 deve funcionar diferente, comece do zero. Isso significaria reunir uma equipe de pessoas altamente qualificadas / experientes para criar um novo CMS. Pode ser que você queira dar uma olhada no polímero para esse fim.
Se se trata de sites multilíngues de codificação / suporte a idiomas nativos, acho que todo programador deve ter uma idéia sobre o unicode. Se você não conhece o Unicode, certamente estragará seus dados. Não siga os milhares de códigos ISO. Eles só economizarão um pouco de memória. Mas você pode fazer literalmente tudo com o UTF-8 até armazenar caracteres chineses. Mas para isso, você precisará armazenar caracteres de 2 ou 4 bytes, o que o torna basicamente um utf-16 ou utf-32.
Se se trata de codificação de URL, novamente você não deve misturar codificações e esteja ciente de que, pelo menos para o nome de domínio, existem regras definidas por diferentes lobbies que fornecem aplicativos como um navegador. por exemplo, um domínio pode ser muito semelhante, como:
ьankofamerica.com ou bankofamerica.com samesamebutdifferent;)
Claro que você precisa do sistema de arquivos para trabalhar com todas as codificações. Outra vantagem para o unicode usando o sistema de arquivos utf-8.
Se é sobre traduções, pense na estrutura dos documentos. por exemplo, um livro ou um artigo. Você tem as
docbook
especificações para entender sobre essas estruturas. Mas em HTML, trata-se apenas de blocos de conteúdo. Então, você gostaria de ter uma tradução nesse nível, também no nível da página da web ou no domínio. Portanto, se um bloco não existe, simplesmente não existe, se uma página da Web não existe, você será redirecionado para o nível de navegação superior. Se um domínio deve ser completamente diferente na estrutura de navegação, é uma estrutura completamente diferente para gerenciar. Isso já pode ser feito com o Typo3.Se for sobre frameworks, os mais maduros que conheço, para fazer coisas gerais como MVC (chavão, eu realmente odeio! Como "performance" Se você quiser vender algo, use a palavra performance e featurerich e vende ... o que o inferno) é
Zend
. Provou ser uma boa coisa trazer padrões aos codificadores de php caos. Mas, o typo3 também possui um Framework além do CMS. Recentemente, foi reconstruído e agora é chamado flow3. As estruturas, obviamente, cobrem a abstração do banco de dados, modelos e conceitos para armazenamento em cache, mas têm pontos fortes individuais.Se for sobre cache ... isso pode ser muito complicado / em várias camadas. No PHP, você pensa em accellerator, opcode, mas também html, httpd, mysql, xml, css, js ... qualquer tipo de cache. É claro que algumas partes devem ser armazenadas em cache e as partes dinâmicas, como as respostas do blog, não. Alguns devem ser solicitados pelo AJAX com URLs gerados. JSON, hashbangs etc.
Em seguida, você deseja que qualquer pequeno componente em seu site seja acessado ou gerenciado apenas por determinados usuários , de maneira conceitual que desempenha um grande papel.
Além disso, você gostaria de fazer estatísticas , talvez tenha distribuído um sistema / facebook de facebooks etc. qualquer software a ser construído sobre o seu sobre os principais cms ... então você precisa de diferentes tipos de bancos de dados em memória, bigdata, xml, qualquer que seja .
bem, acho que isso é o suficiente por enquanto. Se você nunca ouviu falar de typo3 / plone ou de estruturas mencionadas, você tem o suficiente para estudar. Nesse caminho, você encontrará muitas soluções para perguntas que ainda não foram feitas.
Se você pensa assim, vamos criar um novo CMS porque seu 2013 e php estão prestes a morrer de qualquer maneira, então você é bem-vindo para se juntar a qualquer outro grupo de desenvolvedores, espero que não se perca.
Boa sorte!
E aliás. e as pessoas não terão mais sites no futuro? e todos nós estaremos no google +? Espero que os desenvolvedores se tornem um pouco mais criativos e façam algo útil (a não ser assimilado pela borgle)
//// Edit /// Apenas um pouco de reflexão para o seu aplicativo existente:
Se você possui um php mysql CMS e deseja incorporar suporte a vários idiomas. você pode usar sua tabela com uma coluna adicional para qualquer idioma ou inserir a tradução com um ID de objeto e um ID de idioma na mesma tabela ou criar uma tabela idêntica para qualquer idioma e inserir objetos lá, e fazer uma união de seleção, se desejar para que todos sejam exibidos. Para o banco de dados, use utf8 general ci e, é claro, no front / back-end, use utf8 text / encoding. Eu usei segmentos de caminho de URL para URLs da maneira que você já explicou como
domain.org/en/about, você pode mapear o ID de idioma para sua tabela de conteúdo. de qualquer maneira, você precisa ter um mapa de parâmetros para seus URLs, para definir um parâmetro a ser mapeado a partir de um segmento de caminho em seu URL, que seria, por exemplo,
domain.org/en/about/employees/IT/administrators/
configuração de pesquisa
pageid | url
1 | /about/employees/../ ..
1 | /../about/employees../../
mapear parâmetros para o segmento de caminho da URL ""
por dizer, isso já foi coberto no cargo superior.
E para não esquecer, você precisa "reescrever" o URL do seu arquivo php gerador que, na maioria dos casos, seria index.php
fonte
Trabalho de banco de dados:
Criar 'idiomas' da tabela de idiomas:
Campos:
Crie uma tabela no banco de dados 'conteúdo':
Campos:
Trabalho Final:
Quando o usuário seleciona qualquer idioma no menu suspenso ou em qualquer área, salve o ID do idioma selecionado na sessão, como,
$_SESSION['language']=1;
Agora, busque dados do 'conteúdo' da tabela do banco de dados com base no ID do idioma armazenado na sessão.
Detalhes podem ser encontrados aqui http://skillrow.com/multilingual-website-in-php-2/
fonte
Como uma pessoa que mora em Quebec, onde quase todo o site é francês e inglês ... eu tentei muitos, se não o mais, plug-in multilíngüe para o WP ... a única solução útil que funciona em todo o meu site é mQtranslate ... eu vivo e morro com isso!
https://wordpress.org/plugins/mqtranslate/
fonte
E o WORDPRESS +
MULTI-LANGUAGE SITE BASIS
(plugin)? o site terá estrutura:O plugin fornece todas as frases da Interface for Translation, com lógica simples:
então pode ser emitido:
echo translate('my_title', LNG); // LNG is auto-detected
ps no entanto, verifique se o plug-in ainda está ativo.
fonte
Uma opção realmente simples que funciona com qualquer site em que você pode fazer upload de Javascript é www.multilingualizer.com
Permite colocar todo o texto de todos os idiomas em uma página e ocultar os idiomas que o usuário não precisa ver. Funciona bem.
fonte