Esquema multilíngue apropriado ou exagero?


8

ATUALIZAÇÃO 2 : Eu acabei usando isso, e é ótimo depois de alguns ajustes. Aqui está o meu post sobre seu design real e em ação: http://tim.hithlonde.com/2013/lemon-schema-works/

Estou construindo um aplicativo Web e quero que ele suporte vários idiomas. Essa estrutura possui dois componentes:

  1. Conectando a localidade ('english', 'Deutch' etc.) com os termos e tendo uma pedra de roseta conectando termos e termos no idioma específico.
  2. Agrupando termos por página. Eu não quero dizer, SELECIONE termo1, termo2, etc, através dos mais de 30 termos que posso precisar em uma página. Quero perguntar pela página à qual estão conectados.

Aqui está minha estrutura de tabela proposta (observe que todos os IDs têm relacionamentos / índices entre eles para fazer consultas muito eficientes):

Diagrama do esquema

  * locale
      * id
      * value //English, Deutch, etc//
  * terms
    * id
    * value //In English//
  * page 
    * id
    * value //Think add entry, menu//
  * page_group //group all terms to a page, for easy pulling//
    * id
    * page.id
    * term.id
  * rosetta
    * id
    * locale.id
    * term.id
    * value //french word for amount, description, etc//

Isso permitirá consultas como:

SELECT localization.value,
        terms.value
FROM localization
INNER JOIN terms ON terms.id=localization.termid
INNER JOIN page_group ON page_group.termid=localization.termid
INNER JOIN page ON page.id=page_group.pageid
INNER JOIN locale ON locale.id=localization.localeid
WHERE page.value='add_entry' AND locale.id=custlangid
ORDER BY terms.id

Eu só tenho que pedir dois itens; o ID do idioma de que preciso e a página de que preciso. Ele exibirá todos os termos, no idioma especificado, que fazem parte do grupo de termos dessa página.

Eu acho que essa é uma estrutura muito boa, mas eu gostaria de receber algum feedback.

ATUALIZAÇÃO : Para esclarecer, estamos apenas falando sobre a localização dos componentes da interface do usuário . (rótulos, navegação, texto útil) Todas as informações inseridas pelo usuário serão armazenadas em unicode, não neste esquema.

ATUALIZAÇÃO 2 : Acabei usando isso, e é ótimo. Aqui está o meu post sobre o design real e em ação: http://tim.hithlonde.com/2013/lemon-schema-works/


11
Normalmente (pelo que eu vi), a localização é feita através de modelos no lado da web. Que tipo de material você deseja localizar do lado do banco de dados?
Philᵀᴹ

Quero localizar todos os rótulos, menu de navegação e qualquer texto útil (avisos, etc.). Meu motivo para pegar isso no db é: não quero essa lógica nos meus modelos. Nos meus modelos, quero ter <?php echo $term['term_in_english'];?>uma estratégia sólida de MVC.
precisa saber é o seguinte

Respostas:


6

Fizemos muito disso, e os usuários (administrativos) tiveram permissão para corrigir as traduções ao vivo. (Você ainda pode querer uma camada de armazenamento em cache, mas eu estou totalmente empolgado em direcionar isso para um banco de dados real e não para arquivos de recursos - isso lhe dá uma tonelada de poder para consultar e encontrar coisas que precisam ser traduzidas etc.). Eu acho que seu esquema provavelmente está bom, então vou passar algumas coisas que aprendemos na esperança de que sejam úteis.

Uma coisa que você deixou de fora são frases com pontos de inserção. No exemplo abaixo, a ordem é revertida e o idioma ainda é o inglês, mas podem ser facilmente dois idiomas diferentes - finja que são apenas dois idiomas que normalmente colocam as coisas em uma ordem diferente.

Hello, <username> you have <x> points!

You've got <x> points to spend, <username>!

Em nossa pré-.NET, tínhamos uma rotina que fazia a inserção para que as frases ficassem assim:

Hello, {0:username} you have {1:points} points!

You've got {1:points} points to spend, {0:username}!

Obviamente, isso seria simplesmente usado no seu código como <%= String.Format(phrase, username, points); %>ou similar

O que ajudou um pouco o tradutor. Infelizmente, o .NET String.FOrmat não suporta comentários dentro da string de formato.

Como você diz, você não gostaria de lidar com isso no seu php com reconhecimento de localidade ou meta-frases.

Então, o que tínhamos era uma tabela de frases principais:

fraseid, inglês, informações suplementares

e uma tabela localizada:

fraseid, localeid, tradução

Você também assumiu com INNER JOINS que as versões localizadas existem - tendíamos a deixá-las de fora até que fossem traduzidas, para que suas consultas acabassem retornando nada no início (nem mesmo o padrão)

Se não houvesse uma tradução, a nossa adotaria o padrão para inglês e, em seguida, recuaria para o código fornecido (no caso de o banco de dados não possuir o ID, e também ficou claro a partir do código que identificador de frase "TXT_LNG_WRNNG_INV_LOW" estava realmente tentando obter ) - portanto, o equivalente a essa consulta é o que usamos:

SELECT COALESCE(localized.translation, phrase.english, @fallback)
FROM DUAL
LEFT JOIN phrase
    ON phrase.phraseid = @phraseid
LEFT JOIN localized
    ON localized.phraseid = phrase.phraseid
    AND localized.localeid = @localeid

Obviamente, você pode obter todas as coisas ao mesmo tempo usando seu sistema de páginas.

Nós tendíamos a não vincular as coisas à página porque elas eram reutilizadas muito entre as páginas (e não apenas em fragmentos ou controles de página), mas isso certamente é bom.

No caso de nossos aplicativos nativos do Windows, usamos reflexão e um arquivo de mapeamento do controle para a tag de tradução, para que a tradução não exija recompilações (em aplicativos anteriores à .NET, tivemos que marcar os controles usando a Tag ou outras tags especiais. propriedades). Provavelmente, isso é um pouco mais problemático no PHP ou no ASP.NET MVC, mas possível no ASP.NET, onde há um modelo de página completo do lado do servidor.

Para testar, você pode obviamente consultar para encontrar traduções ausentes com muita facilidade. Para encontrar lugares que precisam ser marcados, traduza o dicionário de frases inteiro usando pig-latin ou Klingon ou algo como substituir todos os caracteres não espaciais por? - o inglês deve se destacar e informar que algum texto não criptografado entrou no seu HTML.


Obrigado por isso! Eu não tinha pensado em pontos de inserção. Não acredito que meu aplicativo tenha, mas é bom ter em mente. Além disso, obrigado pelos comentários sobre o esquema. Eu já desenvolvi o design de banco de dados há um tempo, mas sem um bom conjunto de pares para comparar anotações, às vezes me deixa inseguro que estou indo na direção certa. :)
Tim Habersack

0

Normalmente, as traduções são feitas por empresas especializadas externas. Como tal, seria um aborrecimento gerenciar o conteúdo traduzido dentro de um banco de dados. É melhor gerenciar em "pacotes" ou arquivos de propriedades por meio de algum tipo de recurso de idioma oferecido por sua plataforma. Para conseguir isso, no banco de dados, você simplesmente colocaria um mnemônico para a string. Em seguida, com base no idioma desejado, você pesquisaria no pacote. por exemplo.

Data:
Employee_Status = empl_status.active

language Bundles:
Employee.us:  
  empl_status.active=Active

Employee.es
  empl_status.active=<spanish translation goes here>

To get the localized content:
    String status = getLocalizedContent("Employee","empl_status.active", "us");
    String status = getLocalizedContent("Employee","empl_status.active", "es");
    String status = getLocalizedContent("Employee","empl_status.active");

Estou confuso, já que estamos falando da mesma coisa. Eu estarei construindo o equivalente ao seu getLocalizedContent. Exceto no nível do controlador, solicitarei todos os termos conectados a uma página e o idioma em que a quero. Essa função chamará a consulta que descrevi acima e funcionará um pouco de mágica para obter um array associativo de volta, onde a chave será o mnemônico, e o valor será o termo. O número de termos da interface do usuário será pequeno (<100); portanto, não vejo problema em gerenciá-lo em um banco de dados. Provavelmente vou criar uma interface simples para inserir termos traduzidos e agrupar páginas.
precisa saber é o seguinte

0

Basta criar 3 tabelas

1.) Mestre de idiomas (LangId, LangName)

2.) Mestre de Recursos (ResourceMasterId, TableId, ColumnId, ColumnName)

3.) Detalhes do recurso (ResourceMasterId, LangId, Value)

chave composta (ResourceMasterId, LangId) em Detalhes do recurso

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.