Il Bar dell'Ingegneria

LOCAL-LACOL

A passeggio tra le lingue

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

    Advanced Member

    Group
    Member
    Posts
    3,345
    Reputation
    +213

    Status
    Offline
    domanda: è possibile avere una lingua di default (stringhe all'interno del codice) che eviti la fase di assegnazione iniziale?
    questo renderebbe il programma comunque funzionante anche in assenza del file della lingua.
     
    Top
    .
  2.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Member
    Posts
    2,942
    Reputation
    +187

    Status
    Offline
    Reversi, in fase di 'progettazione' iniziale, i moderni IDE (Integrated Development Environment) prevedono il 'disegno' delle varie finestre di dialogo con posizionamento sulla form di Label, EditBox, ComboBox, pulsanti, ecc.

    E questo lo sai già non fosse altro perchè Afazio ha postato più volte le schermate del 'suo' Lazarus.

    E' in questa stessa fase che è possibile definire tutta una serie di proprietà di questi 'oggetti' grafici posizionati sulla form.
    Proprietà che è possibile inserire/modificare tramite il cosiddetto Object Inspector di cui sempre Afazio ha parlato qualche post fa. Una semplice tabella a due colonne che, selezionato un oggetto, si riempie di proprietà nella prima colonna e relativo valore nella seconda.

    Il testo di una Label, di un pulsante, etc. è una di queste proprietà. E questa può essere impostata a "Design Time" proprio dentro l'IDE con l'Object Inspector, oppure a "Run Time" modificata come meglio si desidera durante l'esecuzione del programma stesso.

    Questo per dirti che se il software è progettato bene (ovvero dotato sia di cintura che di bretelle), l'assenza del file della lingua dovrebbe semplicemente far visualizzare le stringhe così come impostate a "Design Time", senza alcuna modifica a "Run Time" (che è cosa che si farebbe per la traduzione 'al volo' del programma che si vuole abbia 2 o più interfacce linguistiche)
     
    Top
    .
  3.     +1   -1
     
    .
    Avatar

    Advanced Member

    Group
    Member
    Posts
    2,942
    Reputation
    +187

    Status
    Offline
    Ho voluto mettere alla prova quanto ho esposto. In particolare l'ultima soluzione che mi ha fornito l'amico programmatore.
    E quale 'laboratorio' migliore di Califfo per fare una prova simile?

    Ecco il primo incoraggiante risultato:

    png

    Ho creato una voce di menù che permette la scelta del linguaggio desiderato (cui fa da 'doppio' nel codice una variabile globale lang, settata a 0=linguaggio default, 1=inglese, 2=poi si vedrà....).

    Poi con un normale editor di testo (Notepad) ho creato un file con una serie di doppie righe, ad esempio:

    CODICE
    Apri
    Open
    Stampa
    Print
    Salva
    Save


    E così via. Quindi un file di 'stringhe' in cui nelle righe dispari c'è la rappresentazione in italiano, nelle pari la corrispondente stringa in inglese. Ho chiamato questo file Lng_EN.clx

    Poi ho dichiarato la seguente struttura dati:

    CODICE
    struct strlanguage
    {
    char orgnstr[250];
    char tradstr[250];
    };


    Ovvero una variabile che prima o poi dovrà contenere la riga dispari (orgnstr) e pari (tradstr) lette dal file suddetto (prima limitazione: 250 caratteri al massimo per singola riga scritta nel file).

    Quindi ho creato due funzioni. Una 'generale' e che va eseguita all'avvio del programma ed ogni volta che l'utente modifica la scelta della lingua tramite apposito comando, ed una 'particolare' che esegue materialmente la traduzione di una stringa alla volta.

    La funzione 'generale' che ho battezzato traduttore(), apre il file di testo con le varie stringhe, e si occupa di memorizzarle in un vettore di variabili struct strlanguage.
    Fatto questo, la funzione ha lo 'immane' compito di tradurre tutte le didascalie di qualsiasi finestra di dialogo (anche la principale) del programma, utilizzando la funzione 'particolare' che ho battezzato translate().

    Cominciamo a vedere il funzionamento della prima funzione, in linguaggio C:

    CODICE
    void traduttore()
    {
    FILE *fp;
    struct strlanguage *stringhe;
    int nstringhe=0;
    char buffer[500],filelanguage[500];

    stringhe=(struct strlanguage *) calloc(nstringhe+1,sizeof(struct strlanguage));

    /* Seleziona il file corretto in funzione della lingua scelta dall'Utente */
    if (lang==ITA) strcpy(filelanguage," ");
    if (lang==ENG) sprintf (filelanguage,"%­sLng_EN.clx",ExtractFilePath(Application->ExeName).c_str());

    /* Apre il file e se esiste carica in memoria tutte le stringhe in esso contenute */
    fp=fopen(filelanguage,"r");

    if (fp!=NULL)
       {
        do
          {
           fgets(stringhe[nstringhe].orgnstr,250,fp);
           stringhe[nstringhe].orgnstr[strlen(stringhe[nstringhe].orgnstr)-1]='\0';

           fgets(stringhe[nstringhe].tradstr,250,fp);
           stringhe[nstringhe].tradstr[strlen(stringhe[nstringhe].tradstr)-1]='\0';

           nstringhe++;
           stringhe=(struct strlanguage *) realloc(stringhe,(nstringhe+1)*sizeof(struct strlanguage));
          }
        while (feof(fp)==NULL);

       }

    fclose (fp);

    /* La funzione continua traducendo le varie stringhe */
    .
    .
    .
    /* Tradotte tutte le stringhe libera la memoria occupata da stringhe */
    free(stringhe);
    }


    Quindi per prima cosa la funzione, interrogando la variabile lang, va ad aprire il file con le stringhe tradotte nel linguaggio desiderato. Il nome del file nel caso di lingua standard (lang=ITA, o che è lo stesso: lang=0) viene posto pari a " " proprio per non far leggere nulla (il file non esiste e il puntatore al file, la variabile fp, varrà NULL). Se il file non esiste (cosa che potrebbe verificarsi anche nel caso di lingua inglese perchè per errore si è cancellato il file Lng_EN.clx) il valore della variabile nstringhe sarà 0 (è cosa che viene utilizzata dalla funzione 'particolare').

    Se invece l'apertura del file ha esisto positivo, si comincia a leggere il suo contenuto cominciando a memorizzare i dati in memoria tramite la una variabile di tipo struct strlanguage di nome stringhe che viene allocata dinamicamente e la cui dimensione viene aumentata ad ogni record (voce originale e voce tradotta) che viene letto e memorizzato (con conseguente incremento anche della variabile nstringhe).

    Poichè per la lettura ho utilizzato una funzione di basso livello (fgets()) questa mi legge anche il carattere 'a capo' '\n', che sono costretto a sostituire con il carattere '\0' che in C significa "fine della stringa".

    A questo punto la funzione traduttore() conterrà una serie infinita di righe di codice come questa:

    CODICE
    FinPrinc->MainMenu1->Items->Items[0]->Items[0]->Caption=translate("Nuovo",stringhe,nstringhe);


    Questa riga in particolare traduce il termine "Nuovo" del menù a tendina di Califfo utilizzando la seconda funzione, translate():

    CODICE
    char *translate(char *original,struct strlanguage *stringhe,int nstringhe)
    {
    int register k;

    for (k=0;k<=nstringhe-1;k++)
        {
         if (strcmp(original,stringhe[k].orgnstr)==0)  return(stringhe[k].tradstr);
        }

    return(original);
    }


    Questa funzione non fa altro che confrontare la stringa data come primo parametro (original) con quelle memorizzate nel campo orgnstr del vettore stringhe che le viene fornito come puntatore, e questo per tutte le righe del vettore stringhe (nstringhe).
    Quando si ha la corrispondenza, la funzione non fa altro che restituire la corrispondente stringa tradotta tradstr.

    Si possono avere 2 casi: variabile nstringhe=0, ovvero la procedura 'genitrice' non ha trovato alcun file di linguaggio e quindi la funzione translate() non fa altro che restituire proprio la stringa che avrebbe dovuto tradurre (quindi non viene eseguito il ciclo for e non viene tradotto un bel nulla), oppure che si sia arrivati alla fine del ciclo for senza trovare alcuna corrispondenza (perchè quella specifica stringa non è presente nel file di linguaggio). Anche in questo caso la stringa restituita è proprio original e di fatto non si è tradotto nulla.

    Con questo modo di procedere il programmatore deve stare attento a cosa digita via via che inserisce le righe di traduzione delle singole didascalie, ma almeno una stringa non tradotta verrà visualizzata nella lingua di default, piuttosto che con una stringa tipo: "Not traslated string", che renderebbe realmente incomprensibile all'utente straniero di cosa tratta quello specifico input.

    A questo punto si deve intervenire nel codice in due casi:

    1) Inserimento di una nuova finestra di dialogo, con sue specifiche stringhe da tradurre (ma se devo inserire una nuova finestra, sto di già intervenendo nel codice);
    2) Inserimento di una nuova lingua (ovvero devo inserire una sola riga con il nome del file da aprire per quello specifico linguaggio).

    Ovviamente per aggiungere una nuova lingua bisognerà scrivere il file di testo di cui all'inizio. E sempre ovviamente l'aggiunta di una nuova finestra e nuove didascalie comporta un ampliamento del/dei file di linguaggio.
     
    Top
    .
17 replies since 26/1/2015, 22:03   350 views
  Share  
.