Was sind Best Practices für das mehrsprachige Datenbankdesign? [geschlossen]

193

Was ist der beste Weg, um eine mehrsprachige Datenbank zu erstellen? Das Erstellen einer lokalisierten Tabelle für jede Tabelle macht das Entwerfen und Abfragen komplex. In anderen Fällen ist das Hinzufügen einer Spalte für jede Sprache einfach, aber nicht dynamisch. Bitte helfen Sie mir zu verstehen, welche für Unternehmensanwendungen am besten geeignet ist

Arsen Mkrtchyan
quelle

Antworten:

222

Wir erstellen zwei Tabellen für jedes mehrsprachige Objekt.

Beispielsweise enthält die erste Tabelle nur sprachneutrale Daten (Primärschlüssel usw.) und die zweite Tabelle enthält einen Datensatz pro Sprache, der die lokalisierten Daten sowie den ISO-Code der Sprache enthält.

In einigen Fällen fügen wir ein DefaultLanguage-Feld hinzu, damit wir auf diese Sprache zurückgreifen können, wenn für eine bestimmte Sprache keine lokalisierten Daten verfügbar sind.

Beispiel:

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>

Mit diesem Ansatz können Sie so viele Sprachen wie nötig verarbeiten (ohne zusätzliche Felder für jede neue Sprache hinzufügen zu müssen).


Update (14.12.2014): In dieser Antwort finden Sie einige zusätzliche Informationen zur Implementierung, mit der mehrsprachige Daten in eine Anwendung geladen werden.

M4N
quelle
14
Was ist, wenn das einzige sprachneutrale Feld die ID ist? und wie genau fügen Sie beim Einfügen einer Zeile die Fremdschlüsselreferenz ein?
Timo Huovinen
4
Es ist lustig, dass ich ein Datenbankschema für ein mehrsprachiges CMS entworfen habe und diese Frage auch im Kopf hatte. Ich habe diesen Ansatz gewählt, bevor ich diese Antwort überhaupt gesehen habe! Danke für diese Antwort!
Patrick Manser
5
Hierbei ist zu beachten, dass in dieser Tabelle entweder keine PK vorhanden ist oder dass ID und Sprache die zusammengesetzte PK sein müssen. Entweder das, oder Sie müssen ein ProductTranslationId-Feld hinzufügen, wahrscheinlich als Identität.
Daniel Lorenz
1
@Luca: Ich habe Ihre Frage beantwortet und gezeigt, mit welchen Implementierungen ich die Daten lade.
M4N
1
@ AarónGutiérrez Nun, komischerweise erstellen Sie eine Tabelle mit einer einzelnen Spalte namens id: D. Zur Erklärung stellt jede ideine Bedeutung dar, an die Sie Wörter aus einer beliebigen Sprache in einer relationalen Tabelle anhängen können. Sie erhalten also zwei Tabellen, meaning(id) und word(id, mean_id), wobei die idin der wordTabelle die Wort-ID darstellt, die idin der meaningdarstellt die Bedeutung, die universell ist.
Timo Huovinen
18

Ich empfehle die Antwort von Martin.

Sie scheinen jedoch besorgt darüber zu sein, dass Ihre Abfragen zu komplex werden:

Das Erstellen einer lokalisierten Tabelle für jede Tabelle macht das Entwerfen und Abfragen komplex ...

Sie denken also vielleicht, anstatt einfache Abfragen wie diese zu schreiben:

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

... müssten Sie anfangen, solche Abfragen zu schreiben:

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

Keine sehr schöne Perspektive.

Anstatt dies manuell zu tun, sollten Sie eine eigene Datenbankzugriffsklasse entwickeln, die das SQL, das Ihr spezielles Lokalisierungs-Markup enthält, vorab analysiert und in das tatsächliche SQL konvertiert, das Sie an die Datenbank senden müssen.

Die Verwendung dieses Systems könnte ungefähr so ​​aussehen:

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

Und ich bin sicher, dass Sie das noch besser machen können.

Der Schlüssel ist, dass Ihre Tabellen und Felder einheitlich benannt werden.

Rene Saarsoo
quelle
Die andere Frage ist, ein Geschäftsobjekt für das Produkt zu erstellen. oder um zwei zu erstellen ... im ersten Fall ist es einfach, mit diesem Element zu arbeiten, im 2. einfach zu schreiben CMS
Arsen Mkrtchyan
14

Ich finde, dass diese Art von Ansatz für mich funktioniert:

Produkt ProduktDetail Land
==================================
ProductId ProductDetailId CountryId
- etc - ProductId CountryName
            CountryId Sprache
            Produktname - etc -
            Produktbeschreibung
            - etc -

Die ProductDetail-Tabelle enthält alle Übersetzungen (für Produktname, Beschreibung usw.) in den Sprachen, die Sie unterstützen möchten. Abhängig von den Anforderungen Ihrer App möchten Sie möglicherweise die Ländertabelle aufteilen, um auch regionale Sprachen zu verwenden.

Nick
quelle
Ich habe denselben Ansatz für ein Projekt gewählt, an dem ich gerade arbeite, da meine verschiedenen Gebietsschemas sehr spezifische Informationen zu Einheitensystemen und Maßnahmen enthalten, die den Benutzern angezeigt werden sollen.
Califrench
8
Land und Sprache (Gebietsschemas) sind verschiedene Dinge. Und ISO-Sprachcodes sind natürliche Schlüssel. Sie vermeiden unnötige Verknüpfungen von Sprache zu Land.
Gavenkoa
10

Ich benutze den nächsten Ansatz:

Produkt

ProductID OrderID, ...

Produktinformation

ProductID Titelname LanguageID

Sprache

LanguageID Name Kultur, ....

omoto
quelle
2

Martins Lösung ist meiner sehr ähnlich. Wie würden Sie jedoch mit Standardbeschreibungen umgehen, wenn die gewünschte Übersetzung nicht gefunden wird?

Wäre dafür für jedes Feld eine IFNULL () - und eine weitere SELECT-Anweisung erforderlich?

Die Standardübersetzung wird in derselben Tabelle gespeichert, wobei ein Flag wie "isDefault" angibt, ob diese Beschreibung die Standardbeschreibung ist, falls für die aktuelle Sprache keine gefunden wurde.

doM
quelle
1
@GorrillaApe: In dieser Antwort finden Sie ein Beispiel, wie Sie auf die Standardsprache zurückgreifen können, wenn die gewünschte Sprache nicht gefunden wurde: stackoverflow.com/a/27474681/19635
M4N