Newsgroup: it.comp.lang.visual-basic
Titolo: Da Italiano a Multilanguage

VB6 Pazza idea: convertire un vecchio progettoin italiano a 
multilanguage.
Almeno le caption dei vari oggetti, come inizio. Poi messaggi e 
intestazioni campi nelle griglie.
Se mai si dovesse fare una cosa del genere, quale sarebbe l'approccio 
migliore?
 
-- 
Greg
 
 


Di quante form si parla?

Dopo dura riflessione, Greg ha scritto :

E' un po' un viaggio nel tempo, parlo al presente ma ï¿œ roba di anni e 
anni fa.
Noi abbiamo una function che itera su tutti i controlli di una form.
Questa function, a cui viene passato il codice della lingua 'attiva', 
puï¿œ girare in diverse modalitï¿œ:
- scrittura: per ogni controllo, verifica se esiste la traduzione nella 
lingua X, e se non esiste fa un inserimento nel db con tutti gli 
identificativi del controllo, caption text tag e tooltip che trova da 
design, e un flag che indica che la traduzione non ï¿œ 'validata'.
- lettura: per ogni controllo, sostituisce i valori da design con 
quelli ricavati dal db.
 
Ovviamente dopo aver lavorato nel progetto, si fa girare in scrittura e 
il db viene 'popolato' con tutte le righe necessarie, si cercano quelle 
non validate e si traducono.
 
Sempre attingendo dallo stesso db, ci sono le traduzioni per i 
messaggi, per i report, ecc..., con concetto analogo.
 
La cosa simpatica ï¿œ che in una fase iniziale, basta mettere questa 
function nell'activate di una form, e si ha giï¿œ 'automatizzato' il 
grosso del processo (ovviamente se si ï¿œ tradotto il contenuto).
Oltre al fatto che si puï¿œ cambiare lingua a runtime con un click. In un 
nostro applicativo, ogni utente ha una sua lingua preferita, ma nella 
schermata di login ha le bandierine ITA-ENG-FRA-RUS, e puï¿œ cambiare al 
volo.
 
Se invece andiamo a parlare di altre forme grafiche, come il cirillico, 
oltre alla traduzione serve anche l'uso di specifici controlli Unicode, 
ma ï¿œ un aspetto a parte.
 
Alberto
 
 

Se non devi far tradurre all'utente il testo ma lo fai tu, io ti consiglio:
Array( 1 to nControllo , 1 To nLingua)
Se poi nel form utilizzi una matrice di controlli Label(1), Label(2)... fai 
ancora pi� veloce a caricare le stringhe con un semplice ciclo for
Ciao. 
 
 

 Di quante form si parla?
 
Ciao Andrea, sono circa 20
 
-- 
Greg 
 
 

 quelle non validate e si traducono.
 
Molto, molto scientifico e professionale. Compliments!
Ma una cosa mi salta subito all'attezione, e non saprei come fare: gestire 
messagebox e impubox in lettura/scrittura (Title, prompt...) inoltre 
esistono solo quanlo li chiamo e non si pososno iterare...quindi come fare?
 
-- 
Greg 
 
 

 solo quanlo li chiamo e non si pososno iterare...quindi come fare?
 
Quelli li devi cercare nel codice, sostituendo il testo cablato nel 
codice con una chiamata alla funzione che restituisca il testo 
equivalente nella lingua attiva.
E ovviamente per ogni stringa devi fare un insert nel db, sempre 
marcandolo come "non validato", per poi tradurlo.
Questo, of course, si fa a manina...
 
Alberto
 
 

 Questo, of course, si fa a manina...
 
Aggiungo che volendo, si pu� fare una enum sul tipo di messaggio.
 
Tipo
GetMessage ( myEnum.ErroreSalvataggio)
 
Invece di mettere proprio il testo specifico, cos� si pu� cambiare "una
virgola" senza noie.

 virgola" senza noie.
 
Beh, piï¿œ o meno ï¿œ come ï¿œ fatto.
Nel senso che io posso chiamare una cosa del tipo (vado a memoria)
Traduttore.TraduciControllo(Label1, LinguaAttiva)
e viene tradotto uno specifico controllo.
Oppure posso chiedere un testo
Traduttore.DammiTesto("ERRORE SALVATAGGIO", LinguaAttiva)
L'enum ï¿œ piï¿œ bella, ï¿œ vero, ma se devo aggiungere un tipo di messaggio 
devo aggiungerlo sia nell'enum che nel db, mentre con una chiamata con 
una banale stringa il metodo del traduttore puï¿œ restituirla o, se ï¿œ 
attivato in modalitï¿œ di "popolamento mancanti", lo stesso traduttore 
quando viene invocato va a scrivere nel db che gli ï¿œ stato chiesto di 
restituire in francese il testo corrispondente a "Errore Salvataggio", 
questo testo ï¿œ mancante, quindi crea un record marcato come "non 
validato".
Dopo aver fatto girare l'applicativo in debug per un po', nel db ci si 
ritrova tutto ciï¿œ che manca e lo si completa.
 
Alberto
 
 

 Alberto
 
Il problema ï¿œ che sono centinaia, tutte diverse.
A parte il lavoraccio di trattarle una ad una, come fare a distinguerle 
una dall'altra? I controlli hanno un nome univoco, ma le msgbox....
 
-- 
Greg
 
 

 una dall'altra? I controlli hanno un nome univoco, ma le msgbox....
 
E' un trova/sostituisci, ti fai una funzione che accetta gli stessi
parametri della msgbox e via.
 
Il problema semmai � riuscire a passarci in tutte per inserirle nel DB,
probabilmente in questo caso puoi cercare con notepad++ all'interno di
tutto il progetto e fai le insert del DB a mano.

 Alberto
 
Grazie di tutte le dritte Alberto.
 
Intanto mi son fatto la funzione che mi popola il dizionario italiano e 
quella che legge la lingua lingua corrente.
Anche in questo modo si cambia lingua senza chiudere e riaprire il 
programma.
Le posto qui sotto per avere critiche e commenti, e magari potranno essere 
utile spunto per qualcun altro.
 
Sub ScriviLang(Frm As Form)
Dim C As Control, DbL As Database, Nome As String, Testo As String
Set DbL = DBEngine.OpenDatabase(App.Path & "\dbLang.mdb")
DbL.Execute ("delete * from T_Lang where Form = '" & Frm.Name & "'")
On Error Resume Next
For Each C In Frm
    Nome = C.Name
    If Not IsNull(C.Index) Then Nome = Nome & "(" & C.Index & ")"
    Nome = Replace(Nome, "'", "''")
    Testo = C.Caption
    If TypeOf C Is CommandButton Then
        DbL.Execute "Insert into T_Lang (Form, TipoControl, NomeControl, 
Ita) Values('" & Frm.Name & "',  'Command','" & Nome & "', '" & Testo & 
"')", dbFailOnError
    End If
    If TypeOf C Is Menu Then
        DbL.Execute "Insert into T_Lang (Form, TipoControl, NomeControl, 
Ita) Values('" & Frm.Name & "',  'Menu','" & Nome & "', '" & Testo & "')", 
dbFailOnError
    End If
    If TypeOf C Is Label Then
        DbL.Execute "Insert into T_Lang (Form, TipoControl, NomeControl, 
Ita) Values('" & Frm.Name & "',  'Label','" & Nome & "', '" & Testo & "')", 
dbFailOnError
    End If
Next
End Sub
 
Non sono riuscito a evitare l'errore quanto testo se il controllo fa parte 
di una matrice e ho dovuto mettere un Resume Next che non mi piace.
 
 
E qui la sub che traduce:
(da notare che traduce solo se trova qualcosa nella lingua prescelta, 
altrimenti lascia in Italiano.)
 
Sub Traduci(F As Form)
Dim C As Control, DbL As Database, RsL As Recordset, Nome as String
Select Case Lingua
    Case Is = "Eng"
        Campo = 4
End Select
Set DbL = DBEngine.OpenDatabase(App.Path & "\dbLang.mdb")
q = "Select * from T_Lang  where Form = '" & F.Name & "'"
Set RsL = DbL.OpenRecordset(q)
Do While Not RsL.EOF
    For Each C In F
        If TypeOf C Is CommandButton Then
            Nome = C.Name
            On Error Resume Next
            If Not IsNull(C.Index) Then Nome = C.Name & "(" & C.Index & ")"
            If Nome = RsL!NomeControl Then
                If RsL.Fields(Campo) > "" Then C.Caption = RsL.Fields(Campo)
                Exit For
            End If
        End If
    Next
    RsL.MoveNext
Loop
End Sub
 
 
 
-- 
Greg 
 
 

di una matrice e ho dovuto mettere un Resume Next che non mi piace.
 
Nome = Nome & "(" & Indice(C) & ")"
 
Private Function Indice(C As Object) As Long
    On Error Goto Errore
    Indice=C.Index
    Exit Function
Errore:
    Indice=-1
End Function
 
 
 
 
 
 
 
 

 End Function
 
Grazie Federico :)
 
-- 
Greg 
 
 

 Alberto
 
Tutto ero come dici, ma pesandoci su un poco in vari momenti mi pare ancora 
piu lungo di come sembrava in un primo momoento.
- copiare il testo della msgbox in una variabile posta 2 righe sopra; la 
variabile direi che meglio farla cominciare con un progressivo, altrimenti 
come si fa distinguere una msgbox da un'altra?
- chiamare la sub che scrive la variabile nel database
- cancellare o commentare la sub che ormai non serve piu
- commentare la variabile che a sto punto serve solo per ricordre a me cosa 
ho scritto nel messaggio
questi sono i passaggi preliminari (a parte la truduzione)
 
poi in esecuzione:
- leggere il testo che comincia con quel numero e passarlo alla messagebox
 
Ci sono troppi passaggi manuali :(
Devo trovare un modo per accorciare, semplificare, ingegnerizzare.....
E ovviamente ogni indicazione � graditissima :)
 
-- 
Greg 
 
 

 ... ingegnerizzare.....
= incasinare
 
 
 

 = incasinare
 
 
ho visto il tuo suggerimento e te ne ringrazio: "Array( 1 to nControllo 
, 1 To nLingua)"
Ho scelto il vocabolario (database) perchï¿œ mi ï¿œ sembrato equivalente ma 
molto pi comodo. In ogni caso la parte label e caption ï¿œ stata superata 
alla grande, il problema resta sulle msgbox. Qui non ho ancora deciso 
nulla, e mi pareva di aver capito che il tuo suggerimento non era 
applicabile alle msgbox, oppure ho capito male?
Ciao
Greg
 
-- 
Greg