webForumDet fria alternativet

Template class - Lokalisering

7 svar · 852 visningar · startad av MickeA.com

MickeA.comMedlem sedan feb. 20034 441 inlägg
#1

Hej,

Använder en template class som ser ut såhär:

<?php

class Template {
    var $vars; /// Holds all the template variables

    /**
     * Constructor
     *
     * @param $file string the file name you want to load
     */
    function Template($file = null) {
        $this->file = $file;
    }

    /**
     * Set a template variable.
     */
    function set($name, $value) {
        $this->vars[$name] = is_object($value) ? $value->fetch() : $value;
    }
	/**
     * Open, parse, and return the template file.
     *
     * @param $file string the template file name
     */
    function fetch($file = null) {
        if(!$file) $file = $this->file;

        if(count($this->vars)>0) //My modification
        	extract($this->vars);          // Extract the vars to local namespace
        ob_start();                    // Start output buffering
        include($file);                // Include the file
        $contents = ob_get_contents(); // Get the contents of the buffer
        ob_end_clean();                // End buffering and discard
        return $contents;              // Return the contents
    }
    
    function printVars() {
    	print_r($this->vars);
    }    
}

/**
* An extension to Template that provides automatic caching of
* template contents.
*/
class CachedTemplate extends Template {
    var $cache_id;
    var $expire;
    var $cached;

    /**
     * Constructor.
     *
     * @param $cache_id string unique cache identifier
     * @param $expire int number of seconds the cache will live
     */
    function CachedTemplate($cache_id = null, $expire = 900) {
        $this->Template();
        $this->cache_id = $cache_id ? 'cache/' . md5($cache_id) : $cache_id;
        $this->expire   = $expire;
    }

    /**
     * Test to see whether the currently loaded cache_id has a valid
     * corrosponding cache file.
     */
    function is_cached() {
        if($this->cached) return true;

        // Passed a cache_id?
        if(!$this->cache_id) return false;

        // Cache file exists?
        if(!file_exists($this->cache_id)) return false;

        // Can get the time of the file?
        if(!($mtime = filemtime($this->cache_id))) return false;

        // Cache expired?
        if(($mtime + $this->expire) < time()) {
            unlink($this->cache_id);
            return false;
        }
        else {
            /**
             * Cache the results of this is_cached() call.  Why?  So
             * we don't have to double the overhead for each template.
             * If we didn't cache, it would be hitting the file system
             * twice as much (file_exists() & filemtime() [twice each]).
             */
            $this->cached = true;
            return true;
        }
    }

    /**
     * This function returns a cached copy of a template (if it exists),
     * otherwise, it parses it as normal and caches the content.
     *
     * @param $file string the template file
     */
    function fetch_cache($file) {
        if($this->is_cached()) {
            $fp = fopen($this->cache_id, 'r');
            $contents = fread($fp, filesize($this->cache_id));
            fclose($fp);
            return $contents;
        }
        else {
            $contents = $this->fetch($file);

            // Write the cache
            if($fp = fopen($this->cache_id, 'w')) {
                fwrite($fp, $contents);
                fclose($fp);
            }
            else {
                die('Unable to write cache.');
            }

            return $contents;
        }
    }
}

?>

Nu vill jag kunna lokalisera statiska texter/ord som finns i alla templates och tänker spara alla fraser i en XML-fil per språk. Sen har jag tänkt mig att varje ord som ska översättas skrivs som t.ex. {PHRASE_NAME} eller liknande.

Min idé är sen att alla ord som omges av {} hämtas i classen ovan, men osäker på hur funktionen skulle kunna se ut samt hur jag hämtar orden. Jag gissar att det ska in någonstans kring include(file) ovan.

Förslag tages tacksamt emot.

MickeA.comMedlem sedan feb. 20034 441 inlägg
#2

Skulle det kunna vara bra att:

  • Splitta mallen med \n (för att få ut varje rad för sig)
  • Plocka ut alla {PHRASE} med t.ex. preg_match()
  • Loopa igenom array'en och köra mot en funktion som letar reda på resp. sträng

Eller finns det bättre sätt?

SPiNMedlem sedan mars 20007 896 inlägg
#3

I och med att klassen läser template-filerna som PHP, så kan du ju sätta informationen på vilket sätt du vill. Du behöver inte ha ytterligare en parsning av dina templates, det känns helt onödigt. Du sparar de cachade sidorna med ett id+språk som cache-id, så blandas inte cachen bland språk.

Alltså:

$tpl = new Template("template.phtml");
$tpl->set("theValue", $yourModel->getTheValueAccordingToLanguage($language));
$content = $tpl->fetch();
echo $content;
MickeA.comMedlem sedan feb. 20034 441 inlägg
#4

Nu använder inte jag cachefunktionerna alls här (av någon anledning, vet faktist inte varför) men du menar alltså att jag kör kopior av alla .tpl filer, en på varje språk och sen ladda in "rätt fil" beroende på språk?

Jag skulle hellre vilja lägga fraser som {PHRASE} i mallarna och sen översätta orden, eftersom filerna uppdateras rätt ofta och det blir omständigt att ändra i flera filer då.

MickeA.comMedlem sedan feb. 20034 441 inlägg
#5

Aha,sorry, nu kollade jag på din kod ovan igen och du föreslår alltså att jag skickar in lokaliserade värden direkt till mallen.

Var inne på det också, men tänkte att det skulle vara snyggare att bygga in nån sorts funktion för det här i templateklassen.

Men det är kanske lika bra att skicka in allt som variabler.
Kollar med på detta i eftermiddag, kom gärna med andra förslag under tiden om det finns några.

Tack!

SPiNMedlem sedan mars 20007 896 inlägg
#6

Nej, du behöver bara en mall för varje sida. Det känns dock onödigt att parsa dina mallar ytterligare en gång (det görs ju först i Template::fetch()). Som jag förstår det nu har du ett språk i dina mallar, men det bästa borde vara att enbart ha (x)html i dom och hämta all information från en datakälla, och bestämma vilken information som ska hämtas beroende på språk.

Typ:

/* show-user.php */
/* Vi ska nu visa en användares information */
/* Svenska som standardspråk */
$lang = (isset($_SESSION['lang']) && $_SESSION['lang'] != '') ? $_SESSION['lang'] : 'swedish';

/* Hämta användarinformation */
$user = getUserInfoFromDb($_SESSION['userId']);

/* Hämta "statiska" informationen, beroende på språk */
$page = getPageInfo("show-user", $_SESSION['lang']);

$tpl = new Template("show-user.phtml");
$tpl->set("pageDescription", $page['description']);
$tpl->set("pageTitle", $page['title']);

$tpl->set("userName", $user->getName());
$tpl->set("userAddress", $user->getAddress());
$tpl->set("userPhone", $user->getUserPhonenumber());

echo $tpl->fetch();

Template-filen 'show-user.phtml'

<html>
<head>
<title><?=$pageTitle ?></title>
</head>
<body>
<p><?=$pageDescription ?></p>
<p>
<?=$userName ?><br>
<?=$userAddress ?><br>
<?=$userPhone ?><br>
</p>
</body>
</html>

Det blir omständigt, men bättre än att behöva parsa sidan två gånger (vilket ändå antagligen blir lika omständigt). Mitt exempel går ju att förbättra avsevärt, men du förstår nog hur du ska applicera det. :)

Det bästa hade dock varit om du använde ett ramverk i grunden, t.ex. Zend - då hade du kunnat använda Zend_Translate till detta ändamål.

MickeA.comMedlem sedan feb. 20034 441 inlägg
#7

Okej, ser bra ut!
Jag har kollat på Zend, tack vara alla trådar i "Artiklar" (bl.a. de som du skrivit) och tänker nog gå över till Zend så småning om.

Fast just nu behöver jag en annan lösning, då jag inte har tid att byta framework.

Tack!

MickeA.comMedlem sedan feb. 20034 441 inlägg
#8

Tänkte bara väcka den här gamla tråden och tala om att jag gjorde enligt din princip ovan och det fungerar hur bra som helst.

Om någon annan får för sig att använda min klass ovan och behöver översätta.

140 ms totalt · 3 externa anrop · v20260731065814-full.fb544a5a
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
137 ms — hämta tråd, inlägg och bilagor (db)