Home / Programmazione / Java / Internazionalizzazione con Java Server Faces
Mattepuffo

Internazionalizzazione con Java Server Faces

Internazionalizzazione con Java Server Faces

In questi giorni mi sto dando allo studio delle Java Server Faces (JSF) e mi sono subito imbattuto in un problema: l'internazionalizzazione.

Volendo evitare modalità "classiche" tipo cookie o salvare i testi direttamente dentro un classe, possiamo procedere in questo modo.

Nel mio package ho creato un sotto package con dentro i file di properties: com.mf.language.

I file di properties devono avere questa nomenclatura: nome_lingua.properties, tranne quello di default.

Io ne ho due:

  • messages.properties (italiano)
  • messages_en.properties (inglese)

I file di properties lavorano con il concetto di chiave:valore:

ciao=CIAO!

Poi dovete scrivere l'equivalente per la altre lingue nei file appositi.

A questo punto creiamo, se non esiste già, il file di configurazione faces-config.xml dentro a WEB-INF, con questo dentro:

<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="2.2"
              xmlns="http://xmlns.jcp.org/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd">
    <application>
        <locale-config>
            <default-locale>it</default-locale>
            <supported-locale>en</supported-locale>
        </locale-config>
        <resource-bundle>
            <base-name>com_mf.language.messages</base-name>
            <var>msg</var>
        </resource-bundle>
    </application>
</faces-config>

In pratica gli diciamo dove sono i file delle lingue, e ne impostiamo una di default.

A questo punto creiamo un ManagedBean per gestire le lingue:

@ManagedBean(name = "language")
@SessionScoped
public class LanguageBean implements Serializable {

    private static final long serialVersionUID = 1L;
    private String locale;
    private static Map countries;

    static {
        countries = new LinkedHashMap();
        countries.put("Italiano", Locale.ITALIAN);
        countries.put("English", Locale.ENGLISH);
    }

    public Map getCountries() {
        return countries;
    }

    public String getLocale() {
        return locale;
    }

    public void setLocale(String locale) {
        this.locale = locale;
    }

    public void localeChanged(ValueChangeEvent e) {
        String newLocaleValue = e.getNewValue().toString();
        for (Map.Entry entry : countries.entrySet()) {
            if (entry.getValue().toString().equals(newLocaleValue)) {
                FacesContext.getCurrentInstance().getViewRoot().setLocale((Locale) entry.getValue());
            }
        }
    }
}

Adesso non rimane altro che richiamare il tutto dentro una pagina web:

<h:form>
<h:outputText value="#{msg['ciao']}" /><br/>
<h:selectOneMenu value="#{language.locale}" onchange="submit()" valueChangeListener="#{language.localeChanged}">
    <f:selectItems value="#{language.countries}"/>
</h:selectOneMenu>
</h:form>

Prima richiamiamo il valore ciao, e sotto riempiamo una lista con le lingue disponibili.

Quando si cambia valore della lista viene cambiata la lingua tramite il metodo localeChanged e aggiornata la pagina.

Sicuramente due miglioramenti da fare sono:

  • salvare la lingua scelta in sessione o su database per ritrovarsela
  • creare le voci della lista delle lingue disponibili su un file e non direttamente nel codice

In sostanza con queste due modifiche renderemmo il tutto un pò più flessibile e comodo.

Ciao!