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

193

Quelle est la meilleure façon de créer une base de données multilingue? Créer une table localisée pour chaque table rend la conception et les requêtes complexes, dans les autres cas, ajouter une colonne pour chaque langue est simple mais pas dynamique, aidez-moi à comprendre quel est le meilleur choix pour les applications d'entreprise

Arsen Mkrtchyan
la source

Réponses:

223

Ce que nous faisons, c'est créer deux tableaux 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 plus le code ISO de la langue.

Dans certains cas, nous ajoutons un champ DefaultLanguage, afin de pouvoir revenir à cette langue si aucune donnée localisée n'est disponible pour une langue spécifié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 des 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.

M4N
la source
15
Et si le seul champ indépendant du langage était l'identifiant? et comment insérer exactement la référence de clé étrangère lors de l'insertion d'une ligne?
Timo Huovinen
4
C'est drôle, que je concevais un schéma de base de données pour un CMS multilingue et que j'avais cette question dans ma tête également. J'ai choisi cette approche, avant même d'avoir vu cette réponse! Merci pour cette réponse!
Patrick Manser
5
Une chose à noter ici est qu'il n'y aurait pas de PK sur cette table ou que l'ID et la langue doivent être le PK composite. Soit cela, soit vous devez ajouter un champ ProductTranslationId, probablement en tant qu'identité.
Daniel Lorenz
1
@Luca: J'ai répondu à votre question, en montrant quelle (s) implémentation (s) j'utilise pour charger les données.
M4N
1
@ AarónGutiérrez Eh bien, curieusement, vous créez une table avec une seule colonne appelée id: D. Pour expliquer, chacun idreprésente une signification à laquelle vous pouvez attacher des mots de n'importe quelle langue dans une table relationnelle, vous obtenez donc deux tables, meaning(id) et word(id, sense_id), le iddans le wordtableau représente le mot id, le iddans le meaningreprésente le sens qui est universel.
Timo Huovinen
18

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

Mais vous semblez préoccupé par le fait que vos requêtes deviennent trop complexes:

Créer une table localisée pour chaque table rend la conception et les requêtes complexes ...

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

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

... vous devrez 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, qui pré-analyse le SQL qui contient votre balisage de localisation spécial et le convertit en SQL réel que vous devrez envoyer à la base de données.

L'utilisation de ce système peut ressembler à ceci:

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 cela.

La clé est d'avoir vos tables et champs nommés de manière uniforme.

René Saarsoo
la source
l'autre question est, pour créer un objet métier pour le produit? ou pour en créer deux ... dans le premier cas, il est facile de travailler avec cet élément, dans le 2 e CMS facile à écrire
Arsen Mkrtchyan
14

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

Produit ProduitDétail Pays
========= =================== =========
ProductId ProductDetailId CountryId
- etc - ProductId CountryName
            Langue CountryId
            Nom du produit - etc -
            Description du produit
            - 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. En fonction des exigences de votre application, vous souhaiterez peut-être décomposer le tableau Pays pour utiliser également les langues régionales.

pseudo
la source
J'ai choisi cette même approche pour un projet sur lequel je travaille actuellement car mes différents paramètres régionaux contiennent des informations très spécifiques sur les systèmes d'unités et les mesures à afficher pour les utilisateurs.
califrench
8
Le pays et la langue (locales) sont des choses différentes. Et les codes de langue ISO sont des clés naturelles, vous éliminez les jointures inutiles d'une langue à l'autre.
gavenkoa
10

J'utilise la prochaine approche:

Produit

ProductID OrderID, ...

Information sur le produit

ProductID Titre Nom LanguageID

Langue

Culture du nom LanguageID, ....

omoto
la source
2

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

Cela nécessiterait-il un IFNULL () et une autre instruction SELECT pour chaque champ?

La traduction par défaut serait stockée dans la même table, où un indicateur comme "isDefault" indique si cette description est la description par défaut au cas où aucune n'a été trouvée pour la langue actuelle.

doM
la source
1
@GorrillaApe: voir cette réponse pour un exemple comment revenir à la langue par défaut, si la langue souhaitée n'a pas été trouvée: stackoverflow.com/a/27474681/19635
M4N