Displaying articles with tag

Classi senza Burocrazia

Posted by Chiaroscuro, Mon Nov 05 01:51:00 UTC 2007

Prendiamo un caso base e procediamo ad astrarlo un passo alla volta. Partiamo con una classe Cat, il mio animale preferito. Come è noto un gatto può essere univocamente e universalmente identificato in base a nome, sesso e colore:

1
2
3
4
5
6
7
  class Cat
    attr_reader :name, :gender, :colour

    def initialize name, gender, colour
      @name, @gender, @colour = name, gender, colour
    end
  end    

Perdonatemi l’idioma per l’assegnamento degli attributi di classe, ma è molto rapido da utilizzare con il copy and paste.

Il primo passo consisterà nel sostituire initialize con qualcosa di più conciso e immediato. Idealmente vorremmo poter usare questo comando nel corpo della classe per poter inizializzare gli attributi:


  init_with :name, :gender, :colour

Il lettore più attento mi dirà che a questo scopo esiste già Struct che mi permette di scrivere concisamente:


  Cat = Struct.new :name, :gender, :colour

E’ vero, Struct è molto utile e rapido, ma presenta anche alcuni problemi. Il problema principale per me consisteva nella difficoltà di trovare al volo classi definite con Struct all’interno del codice. L’occhio è abituato a cercare una struttura di classe, con un certo tipo di indentazione e syntax-colouring e una classe definita con Struct tende a sfuggire e a confondersi con il resto del codice. Un altro problema, a volte molto fastidioso, è che Struct non rappresenta le sue proprietà come attributi di classi, quelli con la chiocciolina per intenderci, ma probabilmente con una hash table. Questo spesso confonde le nostre aspettative su certe operazioni possibili.

Affrontiamo ora il problema di definire init_with. Questo metodo, per poter essere disponibile nel corpo di una qualunque classe, deve essere definito come metodo di classe in Object, oppure nella classe Module, che lo rende disponibile a tutte le classi e tutti i moduli. Riapriamo la classe Module e definiamo un metodo che prende un numero variabile di argomenti:

1
2
3
4
5
6
class Module

    def init_with *args
    end
    
end

Il metodo init_with dovrà generare un costruttore initialize nel contesto della classe che invoca init_with:

1
2
3
4
5
6
7
8
9
10
  def init_with *args
    args_list = args.map {|e| e.to_s }
    attributes_list = args_list.map {|e| '@'+e }
        
    class_eval %{
      def initialize #{args_list.join ','}
        #{attributes_list.join ','} = #{args_list.join ','}
      end
    }
  end    

Innanzitutto generiamo una lista di attributi espressi come stringhe anzichè come simboli:


  args_list = args.map {|e| e.to_s }

Poi decoriamo ogni attributo con una chiocciolina:


  attributes_list = args_list.map {|e| '@'+e }

Infine valutiamo nel contesto della classe chiamante un template di initialize:

1
2
3
4
5
  class_eval %{
    def initialize #{args_list.join ','}
      #{attributes_list.join ','} = #{args_list.join ','}
    end
  }

E questo è quanto. Ora possiamo definire il nostro gatto con un semplice:

1
2
3
4
  class Cat
    attr_reader :name, :gender, :colour
    init_with   :name, :gender, :colour
  end    

mmmhh.. ancora troppe ripetizioni? Facciamo un ultimo sforzo:

1
2
3
4
5
6
7
8
9
10
11
  class Module
    def init_with_readers *args
      sym_list = args.map {|e| ":#{e}" }
      sym_list_string = sym_list.join ', '
        
      class_eval %{
        attr_reader #{sym_list_string} 
        init_with #{sym_list_string}
      }
    end    
  end

Questo codice genera sia i reader che il costruttore in un unico passo. Notate che abbiamo anche riutilizzato init_with senza dover ripetere il codice di generazione per il costruttore.

Il nostro gatto in ultima istanza può ora essere definito come:

1
2
3
  class Cat
    init_with_readers :name, :gender, :colour
  end    

Ruby non è fatto per essere lasciato in pace. Quando scorgete una opportunità per rendere il codice più chiaro e rimuovere ripetizioni, mettete mano alla metaprogrammazione!

12 comments | Filed Under: Filosofia Linguaggio Metodologia | Tags:

Javascript Non Intrusivo nelle Tue Applicazioni Rails

Posted by federico, Tue Nov 21 18:19:00 UTC 2006

Non intrusivo in che senso?

Niente paura! Ve lo spiego subito! In poche parole, questa tecnica si basa sulla stratificazione delle funzionalità dinamiche dell’applicazione in layer funzionali che vengono poi attivati a runtime in base alle funzionalità ablitate sul browser. Cosa? Troppo complesso? Vediamo un esempio, che vale più di mille parole.

Supponiamo di voler costruire una semplice applicazione per gestire una rubrica di nominativi che ci permetta di inserire ed eliminare elementi dalla lista di nomi senza dover ricaricare la pagina ad ogni inserimento.

Vediamo un classico esempio di applicazione AJAX facilmente implementabile in Rails tramite le funzioni della famiglia remote. Per esempio il link Delete potrebbe essere implementato in questo modo:


<%= link_to_remote Delete Article', :url => { :controller => ‘article', :action => delete' } %>

Semplicissimo vero? Vediamo cosa viene prodotto da questo codice nella pagina finale:

1
2
3
<a href="#" onclick="new Ajax.Request('/article/delete', 
{ asynchronous: true, evalScripts: true }); 
return false;">Delete Article</a>

Non propriamente quello che si potrebbe definire del codice pulito…

Il punto è che questa funzionalità viene implementata inserendo del codice javascript all’interno stesso dei tag HTML andando a sporcare notevolmente la struttura della pagina e replicando inutilmente il codice (pensiamo a cosa succederebbe se avessimo un link Delete per ogni elemento della lista).

L’approccio non intrusivo consiste nello sfruttare la capacità di uno script Javascript di poter modificare la struttura della pagina e di poter essere eseguito automaticamente al caricamento della stessa.

In poche parole, non appena la pagina sarà completamente caricata, questo script provvederà a modificare automaticamente le parti della pagina che diventeranno dinamiche, il tutto in modo trasparente e solamente se il motore Javascript non è stato disabilitato dall’utente.

Ecco il risultato dell’esempio precedente implementato tramite questa tecnica:


<a href="/article/delete" id="delete_link">Delete Article</a>
1
2
3
4
document.GetElementById('delete_link').onclick = function() { 
new Ajax.Request('/article/delete', { asynchronous: true, evalScripts: true }); 
return false; 
}

Questo ci permetterà di avere una pagina estremamente pulita e priva di codice Javascript all’interno dei tag, facendo contenti i vecchi browser e garantendoci la massima compatibilità con i possibili client.

Vi presento UJS Rails Plugin

UJS (Unobtrusive Javascript) è un plugin creato da Luke Redpath e Dan Webb che permette di utilizzare la tecnica del Javascript non intrusivo in modo facile ed efficiente.

Vediamo come l’esempio precedente può essere implementato tramite le funzionalità introdotte dal plugin UJS:


apply_behaviour '#delete_link', make_remote_link()

Quelli di voi che conoscono i CSS si saranno insospettiti vedendo un tipico selector come primo parametro. In effetti è proprio così, tramite apply_behaviour è possibile usare tutta la potenza dei selector CSS per selezionare gli elementi della pagina da modificare.

E le sorprese non finiscono qui. Un’altra caratteristica molto potente è quella di poter descrivere i behaviour degli elementi sia con codice Javascript che tramite codice RJS (una particolare sintassi Ruby che viene convertita in Javascript a runtime).

Vediamo qualche esempio:


apply_behaviour 'a:click', 'alert("You clicked me!")'

Chi è stato attento avrà già intuito il risultato di questo comando, tutti i link contenuti nella pagina verranno modificati per lanciare un alert non appena l’utente cliccherà su di essi. Pensate a come avreste potuto implementare una funzionalità simile senza l’uso dei behaviour..

Vediamo ora un esempio che utilizza del codice RJS:

1
2
3
4
apply_behaviour '.list_item:dblclick' do |page, element, event|
  element.replace_html "Deleted." 
  event.stop
end

Tramite questo codice andremo a modificare il comportamento degli elementi di classe list_item in caso di doppio click. All’interno dello script RJS siamo in grado di modificare l’intera pagina (tramite l’oggetto page) o agire sul singolo elemento (element) o l’evento generato (event). Nello specifico lo script andrà a sostituire l’elemento cliccato con la stringa Deleted ed inibirà il comportamento di default del browser tramite event.stop.

Il plugin ci mette inoltre a disposizione dei Behaviour Helper, un insieme di funzioni predefinite che riproducono la maggior parte degli helper di Rails.

Abbiamo già visto make_remote_link() il cui comportamento replica quello di link_to_remote() a differenza del fatto che l’URL dell’action da eseguire viene specificata direttamente nell’attributo HREF all’interno del link HTML.

Similmente a make_remote_link() viene definito anche make_remote_form() che mima il metodo remote_form() di Rails.

Molto interessanti sono inoltre gli helper che implementano le funzionalità di drag&drop, vediamone un esempio:

1
2
3
4
apply_behaviours {
  on 'div.product', make_draggable( :revert => true )
  on '#shopping_basket', make_drop_receiving ( :url => { :action => 'add' } )
}

Tramite la funzione make_draggable() ogni blocco <div> appartenente alla classe product verrà reso trascinabile (draggable), mentre l’elemento con ID shopping_basket sarà in grado di accogliere i prodotti chiamando una specifica action.

Concludendo

In questo breve articolo ho introdotto la tecnica del Javascript non intrusivo che, oltre ad essere un modo per mantenere la compatibilità con tutti i browser presenti nel mercato, ci permette anche di introdurre elementi dinamici nel nostro codice senza per questo rinunciare all’efficienza ed alla pulizia dello stesso.

Questa è a mio avviso una delle tecniche di progettazione delle applicazioni web a cui non può rinunciare chiunque voglia creare prodotti di qualità.

L’autore

Federico Feroldi si occupa di sviluppo e analisi di applicazioni web per la gestione e la pubblicazione di informazioni personalizzate su larga scala. Attualmente è lead engineer presso una delle più importanti multinazionali operanti nel settore internet.

Link

10 comments | Filed Under: Plugin Rails Tutorial | Tags:

La Gioia del Delegare

Posted by Chiaroscuro, Sat Oct 21 23:30:06 UTC 2006

Se anche voi siete come me, il vecchio libro PikeAxe dei pragmatic programmers che trovate online, rimane la vostra principale reference guide quando volete sapere quali metodi ha una classe o quali classi sono disponibili.

Utilissimo libro, però non copre tutto.. e questo l’ho scoperto frugando tra le lib nella directory di installazione di Ruby.

Tra i vari rubini che ho trovato in quelle directory, forwardable è uno di quelli che più mi ha colpito per la sua utilità.

Mettete che avete bisogno di rappresentare un’entità che agisce come contenitore per altre entità. Perchè no, abbozziamo una classe Cassetto!

1
2
3
4
5
6
7
8
9
10
  class Cassetto
      
  end
  
  cassetto_dell_armadio = Cassetto.new
  cassetto_dell_armadio << "calzini"
  cassetto_dell_armadio << "maglietta"
  cassetto_dell_armadio << "maglietta"
  
  puts cassetto_dell_armadio

Per ora abbiamo solamente descritto il comportamento della classe, senza specificarne la struttura interna. Notiamo immediatamente che il nostro Cassetto condivide molte caratteristiche della classe Array. Vogliamo poter usare l’operatore << per inserire magliette e calzine e forse più avanti, quando faremo le valige vorremmo anche essere in grado di svuotare i nostri cassetti in una valigia


  valigia = cassetto_dell_armadio + cassetto_del_comodino

La tentazione è forte.. lo so che è sbagliato, so che Fowler e Booch piangerebbero a vederlo ma.. eccolo qui:

1
2
  class Cassetto < Array
  end

Il cassetto è un Array! Fatto! Finito!

Me ne volete veramente quando l’alternativa sarebbe stata crare un Array dentro Cassetto e poi delegare tutti i metodi che mi servivano, dolorosamente, uno per uno?

Si lo so, purezza del modello di dominio e tutto quanto, ma anche questo codice è doloroso per gli occhi e straripante di ripetizioni che supplicano di essere estratte

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  class Cassetto 
    def initialize
      @vestiti = []
    end      
  
    def << vestito
       @vestiti << vestito 
    end

    def [] i
      @vestiti[i]
    end

    def first
      @vestiti.first
    end

    ...
    ...

    def to_s
       @vestiti.join "\n" 
    end
  end 

In fondo quando dico

1
2
3
   def << vestito
    @vestiti << vestito 
  end

non sto forse dicendo “delega il metodo << al campo @vestiti” ?

E quando dico

1
2
3
  def first
    @vestiti.first
  end

non sto forse dicendo “delega il metodo first al campo @vestiti” ?

Quindi forse, quello di cui abbiamo bisogno è un modo sintetico per esprimere proprio questo concetto di delega, evitando così anche la sporca di ereditare direttamente da Array.

Bene, in ruby possiamo utilizzare direttamente forwardable.rb che ci mette a disposizione def_delegators

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  class Cassetto
    extend Forwardable      
    
    def_delegators :@vestiti, :<<, :[], :first, :to_s
    
    def initialize
      @vestiti = []
    end      

    def to_s
       @vestiti.join "\n" 
    end
  end

  cassetto_dell_armadio = Cassetto.new
  cassetto_dell_armadio << "calzini"
  cassetto_dell_armadio << "maglietta"
  cassetto_dell_armadio << "maglietta"
  
  puts cassetto_dell_armadio
  puts cassetto_dell_armadio[1]
  puts cassetto_dell_armadio.first

Vediamo che estendendo Fordable e usando def_delegators, possiamo dirottare una serie di metodi (<< [] first to_s) su una attributo di classe, che corrisponde all’array contenitore.

Se dovessimo decidere di non mappare i nomi dei metodi uno a uno tra Cassetto e Array posssiamo usare def_delegator, al singolare, aggiungendo:


  def_delegator :@vestiti, :size, :numero_vestiti

e potendo quindi invocare:


 puts cassetto_dell_armadio.numero_vestiti

Niente gemme, niente librerie aggiuntive, questo è tutto caro semplice vecchio Ruby!

0 comments | Filed Under: Linguaggio | Tags:

Il Mondo on Rails - Introduzione a Globalize

Posted by gianluca, Mon Oct 16 01:04:00 UTC 2006

La soluzione adottata

Di fatto Rails non fornisce un supporto nativo al multilingua, ma si appoggia all’ottimo plugin Globalize rilasciato da Josh Harvey sotto la licenza MIT (la stessa sotto la quale è rilasciato Rails).

Esso supporta la traduzione in più lingue sia dei dati presenti nei database, che delle informazioni legate ai controller e ai model, ed inoltre permette la localizzazione del tempo, delle date e dei numeri. Per rendere il tutto più interessante, dimostreremo come tutto ciò possa funzionare costruendo un’applicazione di esempio, che pur non avendo un vero scopo preciso, ci aiuterà a vedere in opera le funzionalità offerte da Globalize.

Perché costruire un’applicazione multilingua

Se qualcuno di voi non fosse ancora convinto dell’utilità portata dall’utilizzo della globalizzazione all’interno della nostra applicazione, elenchiamo alcuni dei problemi più importanti che essa ci permette di risolvere.

  • Formato data ed ora. Una data che in Italia potrebbe essere presentata nel formato 10 Giugno 2005, negli Stati Uniti potrebbe essere presentata nel formato 2005, June 10.
  • Formato valuta. Una valuta che in Italia potrebbe essere presentata nel formato 10.000,25 €, negli Stati Uniti potrebbe essere presentata nel formato 10,000.25 $, in cui cambiano l’ordine dei punti e delle virgole, oltre che al simbolo della valuta.
  • Direzione del testo. Mentre nei paesi europei siamo abituati a leggere il testo da sinistra a destra, in alcuni paesi asiatici la lettura avviene da destra a sinistra.
  • Immagini e colori. La personalizzazione della nostra applicazione oltre che essere legata ai contenuti di tipo testuali, deve essere vicina anche alla cultura del popolo al quale ci poniamo.
  • Numeri di telefono, codici postali, indirizzi e molto altro ancora!

Iniziamo con qualche richiamo teorico

Prima di vedere come implementare un’applicazione multilingua, introduciamo una serie di concetti che ci serviranno a comprendere meglio di che cosa stiamo parlando e il perché tutto questo venga considerato così importante. Chi pensa di avere già queste conoscenze nel proprio bagaglio, o chi desidera subito analizzare il funzionamento di Globalize può saltare questo paragrafo. Ne consigliamo invece la lettura a chi non ha mai affrontato queste tematiche, in quanto spesso si rischia di fare confusione tra concetti che sono sì simili tra loro, ma che hanno sottili ed importanti differenze.

  • L’ internazionalizzazione, spesso chiamata nella forma abbreviata i18n, consiste nell’adattamento della nostra applicazione affinché essa permetta una gestione multilingua. Chiariamo l’idea considerando l’esempio di un’applicazione di e-commerce, in cui possiamo vedere l’internazionalizzazione come la creazione di un pannello di amministrazione che permetta l’inserimento delle diverse lingue in cui i nostri prodotti verranno proposti.
  • La localizzazione, spesso chiamata nella forma abbreviata L10n, invece consiste nell’adattamento della nostra applicazione ad uno specifico mercato, che noi chiameremo locale. Riprendendo l’esempio dell’applicazione e-commerce, la localizzazione consiste nell’inserimento (attraverso il pannello di amministrazione definito nella fase di internazionalizzazione) delle descrizioni dei prodotti nelle lingue desiderate.
  • La globalizzazione, spesso chiamata nella forma abbreviata g11n, non fa altro che riunire le due nozioni appena esaminate ed è il termine che noi utilizzeremo nel proseguo dell’articolo.
Andiamo in profondità…
Prima di proseguire spieghiamo velocemente il significato dello strano modo in cui sono definiti gli acronimi appena visti. Solitamente le sigle i18n, L10n e g11n (composti da lettere e numeri) non si trovano nel web, dove siamo più abituati a sequenze di lettere, ognuna delle quali è semplicemente l’iniziale di una parola (ad esempio RoR sta proprio per Ruby on Rails). In questo caso invece si è deciso di prendere in considerazione solamente la prima e l’ultima lettera dei tre concetti visti, inserendo nel mezzo il numero delle lettere che compongono la parola in inglese. Eliminiamo eventuali dubbi guardando l’immagine che segue.

Inizio dei giochi! Installiamo Globalize

Dopo aver fatto qualche accenno a livello teorico, eccoci arrivare alla parte più interessante del nostro articolo, cioè quella in cui spiegheremo passo passo come poter implementare la globalizzazione all’interno della nostra applicazione.

Prima di tutto abbiamo bisogno di un’applicazione Rails, in cui sia già stata settata la configurazione del database. Questa risulta una prerogativa necessaria, in quando nel momento in cui installeremo Globalize verranno create automaticamente 3 tabelle, necessarie per la gestione multilingua. Quindi una volta effettuata la configurazione iniziale, potremo aggiornare la nostra applicazione.

1
2
3
4
5
6
7
8
# spostamento all'interno del progetto dictionary 
E:\> cd dictionary

# installazione plugin globalize (necessita connessione ad internet attiva) 
E:\dictionary> ruby script/plugin install http://svn.globalize-rails.org/svn/globalize/globalize/branches/for-1.1

# creazione tabelle per la gestione della globalizzazione
E:\dictionary> rake globalize:setup

A seguito di aggiornamenti del progetto, in alcune situazioni il comando ruby script/plugin install potrebbe non andare a buon fine. In questo caso dovremo procurarci Subversion e digitare i seguenti comandi.

1
2
3
4
5
# spostamento all'interno della directory vendor/plugins
E:\dictionary>cd vendor/plugins

# installazione plugin globalize (necessita connessione ad internet attiva) 
E:\dictionary\vendor\plugins>svn export svn://svn.globalize-rails.org/globalize/branches/for-1.1 globalize

Perché queste nuove tabelle

Se ora andiamo a curiosare all’interno del database dictionary_development (il database utilizzato per la nostra applicazione) troveremo tre nuove tabelle che verranno utilizzate per la gestione del contenuto multilingua della nostra applicazione. Andiamo ad esaminarle per capire a fondo quali siano i loro ruoli.

  • globalize_countries elenca 239 nazioni e per ognuna di esse definisce alcuni valori necessari per la formattazione della valuta, della data e molto altro.
  • globalize_languages elenca 186 linguaggi e per ognuno di essi definisce alcuni valori come la direzione del testo o il nome nativo della lingua (ad esempio nel caso della lingua tedesca, il nome nativo è Deutsch).
  • globalize_translations elenca 3420 stringhe già tradotte e pronte all’uso, ed è su questa tabella che noi apporteremo il maggior numero di modifiche, andando a definire di volta in volta le traduzioni di cui avremo bisogno.

Un primo semplice esempio

Una volta installato il plugin ed analizzate le tabelle su cui esso si basa, il secondo passo consiste nel settare la lingua che verrà utilizzata di default nella nostra applicazione. Siccome si tratta di un articolo dedicato ad un pubblico italiano, non potevamo che settare la lingua ed il locale italiano.

1
2
3
4
5
6
7
# Estratto del file config/environment.rb
...

# Include your application configuration below
include Globalize   # inclusione del plugin Globalize
Locale.set_base_language('it-IT')   # settaggio della lingua di default
Locale.set('it-IT')   # settaggio del locale di default

Prima di procedere con lo sviluppo della nostra applicazione di esempio, ci conviene controllare il corretto funzionamento del plugin Globalize. Per farlo la soluzione più rapida è quella di creare un controller ed un’azione di prova, all’interno della quale scriveremo il codice necessario a stampare una data (Time.now). A questa punto aggiungeremo il metodo localize, il quale gestirà in automatico la formattazione della data.

1
2
3
4
5
6
7
8
# Estratto del file app/controllers/test_controller.rb

class TestController < ApplicationController
  def index
    # stampa della data nel linguaggio di default
    render :text => Time.now.localize("%A %d %B %Y")
  end
end

Dopo aver avviato il web server WEBRick, possiamo andare a vedere il nostro primo risultato digitando sul browser l’indirizzo http://localhost:3000/test. Se tutto andrà a buon fine ciò che otterremo sarà una data scritta in italiano simile a Mercoledì 21 Giugno 2006.

A questo punto la nostra curiosità dovrebbe portarci a vedere che cosa accade nel momento in cui cambiamo il Locale della della nostra applicazione. Proviamo quindi a settare quello inglese e poi andiamo a vedere il risultato ottenuto.

1
2
3
4
5
6
7
8
9
# Estratto del file app/controllers/test_controller.rb

class TestController < ApplicationController
  def index
    # stampa della data nella lingua inglese
    Locale.set('en-US')
    render :text => Time.now.localize("%A %d %B %Y")
  end
end

In questo caso, dopo aver aggiornato la nostra pagina web, il risultato sarà simile a Wednesday 21 June 2006. Non male se pensiamo che le righe di codice scritte fino ad ora non sono nemmeno una decina!

Facciamo qualcosa in più

Arrivati a questo punto abbiamo potuto osservare come il plugin funzioni correttamente, ma vorremmo fare qualcosa in più. Cerchiamo allora di affiancare alla data un breve e semplice messaggio di benvenuto, questa volta utilizzando il metodo t (dove la t sta per translate).

Per rispettare il paradigma MVC (Model View Controller) sposteremo questo nuovo messaggio, e la data che avevamo precedentemente definito, all’interno della vista index.rhtml (la vista associata di default all’azione index). Ricordiamo infatti l’importanza di separare la logica applicativa, che sta nelle azioni, e la logica di presentazione, che sta nelle viste.

1
2
3
4
5
6
7
8
9
# Estratto del file app/controllers/test_controller.rb

class TestController < ApplicationController
  def index
    # settaggio lingua italiana 
    Locale.set('it-IT')
    # rendering automatico della vista index.rhtml
  end
end
1
2
3
4
# Estratto del file app/views/test/index.rhtml

<%= 'Benvenuti'.t %> -
<%= Time.now.localize("%A %d %B %Y") %>

Il risultato in questo caso sarà simile a Benvenuti – Mercoledì 21 Giugno 2006.

Andiamo in profondità…
Prima di proseguire ci soffermeremo un minuto su un particolare che forse ha già attirato la nostra attenzione. Questo particolare consiste nella presenza del metodo Locale.set(‘it-IT’) all’interno dell’azione index. La domanda che dovremmo porci è la seguente: perché settare la lingua italiana se è già quella di default? La risposta è tanto semplice quanto importante, in quanto il caricamento della lingua di default, che ricordiamo essere definita nel file environment.rb, avviene solo in fase di avvio dell’applicazione (cioè all’avvio del web server). Se non settassimo la lingua italiana nell’azione index, la lingua attiva rimarrebbe quella inglese (questo perché in precedenza avevamo settato il locale en-US per vedere la data nella formattazione usata in america).


Ora proseguiamo seguendo i passi già fatti precedentemente per la data, cioè cambiando nell’azione index il locale italiano con quello americano en-US. Il risultato ottenuto sarà Benvenuti – Wednesday 21 June 2006. A prima vista sembra che qualcosa non funzioni, in quanto ci aspettavamo il messaggio Welcome – Wednesday 21 June 2006.

Il risultato ottenuto in realtà è corretto (non vi è alcun problema con Globalize); siamo noi che dobbiamo dare maggiori informazioni al plugin. Esso infatti per riuscire a tradurre la parola benvenuto deve cercare tale informazione nella tabella globalize_translations, ma non trovandola ha lasciato il messaggio originale in italiano (l’unico a disposizione).

Dobbiamo quindi inserire un nuovo record per fare in modo che la traduzione abbia esito positivo. Le strade possibili sono due: inserire direttamente quanto desiderato attraverso una query, oppure utilizzare il metodo set_translation offerto da Globalize per effettuare traduzioni al volo in pochi secondi (naturalmente noi useremo questa strada).

I parametri da passare al metodo saranno i seguenti:

  • la stringa da tradurre
  • la lingua in cui vogliamo tradurla
  • la traduzione vera e propria

Ecco il codice necessario per creare la traduzione di benvenuti in welcome.

1
2
3
4
5
6
7
8
9
10
11
# Estratto del file app/controllers/test_controller.rb

class TestController < ApplicationController
  def index
    Locale.set('en-US')
    # creazione della traduzione prima del rendering della vista
    Locale.set_translation('Benvenuti', 
                           Language.pick('en-US'), 
                           'Welcome')
  end
end

Il metodo set_translation non fa altro che creare un nuovo record all’interno della tabella globalize_translation (simile a quello che possiamo vedere nella figura seguente). Ora la traduzione, che prima era incompleta, avverrà correttamente ed il risultato che ottenuto sarà il tanto desiderato Welcome Wednesday 21 June 2006

Alternative a Globalize

Sebbene in questo articolo abbiamo discusso della localizzazione, dell’internazionalizzazione e della globalizzazione basandoci unicamente sul plugin Globalize, va detto che questa non è l’unica soluzione disponibile (seppure al momento venga considerata la migliore tra tutte).

Chiunque desideri approfondire l’argomento può vedere ad altre soluzioni riassunte in pagina di comparazione presente nel wiki di rubyonrails.org nella quale vengono confrontati tutti i sistemi che attualmente permettono la gestione di contenuti multilingua all’interno di applicazioni Rails

Conclusioni

Riassumendo abbiamo dato un’introduzione completa al funzionamento del plugin Globalize, lo strumento utilizzato all’interno di Rails per la gestione dei contenuti multilingua. L’articolo, seppur introduttivo, ha voluto affrontare quanto segue:

  • il significato dei concetti alla base dei sistemi multilingua
  • l’installazione di Globalize
  • la gestione delle caratteristiche più comuni di Globalize

Inoltre abbiamo volutamente deciso di affrontare ed analizzare il come certe cose vengono fatte, analizzando quindi aspetti non strettamente necessari per utilizzare Globalize, ma preziosi per capirne a fondo il funzionamento. In questo modo abbiamo voluto fornire una solida base per i futuri articoli (questo non è che il primo di una serie) in cui cercheremo di avvicinarci passo passo alle problematiche che spesso vengono a crearsi nel momento in cui iniziamo creare un’applicazione destinata a tutte le popolazioni del mondo! Rimanete sintonizzati su The Ruby Mine!

Licenza

Questo articolo è coperto dalla licenza Creative Commons Attribution-NonCommercial-NoDerivs 2.5 Italy.

6 comments | Filed Under: Plugin Rails Tutorial | Tags: