web-dev-qa-db-fra.com

Quelles sont les meilleures pratiques pour la conception de bases de données multilingues?

Quel est le meilleur moyen de créer une base de données multilingue? Créer une table localisée pour chaque table rend la conception et l'interrogation complexes. Dans le cas contraire, l'ajout d'une colonne pour chaque langue est simple mais non dynamique, aidez-moi à comprendre le meilleur choix pour les applications d'entreprise.

177
Arsen Mkrtchyan

Ce que nous faisons, c'est créer deux tables pour chaque objet multilingue.

Par exemple. la première table ne contient que des données indépendantes de la langue (clé primaire, etc.) et la deuxième table contient un enregistrement par langue, contenant les données localisées et le code ISO de la langue.

Dans certains cas, nous ajoutons un champ DefaultLanguage afin de pouvoir utiliser cette langue si aucune donnée localisée n'est disponible pour une langue donnée.

Exemple:

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>

Avec cette approche, vous pouvez gérer autant de langues que nécessaire (sans avoir à ajouter de champs supplémentaires pour chaque nouvelle langue).


Mise à jour (2014-12-14): veuillez consulter cette réponse , pour obtenir des informations supplémentaires sur l'implémentation utilisée pour charger des données multilingues dans une application.

197
M4N

Je recommande la réponse publiée par Martin.

Mais vous semblez craindre que vos requêtes ne deviennent trop complexes:

Créer une table localisée pour chaque table rend la conception et l'interrogation complexes ...

Donc, vous pensez peut-être qu'au lieu d'écrire des requêtes simples comme celle-ci:

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

... vous devriez commencer à écrire des requêtes comme celle-ci:

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

Pas une très jolie perspective.

Mais au lieu de le faire manuellement, vous devez développer votre propre classe d'accès à la base de données, car elle pré-analyse le code SQL contenant votre balise de localisation spéciale et le convertit en code SQL réel que vous devrez envoyer à la base de données.

Utiliser ce système pourrait ressembler à quelque chose comme ça:

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

Et je suis sûr que vous pouvez faire encore mieux que ça.

La clé consiste à nommer vos tables et vos champs de manière uniforme.

14
Rene Saarsoo

Je trouve que ce type d'approche fonctionne pour moi:

 Produit ProductDetail Country 
 ================================== 
 ProductId ProductDetailId CountryId 
 - etc - ProductId Nom de pays 
 CountryId Langue 
 Nom de produit - etc - 
 ProductDescription 
 - etc - 

La table ProductDetail contient toutes les traductions (pour le nom du produit, la description, etc.) dans les langues que vous souhaitez prendre en charge. Selon les besoins de votre application, vous pouvez également décomposer la table des pays pour utiliser également les langues régionales.

13
Nick

J'utilise l'approche suivante:

Produit

ProductID OrderID, ...

Information sur le produit

ProductID Titre Nom LanguageID

La langue

LanguageID Name Culture, ....

9
omoto

La solution de Martin est très similaire à la mienne, mais comment géreriez-vous les descriptions par défaut lorsque la traduction souhaitée n'est pas trouvée?

Est-ce que cela nécessiterait une IFNULL () et une autre instruction SELECT pour chaque champ?

La traduction par défaut serait stockée dans la même table, où un drapeau du type "isDefault" indique si cette description est la description par défaut si aucune n'a été trouvée pour la langue en cours.

2
doM