Forum: PC-Programmierung Mehrsprachigkeit in Datenbank abbilden


von Peter (Gast)


Lesenswert?

Hallo,

wie würdet ihr denn mehrere Sprachen (sinvoll) in einer Datenbank 
abbilden? Dabei soll aber auch beachtet werden, dass es sprachunabhänige 
Inhalte gibt (z.B. Artikelnummer).

Mir würden spontan 2 Ansätze einfallen:

Beispiel Tabelle Artikel Variante 1:

SpracheId|Artikelnummer|Artikeltext
---------+-------------+-----------
1        |0815         |Tastatur
2        |0815         |Keyboard
1        |4711         |Kabel
2        |4711         |Cable

Beispiel Tabelle Artikel Variante 2:

Artikelnummer|ArtikeltextSprache1|ArtikeltextSprache2
-------------+-------------------+-------------------
0815         |Tastatur           |Keyboard
4711         |Kabel              |Cable

An Variante 1 gefällt mir nicht, dass sprachunabhänige Dinge dupliziert 
vorkommen.

An Variante 2 gefällt mir nicht, dass wenn neue Sprachen dazukommen, man 
die Tabelle anpassen muss. Gut: Es werden nur halb so viele Felder im 
Gegensatz zur Variante 1 benötigt.

Wie würdet ihr das lösen und dabei bei einem praxistauglichen DB-Modell 
bleiben? Oder welche Variante würdet ihr bevorzugen?

Viele Grüße,
Peter

von Dennis H. (c-logic) Benutzerseite


Lesenswert?

SpracheId|Artikelnummer|Artikeltext
---------+-------------+-----------
1        |0815         |Tastatur
2        |0815         |Keyboard
1        |4711         |Kabel
2        |4711         |Cable


Nur würde ich den Artikeltext dann eher durch eine Verknüpfung auf eine 
Tabelle ersetzen.

ARTIKEL-DB

Artikelnummer|ArtikeltextID
-------------+-----------
0815         |1
4711         |2

ARTTEXT-DB

Id | Language | Text
1  | GER      | Tastatur
1  | ENG      | Keyboard
2  | ENG      | Cable

Wenns ne Relationale Datenbank ist kann man dann im SQL-befehl schon die 
Strategie einbauen Englisch zu nehmen, wenns keine nationale Übersetzung 
gibt.

von Troll (Gast)


Lesenswert?

Du kannst auch 3 Tabellen erstellen:

Artikel (alle Artikel mit Artikelnummer der ID von Artikel_Sprach_Daten)
Artikelnummer|Beschreibung
-------------+-----------
0815         |1
4711         |2

Sprachen (ID und welche Sprache)
ID |Sprache
---+-----------
1  | Deutsch
2  | Englisch

Artikel_Sprach_Daten (denk dir was aus :) )
(ID, die ID aus Sprachen und die eigentliche Beschreibung)
ID |Sprache | Beschreibung
---+--------+--------------
1  | 1      | tastatur
2  | 1      | maus
3  | 2      | keyboard
4  | 2      | mouse

Mit ein paar JOIN kannst du das gut abfragen.

von Robert L. (lrlr)


Lesenswert?

ich würde den "default" Text (der ja "Pflichtfeld" sein wird)  direkt in 
der Artikel tabelle machen

den rest so wie der " Troll (Gast)"

von D. I. (Gast)


Lesenswert?

Dennis Heynlein schrieb:
> ARTIKEL-DB
>
> Artikelnummer|ArtikeltextID
> -------------+-----------
> 0815         |1
> 4711         |2
>
> ARTTEXT-DB
>
> Id | Language | Text
> 1  | GER      | Tastatur
> 1  | ENG      | Keyboard
> 2  | ENG      | Cable

Das ist die Lösung die im Globalize3 Gem bei Ruby on Rails verwendet 
wird. Ich bin ziemlich zufrieden mit dieser Lösung. Dort hatte ich 
dasselbe Problem die Texte zu Items usw bei BreePets multi-lingual zu 
halten. Und als Fallback ist mindestens der englische Text verfügbar.

von Peter (Gast)


Lesenswert?

...ok, schöne nachvollziehbare Beispiele. Sind diese auch Praxisnah?

Das würde doch in etwa dem entsprechen, dass ich z.B. in einer 
Personentabelle die Wohnorte einer Person auch in eine eigene Tabelle 
auslagere. Dass das mit Joins gut auslesbar ist, ist klar. Aber ist es 
praxisnah?

Also nicht falsch verstehen, ich möchte nur für mich wissen, ob hier die 
Normalisierung zu weit geht, oder ob das ganz normal ist...

Immerhin ist das verknüpfen von Tabellen Naturgemäß für die DB 
aufwendiger als wenn ich in einer Tabelle bleibe. Und gerade Artikel 
können ja durchaus auch mal mehr werden (500.000+).

Wobei das Suchen innerhalb der Texte sollte sich eigentlich mit diesen 
Beispielen auch rel. gut machen lassen. Muss da noch ein wenig über die 
Lösungen nachdenken.

Auf jeden Fall vielen Dank für die schönen Beispiele.

Gruß,
Peter

von D. I. (Gast)


Lesenswert?

Peter schrieb:
> ...ok, schöne nachvollziehbare Beispiele. Sind diese auch Praxisnah?
>
> Das würde doch in etwa dem entsprechen, dass ich z.B. in einer
> Personentabelle die Wohnorte einer Person auch in eine eigene Tabelle
> auslagere. Dass das mit Joins gut auslesbar ist, ist klar. Aber ist es
> praxisnah?

Ja, erprobe ich tagtäglich auf unserer Seite.

von Peter II (Gast)


Lesenswert?

> ...ok, schöne nachvollziehbare Beispiele. Sind diese auch Praxisnah?

die frage ist ob die vorher genau sagen kannst wie viele Sprachen es 
sind. Dann könnte man es als Spalten ablegen, wenn aber später sprachen 
hinzukommen ist die Extra Tabelle eine besser lösung.

man könnte auch nur eine übersetzungstabelle machen:

ArtId   Name
1       Tastatur

Name      LANG      TEXT
Tastatur  ENG       Keyboard

das hätte den Vorteil das man Wenn es mehrfach die Tastatur gibt, nicht 
jedes mal neu die übersetzung eintragen muss. Und ein schneller zugriff 
auf den default Sprache vorhanden ist.

> Und gerade Artikel
> können ja durchaus auch mal mehr werden (500.000+).
mal 100 dann wird es viel. 500.000 kann man ja noch mit access 
verwalten.

von Karl H. (kbuchegg)


Lesenswert?

Peter schrieb:

> Das würde doch in etwa dem entsprechen, dass ich z.B. in einer
> Personentabelle die Wohnorte einer Person auch in eine eigene Tabelle
> auslagere.

Den Wohnort übersetzt du aber auch nicht. Allerdings kann es durchaus 
auch sinnvoll sein, den Wohnort in eine Tabelle auszulagern. Nämlich 
dann, wenn das nicht einfach nur ein dämliches Feld ist, sondern da mehr 
dahintersteckt, wie zb Verknüpfung mit der Postleitzahl, Position des 
nächsten Auslieferungslagers, Link zur Gemeinde-Hompage, etc.

Dein Artikel hat als Artikeltext ganz einfach ein 'Feld', für welches es 
abhängig von einer anderen Einstellung mehrere Möglichkeiten gibt.

Wenn du ein Auto beschreiben müsstest, würdest du ja auch ein Feld 
'Farbe' mit einer Farb-Id vorsehen und in einer getrennten Tabelle davon 
diese Farb-Id zu einem Namen, einer Bitmap, einer RAL-Nummer, dem 
Hersteller des Lacks etc. aufschlüsseln. Gibt es wiederrum mehrere 
Lackherstelller, dann steht dort wieder eine Hersteller-Id und in einer 
weiteren Tabelle die möglichen Hersteller.

Willst du also wissen, wer den Lack für das Auto liefert, musst du dir 
die Info über mehrere Stufen zusammensuchen - abhängig von der Lack-Id 
und der Hersteller-Id

Bei dir ist das dann eben Text-Id (vom Artikel) und Sprach-Id (globale 
Einstellung)


> man könnte auch nur eine übersetzungstabelle machen:
>
> ArtId   Name
> 1       Tastatur
>
> Name      LANG      TEXT
> Tastatur  ENG       Keyboard

Vorsicht mit solchen Sachen. Das sieht auf den ersten Blick wie die 
Lösung des Problems aus, schafft aber oft wieder neue Probleme. Eine 
davon ist: Tippfehler und unterschiedliche Schreibweisen, die keinem 
auffallen. Ein anderes Problem ist, dass es selten Artikeltexte ala 
"Tastatur" gibt. Sondern da steht dann "Tastatur Cherry XYZ850/32". Was 
jetzt? Dafür eine eigene Übersetzung anfertigen? DIe Übersetzung 
wortweise zusammenstoppeln? Was ist, wenn der Hersteller ein paar Dinge 
überhaupt nicht übersetzt. Ikeas 'Billy' heißt meines Wissens weltweit 
überall "Billy". Aber das Regal "Billy May" könnte in Thailand 
"Judo-San" heißen.

Meine Erfahrung: Übersetzungshilfen - ja.
Aber lieber bei der Eingabe der Übersetzungen entsprechenden Aufwand 
treiben. Im Notfall muss es immer möglich sein, das System zu overrulen 
und eine Übersetzung gezielt händisch vorzunehmen. Dazu muss aber der 
Daten-Aufbau stimmen. Fliesst die Übersetzung im Nachhinein irgendwie 
automatisch in das System ein, dann gibt das meistens Ärger. Zb. auch 
dann wenn ein Muttersprachler die thailandische Übersetzung "Judo-San" 
wegen eines Schreibfehlers korrigieren möchte. Da "Judo-San" in der 
Datenbank aber gar nicht existiert, sondern aus Einzelwörtern 
zusammengesetzt (und übersetzt) wurde, gibt es nichts, was er 
korrigieren könnte. Und führt man die Übersetzung auf die Einzelworte 
zurück aus denen sie entstanden ist, dann läuft man wieder Gefahr, Dinge 
zu ändern, die eigentlich nicht geändert werden sollte. Die Übersetzung 
von "Smoerebroed", welche ursprünglich "San" war, soll dann eben nicht 
plötzlich "Son" lauten, nur weil aus "Judo San" ein "Judo Son" werden 
musste.

von Reinhard Kern (Gast)


Lesenswert?

Hallo,

ganz und gar ketzerischer Vorschlag: die Datenbank ist einsprachig, 
übersetzt wird im Frontend, also ist die Bezeichnung Keyboard und auf 
einem Bildschirm in Deutschland erscheint Tastatur. Damit kann man auf 
Standard-Wörterbücher zurückgreifen, aber natürlich muss das erweiterbar 
sein z.B. für Fachbegriffe, die dort nicht zu finden sind.

Klar geht das nicht in allen Fällen, aber ich habe schon vor Jahren 
selbst eine Sprach-Datei aufgebaut für meine CNC-Steuerungen, die nach 
Bedarf erweitert wurde - da ich ja nur Deutsch und Englisch wirklich 
beherrsche, habe ich die ganze (textbasierte) Datei einem Übersetzer 
übergeben, der dann für z.B. "Positionierung läuft" den entsprechenden 
russischen Text eingegeben hat.

Internationale Modellbezeichnungen sind ein Thema für sich, aber 
bestimmte Fordautos heissen ja nicht nur in Europa anders als in USA, 
sondern sind auch anders ausgestattet, da ist der Name noch das 
geringste Problem. Sowas wie Quashquai ist auch kein wirkliches Wort in 
irgendeiner Sprache.

Gruss Reinhard

von MaWin (Gast)


Lesenswert?

> Das ist die Lösung die im Globalize3 Gem bei Ruby on Rails verwendet
> wird.

Übermässig normalisiert und damit übermässig langsam.

> Sind diese auch Praxisnah?

Nein.

Du solltest die Datenbankstruktur nicht ändern müssen,
wenn eine Sprache hinzukommt. Also klar deine Lösung 1

SpracheId|Artikelnummer|Artikeltext
---------+-------------+-----------
1        |0815         |Tastatur
2        |0815         |Keyboard
1        |4711         |Kabel
2        |4711         |Cable


Du solltest dafür sorgen, daß eigentlich alle Abfragen
so aussehen als ob sie nichts von der aktuellen Sprache
wüssten.

Das WHERE SpracheId=1 sollte also transparent für deine
Anwendung sein, das kann man mit einer VIEW erreichen.

Du solltest dafür sorgen, daß nicht alle Einträge
lokalisiert sein müssen, sondern auch Tabelle ohne
spachspezifika existieren können.

Auch das geht gut mit einer VIEW, denn du weisst ja durch
die VIEW gar nicht, ob die Tabelle eine SpracheId Spalte
hat oder nicht.

von D. I. (Gast)


Lesenswert?

Reinhard Kern schrieb:
> ganz und gar ketzerischer Vorschlag: die Datenbank ist einsprachig,
> übersetzt wird im Frontend, also ist die Bezeichnung Keyboard und auf
> einem Bildschirm in Deutschland erscheint Tastatur. Damit kann man auf
> Standard-Wörterbücher zurückgreifen, aber natürlich muss das erweiterbar
> sein z.B. für Fachbegriffe, die dort nicht zu finden sind.

Frontend-Übersetzungen sollte man nur von Dingen machen die auch im 
Frontend angesiedelt sind, z.B. HTML-Dateien sonst wird das nach einiger 
Zeit einfach nur chaotisch.
In RoR zum Beispiel kann man für seine views (die dann zu HTML gerendert 
werden) .yml-Dateien für I18n-Internationalisierung anlegen und diese 
dann verwenden. Das hat den Vorteil dass man alle Frontend-Texte 
gebündelt hat und wenn man sich entschließt eine neue Sprache 
einzuführen kann man einem Übersetzer einfach diese Text-Dateien geben 
ohne auch nur einen Furz View-Logic rausgeben zu müssen.

von D. I. (Gast)


Lesenswert?

MaWin schrieb:
>> Das ist die Lösung die im Globalize3 Gem bei Ruby on Rails verwendet
>> wird.
>
> Übermässig normalisiert und damit übermässig langsam.
>
>> Sind diese auch Praxisnah?
>
> Nein.
>
> Du solltest die Datenbankstruktur nicht ändern müssen,
> wenn eine Sprache hinzukommt. Also klar deine Lösung 1


Nun es gibt genug Anwendungsfälle wo man die Texte und Übersetzungen für 
die meisten Berechnungen garnicht braucht, dann müssen die entweder erst 
mühsam rausprojeziert werden via SELECT (CPU-Last), oder du hast eine 
RAM-Verschwendung via SELECT *, kommt besonders dann zum tragen wenn zu 
kleinen Bezeichnungen umfangreiche Artikelbeschreibungen kommen, also 
nicht nur VARCHAR sondern TEXT-Spalten. DAS ist dann langsam wie sau.
Da tut ein kleiner JOIN, der vorher meist durch ein WHERE 
zurechtgestutzt wird deutlich weniger weh, wenn man die Texte 
tatsächlich braucht, denn üblicherweise sind solche Verknüpfungen auch 
noch indiziert...

Die Datenbänkler haben die letzten 25 Jahre nicht geschlafen...

von Peter (Gast)


Lesenswert?

MaWin schrieb:

> Du solltest die Datenbankstruktur nicht ändern müssen,
> wenn eine Sprache hinzukommt. Also klar deine Lösung 1

Aber wenn neue Sprachen vorkommen müsste ich die Views anpassen, oder? 
Wie sieht es eigentlich mit der Performance bzgl. Views aus. Auch hier 
denke ich dass es ähnliche neg. Effekte wie bei Joins gibt, oder?

Wie Du auch schon geschrieben hast: übermäßig normalisiert. Das ist 
denke ich der Punkt. Wahrscheinlich läuft es wieder um das Abwägen der 
Pros und Contras ab.

Was Karl Heinz Buchegger geschrieben hat, kann ich gut nachvollziehen. 
Das mit der Einzelwortübersetzung würde ich nur für Bestimmte "Terme" 
verwenden (z.B. "Artikelnummer", "Seite", "vor", "zurück" etc...). Aber 
bei Texten ist das denke ich alleine durch die andere Anordnung der 
Wörter innerhalb der verschiedenen Sprachen nicht sinnvoll. Sonst kommt 
sowas in der Art wie bei Google-Translator (in den Anfängen) raus:

 rechtlich:                  physikalisch:
"Haftung ausgeschlossen" >> "Adhesion impossible"

Viele Grüße,
Peter

von D. I. (Gast)


Lesenswert?

Peter schrieb:
> Aber wenn neue Sprachen vorkommen müsste ich die Views anpassen, oder?
> Wie sieht es eigentlich mit der Performance bzgl. Views aus. Auch hier
> denke ich dass es ähnliche neg. Effekte wie bei Joins gibt, oder?
>
> Wie Du auch schon geschrieben hast: übermäßig normalisiert. Das ist
> denke ich der Punkt. Wahrscheinlich läuft es wieder um das Abwägen der
> Pros und Contras ab.

Ich weiß ja nicht mit was für Datenbankkrücken ihr im letzten 
Jahrtausend gearbeitet habt, aber Joins sind mittlerweile Gang und Gäbe. 
Natürlich muss man beim Normalisieren aufpassen nicht übers Ziel 
hinauszuscheißen und es zu übertreiben.
Aber so verhunzte Schemata wie Lösung 1 oder noch schlimmer lassen einem 
regelmäßig die Haare zu Berge stehen. Man sollte sich ein bisschen 
Wartbarkeit und Flexibilität für die Zukunft gönnen.

von Robert L. (lrlr)


Lesenswert?

die "Lösung" von MaWin ist ja wohl suboptimal

da hat man ja schon "Probleme" die Artikelnummer zu ändern..

und es gibt vermutlich ja noch weitere Felder, in der Tabelle Artikel, 
die man dann ständig synchron halten müsste


>. Wahrscheinlich läuft es wieder um das Abwägen der
>Pros und Contras ab.

deshalb: sag ich ja, dass man die "Hauptsprache" in Artikel lässt, und 
eine übersetzungs-tabelle..


das ist IMHO die Praktikabelste lösung, weil es in der Praxis eben oft 
an den Resourcen fehlt, alles bis ins letzte zu übersetzten. So hat man 
IMMER einen Fallback der funktioniert..

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Robert L. schrieb:
> da hat man ja schon "Probleme" die Artikelnummer zu ändern..

Der Primärschlüssel darf sich in einem ordentlichen Datenbankdesign 
nicht ändern. Ggf. muss eine neue Spalte für die dem Endnutzer 
angezeigte Artikelnummer angelegt werden, wenn es möglich sein soll 
diese frei zu gestalten bzw. zu ändern.

von Robert L. (lrlr)


Lesenswert?

@ Andreas Schwarz

ja, sag ich ja..


>wenn es möglich sein soll
>diese frei zu gestalten bzw. zu ändern.

und nachdem diese ja nicht normalisiert wäre, müsste man bei alle 
Artikel mit der selben Artikel_ID die Artikelnummer immer "manuell" 
synchron halten..


ein 2. aspekt ist ja, dass Mehrsprachigkeit meistens erst später 
hinzukommt, es also 100mal einfacher ist eine zusätzliche "übersetzungs" 
tabelle zu machen, als die vorhandene Artikel tabelle aufzubohren...

IMHO ist der Vorschlag von  MaWin  bisher der schlechteste von allen...

von Jens G. (jensig)


Lesenswert?

> Wie sieht es eigentlich mit der Performance bzgl. Views aus. Auch hier
> denke ich dass es ähnliche neg. Effekte wie bei Joins gibt, oder?

Nöö. Denn das hängt einfach davon ab, wie komplex die Joins sind, und 
natürlich auch, wie komplex das Abfrage-SQL selber ist. Letztendlich ist 
es das sich aus der View und dem SQL ergebende effektive SQL, welches 
darüber entscheidet, wie die Performanceeffekte sich gestalten.
Wenn Du ein View v1 as select * from t1 hast, dann ändert das effektiv 
gar nichts, wenn ich die View statt Tabelle benutze ;-)

Ich denke auch, daß MaWins Lösung nicht gerade sehr zeitgemäß ist. Der 
Join von mehreren Tabellen ist doch eher ein klacks, solange die 
Tabellen (wenn es größere sind) einigermaßen sinnvoll indiziert sind, 
und nicht zu viele Rows in die WHERE-Bedingung passen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.