ugrás a tartalomhoz

Varációk több nyelven tárolt adatokra

kalamona · 2008. Május. 11. (V), 19.25
Sziasztok!

Saját keretrendszeremhez szeretnék többnyelvű adatok tárolását elegánsan megoldó megoldást fejleszteni. Mindegyik megfejtés valamilyen kompromisszumot jelentene, az eddigi búvárkodásom alapján. Szerintetek melyik módszernek legjobb a hatékonyság / teljesítmény aránya?
Több egymásnak ellentmondó igényem van. :)
Minél kevésbé bonyolítson minden lekérdezést pusztán az a tény, hogy több nyelven tárolok adatokat.
A lehető legtöbb dolog történjen implicit, hogy kisebb legyen a hibalehetőség, és javuljon az áttekinthetőség (pl. lekérdezések automatius újraírása révén kivitelezve)
Ne legyen nagyságrenddel lassabb tízmillós rekordszám mellett sem a nyelvesítetlen megoldásnál. Ezek a fontosabbak.

  • Az adattáblában egy nyelv mező alapján kérjük le rekord egy bizonyos nyelvű változatát.
    előny: minimálisan bonyolítja a lekérdezéseket (egy AND lang='hun' szerű feltétellel)
    hátrány: sok helyen a legtöbb mezőt nem kéne nyelvesíteni (mindenféle számértékek, flagek), kicsit favágó módszer, bár több helyen használják (persze a többi módszernek is mind van valóságalapja).

  • Az táblák kettéoszlanak egy általános infókat tartalmazó táblára (id, timestamp, stb)
    és egy table_text társtáblára, ahol a táblának a nyelvesítendő mezői szerepelnek kigyűjtve. Ebből aztán egy joinnal megkapjuk a kért mező fordítását
    előny: csak a szükséges mezőket tároljuk, nincs egy nagy mamuttábla minden szöveg fordításával, azaz talán gyorsabb is.
    hátrány: Egyszerű lekérdezésekből is join-ok lesznek. Majdnem minden táblából kettő lesz. Nem rossz módszer, de furcsa a logika, hogy ilyen dimenziót viszünk a táblákra bontásba. Mintha adattípus szerint csinálnék táblákat és az adatok hovatartozását egy "tábla" mező alapján követném vissza. Persze ez túlzás.

  • az adat táblájában semmi nem utal a nyelvre, viszont egy tranlation táblát készítek ilyen mezőkkel:
    [table], [col], [id], [language], [text]
    Ebből aztán vagy sql-ből, vagy akár php-ból egy második selecttel, vagy a lekérdezés implicit átírásával, kérjük le a fordítás táblából az adatot.
    előny: Minden fordított szöveg egy helyen, ha nincs szükség a nyelvekre, akkor egyszerűen ignorálható, ha jól valósítom a meg a lekérésüket, akkor tiszta ügy.
    hátrány: 2 szimpla lekérdézés, lehet hogy lassabb, mint egy join-os, a lekérdezés php-s átírása is jár valamennyi overheaddel. Egy gigászi tábla, ahol ráadásul akár többféle hosszúságú szöveget is kell tárolni (varchar, text). Aggályos.

  • Az előző módszer egy változata, hogy nem használok ennyi metaadatot a translation táblában a rekord azonosítására, hanem közvetlenül az adott szöveg eredetije lesz az "id"-je a fordított változatoknak. Esetleg ha gond az, hogy akár több oldalas is lehet egy szöveg, akkor ebből egy md5 vagy sha hash-t generálnék, és ez lenne a nyelvi adat id-je. (nem nagy az esély, hogy két egyforma legyen, de még ez is kivédhető)
    előny: Egyetlen adat azonosítja a rekordot, áttekinthető, kevesebb php-beli logikát kell programozni mellé. Egyszerűen kihagyható a nyelvesítés szükségtelensége esetén.
    hátrány: Mammuttábla, a plusz kód is lassít, a plusz lekérdezés is lassíthat, továbbá mivel a fordítandó szöveg mérete elég változatos lehet ezért egyféle pl. text tipusu mező nem tél gazdaságos/hatékony, ha többféle adathordozó mezőt hozok létre, akkor már a tipust is le kell kérdeznem, és aszerint is szűrni, belegondolni se jó.


Leginkább azt nem tudom megítélni, hogy mi mennyit nyom a latban. Két egyszerű tiszta select lehet hogy gyorsabb mint egy join, de legalábbis nem jelentősen lassabb. A több, de egyszerűbb lekérdezés adta áttekinthetőség révén nyert hatékonyság sem mellékes szempont, kis overhead legyelhető lenne, ha nyernénk valamit a vámon.

Eleve nem értem miért nem implmentáltak erre egy out-of-the-box megoldást az adatbáziskezelők,
kicsit olyan ez mintha idegenkulcs-kényszer kezelését kellene emulálnom php-ból.
Vannak még gondolataim, de majd a kommentekben megbeszéljük.

Köszönöm előre is gondolataitokat!
 
1

Csak egyszerűen

error · 2008. Május. 12. (H), 14.58
Én általában az első megoldást szoktam használni, mert így nem bonyolítom feleslegesen az adatbázist. Gyakran kiderül az is, hogy a redundáns mezők tulajdonképp nem is redundánsak. Mert nem olyan haszontalam amikor az angol tartalmat külön lehet publikálni.

E mellett a rövidebb statikus szövegek fordítására a negyedik megoldást használom, de nem adatbázisban hanem CSV fájlokban tárolom a szövegeket (Zend_Translate).
2

Kevésbé dinamikus megoldás, de elég kevés a hátránya

kris7topher · 2008. Május. 12. (H), 16.49
Kevésbé dinamikus megoldás, de elég kevés a hátránya a lokalizált szövegeket egy táblán belül külön-külön mezőben tárolni. Például van egy olyan hogy [text_hu] és [text_en], a lekérdezésben meg "SELECT text_{$lang} as text FROM tábla...", a PHP oldaláról viszonylag nem bonyolítja meg a kódot. Esetleg lehet csinálni az egyes nyelvekhez VIEW-kat, így PHP oldalról olcsóbbítani lehet egy sztringművelettel, bár így több minden is kerül tárolásra. Próblémát jelenthet új nyelv felvétele, illetve egy nyelv törlése, ezt talán SQL saját eljárásokkal lehetne a legstílusosabban megoldani, persze ha a tábla elkészítését is a PHP intézi valami scaffold-szerű megoldással (mondjuk csak egy .yml tárolja a táblaszerkezet meg a szükséges nyelveket) ilyen probléma nincs, illetve csak egyszer kell megoldani.
3

sok lekérdezés

winston · 2008. Május. 12. (H), 17.39
azzal, hogy a template-be beágyazva kell megadni a lefordítandót, egyetértek. de ha egyesével kéred le, az rengeteg sql lekérdezés. én a következő módon gondolkozok: bontsd két részre a lefordítani kívánt szövegeket: egyrészt a struktúrális szövegeket (menük, feliratok, lábléc, stb.), és a tartalmakat. a struktúrális részeket tedd nyelvenként egy ini fileba, vagy hasonlóba (szerializált array, akármi), és azokat rántsd be egyszerre, és helyettesítsd be. akár "elő is fordíthatod" a sablonokat nyelvenként. a tényleges tartalmakat meg továbbra is tároldd db-ben, az nem akkora többletterhelés (felveszel egy lng mezőt még), pláne, hogy kikerültek a "lényegtelen" dolgok adatbázisból. azzal vigyázz, hogy a hozzászólásokat, címkéket, amiket a felhasználók hoznak létre, nem nagyon tudod fordítani. érdemes elgondolkodni, hogy ha ilyen jellegű az oldal, hogy nyelvenként külön aloldalt hozz létre, amik tartalmilag nem kötöttek egymáshoz. így akár lehet az is, hogy az angolon más cikk van, mint a magyaron. persze ez az oldal jellegétől erősen függ. remélem érthető volt :)
4

van erre kvázi-szabvány

zila · 2008. Május. 13. (K), 09.11
úgy hívják: gettext