Sito web Multilingua con Switch e link concatenanti

Jonn

Utente Attivo
29 Dic 2012
352
3
18
Pistoia
Salve a tutti,
sto lavorando ad un sito multilingua, solo che non voglio utilizzare CMS già pronti quindi mi sto dilettando nella gestione delle variabili (diciamo così) con PHP (versione 5.3 che ho nel server)

ho fatto un lavoro di questo tipo finora:
ho creato tutta la struttura estetica, ho inserito poi nel content uno switch che prende la variabile (lang) dai link della lingua (immagini con link)
e fa il confronto con uno switch per l'output:

Links per la scelta della lingua (che è una position statica che si trova in tutte le pagine):
HTML:
<a href="?lang=Italiano"><img style="border:1px solid black;" src="immagini/bandierine/Italian.gif" alt="Italiano" /></a>
<a href="?lang=Russian"><img style="border:1px solid black;" src="immagini/bandierine/Russian.gif" alt="Russian" /></a>
<a href="?lang=Deutsch"><img style="border:1px solid black;" src="immagini/bandierine/Deutsch.gif" alt="Deutsch" /></a>
<a href="?lang=English"><img style="border:1px solid black;" src="immagini/bandierine/English.gif" alt="English" /></a>

Quando viene cliccato uno dei link, tramite il GET e SWITCH in PHP richiamati da 2 positions, cambia sia il menu che il content e vengono richiamati entrambi quindi nella lingua richiesta:

1° il modulo navleft:
PHP:
<?php	if (isset($_GET['lang'])) 
						{
							switch($_GET['lang'])
							{
							case "Italiano"         : include('navleft_1_menu_ita.php');break;
							case "English"          : include('navleft_1_menu_eng.php');break;
							case "Deutsch"          : include('navleft_1_menu_deu.php');break;
							case "Russian"          : include('navleft_1_menu_rus.php');break;
							}
						}
						else{include('navleft_1_menu_ita.php');}
				?>

2° la position content (che sarebbe il corpo pagina):
PHP:
<?php
	if (isset($_GET['lang']))
						{
							switch($_GET['lang'])
							{
							case "Italiano"         : include('switch_content_ita.php');break;
							case "English"          : include('switch_content_eng.php');break;
							case "Deutsch"          : include('switch_content_deu.php');break;
							case "Russian"          : include('switch_content_rus.php');break;
							}
						}
						else{include('homepage_ita.php');}
				?>

E fino a qui ci siamo...
Ora analizziamo un secondo il codice del menu che viene richiamato in navleft (ne inserisco uno solo tanto l'unica cosa che cambia rispetto agli altri è la dicitura "ita", "eng", "deu" e "rus":
HTML:
<div class="navleft_mod">
	<div class="navleft_mod_head"><b>Menu Italiano</b></div>
	<div class="navleft_mod_body"><i>
		  <a href="?lang=Italiano&amp;pagina=about_ita"><img src="immagini/moduli/list_menu.png" alt="" /> Home</a>
		<br /><a href="?pagina=nome"><img src="immagini/moduli/list_menu.png" alt="" /> Servizi</a>
		<br /><a href="?pagina=nome"><img src="immagini/moduli/list_menu.png" alt="" /> Men&ugrave;</a>
		<br /><a href="?pagina=nome"><img src="immagini/moduli/list_menu.png" alt="" /> Galleria Fotografica</a>
		<br /><a href="?pagina=nome"><img src="immagini/moduli/list_menu.png" alt="" /> Eventi e Aggiornamenti</a>
		<br /><a href="?pagina=nome"><img src="immagini/moduli/list_menu.png" alt="" /> Dove Siamo</a>
		<br /><a href="?pagina=nome"><img src="immagini/moduli/list_menu.png" alt="" /> Contattaci</a></i>
	</div>
</div>

Ho scritto solo il primo link perchè tanto poi risolto quello, risolvo tutti gli altri di conseguenza.
Come si può vedere nel link ho dichiarato un'altra variabile che viene switchata dal menu.
Il problema è che se io non dichiaro nel link che la variabile lang è settata su Italiano, quest'ultimo (il link) mi rimanda direttamente alla pagina iniziale come se entrambe le variabili (lang e pagina) non fossero settate.
Settando invece la variabile nel link, il tutto funziona alla perfezione e teoricamente il mio sistema multilingua è già funzionante, volevo sapere più che altro se secondo voi questa può essere una soluzione valida oppure no.
Questo perchè non so bene come gestire le variabili, l'idea che avevo in mente era, che di default il sito si apre in italiano (e funziona) poi però quando viene scelta una lingua, viene settata una variabile (lang) che rimane sempre quella, e le pagine fanno riferimento a questa variabile senza doverla sempre dichiarare in tutti i link, fino a che non viene scelta un'altra lingua.
Spero di essere stato chiaro e preciso, grazie in anticipo a tutti.
 

alessandro1997

Utente Attivo
6 Ott 2009
5.302
1
0
26
Roma
alessandro1997.netsons.org
Secondo me è sbagliato il tuo approccio al problema. Invece di includere file diversi per ogni lingua, dovresti semplicemente includere traduzioni diverse. Altrimenti ogni volta che cambi qualcosa nel sito devi cambiarlo per ogni traduzione, e PHP diventa fondamentalmente inutile.

Ti posto una classe che ho creato qualche tempo fa per un sito Web piuttosto semplice:
PHP:
<?php

class I18n
{ 
    /**
     * @var string Path alle lingue
     */
    protected $languagesPath = null;

    /**
     * @var array|null Lingue disponibili
     */
    protected $availableLanguages = null;

    /**
     * @var string Lingua dell'utente
     */
    protected $language = null;

    /**
     * @var array Traduzioni delle lingue
     */
    protected $translations = array();

    /**
     * Crea una nuova istanza della classe.
     *
     * @param string $languagesPath   Path alle lingue
     * 
     * @return I18n
     *
     * @throws \InvalidArgumentException Se il path alle lingue non esiste
     */
    public function __construct($languagesPath)
    {
        if (!is_dir($languagesPath)) {
            throw new \InvalidArgumentException(sprintf(
                'Impossibile trovare le lingue in "%s"',
                $languagesPath
            ));
        }

        $this->languagesPath   = $languagesPath;

        $this->getAvailableLanguages();
    }

    /**
     * Restituisce il path alle lingue.
     *
     * @return string
     */
    public function getLanguagesPath()
    {
        return $this->languagesPath;
    }

    /**
     * Restituisce le lingue disponibili.
     *
     * @param boolean $forceReload Ricaricare tutti i file?
     *
     * @return array
     */
    public function getAvailableLanguages($forceReload = false)
    {
        if (null === $this->availableLanguages || $forceReload) {
            foreach (glob("{$this->languagesPath}/*.php") as $file) {
                $this->availableLanguages[] = basename($file, '.php');
            }
        }

        return $this->availableLanguages;
    }

    /**
     * Determina se la lingua specificata è disponibile.
     *
     * @param string $language Lingua
     *
     * @return boolean
     */
    public function isLanguageAvailable($language)
    {
        return in_array($language, $this->getAvailableLanguages(), true);
    }

    /**
     * Imposta la lingua attuale.
     *
     * @param string $language Lingua
     *
     * @throws \InvalidArgumentException Se la lingua non esiste
     */
    public function setLanguage($language)
    {
        try {
            $this->checkLanguage($language);
        } catch (\InvalidArgumentException $e) {
            throw $e;
        }

        $this->language = $language;
    }

    /**
     * Restituisce la lingua dell'utente.
     * 
     * @return string
     */
    public function getLanguage()
    {
        return $this->language;
    }

    /**
     * Traduce la chiave specificata.
     *
     * @param string      $key      Chiave di traduzione
     * @param array       $params   Parametri
     * @param string|null $language Lingua (quella dell'utente di default)
     *
     * @return string Traduzione
     *
     * @throws \InvalidArgumentException Se la traduzione non esiste
     */
    public function translate($key, $params = array(), $language = null)
    {
        $language = (null !== $language) ? $language : $this->language;

        try {
            $this->checkLanguage($language);
        } catch (\InvalidArgumentException $e) {
            throw $e;
        }

        $this->loadLanguage($language);

        if (!isset($this->translations[$key])) {
            throw new \InvalidArgumentException(sprintf(
                'Impossibile trovare la traduzione "%s" per la lingua "%s"',
                $key,
                $language
            ));
        }

        $translation = $this->translations[$key];

        foreach ($params as $key => $value) {
            $translation = str_replace($translation, "%{{$key}}", $value);
        }

        return $translation;
    }

    /**
     * Carica la lingua specificata.
     *
     * @param string  $language    Lingua
     * @param boolean $forceReload Ricaricare i file?
     *
     * @return array Chiavi di traduzione
     *
     * @throws \InvalidArgumentException Se la lingua non è disponibile
     */
    public function loadLanguage($language, $forceReload = false)
    {
        try {
            $this->checkLanguage($language);
        } catch (\InvalidArgumentException $e) {
            throw $e;
        }

        if (!isset($this->translations[$language]) || $forceReload) {
            $this->translations[$language] = require "{$this->languagesPath}/{$language}.php";
        }

        return $this->translations[$language];
    }

    /**
     * Testa la validità della lingua.
     *
     * @param string $language Lingua
     *
     * @throws \InvalidArgumentException Se la lingua non è disponibile
     */
    protected function checkLanguage($language)
    {
        if (!$this->isLanguageAvailable($language)) {
            throw new \InvalidArgumentException(sprintf(
                'La lingua "%s" non è valida (disponibili: %s)',
                $language,
                implode(', ', $this->getAvailableLanguages())
            ));
        }
    }
}
Considera che in questo momento non posso testarla perché non sviluppo in PHP da un po' e ho cambiato alcune cose, quindi assicurati che funzioni.

È da usare in questo modo: crea una cartella languages in cui metterai i file di lingua in questo formato:
PHP:
<?php
return array(
    'key' => 'ciao',
    'key_2' => 'traduzione con %{param}',
    // ...
);

E nella tua index.php istanzia la classe così:
PHP:
<?php

require_once 'I18n.php';

// helper per le traduzioni
function t($key, $params = array(), $language = null)
{
    // evitare le variabili globali in generale: qui semplificano molto le cose,
    // quindi sono un male necessario
    global $i18n;

    return $i18n->t($key, $params, $language);
}

$i18n = new I18n(__DIR__ . '/languages');

// imposta eventualmente una lingua di default
if (!isset($_COOKIE['language'])) {
    $language = 'it';
}

if (isset($_GET['language'])) { // se l'utente vuole cambiare lingua...
    // ...imposta la nuova lingua
    $language = $_GET['language'];
} elseif (isset($_COOKIE['lanugage'])) { // se l'utente ha già una lingua...
    // ...usa la lingua preferita
    $language = $_COOKIE['language'];
} else { // se è la prima visita (o il cookie è scaduto)...
    // ...usa la lingua di default
    $language = 'it';
}

try {
    // prova a impostare la lingua dell'utente
    $i18n->setLanguage($language);
} catch (\InvalidArgumentException $e) {
    // se non esiste (tentativo di manomissione?) imposta quella di default
    $i18n->setLanguage('it');
}

// a ogni richiesta reimposta il cookie per un anno
setcookie('language', $i18n->getLanguage(), time() + 31536000);

Adesso puoi scrivere le traduzioni in questo modo:
PHP:
<?php
echo t('key'); // ciao
echo t('key_2', array('param' => 'parametri')); // traduzione con parametri

Direi che non è male, no? :)
 
Ultima modifica:

Jonn

Utente Attivo
29 Dic 2012
352
3
18
Pistoia
Bene,
diciamo che hai abbattuto il mio castellino di carte con un bazooka!
Comunque la tua soluzione mi sembra molto professionale, mi sono messo a studiarla per capire bene come funzioni visto che ho molte poche nozioni di PHP.
Considero comunque il 3D risolto!
Grazie mille Alessandro ;)
 

Jonn

Utente Attivo
29 Dic 2012
352
3
18
Pistoia
Ti dirò, il fatto è che la tua soluzione mi sembra più che soddisfacente perchè ho capito a grandi linee come funziona.
solo che secondo me una soluzione più semplice esiste, più che altro perchè è un sito completamente statico quindi gli eventuali cambiamenti li apporto io.
La tua soluzione me la studio comunque, ma pensavo a come dichiarare una variabile vuota ($lang), poi tramite il get questa variabile assume un valore (passato dai links, per esempio il valore 'English') che rimane sempre memorizzato durante la navigazione nel menu fino a quando viene selezionato un altro link che cambia il valore (da English per esempio a Italiano) e così via.
Però ecco, con le poche nozioni che ho in php è come se mi avessi scaricato addosso la Treccani 2013 da studiare per un sito che non ha pretese particolari. XD
 

Nefyt

Utente Attivo
17 Apr 2012
1.102
0
0
Mi pare ottimale la soluzione di alessandro ma un po troppo complessa per piccoli/medi progetti secondo me. Io di solito uso un approccio col json per il multilingua, mettendo la traduzione in unico file sotto diverse chiavi, del tipo
Codice:
{
    "ita": {
      //etc...
    },
    "eng": {
      //etc...
    },
    "fr": {
      //etc....
    }
//etc...
}
In questo modo posso avere anche un accesso diretto da js senza risposta dal php
es.
Codice:
//lang sarà una variabile js che prende il valore dal document.cookie o viene settata prima dal php
$.getJSON('lang.json').done(function(data){ alert(data[lang].key); });

E da php ovviamente verrà gestito come array con json_decode

Pro:
Hai un solo file da gestire e puoi utilizzarlo anche senza php
Contro:
Se si hanno molte chiavi puo diventare un po pesante, in questo caso è meglio un metodo con file singoli

Infine 2 considerazioni sulla classe di alessandro:
Secondo me era meglio se facevi le funzioni statiche per evitare nuove istanze e global
Per i parametri nelle traduzioni avrei usato vsprintf()
 

alessandro1997

Utente Attivo
6 Ott 2009
5.302
1
0
26
Roma
alessandro1997.netsons.org
Interessante la soluzione con JSON soprattutto perché permette di accedere alle traduzioni tramite Javascript. Non ne ho mai avuto bisogno quindi non mi sono mai posto il problema.

A rendere i metodi statici avevo pensato, ma non mi sembrava corretto sotto un punto di vista architetturale. Per di più l'uso della funzione helper t() permette di centralizzare il processo di traduzione. In questo modo è semplice modificare la logica dell'applicazione ed eliminare la variabile globale. Diciamo che in un'applicazione professionale l'approccio migliore è l'iniezione delle dipendenze.

Interessante la funzione vsprintf(), non la conoscevo proprio. Del resto ormai è tardi: ho smesso di sviluppare in PHP da un po'. :)
 
Discussioni simili
Autore Titolo Forum Risposte Data
R Aiuto ripristino sito web Presentati al Forum 0
A Vendo sito web news economia, finanza, immobiliare online da pochi mesi Compravendita siti e domini 0
M Vendo il mio sito web teknosurfng.com, che trasmette nel campo della tecnologia Compravendita siti e domini 0
M [cerco webmaster] sito web da modificare Offerte e Richieste di Lavoro e/o Collaborazione 0
F Animazione testo sito web diminuire grandezza di un testo allo scroll Javascript 0
N Vendo sito web di casino online con 1000 giochi Compravendita siti e domini 0
A Web master per semplice sito web Offerte e Richieste di Lavoro e/o Collaborazione 2
N Creazione sito web senza Partita IVA (Era: mettersi in regola) Leggi, Normative e Fisco 1
A [Cerco][Retribuito] Correzioni errori sito web Offerte e Richieste di Lavoro e/o Collaborazione 3
N Consigli SEO per il mio sito di web design SEO e Posizionamento 0
A Consiglio per creazione sito web CMS (Content Management System) 1
Tommy03 App mobile+ sito web con lo stesso database Sviluppo app per Android 4
A Progetto Sito web responsive HTML e CSS 2
S Problemi di visualizzazione form contatti sito web HTML e CSS 2
Web93 CREARE SITO WEB COMICS CON WORDPRESS WordPress 0
M [VENDO]Sito web su misura e richiesta Compravendita siti e domini 0
A Cornici immagini per sito Web Wordpress WordPress 1
felino [Wordpress] Sito web con codice malevolo WordPress 7
O IP Cam in streaming su sito web IP Cam e Videosorveglianza 2
Web93 RICHIESTA CONSIGLIO - FARE UN SITO WEB CMS (Content Management System) 1
Web93 PROBLEMA SITO WEB WORDPRESS - LOGIN DASHBOARD Programmazione 3
A Mantenere la validazione reindirizzandoci su un secondo sito WEb. (ASP.NET) ASP.NET 0
A [HTML] Creare sito web per eLearnig HTML e CSS 2
C [Vendo] Spazio Web su sito informatico e tech Vendere e Acquistare pubblicita' online 0
C [WordPress] Retribuzione creazione Sito Web vetrina Discussioni Varie 3
Domenico_Falco1 Rendere dinamico un sito web con chiamate ajax e php e variabili json PHP 12
C [Vendo] Sito web video animali e divertenti Compravendita siti e domini 0
M Web server domestico per sito con 50 accessi contemporanei, potenza necessaria? Hardware 0
C [ OFFRO ] Realizzazione Sito Web Responsive design e Ottimizzato Offerte e Richieste di Lavoro e/o Collaborazione 1
svtmaster professionalità per gestire sito web Offerte e Richieste di Lavoro e/o Collaborazione 4
F Shop Account facebook / instagram / Visite reali sul sito web e molto altro! Annunci servizi di Social Media Marketing 0
A Problema sito web - Joomla Presentati al Forum 1
P Cerco per sito web Offerte e Richieste di Lavoro e/o Collaborazione 2
G VENDO sito web di notizie Compravendita siti e domini 0
G [HTML] mettere link in facebook link invece che su sito web Social Media Marketing 1
M [VENDO] Sito web consolidato da anni Compravendita siti e domini 0
S Pubblicizzare sito web SEO e Posizionamento 3
Federico.Marcelo Il mio sito web - Instagram Automation Tools Presenta il tuo Sito 2
L anonimato in un sito web Leggi, Normative e Fisco 8
W Vendo Visite al sito web ITALIANE a 1 euro ogni 1000 Vendere e Acquistare pubblicita' online 4
A Ricerca con collegamento in altro sito web Discussioni Varie 0
P [HTML] Problema con menu orizzontale a tendina per sito web HTML e CSS 17
Store creazione barra search sito web Presentati al Forum 3
M [WordPress] [HTML] INTEGRARE GESTIONALE IMMOBILIARE SU UN SITO WEB DA FARE WordPress 0
S vendo sito web ben avviato Compravendita siti e domini 1
I VENDO italian-apartment SITO WEB DI ANNUNCI PER VENDERE IMMOBILI ALL'ESTERO. Compravendita siti e domini 2
S [PHP] estrarre dati sito web protetto con username e password PHP 13
C [WordPress] Creare e gestire un nuovo sito web WordPress 5
M Cerco socio sviluppatore sito web Offerte e Richieste di Lavoro e/o Collaborazione 0
S [cerco] persona per SEO, posizionamento sito web Offerte e Richieste di Lavoro e/o Collaborazione 4

Discussioni simili