Gestion des langues

Partagez votre expérience de PureBasic avec les autres utilisateurs.
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Gestion des langues

Message par Dr. Dri »

PB ne gère pas encore l'unicode en natif, enfin bon ca peut toujours aider à faire dans le multilingue. Avec l'ascii on peut déjà faire un programme qui supporte les langues latines et germaniques (ca fait déjà un très bon panel multilingue!)

Code : Tout sélectionner

Enumeration
  #LANG_NEUTRAL
  #LANG_ARABIC
  #LANG_BULGARIAN
  #LANG_CATALAN
  #LANG_CHINESE
  #LANG_CZECH
  #LANG_DANISH
  #LANG_GERMAN
  #LANG_GREEK
  #LANG_ENGLISH
  #LANG_SPANISH
  #LANG_FINNISH
  #LANG_FRENCH
  #LANG_HEBREW
  #LANG_HUNGARIAN
  #LANG_ICELANDIC
  #LANG_ITALIAN
  #LANG_JAPANESE
  #LANG_KOREAN
  #LANG_DUTCH
  #LANG_NORWEGIAN
  #LANG_POLISH
  #LANG_PORTUGUESE
  #LANG_ROMANIAN   = 24
  #LANG_RUSSIAN
  #LANG_CROATIAN
  #LANG_SERBIAN    = 26
  #LANG_SLOVAK
  #LANG_ALBANIAN
  #LANG_SWEDISH
  #LANG_THAI
  #LANG_TURKISH
  #LANG_URDU
  #LANG_INDONESIAN
  #LANG_UKRAINIAN
  #LANG_BELARUSIAN
  #LANG_SLOVENIAN
  #LANG_ESTONIAN
  #LANG_LATVIAN
  #LANG_LITHUANIAN
  #LANG_FARSI      = 41
  #LANG_VIETNAMESE
  #LANG_ARMENIAN
  #LANG_AZERI
  #LANG_BASQUE
  #LANG_MACEDONIAN = 47
  #LANG_AFRIKAANS  = 54
  #LANG_GEORGIAN
  #LANG_FAEROESE
  #LANG_HINDI
  #LANG_MALAY      = 62
  #LANG_KAZAK
  #LANG_SWAHILI    = 65
  #LANG_UZBEK      = 67
  #LANG_TATAR
  #LANG_BENGALI
  #LANG_PUNJABI
  #LANG_GUJARATI
  #LANG_ORIYA
  #LANG_TAMIL
  #LANG_TELUGU
  #LANG_KANNADA
  #LANG_MALAYALAM
  #LANG_ASSAMESE
  #LANG_MARATHI
  #LANG_SANSKRIT
  #LANG_KONKANI    = 87
  #LANG_MANIPURI
  #LANG_SINDHI
  #LANG_KASHMIRI
  #LANG_NEPALI
EndEnumeration

#LOCALE_SISO639LANGNAME = $59

Structure Longs
  l.l[0]
EndStructure

Structure DLGTEMPLATEEX Extends DLGTEMPLATE
    menu.w
    class.w
    title.l
EndStructure

Structure LangRequesterParams
  Title.s
  Text.s
  IconID.l
  Pattern.s
EndStructure

Procedure.s GetLangName(Locale.l)
  Protected LangName.s, Temp.s, Length.l
 
  Length = GetLocaleInfo_(Locale, #LOCALE_SNATIVELANGNAME, #Null, #Null)
 
  If Length > 0
    Temp = Space(Length - 1)
    GetLocaleInfo_(Locale, #LOCALE_SNATIVELANGNAME, Temp, Length)
   
    LangName = UCase( Left (Temp, 1) )
    LangName + LCase( Right(Temp, Length - 2) )
  EndIf
 
  ProcedureReturn LangName
EndProcedure

Procedure.s GetLangCode(Locale.l)
  Protected LangCode.s, Length.l
 
  Length = GetLocaleInfo_(Locale, #LOCALE_SISO639LANGNAME, #Null, #Null)
 
  If Length > 0
    LangCode = Space(Length - 1)
    GetLocaleInfo_(Locale, #LOCALE_SISO639LANGNAME, LangCode, Length)
  EndIf
 
  ProcedureReturn LangCode
EndProcedure

Procedure.l GetLangLocale(LangCode.s)
  Protected Locale.l, Done.l
 
  If Len(LangCode) = 2
    While Locale < #LANG_NEPALI And Done = #False
      Locale + 1
     
      If LangCode = GetLangCode(Locale)
        Done = #True
      EndIf
    Wend
  EndIf
 
  If Done = #False
    Locale = #Null
  EndIf
 
  ProcedureReturn Locale
EndProcedure

Procedure.l IsLangSupported(Locale.l)
  ProcedureReturn (GetLangLocale( GetLangCode(Locale) ) = Locale) Or #False
EndProcedure

Procedure.l LangRequesterCallback(WindowID.l, Message.l, wParam.l, lParam.l)
  Protected *params.LangRequesterParams
  Protected Title.s, Text.s, IconID.l, Pattern.s
  Protected Temp.l, x.l, y.l, cx.l, cy.l, Locale.l, Location.s
  Protected SH.SHFileInfo, rc.RECT
 
  Static Image, Label, ComboLangs, ButtonOK, ButtonCancel, nLangs, *Langs.Longs
 
  Select Message
    Case #WM_INITDIALOG
      *params = lParam
      Title   = *params\Title
      Text    = *params\Text
      IconID  = *params\IconID
      Pattern = *params\Pattern
     
      MoveWindow_(WindowID, 0, 0, 297, 125, #False)
      
      GetClientRect_(WindowID, rc)
      cx = (2 * 297) - (rc\right - rc\left)
      cy = (2 * 125) - (rc\bottom - rc\top)
      
      x = (GetSystemMetrics_(#SM_CXSCREEN) - cx) / 2
      y = (GetSystemMetrics_(#SM_CYSCREEN) - cy) / 2
      
      MoveWindow_(WindowID, x, y, cx, cy, #False)
     
      If Title = #NULL$
        Title = "Language configuration"
      EndIf
     
      If Text = #NULL$
        Text = "Please select a language."
      EndIf
     
      If IconID = #Null
        Location = Space($500)
        GetModuleFileName_(#Null, Location, $500)
       
        SHGetFileInfo_(Location, 0, SH, SizeOf(SHFileInfo), #SHGFI_ICON|#SHGFI_LARGEICON)
        IconID = SH\hIcon
      EndIf
     
      SetWindowText_(WindowID, Title)
     
      CreateGadgetList(WindowID)
      Image        = ImageGadget(#PB_Any, 8, 8, 32, 32, IconID)
      Label        = TextGadget(#PB_Any, 53, 8, 235, 32, Text)
      ComboLangs   = ComboBoxGadget(#PB_Any, 53, 56, 235, 100)
      ButtonOk     = ButtonGadget(#PB_Any, 133, 93, 75, 23, "OK", #PB_Button_Default)
      ButtonCancel = ButtonGadget(#PB_Any, 214, 93, 75, 23, "Cancel")
     
      Temp = CountString(Pattern, "|") + 1
     
      For x = 1 To Temp
        Locale = GetLangLocale( StringField(Pattern, x, "|") )
       
        If Locale
          AddGadgetItem(ComboLangs, #PB_Default, GetLangName(Locale))
          nLangs + 1
        EndIf
      Next x
     
      If nLangs > 0
        *Langs = AllocateMemory(SizeOf(Long) * nLangs)
        nLangs = 0
        
        SetGadgetState(ComboLangs, 0)
        
        For x = 1 To Temp
          Locale   = GetLangLocale( StringField(Pattern, x, "|") )
          
          If Locale
            If Locale = GetUserDefaultLangID_() & $FF
              SetGadgetState(ComboLangs, nLangs)
            EndIf
            *Langs\l[nLangs] = Locale
            nLangs + 1
          EndIf
        Next x
        
        ActivateGadget(ComboLangs)
      Else
        EndDialog_(WindowID, #LANG_NEUTRAL)
      EndIf
      
    Case #WM_COMMAND
      If lParam = #Null Or lParam = GadgetID(ButtonCancel) Or lParam = GadgetID(ButtonOK)
        If lParam = GadgetID(ButtonOK)
          x = GetGadgetState(ComboLangs)
          Locale = *Langs\l[x]
        Else
          Locale = #LANG_NEUTRAL
        EndIf
       
        FreeMemory(*Langs)
        EndDialog_(WindowID, Locale)
      EndIf
     
  EndSelect
 
  ProcedureReturn #Null
EndProcedure

Procedure.l LangRequester(Title.s, Message.s, IconID.l, Pattern.s)
  Protected Template.DLGTEMPLATEEX, Params.LangRequesterParams
 
  Template\style = #WS_SYSMENU|#WS_CAPTION|#DS_CENTER|#DS_MODALFRAME
  Template\cx    = 303
  Template\cy    = 150
 
  Params\Title   = Title
  Params\Text    = Message
  Params\IconID  = IconID
  Params\Pattern = Pattern
 
  Lang = DialogBoxIndirectParam_(#Null, Template, WindowID(), @LangRequesterCallback(), Params)
 
  ProcedureReturn Lang
EndProcedure
Dri
Dernière modification par Dr. Dri le mer. 19/oct./2005 11:11, modifié 5 fois.
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Message par Anonyme2 »

J'adopte :D
lionel_om
Messages : 1500
Inscription : jeu. 25/mars/2004 11:23
Localisation : Sophia Antipolis (Nice)
Contact :

Message par lionel_om »

J'v tester :wink:
Webmestre de Basic-univers
Participez à son extension: ajouter vos programmes et partagez vos codes !
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

J'ai remanié vite fait les fonctions qui étaient déjà là et j'en ai ajouté une qui m'a pris deux bonnes heures (sans compter les recherches pour trouver comment faire).

Et là bien sûr les problèmes:
Comment avec une fenêtre dont on ne connait que le handle, changer sa taille, mais juste la partie où on met les gadgets ? (comme en PB)

Sinon deux ptits exemples :

Code : Tout sélectionner

Select LangRequester("Mais qui es-tu ?", "Toi, oui toi! Tu es ?", #Null, "en|fr|de|it|es")
  Case #LANG_ENGLISH
    Debug "I love rosbeaf"
  Case #LANG_FRENCH
    Debug "Chui un malpoli"
  Case #LANG_GERMAN
    Debug "Ich bin ein Berliner"
  Case #LANG_ITALIAN
    Debug "Yé bouffe des macaronis"
  Case #LANG_SPANISH
    Debug "Aye carramba"
  Default
    Debug "Suis pas dans la liste <_<"
EndSelect

Code : Tout sélectionner

For i = #LANG_ARABIC To #LANG_NEPALI
  If IsLangSupported(i)
    Debug GetLangCode(i) + " " + GetLangName(i)
  EndIf
Next i
Dri ;)
Dernière modification par Dr. Dri le mar. 18/oct./2005 17:03, modifié 2 fois.
Avatar de l’utilisateur
Chris
Messages : 3731
Inscription : sam. 24/janv./2004 14:54
Contact :

Message par Chris »

Code:
For i = #LANG_ARABIC To #LANG_NEPALI
If GetLangLocale( GetLangCode(i) ) = i ;si la langue est supportée
Debug GetLangCode(i) + " " + GetLangName(i)
EndIf
Next i
T'as l'intention de vendre tes progs au Dalaï Lama ?

Ils ont pas l'electricité pour faire tourner les ordinateurs! :roll:
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

@Chris
T'as rien compris, je vais programmer un "J'apprend le Népali en 90 leçons" (sur mon ptit 98 cette langue n'est pas supportée :lol:)

bon c'est l'usine à gaz mais j'ai modifiée la callback pour correctement gérer la taille de la fenêtre.

Dri
Avatar de l’utilisateur
Chris
Messages : 3731
Inscription : sam. 24/janv./2004 14:54
Contact :

Message par Chris »

Et en plus, je me suis planté, (mais personne n'a relevé... Tant mieux...), le Dalaï Lama, c'est pas au Népal, c'est au Tibet :oops:
lionel_om
Messages : 1500
Inscription : jeu. 25/mars/2004 11:23
Localisation : Sophia Antipolis (Nice)
Contact :

Message par lionel_om »

Il me manque une structure (v3.93), j'peux pas le faire tourner ! :cry:
(j'c plus c laquelle)
Webmestre de Basic-univers
Participez à son extension: ajouter vos programmes et partagez vos codes !
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

@lio
donne moi plus de détails dès que t'as le temps

sinon j'aimerais avoir des échos... je n'ai que mon ptit windows 98 donc je sais pas si ca fonctionne sur las autres windows...
Et éventuellement si y'a des choses à changer ou améliorer...

Dri
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

ca marchais pas avec XP, j'ai modifié la callback en conséquence (grace à un de mes contacts msn)

a priori y'a plus de problème, mais si vous en trouvez dites-le ^^
(faudrait essayer avec les autres windows aussi)

Dri
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

Bon c'est bien beau d'avoir une gestion des langues mais maintenant y'a rien de concret. Donc je me lance dans un petit exemple de multilingue faisant appel aux resources (stringtable)

alors d'abord un fichier de resource multilingue avec en exemple deux chaines de caractere dans deux langues différentes.

Code : Tout sélectionner

#define LANG_ENGLISH  9
#define LANG_FRENCH  12

#define SUBLANG_DEFAULT 1

STRINGTABLE
LANGUAGE LANG_FRENCH, SUBLANG_DEFAULT
{
    1, 	"Français"
    2, 	"France"
}

STRINGTABLE
LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
{
    1, 	"English"
    2, 	"England"
}
faut pas oublier de dire au compilateur de compiler le fichier rc avec l'exe
là c'est un exemple de fonction maison pour récupérer une chaine
elle gère sans probleme la longueur de la chaine et renvoie une chaine vide si elle n'existe pas

Code : Tout sélectionner

Procedure.s LoadString(Library.l, Index.l)
  Protected String.s, Length, LibraryID.l
  Shared    ModuleID.l
  
  If ModuleID = #Null
    ModuleID = GetModuleHandle_(#Null)
  EndIf
  
  If Library = #PB_Default
    LibraryID = ModuleID
  Else
    If IsLibrary(Library)
      LibraryID = LibraryID(Library)
    EndIf
  EndIf
  
  If LibraryID
    Repeat
      Length + $400
      String = Space(Length)
    Until LoadString_(LibraryID, Index, String, Length) < (Length - 1)
  EndIf
  
  ProcedureReturn String
EndProcedure
maintenant un programme d'exemple...

Code : Tout sélectionner

Debug LoadString(#PB_Default, 1)
Debug LoadString(#PB_Default, 2)
Debug LoadString(#PB_Default, 3)
Chez moi le debugger affiche:
Français
France
C'est bien beau comme méthode, ca m'affiche la resource dans la langue de l'utilisateur (si elle existe) mais si avec le (superbe :lol:) LangRequester je choisis une autre langue ? Comment faire ?

Dans ce cas il faut mettre les stringtable dans des fichiers dll séparés. par exemple dans un dossier 'lang' y'aurait fr.dll, en.dll et de.dll

De cette manière en chargeant les dll (LoadLibrary) il est possible d'utiliser la fonction LoadString en spécifiant le numéro PB de la dll ^^

Dri ;)
lionel_om
Messages : 1500
Inscription : jeu. 25/mars/2004 11:23
Localisation : Sophia Antipolis (Nice)
Contact :

Message par lionel_om »

Simpa mais faut apprendre à utiliser les ressources... :? même si ca doit pas être tré compliqué (du moin spour gérer cet usage)

Par contre le problème de ce système c'est que c'est du compilé. Pour l'instant je préfère encore les fichiers de type ".prefs" ou ".ini".
Mais bon faut voir, car si ca peut se présenter sous la forme de DLL, ca peut être cool ! :lol:
Webmestre de Basic-univers
Participez à son extension: ajouter vos programmes et partagez vos codes !
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

lionel_om a écrit :Simpa mais faut apprendre à utiliser les ressources... :? même si ca doit pas être tré compliqué (du moin spour gérer cet usage)

Par contre le problème de ce système c'est que c'est du compilé. Pour l'instant je préfère encore les fichiers de type ".prefs" ou ".ini".
Mais bon faut voir, car si ca peut se présenter sous la forme de DLL, ca peut être cool ! :lol:
L'avantage des resource c'est que ca peut se hacker, par exemple resourcehacker le fait, donc même si c'est compilé c'est modifiable

Dri ;)
lionel_om
Messages : 1500
Inscription : jeu. 25/mars/2004 11:23
Localisation : Sophia Antipolis (Nice)
Contact :

Message par lionel_om »

oki.
Et c'est doncx modifiable que par des gens qui s'y connaisse un peu en info, donc les données seront dans un format correct au final, donc ca veut dire moins de contrôle de fiabilité des données...

Cool ! :lol:
Webmestre de Basic-univers
Participez à son extension: ajouter vos programmes et partagez vos codes !
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

lionel_om a écrit :oki.
Et c'est doncx modifiable que par des gens qui s'y connaisse un peu en info, donc les données seront dans un format correct au final, donc ca veut dire moins de contrôle de fiabilité des données...

Cool ! :lol:
ca veut aussi dire que tu peux programmer toi même un patch pour modifier les resources. mais bon j'ai pas encore le niveau pour proposer un exemple :lol: ResourceHacker en est juste la preuve ^^

Dri ;)
Répondre