Android lezione 12 – Creare una app multilingua e string resources

O come sottotitolo: una prima introduzione alle risorse dell’applicazione!

Fino adesso abbiamo visto diverse componenti del sdk android, questa volta puntiamo a  due argomenti  leggeri, e collegati fra loro ovvero:

  • Come evitare di dichiarare le stringhe all’interno del codice java o nel layout (e perchè vale la pena farlo)?
  • come rendere una applicazione multilingua.

Partiamo dal primo punto. Perchè non dichiarare le stringhe nel codice java? La prima risposta è: perchè se no la nostra applicazione non potrá essere multilingua. La seconda è: perchè se abbiamo 50 pulsanti nella app con lo stesso testo come per esempio: “Cambia  Testo” e volessimo modificarlo in: “Modifica testo”, avremo sicuramente un lungo lavoro da fare a cercare e modificare il testo dei pulsanti in ogni punto.

Quindi per questo conviene dichiarare tutte le stringhe una sola volta. Anche in questo caso l’sdk di Android ci viene  incontro. Permettendoci di dichiarare tutte le stringhe all’interno di un file xml, e assegnando loro un id tipo R.string.nomestringa.

Le stringhe, come tutte le altre risorse che si possono esternalizzare dalla applicazione (colori, valori, immagini, layout) verranno inserite all’interno della cartella res (che appunto é l’abbreviazione di resources).

Questa cartella gia la conosciamo perchè al suo interno andiamo a inserire gli xml con i layout delle interfaccie grafiche delle nostre applicazioni nella sottodirectory chiamata appunto layout (o layout-xyz per alcune versioni particolari di layout, che magari vedermo prossimamente). Ma all’interno di questa cartella trovano collocazione anche altre risorse, che mi limiterò ad elencarvi:

  • animator/
  • color/
  • drawable/
  • layout/
  • menu/
  • raw/
  • values/
  • xml/

Per maggiori informazioni su cosa inserire in queste cartelle (anche se i nomi sono abbatanza autoesplicativi) vi rimando al seguente link: http://developer.android.com/guide/topics/resources/providing-resources.html#ResourceTypes

Nel nostro caso le stringhe andranno inserite all’interno della cartella values/ (cartella che contiene appunto risorse di tipo stringa, numerico, colori, etc.). Ora mentre il nome della cartella nel quale andiamo a inserire i vari componenti delle risorse è importante (non possiamo mettere un xml di layout per esempio in values), il nome del file nel quale andiamo a salvare queste informazioni è arbitrario, in quanto l’sdk organizza le risorse in base alla loro tipologia, comunque per chiarezza andremo a salvare le nostre stringhe in un file chiamato strings.xml. Possiamo sfruttare se vogliamo il wizard dell’ide per creare lo scheletro del nostro xml, quindi portiamoci all’interno della cartella res/ e se non esiste la cartella values creiamone una. A questo punto a partire da questa, facciamo File->New->Other e selezioniamo

  • Android/Android XML Values Files

come mostrato in figura:

Nella schermata successiva ci viene chiesto il nome del file, e infine nell’ultima schermata, alcuni parametri aggiuntivi se necessari (in questo caso no!).

Quindi una volta creato il nostro file xml avremo qualcosa simile alla seguente:

<!--?xml version="1.0" encoding="utf-8"?-->
<resources>
    <string name="app_name">StringFileExample</string>
    <string name="action_settings">Settings</string>
    <string name="hello_world">Hello world!</string>
</resources>

Questo esempio contiene giá alcune stringhe, ed è stato preso dal file strings che viene creato automaticamente da alcuni template di progetti android disponibili nell’sdk.

Come potete vedere ogni linea identifica una stringa, che è composta da due parti:

  • l’attributo name che sará l’identificativo della stringa, che utilizzeremo per accedervi tramite R. Definito all’interno del tag <string>
  • Il contenuto della stringa, che invece sará quello che verrá mostrato nell’applicazione.

Tutte le strignhe che andremo ad inserire andranno inserite all’interno dei tag <resources></resources>. Come potete vedere la loro definizione è abbastanza semplice. Ora come dicevamo, android raggruppa tutte le risorse in base al loro tipo, e le rende accessibili mediante la classe R  quindi avremo per esempio:

  • R.drawable.nomeoggettodrawable che conterrá tutti i riferimenti a degli oggetti appunto drawable (possono essere sia immagini png che dei file xml, il nome del drawable, diventa il nome del file all’interno della cartella)
  • R.layout.nomelayout che conterrá i rifierimenti a tutti i layout definiti (anche in questo caso il nome del layout equivale al nome del file, da non confondere con l’id che viene dato al layour  (mediante l’attributo android:id) che invece è accessibile tramite R.id.
  • R.strings.nomestringa che conterrá appunto tutte le stringhe che sono state definite,
  • R.id che contiene tutti gli identificatori degli oggetti che abbiamo definito nei layout.

Vi sono molti altri attributi di R, ma non vorrei andare troppo fuori tema, vi rimando alla documentazione ufficiale android (visitate il link che vi ho postato poco sopra).

Quindi come potete ben immaginare per accedere alla stringa StringFileExample (definita nell’esempio precedente) ci basterá, usare il seguente riferimento:

R.string.app_name

Questi riferimenti, possono essere usati sia all’interno del codice java che all’interno dei vari file xml del layout.

Nel caso dobbiamo richiamare le stringhe all’interno di un oggetto del layout usiamo la forma: @string/nomestringa, per esempio se abbiamo una textview come la segunete:

 

    <TextView
        android:id="@+id/textview1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="String Example" />

Quindi se non lo abbiamo gia fatto dobbiamo inserire la stringa in res/values/strings.xml:

        <string name="example">String Example</string>

Dopo di che cambieremo l’attributo android:text della TextView:

       android:text="@string/example"

Ora vediamo invece cosa dobbiamo fare per accedervi programmaticamente. Distinguiamo due casi:

  1. Il primo caso è quando vogliamo accedervi per modificare programmaticamente il testo dei vari componenti della gui della nostra applicazione.
  2. Mentre il secondo è quando vogliamo accedervi in altre parti del programma che non coinvolgono componenti dell’interfaccia grafica (per esempio se vogliamo fare una query sql, o ci servono per fare dei confronti).

Nel primo caso, gli oggetti android gia sanno come tradurre i riferimenti a stringhe. Quindi se per esempio vogliamo modificare il testo di una TextView ci basterá fare:

TextView myTv = (TextView) findChildbById(R.id.textView1);
myTv.setText(R.string.example);

Quindi quello che sará stampato nella textView sará “String Example”. Ovviamente avremo potuto fare anche:

myTv.setText("String Example");

ottenendo lo stesso risultato. Ma non sempre esiste un metodo che accede per noi alla stringa, in diverse occasioni potrebbe servirci di accedere direttamente alla stringa per utilizzarla per fare dei confronti, o semplicemente per concatenarla con altre stringhe, o qualsiasi altro utilizzo ci venga in mente. In questo caso possiamo ancora accedere alle stringhe in due modi:

  • Utilizzando un oggetto Resources, e chiamando il metodo getString. In molti casi possiamo usare direttamente una chiamata simile alla seguente:
    String myString = getResources().getString(R.string.example);

    Il metodo getResources è disponibile a livello di Activity o di Contesxt. Quindi per chiamarlo dobbiamo necessariamente avere a disposizione almeno uno di questi oggetti.

  • Se invece siamo all’interno di un activity possiamo usare direttamente il metodo getString(R.string.example) che altro non fa che chiamare il getResources().getString(…);

Bene, ora possiamo considerarci padroni delle stringhe di testo :D. Passiamo alla seconda parte della lezione, ovvero far parlare più lingue alla nostra applicazione! Se vi state domando perchè, beh la rispsota è semplice se facciamo la nostra applicazione solo  in italiano limiteremo la sua visibilitá esclusivamente al mercato interno. Mentre se la traduciamo in almeno una seconda lingua (magari l’inglese) il bacino di utenza potenziale si allarga. Anche in questo caso chi ci viene in aiuto sono le risorse dell’applicazione nella cartella res (e sono anche un motivo in più per utilizzare le stringhe definite all’interno del file xml).

Come visto precedentemente, per dichiarare le risorse stringhe, andiamo a creare un file xml all’interno di res/values/. Quindi ogni qualvolta che android incontra un riferimento tipo R.string.example va a cercare se la stringa dal nome example si trova definita da qualche parte all’interno di values.  Ma in realtá android fa di più, infatti ci permette di definire differenti versioni delle stesse risorse. Per farlo basta aggiungere una creare altre versioni della cartella values il cui nome è così composto:

values-identificatore

dove identificatore in questo caso è la sigla a due cifre della lingua che vogliamo definire (it per l’italiano, en per l’inglese, etc) gli identificatori di lingua non sono gli unici possibili, ma dato che qui non è il mio scopo spiegare tutti i possibili identificatori disponibili, vi rimando all’articolo sul sito android: http://developer.android.com/guide/topics/resources/providing-resources.html#AlternativeResources) , quindi in res creaimo una cartella che conterrá tutte le stringhe in italiano, il suo nome sará:

values-it

Al suo interno creiamo una copia del file strings.xml e aggiungiamo tutte quelle che sono le stringhe che vogliamo disponibili nella lingua italiana, con anche la traduzione. Quindi per esempio se volessimo tradurre le stringhe fino adesso viste, avremo il seguente contenuto:

<!--?xml version="1.0" encoding="utf-8"?-->
<resources>
    <string name="app_name">StringFileExample</string>
    <string name="action_settings">Configurazione</string>
    <string name="hello_world">Ciao Mondo!</string>
    <string name="example">Stringa di esempio!</string>
</resources>

E… Basta. Non dobbiamo fare altro. Ora se la nostra applicazione gira su un android in italiano, avremo tutte le scritte in italiano (o almeno quelle definite tramite xml). Se gira su qualsiasi altro device invece avremo le scritte in inglese.

Ora magari qualcuno di voi si stará domandando: e values-en? Non la creiamo? La risposta in questo caso è no. In quanto diciamo che avendo gia delle stringhe definite all’interno di values/ quelle agiscono un pò come caso di default! Ovvero se la risorsa che  ricerco non sta in tutte le altre possibili cartelle disponibili, allora la si va a cercare all’interno di values. Quindi in questo esempio sarebbe stato inutile fare anche una cartella values-en. Ma magari avremo potuto decidere di fare values-es?

Ovviamente per provare questa parte dobbiamo necessariamente cambiare lingua al nostro device (almeno per qualche istante). Se siamo su device con android 2.3 o giù di lì andate su:

  • Impostazioni -> Lingua e Testo -> Selezione Lingua

  • Mentre se siete su android 4 o superiore Impostazioni -> Lingua e immissione -> Lingua

Infine anche in questa lezione ho preparato una app di esempio che trovate su github nel mio repository dedicato agli esempi del sito. L’url per accedervi è: https://github.com/inuyasha82/ItalialinuxExample

Questa app è abbastanza semplice, e mostra principalemnte i vari modi per ottenere e manipolare il testo dichiarato all’interno di files xml. Vi consiglio di dare un occhiata al codice. E a come è strutturata.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.