CocoaHeads Rennes #1 : internationalisation

23
Traduction des interfaces de vos applications Cocoa Olivier Halligon, avril 2011

description

Slides de la présentation "Traduction automatique et intelligente d'applications Cocoa" de la session des CocoaHeads Rennais du 21 avril 2011. Présentation assurée par Olivier Halligon, créateur de Food Reporter.

Transcript of CocoaHeads Rennes #1 : internationalisation

Page 1: CocoaHeads Rennes #1 : internationalisation

Traduction des interfaces de vos applications Cocoa

Olivier Halligon, avril 2011

Page 2: CocoaHeads Rennes #1 : internationalisation

Som

mai

re

Sommaire

• Introduction

• Traduction par la méthode «standard»

• La traduction automatiquede votre interface

• Astuces, pièges à éviter

• Conclusion

2

Page 3: CocoaHeads Rennes #1 : internationalisation

Intr

oduc

tion

Introduction

• Présentation

• Olivier Halligon

• Food Reporter

• Objectif

• Base de la traduction

• Traduction auto de XIB

3

Food Reporter

Page 4: CocoaHeads Rennes #1 : internationalisation

Trad

uctio

n pa

r la

mét

hode

«st

anda

rd»

Traduction par la méthode «standard»

• Ressources localisées

• Fichiers «strings»

• Limitations de cette méthode

4

Page 5: CocoaHeads Rennes #1 : internationalisation

Trad

uctio

n pa

r la

mét

hode

«st

anda

rd»

Ressources localisées

• Un dossier «.lproj» par locale

• Locale = langue + région (en_US, en_UK)

• Dans le dossier .lproj

• Images

• XIB

• Textes

5

Page 6: CocoaHeads Rennes #1 : internationalisation

Trad

uctio

n pa

r la

mét

hode

«st

anda

rd»

Fichiers «strings»

• Textes dans fichier «Localizable.strings»• /* Text to say hello */

"greetings" = "Welcome in Food Reporter!";

• /* Text to say hello */"greetings" = "Bienvenue sur Food Reporter !";

• NSLocalizedString• NSLocalizedString(@"greetings",@"Text to say hello")

• genstrings

• Outil de génération des fichiers .strings après analyse du code source

6

Page 7: CocoaHeads Rennes #1 : internationalisation

Trad

uctio

n pa

r la

mét

hode

«st

anda

rd»

En pratique

• Macro longue n’incitant pas à l’utiliser

• XIB compliqué pour le traducteur

• N’a pas forcément Interface Builder (ou ne maîtrise pas l’outil)

• Préfère un simple fichier texte

• genstrings peu pratique

• Ajout de texte au fur et à mesure des versions

• extraction et réinjection de chaînes dans les XIB (par ibtool) peu pratique

7

Page 8: CocoaHeads Rennes #1 : internationalisation

Trad

uctio

n pa

r la

mét

hode

«st

anda

rd»

Limitations de cette méthode

• Duplication des XIB

• Maintenance et évolutions complexe

• Modifications à répercuter pour chaque langue

• Compliqué pour le traducteur

• Un XIB unique ?

• Traduction des éléments un à un par code

• Nécessite d’avoir un IBOutlet sur chaque élément d’interface

8

Page 9: CocoaHeads Rennes #1 : internationalisation

La t

radu

ctio

n au

tom

atiq

ue d

e vo

tre

inte

rfac

e

La traduction automatiquede votre interface

• Principe

• Automatisation : éviter le glue code

• Aller plus loin

9

Page 10: CocoaHeads Rennes #1 : internationalisation

La t

radu

ctio

n au

tom

atiq

ue d

e vo

tre

inte

rfac

e

Principe

• Une méthode générique sachant traduire chaque type d’élément de l’UI

• Appeler à chaque chargement de XIB

• Appeler sur tous les éléments du XIB

10

Page 11: CocoaHeads Rennes #1 : internationalisation

La t

radu

ctio

n au

tom

atiq

ue d

e vo

tre

inte

rfac

e

Automatisation

• Sous-classer et surcharger• Pas pratique, et lourd à mettre en place

• Catégories• Pas fait pour, et aucune garantie

• Method Swizzling

But : appeler automatiquement la méthode

awakeFromNib

11

Page 12: CocoaHeads Rennes #1 : internationalisation

La t

radu

ctio

n au

tom

atiq

ue d

e vo

tre

inte

rfac

e

Automatisation

[obj awakeFromNib]; awakeFromNib { ??? }

[obj myAwakeFromNib];

-(void)myAwakeFromNib { [self autoL10n]; [self awakeFromNib];}

Method Swizzling : intervertir deux implémentations

12

[obj awakeFromNib]; awakeFromNib { ??? }

[obj myAwakeFromNib];

-(void)myAwakeFromNib { [self autoL10n]; [self myAwakeFromNib];}

Avant

Après

Page 13: CocoaHeads Rennes #1 : internationalisation

La t

radu

ctio

n au

tom

atiq

ue d

e vo

tre

inte

rfac

e

Automatisation! Method awakeFromNib = class_getInstanceMethod([NSObject class], @selector(awakeFromNib));! Method localizeNibObject = class_getInstanceMethod([NSObject class], @selector(localizeNibObject));! method_exchangeImplementations(awakeFromNib, localizeNibObject);

13

#define LocalizeIfClass(Cls) if ([self isKindOfClass:[Cls class]]) localize##Cls((Cls*)self)-(void)localizeNibObject {! LocalizeIfClass(UIBarButtonItem);! else LocalizeIfClass(UIBarItem);! else LocalizeIfClass(UIButton);! else LocalizeIfClass(UILabel);! else LocalizeIfClass(UINavigationItem);! else LocalizeIfClass(UISearchBar);! else LocalizeIfClass(UISegmentedControl);! else LocalizeIfClass(UITextField);! else LocalizeIfClass(UITextView);! else LocalizeIfClass(UIViewController);!! [self localizeNibObject]; // actually calls awakeFromNib as we did some method swizzling}

Lorsqu’un objet recevera le message awakeFromNib,c’est sa méthode localizeNibObject qui sera exécutée

Cette méthode va appeler une méthode différente en fonction du type d’élément.

Page 14: CocoaHeads Rennes #1 : internationalisation

La t

radu

ctio

n au

tom

atiq

ue d

e vo

tre

inte

rfac

e

Automatisation

14

Il suffit de traduire chaque type d’objet. Par exemple pour un label:

static inline void localizeUILabel(UILabel* lbl){ lbl.text = NSLocalizedString(lbl.text); }

pour qu’un UILabel soit automatiquement traduit,il suffira alors de lui mettre la clé de traduction dans son champ text.

De la même manière, pour un UITextField:

static inline void localizeUITextField(UITextField* tf){ tf.text = NSLocalizedString(tf.text); tf.placeholder = NSLocalizedString(tf.placehoder); }

Si on veut qu’un élément ne soit pas traduit, on peut imaginer rajouter un caractère précis devant le texte de cet élément, comme par exemple «$», et dans sa méthode

de localisation, ne le traduire que s’il ne commence pas par ce caractère.

Page 15: CocoaHeads Rennes #1 : internationalisation

La t

radu

ctio

n au

tom

atiq

ue d

e vo

tre

inte

rfac

e

Aller plus loin

• Personnalisation possible du code

• Vérifier les oublis de traduction

• Gérer les exceptions (chaînes fictives)

• Gérer les variantes singulier/pluriel

15

#define _T(x) NSLocalizedString((x),@"")#define _Tf(x,...) [NSString stringWithFormat:_T(x),__VA_ARGS__]#define _Tf_n(x,n,...) _Tf( (n<=1)?(x):(x"(+)") , n , ##__VA_ARGS__ )

NSString* s1 = _Tf_n(@"dish.comments.count",n);NSString* s2 = _Tf_n(@"user.dishes.count",n,userName);

"dish.comments.count" = "%d commentaire";"dish.comments.count(+)" = "%d commentaires";

"user.dishes.count" = "%2$@ a publié %$1d plat";"user.dishes.count(+)" = "%2$@ a publié %$1d plats";

Page 16: CocoaHeads Rennes #1 : internationalisation

Les

astu

ces,

les

pièg

es à

évi

ter

Les astucesLes pièges à éviter

• Impacts sur l’interface

• Intégration avec un SI

• Gérer l’ordre des paramètres

• Penser au formattage des nombres

• Suivi de version

16

Page 17: CocoaHeads Rennes #1 : internationalisation

Les

astu

ces,

les

pièg

es à

évi

ter

Impacts sur l’interface

• Différentes tailles selon la langue

• sizeToFit

• Images à taille variable

• stretchableImageWithLeftCapWidth:topCapHeight:

• Tester !!

17

Push

Page 18: CocoaHeads Rennes #1 : internationalisation

Les

astu

ces,

les

pièg

es à

évi

ter

Intégration avec un SI

• Applications utilisant un WebService

• Envoyer la locale au WS

• Utilisation de clés de localizable.strings dans le retour du WS

• Filtrage de contenu selon la locale

18

Page 19: CocoaHeads Rennes #1 : internationalisation

Les

astu

ces,

les

pièg

es à

évi

ter

Gérer l’ordre des paramètres

• 5 green apples

• NSLog(«%1$d %2$@ %3$@»,n,color,fruit)

• 5 pommes vertes

• NSLog(«%1$d %3$@ %2$@»,n,color,fruit)

19

Page 20: CocoaHeads Rennes #1 : internationalisation

Les

astu

ces,

les

pièg

es à

évi

ter

Formattage des nombres

• NSNumberFormatter

• séparateur de décimales, de milliers

• monnaie (currency)

• Utiliser les versions localisées des méthodes

• localizedStringWithFormat

• localizedDescription

• localizedScannerWithString

• ...

20

Page 21: CocoaHeads Rennes #1 : internationalisation

Les

astu

ces,

les

pièg

es à

évi

ter

Suivi de versions

• Version «live» pendant votre développement

• Version livrée aux divers traducteurs

• Versions itératives

• Attention aux chaînes liées avec le SI

• Plusieurs versions de votre application en circulation

21

Page 22: CocoaHeads Rennes #1 : internationalisation

Con

clus

ion

Conclusion

• Traduction d’application se fait en plusieurs étapes

• Internationalisation (i18n) : préparer les traduction (NSLocalizedString, ...)

• Localisation (L10n) : effectuer les traductions (créer un .strings par locale)

• Intégration d’une nouvelle langue pas si anodin

• Méthodes pour faciliter la traduction de XIB• Evite de multiplier les XIB pour chaque langue

• Facilite la communication avec vos traducteurs

22