Brno? Vypsali jsme pro vás nové termíny školení Základů programování a OOP v Brně!
Avatar
maaaca
Člen
Avatar
maaaca:8. dubna 20:35

Řeším pro jeden vícejazyčný web překlad kratších frází, například ve formulářích. A myšlenka je jít na to s pomocí databáze. Využívám PDO + MySQL. Mořím se tu s tím celé odpoledne a nic funkčního na mě nevypadlo, potřeboval bych navézt na správnou cestu.

Zkusil jsem: Mám v MySQL takvouto tabulku:

id var cz en
1 titleOne Ahoj světe! Hello World!

Chci docílit: Výsledek by měl být takový, že například ve formulářích, kde potřebuji přeložit jenom několik frází, tudíž bych se hned na začátku připojil k databázi, jednou načetl všechny proměnné v daném jazyce a na žádoucích místech jen vypsal stylem:

...
            <label for="reservationName"><?php echo $translations["titleOne"]; ?></label>
...
 
Odpovědět 8. dubna 20:35
Avatar
Tomáš Novotný:8. dubna 20:59

Ahoj, když pominu, že jsou jistě lepší metody jak toho docílit...ale berme to tak, že si procvičuješ, takže ke tvému snažení, by to chtělo asi jedním dotazem do DB vytáhnout všechny relevantní informace tj. např. var a cz sloupce pro daný formulář/stránku a z těch si poskládat asociativní pole, kde var bude klíč a cz bude hodnota... pak můžeš použít něco takového, co máš v kódu a mělo by to fungovat
asi nebudeš vůbec potřebovat sloupec id, jelikož var by měl být patrně označen jako unikátní string...
případně přidat nějaký další kontextový sloupec...tzn., že některé překlady se týkají jen určité části webu, např. přihlašovacího formuláře.. důvodem je to, abys nenačítal vždy všechny

Nahoru Odpovědět 8. dubna 20:59
∞ ... the exact amount of possibilities how to deal with the situation ... so by calm, your solution is one of many
Avatar
Odpovídá na maaaca
Martin Konečný (pavelco1998):8. dubna 21:18

Ahoj, viděl bych to spíše tak, že budeš mít tabulky:

table_text:
id INT AUTO_INCREMENT PRIMARY KEY,
var VARCHAR,
page VARCHAR DEFAULT NULL

table_language:
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR,
acronym VARCHAR

table_text_language:
id INT AUTO_INCREMENT PRIMARY KEY,
text_id INT,
language_id INT,
content TEXT

Kdy sloupec page bude obsahovat název stránky. Když bude NULL, bude to nějaký obecný text (třeba text do hlavičky, patičky, nebo něco, co se vyskytuje často - taková ta obecná slova jako "ano", "ne" atd.).
V tabulce language budeš mít jednotlivé jazyky (cz, sk, en, ...), kterou si můžeš libovolně rozšířit (např. si dát sloupec, který určuje, zda je daný jazyk na webu povolen).
Pomocí tabulky text_language pak "propojíš" jeden text s více jazyky (sloupec content obsahuje konkrétní text pro konkrétní jazyk).

Do PHP pole to pak můžeš nacpat například takto:

$page = $_GET["page"];  // např.  index.php?page=homepage -> $page = homepage
$language = $_GET["language"];  // např. index.php?page=homepage&language=cs -> $language = cs

$textsQuery = $pdo->prepare("
        SELECT * FROM `table_text_language`
        INNER JOIN `table_language` ON `table_text`.`language_id` = `table_language`.`id`
        INNER JOIN `table_text` ON `table_text_language`.`text_id` = `table_text`.`id`
        WHERE `table_language`.`name` = ? AND (`table_text`.`page` = ? OR `table_text`.`page` IS NULL)
");

$textsQuery->execute(array($language, $page));
$textsData = $textsQuery->fetchAll();

$translations = array();
foreach ($textsData as $textData) {
        $translations[$textData["var"]] = $textData["content"];
}

Pokud bys chtěl předejít případným chybám, že daný text podle 'var' v databázi není, můžeš si udělat jednoduchou funkci

function getText($name, $default = NULL)
{
        global $translations;   // pro ukázku neřešme, že global je fuj

        if (isset($translations[$name])) {
                return $translations[$name];
        }

        // pokud neexistuje daný text, vrátí se něco výchozího
        if ($default !== NULL) {
                return $default;
        }

        // pokud není zadáno nic výchozího, vrátí se třeba "název" toho textu
        return $name;
}

// použít to pak můžeš jednoduše
<div>
        <?php echo getText("todayDateIs"); ?> <?php echo date("d.m.Y"); ?>  // vypíše např. "Dnešní datum je 8.4.2019"
</div>
Nahoru Odpovědět 8. dubna 21:18
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Jaroslav Smrž:9. dubna 6:59

Ahoj, jestli tomu dobře rozumím, tak máš někde v menu jazykovou mutaci pouze CZ a EN a nechceš měnit celý obsah. Pak bych na to šel asi jinak. V případě češtiny bych nechal stránce normální běh a pouze při volbě EN bych spustil session. Při kliku z EN na CZ bych zas session ukončil. Pak jednoduchá podmínka jestli je session spuštěná nebo ne a podle toho vypsat hodnotu z pole. Pokud těch dynamických prvků nebude příliš a neuvažuješ o rozšiřitelnosti, tak mi to přijde jako nejrychlejší způsob a databázi vůbec nepotřebuješ.

Nahoru Odpovědět 9. dubna 6:59
I have no idea what it is doing but I´m scared to delete it... xD
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:9. dubna 8:03

Taky bych mel reseni. Podobne M. Konečný. Myslim si, ze odolne vuci chybam.
tab. stranky - page_id, name, content
tab. jazyky - lang_id, name
tab. prekladu - transl_id, name, translate
tab. propojovaci - lang_id, page_id, transl_id
nebo bez tab jazyky:
tab. prekladu - transl_id, page_id, name, translate_cz, translate_en
Nebo nejak jinak :)

Potrebujes, aby sql dotaz vratil pro konkretni stranku konkretni name konkretni text. V podstate by misto name v posledni tabulce slo pouzit transl_id. transl_id by se nemelo na strance opakovat. (Vim, spousta lidi ma predstavu, ze vyuzije slovnik univerzalne, ale to je obecne spatne reseni. Pokud ovsem nemas ve slovniku vsechny mozne tvary.)
A potrebujes tim dotazem vratit vsechny preklady podle page_id, abys nemusel dotaz volat vicekrat. Ty ulozis do pole, jak psal T. Novotný.

translate_cz or translate_en or name
Name zadavas v php. Pokud neexistuje cesky preklad, melo by to vratit anglicky. Pokud ani ten nebo nastane jina chyba, melo by to vratit aspon name. Pokud by to vratilo prazdne policko, je to chyba, neklikatelny odkaz a pod. Viz tez M. Konečný.

<a href=123></a>
<a href=123>titleOne</a>

Ale ja bych jeho podminky rozsiril, pokud text je null nebo trim(text), ktery ma jit do returnu je '' (prazdny) , tak by mel vratit name. Muze se stat, ze v tom poli (T. Novotný) proste ta hodnota je undefined, null nebo '' a nebo mezera, tabelator, novy radek, proto trim.

Editováno 9. dubna 8:05
 
Nahoru Odpovědět 9. dubna 8:03
Avatar
Tomáš Novotný:9. dubna 9:14

Pokud bych měl navrhnout řešení lokalizace, tak bych využil spíše než DB tak GetTextu a *.mo, *.po a *.pot souborů. Už jeho samotné použití řeší některé zde zmíněné jazykové fallbacky, pokud překlad v daném jazyce neexistuje.. Navíc přidává možnosti do lokalizovaného textu jednoduše vkládat i proměnné. Tento způsob se používá v různých obdobách a jazykový implementacích bez mála 30 let.
více třeba tu https://cs.wikipedia.org/…/GNU_gettext
počáteční nastudování by se mohlo zdát pro někoho obtížnější, ale přínos dle mne jistě vyváží časovou investici a to i pro menší projekty
reálné použití lze omrknout u většiny opensource CMS

Nahoru Odpovědět  +1 9. dubna 9:14
∞ ... the exact amount of possibilities how to deal with the situation ... so by calm, your solution is one of many
Avatar
Tomáš Novotný:9. dubna 9:36

další zajímavý plus vidím v tom, že případnou lokalizaci do exotického jazyka (většinou z en) zvládne díky šabloně *.pot a např. programu PoEdit běžný uživatel PC
přidáš něco na web tj. zaktualizuješ soubor šablony s texty a můžeš ho předat překladatelům, kteří mohou udělat i nějaké revize stávajícího. Myslím, že je tam implementováno i něco jako max. délka překladu - tj. aby ti to nerozbilo layout pro různé mutace. Také jsou tam možnosti pro použití množného/jednotného čísla, pokud existují rozdílné tvary pro jednotlivé jazyky.

Nahoru Odpovědět 9. dubna 9:36
∞ ... the exact amount of possibilities how to deal with the situation ... so by calm, your solution is one of many
Avatar
Odpovídá na Tomáš Novotný
Jaroslav Smrž:9. dubna 10:25

Tomáši, díky za zmínění getTextu. Naposledy jsem o něm četl před mnoha lety a to v souvislosti s C++. Je dobré vědět, že se stále používá. Potenciál využití je celkem široký i na dnešní dobu.

Nahoru Odpovědět  +1 9. dubna 10:25
I have no idea what it is doing but I´m scared to delete it... xD
Avatar
maaaca
Člen
Avatar
maaaca:9. dubna 20:47

Díky všem. Nakonec jsem zkusil jít cestou gettextu, ale narazil jsem na problém při nasazování u Wedosu s tím, že nepodporuje putenv. Přitom gettext podporuje.

putenv('LANG=' . $language);
setlocale(LC_ALL, $language);

// Set the text domain as 'messages'
$domain = "messages";
bindtextdomain($domain, "Locale");
textdomain($domain);

Jde to nějak obejít?

 
Nahoru Odpovědět 9. dubna 20:47
Avatar
Odpovídá na maaaca
Tomáš Novotný:9. dubna 21:07

Patrně nemáš přístup ke změnám proměnné LANG v prostředí webhostingu... na druhou stranu úplně netuším, k čemu to potřebuješ nastavovat... třeba php manuál uvádí v příkladu jinou implementaci gettextu než si poslal...
https://www.php.net/….gettext.php

Editováno 9. dubna 21:08
Nahoru Odpovědět 9. dubna 21:07
∞ ... the exact amount of possibilities how to deal with the situation ... so by calm, your solution is one of many
Avatar
maaaca
Člen
Avatar
maaaca:9. dubna 21:21

Jel jsem podle jednoho tutorialu. Nicméně i v tvém odkazovaném manuálu vidím verzi s putenv. Asi potřebuji silnější nakopnutí :)

 
Nahoru Odpovědět 9. dubna 21:21
Avatar
Odpovídá na maaaca
Tomáš Novotný:9. dubna 21:51

Ah táák, měl jsem za to, že nemáš přístup jen k některým nastavením. Nemyslel jsem si, že by zakázali celou funkci... ale když tak koukám do phpinfo.... tak to je na konzultaci s hostingovou podporou, co je k tomu vede.

Nahoru Odpovědět 9. dubna 21:51
∞ ... the exact amount of possibilities how to deal with the situation ... so by calm, your solution is one of many
Avatar
maaaca
Člen
Avatar
maaaca:10. dubna 16:54

Tak z podpory mi zatím odpověděli, že mám ten řádek s putenv zakomentovat...

Jde to rozchodit i bez použití funkce putenv? Návodů k gettextu je na internetu fakt minimum, ale přijde mi to jako hodně elgantní řešení, tak bych to nechtěl vzdát. Měnit hosting kvůli tomu ale nebudu...

 
Nahoru Odpovědět 10. dubna 16:54
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 13 zpráv z 13.