Il Bar dell'Ingegneria

LOCAL-LACOL

A passeggio tra le lingue

« Older   Newer »
 
  Share  
.
  1.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Member
    Posts
    2,939
    Reputation
    +187

    Status
    Offline
    Da una settimana faccio ricerche internet (senza grande costrutto) sulla 'localizzazione' di software.

    Per 'localizzazione' si intende la traduzione dell'interfaccia utente di un qualsivoglia software nella lingua desiderata dall'utente.

    La 'localizzazione' non è operazione banale. Perchè indipendentemente dagli aspetti informatici più o meno semplici, coinvolge tutto quanto è il 'contenuto' di un programma. Dalle semplici 'didascalie' presenti in ogni singola finestra di dialogo, alle voci di menù, alle diciture nei pulsanti, ma anche l'help in linea, la documentazione più o meno 'cartacea', fino a giungere pure alle icone del programma stesso, non necessariamente sempre immediatamente comprensibili ad ogni latitudine del nostro variegato mondo.

    Oggi sono stato più fortunato perchè si sono verificati due eventi.
    Ho trovato notizie in rete della libreria GNU denominata gettext, ed ho avuto modo di parlare con un programmatore 'professionista'.
    Quest'ultimo risponde perfettamente agli stereotipi che di tali personaggi abbiamo in testa: grosso faccione incorniciato da barbone e capelli lunghi e incolti, lenti spesse e grossa pancia.

    Questo in estrema sintesi quanto ho raccolto: Non esiste ad oggi una procedura "automatica" di localizzazione. In nessuno dei sistemi operativi che conosciamo.

    Mi ero lasciato ingannare da pagine e pagine internet su Microsoft e su Windows Vista, il primo sistema operativo, a quanto pare, ad essere dotato di tecnologia MUI (Multilingual User Interface).
    Tecnologia che consente, ma al solo sistema operativo, di essere distribuito da Microsoft con unico codice sorgente, e che può essere installato, dotandolo dell'opportuno language-pack, in tutte le lingue. Anche più d'una in modo che l'utente possa passare 'al volo' dall'una all'altra lingua (se avete Vista, Seven, o superiori, vedrete nella barra delle applicazioni, a fianco della Tray-bar il simbolino IT, e potrete probabilmente settarlo, facendovi sopra click, in EN, modificando ).

    Questo dunque quanto fa e può fare Windows. Ma un mio (o vostro) programma?

    Quindi mi tocca parlare per prima cosa di gettext.
     
    Top
    .
  2.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Member
    Posts
    2,939
    Reputation
    +187

    Status
    Offline
    Questo benedetto gettext sembra chissà che.......

    Si tratta di una libreria di funzioni dedicate proprio agli aspetti di localizzazione distribuita dal progetto GNU.
    Quindi è liberamente scaricabile, ecc. E' compatibile con parecchi linguaggi di programmazione tra cui gli immancabili C, C++, Pascal, Phyton, Java, ecc.

    In sintesi ogni volta che il programma 'dichiara' il contenuto di una stringa, sia essa la didascalia di una label, una voce di menù, un testo da scrivere liberamente su una canvas, ecc. esso va 'incorniciato' tramite la funzione gettext()

    Quindi al posto di scrivere:

    CODICE
    printf("Hello world!");


    si dovrà scrivere:

    CODICE
    printf(gettext("Hello world!"));


    A questo punto si darà il listato del programma, così impostato, in pasto al programma xgettext, il quale non farà altro che generare un file di testo, in cui inserirà tutte le stringhe che ha riscontrato 'incorniciate' dentro gettext.

    Questo file è un 'template', con estensione .pot
    Ogni singola parte del file dovrebbe avere questo aspetto:

    CODICE
    #: src/name.c:36
    msgid "Hello world!"
    msgstr ""


    (copiato da Wikipedia)
    Quindi una volta generato il file 'modello', si potranno generare tutti i 'file di linguaggio' che si vogliono.
    Basta utilizzare un altro programma: msginit, che creerà tanti file con estensione .po, quante le lingue in cui si desidera l'interfaccia del programma.

    Per ogni lingua il file .po, avrà inizialmente questo aspetto:

    CODICE
    #: src/name.c:36
    msgid "Hello world!"
    msgstr "Hello world!"


    Ovvero questo 'fantastico' programma non ha fatto altro che inserire nella 'chiave' msgstr lo stesso contenuto della chiave msgid.
    E' a questo punto che entra in gioco la parte manuale della questione. Ovvero la traduzione di tutte le stringhe msgstr nella lingua desiderata.
    Ci si potrà avvalere di traduttori qualificati, oppure dei vari servizi in linea dedicati alle traduzioni.
    Nella libreria gettext a quanto pare esiste il programma poedit che si occuperebbe di questa fase.

    Quindi il file a questo punto diventerebbe (in una ipotesi di traduzione italiana):

    CODICE
    #: src/name.c:36
    msgid "Hello world!"
    msgstr "Ciao mondo!"


    In tutto questo il nostro codice non è affatto cambiato, abbiamo la nostra stringa 'incapsulata' dentro la funzione gettext, che non abbisogna di alcuna modifica.

    Trovo scritto su Wikipedia, che il file di testo così ricavato dovrà essere ripassato, per la sua compilazione, tramite il programma msgfmt, generando un file con estensione .mo.

    Il programma a questo punto dovrà solamente essere eseguito, e la scritta, 'filtrata' dalla funzione gettext, utilizzerà la traduzione del file .mo corrispondente al valore della variabile d'ambiente LANGUAGE, comunemente preimpostata in tutte le distribuzioni di software libero.

    (La parte in corsivo l'ho ripresa dalla pagina wikipedia. http://it.wikipedia.org/wiki/Gettext)
     
    Top
    .
  3.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Member
    Posts
    3,345
    Reputation
    +213

    Status
    Offline
    una volta ho tradotto pure io un programma in italiano. girava sotto linux ed aveva un file di testo esterno nel quale ogni riga riportava una stringa usata dal programma stesso. il programma sapeva in quale riga cercare così la traduzione consisteva semplicemente nel modificare le righe del file di testo.

    oggi questo sistema si è evoluto e non si usa più un file di testo ma un file .xml.

    al link http://languages.foxitsoftware.com/get_fil...4,16,lang_it_it ad esempio si può scaricare il file .xml per localizzare foxit reader in italiano (per vederne il contenuto, il file .xml può essere aperto con il browser).

    a mio parere un sistema del genere sarebbe l'ideale. ogni stringa all'interno del programma ha un id, sia essa voce di menu o contenuto della finestra. il file .xml associa ad ogni id la stringa appropriata (presumo tuttavia che la lingua di default sia incorporata anche nel codice per consentire al programma di funzionare anche in assenza di qualunque file .xml).

    scorrendo il file linkato, si potrà anche notare che la traduzione non è ancora completa, permanendo molte stringhe in inglese, che però -fatto salvo l'effetto minestrone- non inficiano il funzionamento del programma. è però possibile per l'utente completare la traduzione o addirittura scrivere nel file quello che gli pare per personalizzare ancor più l'interfaccia del programma.

    qui: www.shadowspro.com/help/it/trad.html un'altra possibile idea per la traduzione del programma shadows, che fa uso di un file di testo esterno.

    Edited by reversi - 26/1/2015, 23:23
     
    Top
    .
  4.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Administrator
    Posts
    8,163
    Reputation
    +294

    Status
    Offline
    CITAZIONE (zax2013 @ 26/1/2015, 22:41) 
    Quindi al posto di scrivere:

    CODICE
    printf("Hello world!");


    si dovrà scrivere:

    CODICE
    printf(gettext("Hello world!"));


    A questo punto si darà il listato del programma, così impostato, in pasto al programma xgettext, il quale non farà altro che generare un file di testo, in cui inserirà tutte le stringhe che ha riscontrato 'incorniciate' dentro gettext.

    ...

    Riesco a comprendere il processo per la traduzione delle varie stringe di testo presenti nel corpo del programma, ma per tradurre tutti i testi presenti nei vari oggetti distribuiti su un dialogo come agire?

    Se inserisco il rigo:

    Button1.caption:=gettext('Annulla')

    posso immaginare che la cosa funzioni ancora, ma se il testo "Annulla" viene inserito direttamente tramite l'object inspector nella fase di progettazione del dialogo che succede?

    Edited by afazio - 27/1/2015, 13:03
     
    Top
    .
  5.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Member
    Posts
    2,939
    Reputation
    +187

    Status
    Offline
    Come ben sai Afazio, il testo di una Label, di una casella di input, di un pulsante è possibile inserirlo con l'Object Inspector, ma si tratta di una 'proprietà' dell'oggetto che può essere modificata a runtime.

    Ad esempio, è quello che faccio io in Califfo quando si modificano le unità di misura. Se noti, le singole didascalie non rimangono "Base[B]:", ma di volta in volta possono assumere la forma "Base [B] (cm):" o "Base [B] (m):" o "Base [B] (mm):", e così per tutto il resto dell'input che prevede una ben specifica unità di misura.
    Io nell'Object Inspector inserisco un valore, ma poi lo 'manipolo' a runtime in funzione della effettiva unità di misura selezionata.

    Identicamente si dovrà fare per le stringhe che si vorranno tradurre nei vari linguaggi. Da qualche parte nel codice, ci dovranno essere le 'assegnazioni' della stringa.

    Ma adesso che mi libero per 5 minuti (forse tra un'oretta) spiegherò il 'metodo' del programmatore con cui ho parlato.
     
    Top
    .
  6.     +1   -1
     
    .
    Avatar

    Member

    Group
    Member
    Posts
    766
    Reputation
    +23

    Status
    Offline
    Questo post è molto interessante dal punto di vista tecnico-informatico, è un problema che non ho mai sentito l’esigenza di affrontare. Io personalmente sono contrario alla localizzazione dei software e dei sistemi operativi in lingue diverse dall’inglese, ed in particolare per quanto riguarda i software ingegneristici e multifisici, mentre per i gestionali sono favorevole. Le motivazioni che mi inducono a questa idea è che ormai viviamo in un mondo globalizzato e connesso alla rete, l’informatica moderna ed i testi scientifici sono tutti scritti in inglese, chi non sa leggere l’inglese oggi è tagliato fuori, perciò conviene usare fin da subito il software in lingua inglese piuttosto che lo stesso software localizzato, anche in prospettiva di dover lavorare all’estero o per l’estero. Inoltre la compatibilità tra software nativo inglese nella localizzazione può presentare degli inconvenienti che non si limitano alla pessima traduzione di alcuni menù o didascalie. Posso citare ad esempio le macro localizzate di autocad in italiano se non vengono adottate certe precauzioni non girano su tutte le versioni localizzate di altri paesi, e la manualistica solo in parte è stata tradotta in italiano, la parte più corposa e specialistica è scritta solo in lingua inglese. Manutenere un grosso software multilingua ritengo sia un lavoro piuttosto oneroso e distogliente dalle funzionalità principali del programma.
     
    Top
    .
  7.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Member
    Posts
    2,939
    Reputation
    +187

    Status
    Offline
    Ciao Tex, mi aspettavo un tuo intervento. Hai ragione circa la complessità ma che non si limita ai soli aspetti informatici.
    Esistono lingue che si scrivono da destra verso sinistra, piuttosto che come la/le nostre, oppure dall'alto verso il basso, ecc. E tutto questo quando si voglia localizzare in 'automatico' diventa arduo e complicato.

    In questi giorni ho visionato diversi siti di aziende che propongono alle softwarehouse i loro servizi di traduzione. Traduzione che spesso deve essere per forza molto tecnica, magari particolarmente specialistica e che prevede la necessità di persone di ben specifici ambiti e ben precise specializzazioni.

    Esistono poi software che si occupano della questione, questo sito ne è un esempio: www.sisulizer.com/?s=g-sl-1 (trovo strano che un software del genere preveda delle pagine Internet 'localizzate' solamente in 3 lingue.....)

    Torno un attimo alla libreria gettext

    Dalla descrizione che ne ho fatto è un prodotto tipicamente Linux. Ogni singolo passaggio fatto da un programmino che si occupa di una singola fase dell'intero processo. Una serie di filtri successivi che l'utente volenteroso dovrà per forza di cose ripetere ogni volta che introdurrà una nuova finestra nel suo applicativo, con nuove stringhe da tradurre, ecc.

    E' tipico di quell'ambiente, dove il processo software viene 'spezzettato' e dove il concetto stesso di 'condivisione' prevede che ogni singolo sviluppatore si occupi di un singolo mattoncino della costruzione globale.
    Immagino che qualche altro sviluppatore abbia creato delle macro che 'automatizzino' il processo. E che rendano più semplici le revisioni successive alla prima.
     
    Top
    .
  8.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Member
    Posts
    2,939
    Reputation
    +187

    Status
    Offline
    Da un punto di vista Windows esistono delle funzioni API che permettono di conoscere la lingua con cui il sistema stesso (Windows) è configurato. Pertanto si avrebbe una doppia possibilità. All'avvio del programma, è quest'ultimo che interroga il sistema, e si 'setta' di conseguenza. Oppure il programma prevede una opzione utente che consente di scegliere la lingua con cui si desidera l'interfaccia.
    Nel primo caso il nostro programma dovrebbe 'possedere' tutte le lingue di Windows, oppure utilizzare un default nel caso in cui il sistema ha una lingua per il nostro programma sconosciuta.
    Nel secondo caso invece il programma potrà settare la lingua in fase di installazione, oppure ad installazione avvenuta.

    In teoria, sempre per sottolineare la complessità della cosa, va considerato che la 'localizzazione' non dovrebbe limitarsi alla lingua delle singole didascalie, ma anche ai formati data, numero, ecc.
     
    Top
    .
  9.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Member
    Posts
    2,939
    Reputation
    +187

    Status
    Offline
    Andiamo invece ai suggerimenti del programmatore con cui ho parlato.

    La sintesi è: "se gettext opera nella maniera che sappiamo proviamo a 'replicarne' in qualche modo il funzionamento con qualcosa fatta in casa, ma che abbia le potenzialità di permettere facilmente l'introduzione di una nuova lingua alla bisogna".

    Ecco quindi che mi ha fornito una doppia possibilità.
    Ambedue passano attraverso la creazione di file di testo, da battezzare .dat o come meglio si preferisce, in cui ogni singolo file di questa specie contenga le stringhe nella lingua desiderata.

    Illustro prima l'opzione 'semplice'.

    1) Creazione di un semplice file .dat, in cui vengono memorizzate tutte le stringhe che il programma utilizza.
    (Rispetto ad una mia 'visione' la memorizzazione di una stringa avviene una sola volta, anche se il programma utilizza quella 'voce' in più punti del programma. Immaginate ad esempio il pulsante "Annulla" (in italiano) presente in tutte le finestre di dialogo, che nella traduzione inglese debba diventare "Cancel". Ebbene memorizzerò una sola volta la stringa tradotta, e poi dovrò dire al programma per tutti questi pulsanti di utilizzare una ed una sola specifica stringa).

    2) All'apertura del programma, conosciuta la lingua di interfaccia, il programma apre il file .dat corretto e provvede a memorizzare in memoria l'elenco delle stringhe in un vettore di opportuna capienza (bisognerà allocare memoria).

    3) Con apposita procedura provvederà ad 'inizializzare' tutte le stringhe di tutte le finestre di dialogo del programma, utilizzando l'indicizzazione del vettore in memoria per 'reperire' la stringa giusta.

    Quest'ultima operazione può eseguirsi ogni volta che si dovrà visualizzare una finestra di dialogo (e quindi far permanere in memoria il vettore delle stringhe), oppure all'inizio della elaborazione per tutte le finestre (e quindi una volta utilizzata buttare a mare il vettore e liberare lo spazio in memoria occupato).
     
    Top
    .
  10.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Member
    Posts
    3,345
    Reputation
    +213

    Status
    Offline
    invece delle stringhe, potresti dare ad ognuna un codice ed il programma poi cerca quel codice nel file di testo e legge la stringa.
     
    Top
    .
  11.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Member
    Posts
    2,939
    Reputation
    +187

    Status
    Offline
    Aspetta Reversi, aspetta. Dammi tempo di esporre tutte le possibilità.

    Avevi già aperto la strada con esempi sul 'campo'.
    Il file di testo da editare "anche in Excel" di Foxit segue esattamente la strada prefigurata.

    La storia del codice ID è la seconda strada che il programmatore mi ha prospettato. Ma con una 'furbata' simile a quella di gettext.

    Perchè parliamoci chiaro....il codice ID nella prima ipotesi che ho tracciato è la posizione nel vettore di stringhe di cui parlavo prima, quindi siamo esattamente alla tua ipotesi (con una differenza sostanziale però: avendo tutto in memoria non devo aprire e chiudere il file di testo ogni volta alla ricerca della stringa giusta, con conseguente perdita di tempo).

    Quindi nel mio codice dovrei scrivere qualcosa del tipo:

    CODICE
    printf("%­s", stringhe[12]);


    dove stringhe[12] è la 13-esima posizione del mio vettore di stringhe, e lì è stata memorizzata la stringa "Ciao Reversi".

    Ora, capisci che se hai un file con 10-20 stringhe diventa tutto sommato semplice non sbagliare, ma con un file di 100-200 e più 'voci', sapere cosa effettivamente il programma scriverà digitando stringa[167] non è per niente facile.
     
    Top
    .
  12.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Member
    Posts
    3,345
    Reputation
    +213

    Status
    Offline
    per me il codice id non è per niente la posizione nel vettore di stringhe.
    se così fosse, sarebbe un problema inserire una stringhe tra 2 esistenti perché vorrebbe dire spostare tutte le successive.
    io invece immaginavo un id, ad esempio, di 3 cifre, partendo da 0xx per il primo menu/maschera/messaggio, partendo da 1xx per il secondo menu/maschera/messaggio, ecc.
    l'inserimento di una nuova stringa ne farebbe spostare solo un po' (quelle che iniziano con la stessa cifra) oppure potrebbe avvenire in coda a quelle dello stesso gruppo.
    il file potrebbe poi essere strutturato tipo un .csv in cui sappiamo già che i primi 4 caratteri sono l'id (i primi 3 caratteri) seguito dalla virgola e quindi ciò che viene dopo è la stringa.
    su ogni riga c'è una sola stringa, lunga quanto si vuole, senza testo a capo.
     
    Top
    .
  13.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Member
    Posts
    2,939
    Reputation
    +187

    Status
    Offline
    Andiamo quindi all'opzione "furba".

    E' una opzione che consente di fare a meno di un codice ID, di non doverlo memorizzare (a mente).
    Forse sarò ripetitivo, ma dobbiamo considerare che il codice non si scrive tutto in una volta. Spesso tra una 'revisione' e l'altra possono passare mesi, e ricordare per filo e per segno cosa si era fatto e perchè non è facile. Quindi se possiamo fare a meno di codici mnemonici è tanto di guadagnato.

    Ovviamente come in tutte le cose c'è il rovescio della medaglia, che nella fattispecie significa un maggior impegno in memoria.

    Dobbiamo fare, per quanto con codice 'fatto in casa', esattamente quello che fa la funzione gettext().
    Ovvero il codice ID sarà esattamente il testo nella nostra lingua 'originaria'. E nel file .dat dovremmo inserire la doppia 'notazione':

    1° riga: testo nella lingua 'originaria';
    2° riga: testo tradotto;

    (La doppia riga ci svincola dal dover utilizzare un separatore certamente mai utilizzabile nelle nostre stringe, in modo da capire perfettamente quando finisce l'una e quando comincia l'altra).

    Ovviamente dobbiamo 'costruire' noi la funzione gettext() (o nome simile).
    Funzione che andrà alla ricerca della stringa tradotta (2° riga), avendo come 'chiave' di ricerca la 1° riga. Il tutto dovrà essere svolto lavorando in memoria e non certamente aprendo e chiudendo il file di testo ogni volta.

    Io sono dell'avviso che tale operazione vada svolta una sola volta all'avvio del programma. Si legge il file .dat e lo si carica tutto in memoria, quindi si 'assegna' ad ogni label, ad ogni bottone, di ogni finestra, la giusta dicitura, e si libera subito dopo la memoria impegnata.

    Ovviamente la funzione gettext() dovrà restituire una stringa opportuna nel caso in cui non riscontra il testo da tradurre, in modo da evidenziare il fenomeno e riuscire ad intervenire in fase di scrittura del programma.
    Non è un male in se. Questo comporterà automaticamente la necessità di utilizzare parole, frasi, quanto più 'standardizzate' possibile e sempre uguali in più parti del programma.
     
    Top
    .
  14.     +1   -1
     
    .
    Avatar

    Member

    Group
    Member
    Posts
    766
    Reputation
    +23

    Status
    Offline
    1° riga: testo nella lingua 'originaria';
    2° riga: testo tradotto lingua 'A';
    3° riga: testo tradotto lingua 'B';
    4° ................................
    n° riga: testo tradotto lingua 'n';

    CITAZIONE
    Ovviamente dobbiamo 'costruire' noi la funzione gettext() (o nome simile).
    Funzione che andrà alla ricerca della stringa tradotta (n° riga), avendo come 'chiave' di ricerca la 1° riga. Il tutto dovrà essere svolto lavorando in memoria e non certamente aprendo e chiudendo il file di testo ogni volta.

    Lo svantaggio nell'utilizzo di un record di questa natura stà in una latenza in fase di avvio del programma dipendente dal numero di stringhe da ricercare e sostituire.
    Una alternativa sarebbe quella di adottare un file binario opportunamente strutturato ed indicizzabile, utilizzando dei #DEFINE per rendere il codice leggibile e manutenibile.
     
    Top
    .
  15.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Member
    Posts
    2,939
    Reputation
    +187

    Status
    Offline
    CITAZIONE (texitaliano64 @ 27/1/2015, 19:02) 
    1° riga: testo nella lingua 'originaria';
    2° riga: testo tradotto lingua 'A';
    3° riga: testo tradotto lingua 'B';
    4° ................................
    n° riga: testo tradotto lingua 'n';

    Lo svantaggio nell'utilizzo di un record di questa natura stà in una latenza in fase di avvio del programma dipendente dal numero di stringhe da ricercare e sostituire.
    Una alternativa sarebbe quella di adottare un file binario opportunamente strutturato ed indicizzabile, utilizzando dei #DEFINE per rendere il codice leggibile e manutenibile.

    Tex, stranamente, almeno da quel che ho visto, pare si preferisca avere tanti file differenti per ogni singolo linguaggio che si vuol 'gestire'.
    E' probabile che si faccia per non incasinare la fase di editing del file stesso, oppure per evitare di portarsi dietro 'troppa roba' in un colpo solo.....non saprei.

    Circa la latenza...una bella Splash Window in fase di avvio ed è fatta!
     
    Top
    .
17 replies since 26/1/2015, 22:03   348 views
  Share  
.