Creare un sito multilingua in PHP

Per gestire un sito multilingua nei CMS spesso ci vengono in aiuto i plugin ma nel caso di siti molto semplici e con poche pagine potremmo anche pensare di non avere la necessità di creare un pannello back-end e quindi di ritrovarci a dover gestire più lingue.
Creare molti files separati probabilmente è la prima idea che potrebbe venirci in mente ma, francamente, non è certo la migliore!
Il concetto alla base è molto semplice: sfruttare un array in PHP che contenga le varie parole o i testi che dovranno essere inseriti all’interno del sito; ciascuna lingua avrà un array con lo stesso nome che conterrà i testi localizzati e includeremo solo quello della lingua desiderata.
Vediamo come:

<?php
// la lingua può essere selezionata passando un valore in GET all'attributo 'lang'
// rileviamo se esiste un parametro get per 'lang' e lo assegniamo alla variabile $lang
if(isSet($_GET['lang'])) {
    $lang = $_GET['lang'];
// in caso contrario rileviamo la lingua preferita del browser dell'utente
// e la assegniamo alla variabile
} else {
    $lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
}

// Verifichiamo se il valore di $lang corrisponde ad una delle lingue
// di cui il nostro sito dispone e assegnamo il valore corretto alla varibile
// impostando come default l'inglese per far si che internazionalmente
// venga visualizzato l'inglese
switch ($lang){
    case 'it':
        $lang = 'it';
        break;
    case 'en':
        $lang = 'en';
        break;        
    default:
        $lang = 'en';
        break;
}
// includiamo il file contenente l'array con le traduzioni corrispondente
// alla lingua ricavata qui sopra
require_once 'lang/lang.'.htmlspecialchars($lang).'.php';

Com’è facile intuire dal codice nella nostra ‘index.php’ ora abbiamo a disposizione un codice identificativo di una lingua non solamente scelta dall’utente ma persino rilevata in automatico dalle preferenze del browser; ora non ci resta che creare gli array contenenti le traduzioni e poi integrarle nell’HTML, iniziamo con l’italiano:

<?php
/*
------------------
Language: Italian
------------------
*/

 
$lang = array();

$lang['PAGE_TITLE'] = "Sito Multilingua";
$lang['PAGE_HEADER'] = "Questo &egrave; un sito multilingua!";

Salviamo il file all’interno della cartella “lang” nominandolo “lang.it.php” e creaiamo quello per l’inglese:

<?php
/*
------------------
Language: English
------------------
*/

 
$lang = array();

$lang['PAGE_TITLE'] = "Multilanguage Website";
$lang['PAGE_HEADER'] = "This is a multilanguage website!";

Salviamo anche questo file all’interno della cartella “lang” nominandolo “lang.en.php” e procediamo infine ad inserire le variabili nell’index (sotto al codice PHP mostrato all’inizio dell’articolo)

<!-- codice all'inizio dell'articolo -->
<!DOCTYPE html>
<html>
<head>
    <title><?php echo $lang['PAGE_TITLE']; ?></title>
    <meta charset="utf-8">
    <meta name="robots" content="index, follow" />
</head>
<body>
    <h1><?php echo $lang['PAGE_HEADER']; ?>
</body>

</html>

Come avete visto nel sorgente dell’index è possibile tradurre anche i vari tag all’interno dell’head permettendoci così di ottimizzare anche la SEO del nostro sito, lo step successivo potrebbe essere quello di ottimizzare l’URL per renderlo più user-friendly utilizzando il la mod_rewrite del file .htaccess.
Ed ecco concluso il nostro sito multi-lingua!
Possiamo ovviamente gestire quanti testi e lingue desideriamo (nel limite del buon senso) ed aggiungerli agli array.
Ci sono molte strade per sviluppare un sito multi-lingua questa è sicuramente tra le più immediate anche se probabilmente ce ne sarebbero di più corrette come ad esempio l’utilizzo dell’estensione PHP gettext che utilizza i files .po e .mo oppure, banalmente, l’utilizzo di un database per archiviare le varie lingue ma per siti di piccole dimensioni la soluzione sopra spiegata funziona egregiamente!

Trasformare degli SVG linkati con img in SVG inline con jQuery

Per modificare i valori, siano il colore o la dimensione, di immagini SVG in CSS è necessario che siano inline e non inseriti con il tag <img>, risulta però molto più comodo includerli in quest’ultimo modo;
Includendoli con il tag <img> infatti potremmo aggiornare il file senza modificare il sorgente della pagina e al tempo stesso mantenere molto più ordinato il sorgente.
La soluzione è molto semplice in realtà, grazie a jQuery:

// cicliamo tutti tag img che hanno la classe 'svg'
$('img.svg').each(function(){
    // memorizziamo il file e gli attributi del file
    var $img = $(this);
    var imgID = $img.attr('id');
    var imgClass = $img.attr('class');
    var imgURL = $img.attr('src');

    // effettuiamo una chiamata ajax al file per recuperare il contenuto dell'SVG
    $.get(imgURL, function(data) {
        // memorizziamo solamente il contenuto del tag svg ignorando il resto
        var $svg = $(data).find('svg');

        // se ha un id lo memorizziamo e lo assegnamo al nostro nuovo svg
        // ricostruito
        if(typeof imgID !== 'undefined') {
            $svg = $svg.attr('id', imgID);
        }
        // aggiorniamo allo stesso modo le classi aggiungendoci anche un prefisso
        if(typeof imgClass !== 'undefined') {
            $svg = $svg.attr('class', imgClass+' replaced-svg');
        }

        // Rimuoviamo tutti i tag xml che non sono validi per il w3c
        $svg = $svg.removeAttr('xmlns:a');

        // sostituiamo il tag iniziale img con il nuovo svg inline
        $img.replaceWith($svg);

    }, 'xml');
});

Generare un file CSS con PHP

Mi è capitato, di recente, di dover passare dei parametri da PHP a CSS; Nello specifico, dopo aver creato un pannello di controllo per le opzioni di un tema wordpress ho avuto la necessità di dare la possibilità di modificare lo schema colori direttamente da wordpress utilizzando un colorpicker.
Ho analizzato le possibili soluzioni e quella più comoda sarebbe stata incorporare il CSS direttamente nell’head del file comprendendolo tra i due tag <style></style> ma, così facendo avrei generato una query in più ad ogni refresh della pagina.
La conclusione è stata quella di generare/aggiornare un file CSS ogni qual volta venisse salvato nel Database il valore del colorpicker:

<?php
function kldg_make_stylesheet( $url, $file_name, $output_name ) {
    ob_start(); // Attivo il buffering output
    require($url . $file_name); // Genera il CSS
    $css = ob_get_clean(); // Ottieni il CSS dal buffer
    file_put_contents($url . $output_name, $css, LOCK_EX); // Salva il CSS
}

// chiamo la funzione passando i parametri del file che voglio generare
kldg_make_stylesheet('css/', 'stylesheet.php', 'style.css');

Il file ‘css/stylesheet.php’ poi potrà contenere un codice di questo tipo:

<?php header("Content-type: text/css");  $main_color = '#f00';  ?>
body {
background-color: <?php echo $main_color ?>;
}

Object-fit: ridimensionare le immagini ma mantenendo l’aspect ratio in CSS

Svariate volte mi sono chiesto come emulare il comportamento di background-size: cover; ma con un’immagine semplice e non con uno sfondo; Esistono a tal proposito vari work-around che possono venirci in soccorso ma una soluzione semplice e concisa sarebbe l’ideale.

Ecco che ci arriva in soccorso object-fit:

img {
    height: 200px;
    width: 200px;
    object-fit: cover;
}

Con queste poche linee di codice anche se avessimo un’immagine con delle proporzioni diverse, l’aspetto verrà mantenuto ma l’immagine verrà automaticamente tagliata e riempirà le dimensioni che gli abbiamo assegnato, esattamente come succede negli sfondi assegnando la proprietà background-size: cover.

A object-fit è possibile assegnare anche altri valori oltre a cover tra cui contain (che mostra tutta l’immagine con le proporzioni esatte) e fill (che al contrario stretcha l’immagine fino a riempire totalmente le dimensioni che abbiamo assegnato).

Il supporto di object-fit non è però eccezionale:
Chrome e Opera lo supportano ormai da tempo, firefox dalla versione 36, Android Browser solo dalla versione 4.4.4 ed IOS Safari lo supporta parzialmente dalla versione 7.1 in poi.

Ovviamente Internet Explorer non ci delude mai (ironico) non avendo nessun tipo di support nemmeno nella versione 11.

Assegnare una variabile costante ad una funzione in Javascript

Spesso mi è capitato di dover dichiarare un valore da utilizzare successivamente all’interno di una funzione, potrebbe poi esserci la necessità che tale valore possa essere utilizzato nuovamente nel momento in cui la funzione venga chiamata più volte.

Pensiamo ad esempio ad una funzione che fa da contatore e restituisce un ID differente ogni volta che viene chiamata, certo potremmo dichiarare una variabile globale ma ciò sicuramente “inquinerebbe” il namespace inutilmente.
Possiamo però dichiarare delle proprietà personalizzate della funzione:

contatore.id = 0;
function contatore() {
    return contatore.id++;
}

contatore(); // restituisce 0
contatore(); // restituisce 1
contatore(); // restituisce 2 .... ecc