IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 15 - Šablonovací systém XSLT v PHP - Vícejazyčné šablony

V minulé lekci, Šablonovací systém XSLT v PHP - Jednoduché čtení RSS, jsme si ukázali jednoduché čtení RSS pomocí transformace XSLT.

Transformace XSLT je nástroj vhodný i pro vícejazyčné šablony. Dnes si ukážeme jednoduchý způsob vytváření vícejazyčných šablon v XSLT.

Vícejazyčný web

Možná je načase vytáhnout zbraně silnějšího kalibru. Co když chceme vytvořit vícejazyčný web? Možností je několik. Například můžeme všechny texty uložit do databáze, před vlastní prezentací si je vytáhnout a použít v šabloně. Myšlenka je to lákavá a zřejmě i velmi často používána.

Uvedené řešení však má několik nevýhod. Například zbytečnou zátěž databáze při hromadném výběru celého slovníku. Co kdybychom měli každý slovník v jiném souboru? Stejně ho vždy musíme přečíst celý. Jako obvykle však musíme vybrat vhodný formát. Jenže když už výstupní šablonu mám v XSLT, co kdybych udělal v XSLT i slovník? Ano, tohle řešení funguje.

Šablona

Vhodný postup jsem našel na jednom webu, i když nebyl zcela ideální. Proto jsem ho přizpůsobil svým potřebám. Nejprve tedy výstupní šablona, kterou uložím do souboru sablona.xsl:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'>
    <xsl:output method="html" cdata-section-elements="a"/>

    <xsl:variable name="lang.webname">Český název webu</xsl:variable>

    <xsl:template match="/stranka">
    <xsl:text disable-output-escaping="yes">&lt;!DOCTYPE html&gt;</xsl:text>
        <html lang="{$lang}">
            <head>
                <xsl:apply-templates select="title"/>
                <link rel="StyleSheet" href="/style.css" type="text/css" />
            </head>
            <body>
                <h1><xsl:value-of select="$lang.webname"/></h1>
                <p><xsl:value-of select="$lang.text"/></p>
            </body>
        </html>
    </xsl:template>

</xsl:stylesheet>

Je vidět, že zde používáme proměnné $lang, $lang.webname a $lang.text. Tyto texty budeme chtít napsat v požadovaném jazyce.

Překlady

Vytvořím tedy další soubory.

Prvně pro český jazyk lang-cs.xsl:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'>
    <xsl:import href="sablona.xsl"/>
    <xsl:output method="html" encoding="utf-8" indent="yes"/>

    <xsl:variable name="lang">cs</xsl:variable>
    <xsl:variable name="lang.webname">Český název webu</xsl:variable>
    <xsl:variable name="lang.text">Český pevný text</xsl:variable>
</xsl:stylesheet>

A druhý pro anglický jazyk lang-en.xsl:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'>
    <xsl:import href="sablona.xsl"/>
    <xsl:output method="html" encoding="utf-8" indent="yes"/>

    <xsl:variable name="lang">en</xsl:variable>
    <xsl:variable name="lang.webname">English webname</xsl:variable>
    <xsl:variable name="lang.text">English fixed text</xsl:variable>
</xsl:stylesheet>

Pro každý jazyk si napíšeme další slovník s uvedenou strukturou. Výstupní šablona stále zůstává jen jedna. Všimněme si, že jsem v původní šabloně definoval hodnotu proměnné $lang.webname. Pokud bychom ji zapomněli definovat ve slovníku, bude použita jako defaultní hodnota.

A jak dál? Už skoro nic. Jen je potřebné zavolat ten správný slovník, viz předchozí lekce:

$sablona = new DOMDocument();
$sablona->load('lang-cs.xsl');

$xsl = new XSLTProcessor();
$xsl->importStyleSheet($sablona);

$dokument = new DOMDocument();
$dokument->load('sablona.xsl');
echo($xsl->transformToXML($dokument));

Výsledek:

Tvoje stránka
localhost

Toto řešení má jednu nevýhodu:

  • Pro každou šablonu je nutná sada jazykových šablon. Ovšem většinou si vystačíme s jedinou šablonou na celý portál a proto je tato nevýhoda nepodstatná.

A rychlost? Zpracování šablony se slovníkem, který měl 1000 slov trvalo na mém Celeronu cca 100 ms. Většinou si však vystačíme s desetinovým i kratším, proto i výstupní časy budou kratší než 10 ms. Databázi by to trvalo déle.

K čemu se to hodí? Hlavně k lokalizaci menu, hlavního nadpisu, patičky, copyrightu a dalších pevných textů, které se generují na většině podstránek. Nehodí se na dynamická menu, tedy menu rozšiřovaná do databáze. Takové menu je lepší řešit přímo v databázi.

Prezentace stromové struktury z databáze

Nedávno jsem se v diskuzním fóru zmínil o tom, že jsem vyřešil prezentace stromové struktury z databáze. Nelze to dělat přímo v databázi, protože relační databáze na takový typ dat nejsou stavěny. Je však možné zkombinovat to nejlepší z databáze i PHP.

Nejprve si založíme databázi a naplníme ji nějakými daty:

> sqlite3 tree.sqlite

BEGIN TRANSACTION;
CREATE TABLE strom
(
    id    integer primary key autoincrement,
    gid   int,
    pid   int,
    nazev text
);
INSERT INTO "strom"
VALUES (1, 1, NULL, 'první vlákno');
INSERT INTO "strom"
VALUES (2, 1, NULL, 'první vlákno 2');
INSERT INTO "strom"
VALUES (3, 1, 1, 'první vlákno 3');
INSERT INTO "strom"
VALUES (4, 2, NULL, 'druhé vlákno 1');
INSERT INTO "strom"
VALUES (5, 2, NULL, 'druhé vlákno 2');
INSERT INTO "strom"
VALUES (6, 2, 4, 'druhé vlákno 13');
INSERT INTO "strom"
VALUES (7, 2, 4, 'druhé vlákno 14');
INSERT INTO "strom"
VALUES (8, 2, 1, 'druhé vlákno 15');
INSERT INTO "strom"
VALUES (9, 2, 7, 'druhé vlákno 141');
INSERT INTO "strom"
VALUES (10, 2, 7, 'druhé vlákno 142');
INSERT INTO "strom"
VALUES (11, 2, 9, 'Příšerně žluťoučký kůň úpěl ďábelské ódy');
INSERT INTO "strom"
VALUES (12, 2, 5, 'Přidaný text');

DELETE
FROM sqlite_sequence;
INSERT INTO "sqlite_sequence"
VALUES ('strom', 12);

COMMIT;

Význam sloupců:

  • id - jednoznačná identifikace záznamu
  • gid - identifikace stromu. V jedné tabulce může být víc stromů
  • pid - označení rodiče aktuálního záznamu
  • nazev - jakýkoli text

Jako primární klíč ponechám id, pro větší fórum je vhodné udělat další index podle gid.

Data už máme, zbývá nám pouze jejich výpis:

$databaze = new PDO('sqlite:tree.sqlite');
$dotaz = $databaze->prepare('SELECT id, pid, nazev FROM strom WHERE gid=? ORDER BY id;');
$dotaz->execute(array(2));
$xml = new DOMdocument();
$elementy = array();
$elementy[0] = $xml->appendChild(new DOMElement('forum'));
while ($radek = $dotaz->fetch(PDO::FETCH_ASSOC)) {
    $id = $radek['id'];
    $pid = $radek['pid'] ?? 0;
    $pid = isset($elementy[$pid]) ? $pid : 0;
    $elementy[$id] = $elementy[$pid]->appendChild(new DOMElement('item', $radek['nazev']));
}
$xsl = new DOMdocument();
$xsl->load('strom.xsl');
$xslt = new XSLTProcessor();
$xslt->importStylesheet($xsl);
echo($xslt->transformToXML($xml));

Jak je vidět, v průběhu načítání dat z něj vytváříme stromovou strukturu v paměti. Tuto strukturu už přímo předáme šablonovacímu systému.

Výstupní šablona strom.xsl:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="html" encoding="UTF-8"/>

    <xsl:template match="/">
        <xsl:text disable-output-escaping="yes">&lt;!DOCTYPE html&gt;</xsl:text>
        <html>
            <xsl:apply-templates/>
        </html>
    </xsl:template>

    <xsl:template match="/forum">
        <head>
            <title>Diskuzní fórum</title>
            <link rel="stylesheet" type="text/css" href="style.css"/>
        </head>
        <body>
            <xsl:apply-templates/>
        </body>
    </xsl:template>

    <xsl:template match="item">
        <div class="vetvicka">
            <xsl:apply-templates/>
        </div>
    </xsl:template>

</xsl:stylesheet>

A nakonec ještě odkazovaný kaskádový styl style.css. Ten pro náš účel nemusí být vůbec dlouhý:

.vetvicka {
        margin-left: 4%;
}

A to je vše:

Diskuzní fórum
localhost

Aby z toho vzniklo opravdové diskuzní fórum, musel bych přidat vstupní formulář, jeho zpracování a uložení dat do databáze. K tomu by se hodila nějaká antispamová ochrana a administrační rozhraní pro moderátora. Pro náročnější bychom přidali ještě registraci uživatelů, přístupová práva... Chybí toho ještě hodně.

Uvedený příklad vůbec neřeší běhové chyby ani formátování příspěvku. Je to jen ukázka jednoduché prezentace stromového diskuzního fóra.

V další lekci, Práce s dokumenty Excel v PHP - Úvod a první skripty, se začneme věnovat knihovně PhpSpreadsheet pro práci s tabulkovými dokumenty a vytvoříme první .xlsx soubor.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 1x (5.28 kB)
Aplikace je včetně zdrojových kódů v jazyce PHP

 

Předchozí článek
Šablonovací systém XSLT v PHP - Jednoduché čtení RSS
Všechny články v sekci
Soubory a práce s nimi v PHP
Přeskočit článek
(nedoporučujeme)
Práce s dokumenty Excel v PHP - Úvod a první skripty
Článek pro vás napsal Kit
Avatar
Uživatelské hodnocení:
6 hlasů
Jsem spokojeným uživatelem operačních systémů založených na linuxovém jádře. Zejména openSUSE a Ubuntu. Pro psaní veškerých textů a programů používám vynikající textový editor Vim. Aplikace se snažím psát vždy v tom nejvhodnějším programovacím jazyk...
Aktivity