Hi!
ich arbeite gerade an einem Projekt, welches ich sprachlich überhaupt nicht einschränken wollte. Mehr oder minder jede verdammte Sprache auf diesem Planeten soll darauf verfügbar sein.
Du bist doch nicht der erste, der ein mehrsprachiges Projekt in Angriff nimmt. Was für Lösungen zu dieser Problematik hast du dir schon angesehen und was hat dir daran nicht gefallen, dass du das Rad nochmal neu zu erfinden gedenkst?
Anstatt ein array zu erzeugen bzw. eben drei arrays und mich dann daraus zu bedienen dachte ich es vielleicht geschickter das ganze in einer Datenbank zu handeln.
Den Inhalt einer Datenbank kann man aber nicht so einfach mal eben kopieren und jemandem zum Übersetzen geben. Dateien sind da erst einmal einfacher in der Handhabung. Wenn du dir Performance-Gedanken machst, solltest du die Szenarien erst einmal (mit einer realistischen Menge an Daten) durchspielen. Das was du vielleicht für das Array mehr an Speicher belegst ist die DBMS-Lösung möglicherweise langsamer. Beachte auch die unterschiedlichen Rechnerkonstellationen in deinem Entwicklungslabor und in der Produktivumgebung.
$AusgabeVariable[] = '<div class="example">'.htmlentities($texte['name_des_textes']).'</div>(...)';
Was hantierst du hier mit htmlentities() rum? Wenn du schon etwas Multilinguales aufstellst, dann verwende UTF-8, alles andere wäre - 'tschuldigung - dämlich. Einzig htmlspecialchars() benötigst du dann noch für den HTML-Kontext (und für die anderen Kontexte natürlich etwas dort benötigtes).
Die Ausgabe so zu gestalten, dass man in die Variable einen Platzhalter einfügt und in eine Liste die Texte einträgt, die man so braucht:
$AusgabeVariable[] = '<div class="example">%%%name_des_textes%%%</div>(...)';
$verwendete_Texte[] = 'name_des_textes';
> und direkt vor der Ausgabe erfolgt dann eine Abfrage auf der Datenbank gegen alle in $verwendete\_Texte eingetragenen Namen, welche dann in der AusgabeVariable über eine der mannigfaltigen replace-Methoden ersetzt wird.
Die Array-Lösung käme mehr oder weniger mit einem strtr(), str\_replace() oder preg\_replace() aus (eigentlich eher preg\_replace\_callback(), denn irgendwie musst du beim Einfügen ja noch die kontextspezifische Kodierung reinbringen). Die DBMS-Lösung müsste zunächst alle Platzhalter zusammentragen, eine Abfrage generieren, das Ergebnis abholen und dann die Ersetzung mit einer der genannten Funktionen vornehmen. Jeden Begriff einzeln abzufragen wäre ... - du kannst dir das bestimmt vorstellen.
> Zudem wollte ich die Benutzer ein wenig einspannen, zwischendurch oder auch ständig irgendwo wo's nicht stört (ne Sitebar oder sowas) bittet man den Benutzer einen Begriff oder ganzen Text zu übersetzen von einer Sprache, die er beherrscht in eine Sprache, die er beherrscht.
Dafür eignen sich Textdateien primär schlecht. Aber was ist mit einer Qualitätskontrolle? Jeder Formularspammer kann dir dann deine Texte "übersetzen" - abgesehen von engagierten aber sprachlich doch nicht so ganz fitten Mitarbeitern.
> ich kann mit vorstellen die Tabellen etwa so zu stukturieren:
> id | textname | lang | value |
> 1 | 'greet' | 'de' | 'Hallo' |
> 2 |'name\_des\_| 'de' | 'Inhalt Inhalt Inhalt'|
> | textes' | | |
> 3 | 'greet' | 'en' | 'Hello' |
Eine ID benötigst du im Prinzip nicht, denn der Primärschlüssel ergibt sich eigentlich schon aus den Feldern textname und lang. Sie kann trotzdem sinnvoll sein, wenn Abhängigkeiten zu anderen Tabellen bestehen und sich mal ein Textname ändert. Allerdings solltest du dir eine solche Umbenennung im laufenden Betrieb gut überlegen. Der Grund dafür wäre sicher ein geänderter Text aufgrund neuer Rahmenbedingungen. Alle Übersetzungen stimmen dann sicher nicht mehr und du kämest vermutlich besser, neue Datensätze anzulegen.
> textname (primary) | (...) | de | en | (...) | zu |
> 'greet' | |'Hallo'|'Hello'| | |
> 'name\_des\_textes' | |'Inhlt'| | | |
Diese Variante hat nur den Vorteil, dass du mit einer einfachen Abfrage auf einen Blick siehst, welche Übersetzungen fehlen. Im Allgemeinen wird ein solches Design jedoch abgelehnt, da das Hinzufügen einer neuen Sprache immer mit einem Ändern der Struktur einhergehen muss. Bei der ersten Variante musst du "nur ein paar Datensätze" hinzufügen.
> Ich tendiere zu ersterem, weil ich denke dass ich erstmal weniger Speicher in der Datenbank belege (keine leeren Sprach-Zellen)
Das Speicherproblem überlass mal dem DBMS. Ganz sicher wirst du VARCHAR-Felder haben und - wofür steht gleich nochmal das VAR?
> und wohl auch die Anfrage besser stellen kann (nämlich: nach Sprache2 nur suchen wenn der Text in Sprache1 nicht gefunden wurde... wobei ich nicht weiß wie das mit MySQL geht, aber das finde ich dann schon raus).
Joins heißt ein Stichwort. Du wirst eine Sprache haben, die vollständig ist. Mit einem Left Join bindest du daran die gewünschte Sprache an. Ist für die zweite Sprache kein Datensatz vorhanden, ergeben deren Felder NULL. Mit COALESCE() beispielsweise kannst du nun den Inhalt der zweiten Sprache oder als Rückfall (bei NULL) den der ersten Sprache liefern lassen.
> Aber vielleicht ist auch die zweite Variante geschickter, weil man nur nach einer ID suchen muss und dann gleich alle Sprachen zur Hand hat, die man braucht.
Während du bei Variante 1 die gewünschte Sprache als Parameter in der WHERE-Klausel angibst, musst du in Variante 2 immer das Statement selbst anpassen und die gewünschten Sprachfelder einfügen.
> Vielleicht ist es sogar sinnvoll statt textname einen nummerischen Index (bzw. Suchwert) zu wählen, da fürchtete ich nur um Kollisionen bei der Programmierung (wenn man nicht mehr weiß was der letzte Wert noch gleich war...).
Nicht nur das. Wenn du eine Zahl siehst, weißt du gar nichts zu dem Text, der hier angezeigt werden soll. Wenn du einen sprechenden Bezeichner nimmst, kannst du zumindest ahnen, worum es geht, ohne dir zusätzliche Kommentare ins Programm schreiben zu müssen. Die Kommentierdispziplin lässt ja bei den meisten Programmiereren (mich eingeschlossen) zu wünschen übrig.
> In Variante 1 KÖNNTE man sogar noch überlegen mehrere Einträge der gleichen Sprache für den gleichen Text zu vergeben und dann über eine Voting-Funktion deren Wert zu bestimmen (Laien-Übersetzungen können ja auch mal schief gehen).
Mach es nicht zu komplex/kompliziert. Du musst dir dann auch wieder einen Votingfunktionsmissbrauchsschutz implementieren.
> Wie könnte ich bei einer solchen Sache noch variable Inhalte in die Texte eingeben? Also das ein Text einen anderen enthält.
Jetzt wird es anspruchsvoll. Also, nicht was die reine Umsetzung mit Platzhaltern angeht, sondern das Berücksichtigen der sprachlichen <del>Gemein</del><ins>Besonder</ins>heiten. Um mal nur ein Beispiel zu nennen: nicht nur, dass manche Sprachen Einzahl und Mehrzahl unterscheiden und dafür unterschiedliche Wortformen verwenden und andere hingegen nicht, es gibt auch noch Sprachen, die für unterschiedliche Mengen unterschiedliche Formen im Angebot haben (Tschechisch, glaub ich, war so eine. 1 Einzahl, 2-4 Mehrzahl, 4-... andere Mehrzahlform).
> Grundsätzlich könnte man in die Texte selber den entsprechenden Platzhalter einfügen, [...] (so will ich Kosistenz in den Bezeichnungen erreichen, nicht das die gleiche Sache hier so und dort anders bezeichnet/übersetzt wird).
Nicht immer ist eine 1:1-Übersetzung möglich. Gelegentlich muss man da je nach Kontext unterschiedlich translieren.
> Und letztlich: Was würdet ihr als fallback wählen?
Englisch. Das verstehen noch die meisten, die einen Begriff nicht in ihrer bevorzugten Sprache finden. Von Englisch nach Sprache X gibt es zudem die meisten Wörterbücher (online). Von X nach Y ist das nicht immer gegeben.
> Ich bin für alle Ideen, Gedanken, Denkanstöße, Tipps, Erfahrungen und so fort dankbar und daran interessiert, immer mal her damit :)
Wie sieht es mit unterschiedlichen Schreibweisen für Datum, Zahlen und Messwerten aus? Die korrekt anzugeben und bei Eingaben zu interpretieren wirst du allein mit Platzhalterersetzungen nicht auf die Reihe bekommen. (Übrigens, im Zend Framework steckt auch ein umfangreiches Paket zu diesem Thema. Deswegen ist der Download auch so groß, weil ein wesentlicher Teil davon Daten für ebendieses sind.)
> ...
Einige der Fragen habe ich ja weiter oben schon implizit mitbeantwortet, weswegen ich nicht noch einmal darauf eingehe.
Lo!