it-swarm.com.de

Was ist die beste Datenbankstruktur für mehrsprachige Daten?

Mögliches Duplizieren:
Schema für eine mehrsprachige Datenbank

Hier ist ein Beispiel:

[ products ]
id (INT)
name-en_us (VARCHAR)
name-es_es (VARCHAR)
name-pt_br (VARCHAR)
description-en_us (VARCHAR)
description-es_es (VARCHAR)
description-pt_br (VARCHAR)
price (DECIMAL)

Das Problem: Jede neue Sprache muss die Tabellenstruktur ändern.

Hier ist ein anderes Beispiel:

[ products-en_us ]
id (INT)
name (VARCHAR)
description (VARCHAR)
price (DECIMAL)

[ products-es_es ]
id (INT)
name (VARCHAR)
description (VARCHAR)
price (DECIMAL)

Das Problem: Für jede neue Sprache müssen neue Tabellen erstellt werden, und das Feld "price" wird in jeder Tabelle dupliziert.

Hier ist ein anderes Beispiel:

[ languages ]
id (INT)
name (VARCHAR)

[ products ]
id (INT)
price (DECIMAL)

[ translation ]
id (INT, PK)
model (VARCHAR) // product
field (VARCHAR) // name
language_id (INT, FK) 
text (VARCHAR)

Das Problem: hart?

54
Thiago Belem

Ihr drittes Beispiel ist die Art und Weise, wie das Problem normalerweise gelöst wird. Schwer, aber machbar.

Entfernen Sie den Verweis auf das Produkt aus der Übersetzungstabelle und setzen Sie dort, wo Sie es benötigen, einen Verweis auf die Übersetzung (umgekehrt).

[ products ]
id (INT)
price (DECIMAL)
title_translation_id (INT, FK)

[ translation ]
id (INT, PK)
neutral_text (VARCHAR)
-- other properties that may be useful (date, creator etc.)

[ translation_text ]
translation_id (INT, FK)
language_id (INT, FK) 
text (VARCHAR)

Als Alternative (nicht besonders gut) können Sie ein einziges Feld verwenden und alle Übersetzungen dort zusammenführen (z. B. als XML).

<translation>
  <en>Supplier</en>
  <de>Lieferant</de>
  <fr>Fournisseur</fr>
</translation>
28
user151323

Ähnlich wie bei Methode 3:

[languages]
id (int PK)
code (varchar)

[products]
id (int PK)
neutral_fields (mixed)

[products_t]
id (int FK)
language (int FK)
translated_fields (mixed)
PRIMARY KEY: id,language

Erstellen Sie also für jede Tabelle eine andere Tabelle (in meinem Fall mit dem Suffix "_t"), die die übersetzten Felder enthält . Wenn Sie SELECT * FROM products sind, einfach ... LEFT JOIN products_t ON products_t.id = products.id AND products_t.language = CURRENT_LANGUAGE.

Nicht so schwer und hält dich frei von Kopfschmerzen.

35
Gipsy King

Um die Anzahl der JOINs zu reduzieren, können Sie die übersetzten und die nicht übersetzten in zwei separaten Tabellen getrennt halten:

[ products ]
id (INT)
price (DECIMAL)

[ products_i18n ]
id (INT)
name (VARCHAR)
description (VARCHAR)
lang_code (CHAR(5))
13
Clément

Bei meinem $ DAYJOB verwenden wir gettext für I18N. Ich habe ein Plugin in xgettext.pl geschrieben, das den gesamten englischen Text aus den Datenbanktabellen extrahiert und dem Master messages.pot hinzufügt.

Es funktioniert sehr gut - Übersetzer bearbeiten beim Übersetzen nur eine Datei - die po-Datei. Es gibt kein Fummeln mit Datenbankeinträgen beim Übersetzen.

3
holygeek

[Sprachen] id (int PK) code (varchar)

[products]
id (int PK)
name
price
all other fields of product
id_language ( int FK )

Ich benutze diese Methode tatsächlich, aber in meinem Fall ist dies nicht aus Produktsicht, für die verschiedenen Seiten in meinem CMS ist dies ziemlich gut.

Wenn Sie viele Produkte haben, kann es ein Problem sein, ein einzelnes in 5 oder 6 Sprachen zu aktualisieren ... aber es ist eine Frage des Layouts.

2
Tio

Was ist mit der vierten Lösung?

[ products ]
id (INT)
language (VARCHAR 2)
name (VARCHAR)
description (VARCHAR)
price (DECIMAL)
*translation_of (INT FK)*

* Translation_of * istFKvon sich selbst. Beim Hinzufügen der Standardsprache ist * translation_of * auf Null gesetzt. Wenn Sie jedoch eine zweite Sprache hinzufügen, übernimmt * translation_of * die primäre Produktsprachen-ID.

SELECT * FROM products WHERE id = 1 AND translation_of = 1

In diesem Fall erhalten wir alle Übersetzungen für das Produkt mit der ID 1.

SELECT * FROM products WHERE id = 1 AND translation_of = 1 AND language = 'pl'

Wir erhalten nur Produkte in polnischer Übersetzung. Ohne zweiten Tisch und JOINS.

0
chf