Quais são as práticas recomendadas para o design de banco de dados em vários idiomas? [fechadas]

193

Qual é a melhor maneira de criar banco de dados multilíngue? Para criar tabela localizada para cada tabela, o design e a consulta são complexos; caso contrário, adicionar colunas para cada idioma é simples, mas não dinâmico, por favor, ajude-me a entender qual é a melhor escolha para aplicativos corporativos

Arsen Mkrtchyan
fonte

Respostas:

223

O que fazemos é criar duas tabelas para cada objeto multilíngue.

Por exemplo, a primeira tabela contém apenas dados com neutralidade de idioma (chave primária, etc.) e a segunda tabela contém um registro por idioma, contendo os dados localizados mais o código ISO do idioma.

Em alguns casos, adicionamos um campo DefaultLanguage, para que possamos retornar a esse idioma se nenhum dado localizado estiver disponível para um idioma especificado.

Exemplo:

Table "Product":
----------------
ID                 : int
<any other language-neutral fields>


Table "ProductTranslations"
---------------------------
ID                 : int      (foreign key referencing the Product)
Language           : varchar  (e.g. "en-US", "de-CH")
IsDefault          : bit
ProductDescription : nvarchar
<any other localized data>

Com essa abordagem, você pode lidar com quantos idiomas forem necessários (sem precisar adicionar campos adicionais para cada novo idioma).


Atualização (14/12/2014): consulte esta resposta para obter informações adicionais sobre a implementação usada para carregar dados multilíngues em um aplicativo.

M4N
fonte
15
e se o único campo de idioma neutro for o id? e como exatamente você insere a referência de chave estrangeira ao inserir uma linha?
Timo Huovinen
4
É engraçado que eu estivesse projetando um esquema de banco de dados para um CMS multilíngue e que também tivesse essa pergunta em minha mente. Eu escolhi essa abordagem antes mesmo de ver essa resposta! Obrigado por esta resposta!
Patrick Manser
5
Uma coisa a observar aqui é que não haveria PK nesta tabela ou o ID e o idioma precisariam ser o PK composto. Ou você precisa adicionar um campo ProductTranslationId, provavelmente como uma identidade.
18713 Daniel Lorenz #
1
@Luca: eu respondi sua pergunta, mostrando quais implementações eu uso para carregar os dados.
M4N
1
@ AarónGutiérrez Bem, o engraçado é que você cria uma tabela com uma única coluna chamada id: D. Para explicar, cada idum representa um significado ao qual você pode anexar palavras de qualquer idioma em uma tabela relacional, para obter duas tabelas meaning(id) e word(id, meaning_id), idna wordtabela representa a palavra id, idna meaningrepresenta o significado que é universal.
Timo Huovinen
18

Eu recomendo a resposta postada por Martin.

Mas você parece estar preocupado com o fato de suas consultas ficarem muito complexas:

Criar tabela localizada para cada tabela torna o design e a consulta complexos ...

Então você deve estar pensando que, em vez de escrever consultas simples como esta:

SELECT price, name, description FROM Products WHERE price < 100

... você precisaria começar a escrever consultas assim:

SELECT
  p.price, pt.name, pt.description
FROM
  Products p JOIN ProductTranslations pt
  ON (p.id = pt.id AND pt.lang = "en")
WHERE
  price < 100

Não é uma perspectiva muito bonita.

Mas, em vez de fazê-lo manualmente, você deve desenvolver sua própria classe de acesso ao banco de dados, que pré-analisa o SQL que contém sua marcação de localização especial e o converte no SQL real que você precisará enviar ao banco de dados.

Usar esse sistema pode ser algo como isto:

db.setLocale("en");
db.query("SELECT p.price, _(p.name), _(p.description)
          FROM _(Products p) WHERE price < 100");

E tenho certeza que você pode fazer ainda melhor isso.

A chave é ter suas tabelas e campos nomeados de maneira uniforme.

Rene Saarsoo
fonte
a outra pergunta é criar um objeto de negócios para o produto? ou para criar dois ... no primeiro caso é fácil trabalhar com esse item, no 2º fácil escrever CMS
Arsen Mkrtchyan
14

Acho que esse tipo de abordagem funciona para mim:

País do produto
========= ================== =========
ProductId ProductDetailId CountryId
- etc - ProductId CountryName
            CountryId Idioma
            Nome do produto - etc -
            Descrição do Produto
            - etc -

A tabela ProductDetail contém todas as traduções (por nome do produto, descrição etc.) nos idiomas que você deseja oferecer suporte. Dependendo dos requisitos do seu aplicativo, convém dividir a tabela País para usar os idiomas regionais também.

usuario
fonte
Eu escolhi essa mesma abordagem para um projeto no qual estou trabalhando atualmente, porque meus diferentes locais contêm informações muito específicas sobre sistemas de unidades e medidas a serem exibidas aos usuários.
Californch
8
País e idioma (localidades) são coisas diferentes. E os códigos de idioma ISO são chaves naturais, você elimina a junção desnecessária do idioma para o país.
precisa saber é o seguinte
10

Estou usando a próxima abordagem:

produtos

ProductID OrderID, ...

Informação do produto

ProductID Título Nome LanguageID

Língua

IdiomaID Nome Cultura, ....

omoto
fonte
2

A solução de Martin é muito semelhante à minha, no entanto, como você lidaria com as descrições padrão quando a tradução desejada não for encontrada?

Isso exigiria um IFNULL () e outra instrução SELECT para cada campo?

A tradução padrão seria armazenada na mesma tabela, onde um sinalizador como "isDefault" indica se essa descrição é a descrição padrão, caso não tenha sido encontrada nenhuma para o idioma atual.

doM
fonte
1
@GorrillaApe: ver essa resposta para um exemplo de como a cair de volta para o idioma padrão, se o idioma desejado não foi encontrado: stackoverflow.com/a/27474681/19635
M4N