Support multilangue

Support multilangue

Ajouté le mercredi 27 janvier 2016 par Seyjin
  • Auteur du tutorial: Seyjin

Salut salut,

Par souci d'être accessible au plus grand nombre d'utilisateurs, beaucoup (trop) de jeux sont fait exclusivement en anglais. Avouons que c'est dommage. Voyons ça ensemble...


Multilangue, méthode simple
Nous allons, pour commencer poser nos objets "Chaîne" dans la scène. Et définissons pour chacun deux paragraphes, l'un en français et l'autre en anglais.


Ajoutons-leur également un qualifieur, "Bon" par exemple, le qualifieur importe peu, cela sert juste à les grouper.


Posons ensuite deux objets actifs, ajoutons-leur un qualifieur, "Boutons" :

Ces deux drapeaux nous servirons de boutons pour changer la langue. Pour cela, définissons-leur une valeur, 1 et 2 (c'est normalement 0 et 1 mais il y à une erreur d'indexation des paragraphes), correspondant aux paragraphes 0 et 1.


Il nous faut définir aussi une valeur globale dans les propriétés de l'application, en fait on peut laisser "Valeur globale A" mais là appelons-là "L simple".


Allons maintenant dans l'éditeur d'événements, créons deux événements :

• En début de scène
         [Le timer] : Lancer l'événement "Langue" après 00" -00

• Lors de l'événement timer "Langue"
         [Groupe Bon] : Afficher le paragraphe L simple

Le premier événement ne fait que lancer le second. L'utilité est qu'en plus d'aérer son click-code (et donc de facilement s'y retrouver) ça permet d'exécuter les action à partir de plusieurs événements différents, c'est justement ce que nous allons faire.
Et le deuxième événement  redéfini le paragraphe correspondant à la valeur globale "L simple" de tous les objets du groupe "Bon".

Pour finir, un troisième événement.

• L'utilisateur clique avec le bouton gauche sur [groupe Boutons]
         [Conditions spéciales] : Fixer L simple à Langue( "Groupe Boutons" )
         [Le timer] : Lancer l'événement "Langue" après 00" -00

C'est à dire que quand l'utilisateur clique sur un objet du groupe "boutons", on redéfini la valeur globale "L simple" sur la valeur "Langue" de ce bouton. Puis on lance l'événement "Langue".

Ça nous fait maintenant une belle interface multilangue. Avouez que c'est quand même plus classe comme ça.

Multilangue, Méthode Fichier ini
La manipulation d'un fichier ini ne sera pas détaillé ici Pour cela, je vous renvois au tuto de Monos sur les fichiers ini (quoi que un peu confus je trouve), il n'est néanmoins pas nécessaire pour ce tutoriel.
Le fichier ini utilisé à été encodé en UTF-8 (sans BOM).

Bon, reprenons notre précédente partie. Et à la place des valeurs modifiable des drapeaux, définissons les chaînes modifiables sur Fra et Eng.

"Fra" et "Eng" correspondent aux groupes dans notre ficher ini

Code: (Multilangue.ini)
[Fra]
Sous-titre=Méthode Fichier ini
1_N=Nouvelle Partie
2_E=Éditeur de Carte
3_S=Succès
4_P=Paramètres
5_Q=Quitter
[Eng]
Sous-titre=ini File Methode
1_N=New Game
2_E=Map Editor
3_S=Achievements
4_P=Settings
5_Q=Leave

Nous allons aussi définir une autre chaîne globale, au doux nom de "L ini" et par défaut égale à Fra.

Sans oublier d'ajouter l'objet ini, donnons-lui pour nom ./Multilangue.ini et décochons la case en dessous.


Dans l'éditeur d'événement, modifions l'un de nos événements

L'utilisateur clique avec le bouton gauche sur [groupe Boutons]
         [Conditions spéciales] : Fixer L ini à Langue( "Groupe Boutons" )
         [Le timer] : Lancer l'événement "Langue" après 00" -00

Notons bien qu'ici "L ini" et Langues sont des chaînes et non plus des valeurs comme sur la méthode d'avant.

Modifions également un autre de nos événements

Lors de l'événement timer "Langue"
         [1 Novelle] : Fixer la chaine modifiable à GroupItemString$( "Ini", L ini, "1_N" )
         [2 Éditeur] : Fixer la chaine modifiable à GroupItemString$( "Ini", L ini, "2_E" )
         ...

En clair, on va chercher dans le fichier ini le texte de chacun des objets "Chaîne" à traduire ("1 Novelle" — oui j'ai fait une faute, mais la flemme de modifier l'exemple —, "2 Éditeur", "3 Succes"...).

Multilangue, Méthode Adaptative
Cette méthode a un grand avantage : elle permet de pouvoir ajouter autant de langues que l'on veut sans avoir besoin de modifier l'application, ça c'est vraiment cool.

Pour ça, reprenons ce qu'on à déjà fait. Et à la place des deux objets Actifs qui servent de boutons plaçons un objet Liste.

Nous avons aussi besoin de changer la structure du fichier ini

Code: (Multlangue_Fr.ini)
[Chaines]
Langue=Français
Sous-titre=Méthode Adaptative
1_N=Nouvelle Partie
2_E=Éditeur de Carte
3_S=Succès
4_P=Paramètres
5_Q=Quitter

On remarque qu'il n'y a qu'une seule langue. Il suffira par la suite de copier le fichier en changeant les dernières lettres pour chacune des langues.

Nous allons aussi définir une autre chaîne globale, au doux nom de "L adaptative" et par défaut égale à Multilangue_fr.ini (remarquons au passage comment cette ligne a été sauvagement copiée/collée :P).

Dans l'éditeur d'événements, ajoutons d'abord une action à l'événement d'entrée de scène

En début de scène
         [Le timer] : Lancer l'événement "Langue" après 00" -00

         [Liste] : Charger la liste des fichiers de Apppath$ + "Multilangue_*.ini"

Puis modifions l'événement qui suit

• [Liste] : Sélection modifiée
         [Conditions spéciales] : Fixer L adaptative à List Select$( "Liste" )
         [Le timer] : Lancer l'événement "Langue" après 00" -00

Ce qui fait que quand l'utilisateur clique sur l'une des lignes de la liste, on redéfini la chaîne globale "L adatative" sur la ligne en question.

Nous n'avons plus qu'à modifier le dernier événement

Lors de l'événement timer "Langue"
         [Ini] : Fixer fichier courant à Apppath$ + L adaptative
         [1 Novelle] : Fixer la chaine modifiable à GroupItemString$( "Ini", "Chaines", "1_N" )
         [2 Éditeur] : Fixer la chaine modifiable à GroupItemString$( "Ini", "Chaines", "2_E" )
         ...

Voilà voilà, ce petit tutoriel est terminé. Mais restons un peu pour voire quelques petits trucs en bonus...

Multilangue, Bonus Stages

1-01 / La simpification
Au tout début, nous avons utiliser les valeurs des drapeaux (valeurs ou chaînes modifiables — ça fait bizarre comme ça mais les chaînes sont classées avec les valeurs —) en utilisant un qualifieur pour déterminer la langue. Pourquoi ne pas faire pareil pour aller chercher les textes dans le ficher ini et ainsi simplifier l'événement (parce qu'avec 42 lignes à traduire par exemple, c'est un peu long) ?

En fait, puisque les objets Chaînes n'ont pas de valeurs, nous utiliseront les paragraphes.

         [Groupe Bon] : Fixer la chaine modifiable à GroupItemString$( "Ini", "Chaines", paragraph$( "Groupe Bon", 0 ) )

(Notons qu'ici le numéro du paragraphe est bien 0 contrairement à toute à l'heure)

2-01 / ini automatique
Dans l'exemple qui accompagne ce tuto, on doit appuyer sur une touche pour créer les fichiers ini nécessaire. Mais ça serait mieux que cela se fasse automatiquement.

Nous pouvons utiliser l'objet Fichier pour détecter la présence (ou plutôt la non-présence) des fichiers, ou mieux, nous allons comparer la taille du fichier. Il nous faut aussi les objets Chaîne (qui contient le texte du fichier ini) et Rich Edit, déjà présents dans l'exemple.

La condition se trouve dans les Conditions spéciales → Comparer deux valeurs générales. La valeur à indiquer est la taille en octets du fichier ini.

• Sizeof( "Fichier 2", Apppath$ + "Multilangue_Fr.ini" ) < 177
         [Rich Edit] : Changer le texte en paragraph$( "Fichier", 0 )
         [Rich Edit] : Enregistrer le texte "Multilangue_Fr.ini"

Ici, "Fichier" est notre objet Chaîne et "Fichier 2" est l'objet Fichier, ce dernier n'étant pas prévu au début de ce tutoriel. Et on fait pareil pour les autres langues.

3-01 / Le retour des drapeaux
Une chose a disparue quand nous sommes passés à la méthode adaptative : les jolis drapeaux. Du coup, nous allons voir comment les avoir de nouveau.

Ajoutons déjà un élément dans nos fichiers ini pour indiquer l'image à afficher :

Code: (Multilangue_Fr.ini)
...
Image=MultilangueFr.bmp
...

Et pour les importés, nous utiliserons un Image Active avec une chaîne modifiable nommée Langue (que nous pouvons poser à l'extérieur de la scène). Ajoutons aussi un objet Actif invisible (pour ça, décochons "visible en début de scène" dans ses propriétés) qui servira pour créer la liste des drapeaux.

Modifions l'événement de début de scène pour ajouter une petite boucle.

En début de scène
         [Le timer] : Lancer l'événement "Langue" après 00" -00
         [Liste] : Charger la liste des fichiers de Apppath$ + "Multilangue_*.ini"

         [Conditions spéciales] : Démarrer la boucle "Drapeaux" List Nb Lines ( "Liste" ) fois

Ok, comme ça, ça peut paraitre confus. Cela signifie que la boucle "Drapeaux" sera exécutée pour chaque ligne de la Liste. Par exemple, si il y a 3 lignes la boucle sera faite 3 fois.

Donc :

• Lors de la boucle "Drapeaux"
         [Création de nouvel objet] : Créer "Image Active" à (0,0) de "Marqueur"
         [Image Active] : Fixer Langue à List Line Text$( "Liste", loopIndex("Drapeaux") + 1 )

Pause ! Un peut d'explications : List Line Text$( ) signifie qu'on va chercher le contenu d'une ligne d'un objet Liste, "Liste" c'est donc le nom de l'objet, loopIndex("Drapeaux") + 1 est le numéro de la ligne qu'on veut (qui correspond à l'index de la boucle + 1, puisque les boucles sont indexées sur 0)

         [Ini] : Fixer fichier courant à Apppath$ + Langue( "Image Active" )
         [Image Active] : Nouvelle image: Apppath$ + GroupItemString$( "Ini", "Chaines", "Image" )

Là, on affiche l'image indiquée dans le fichier ini.

         [Marqueur] : Fixer la position en Y à Y( "Marqueur" ) + 18

Cette dernière action déplacera le Marqueur de 18 pixels vers le bas pour la ligne suivante.

Bon, j'avoue, j'avais un peu le cerveau en ébullition. Pas de panique, c'est terminé. Enfin presque, un tout petit détail :

• L'utilisateur clique avec le bouton gauche sur [Image Active]
         [Conditions spéciales] : Fixer L adaptative à Langue( "Image Active" )
         [Le timer] : Lancer l'événement "Langue" après 00" -00

C'est tout pour aujourd'hui

3-02 / Parchemins
Nous voilà au bout de ce tuto. J'espère qu'il aura été bénéfique pour de nombreuses personnes. J'ai moi même découvert quelques trucs en le faisant.

Bon, avant de se quitter, il nous reste une petite chose à voire. C'est bien joli d'avoir refait un système de drapeaux, mais si il y à beaucoup de langues on va avoir un problème et certains vont se retrouver en dehors de la scène.

Du coup ça serait bien de pouvoir les faire défiler à l'aide de la roulette de la souris. Nous allons nous servir du Marquer vu précédemment. Nommons une de ses valeurs Défilement, par défaut égale à 0.

Premier événement :

• La roulette de la souris est bougée vers le haut
+ Défilement de [Marqueur] = 0
         [Marqueur] : Fixer défilement à 6

Pourquoi 6 ?
C'est pour faire plus simple en fait. Les drapeaux sont décalés de 18 pixels. Si nous les faisons se décaler 6 fois de suite de 3 pixels, ça nous fait un mouvement fluide et bien aligné.

• Défilement de [Marqueur] > 0
         [Image Active] : Fixer La position en Y à Y( "Image Active" ) - 3
         [Marqueur] : Soustraire 1 à Défilement

l'événement se répétera tant que la valeur Défilement sera supérieur à 0.

Voyons maintenant pour ramener les drapeaux qui sont tout en bas en haut de la liste :

• La position en Y de [Image Active] = Y( "Marqueur" )
         [Image Active] : Fixer la position en Y à Y( "Marqueur" ) - 18 * (NObjects( "Image Active" ) - 1 ) )

Donc, si la position d'un drapeau est égale à celle du marqueur (qui est tout en bas), il est déplacé 18 fois le nombre de drapeaux pixels plus haut. Et le -1 c'est parce qu'on a un objet Image Active en plus qui à servi pour l'ajouter à la scène.

Il ne reste plus qu'a faire là même chose pour le défilement vers le haut.