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.
2. Sommaire
• Introduction
• Traduction par la méthode «standard»
Sommaire
• La traduction automatique
de votre interface
• Astuces, pièges à éviter
• Conclusion
2
3. Introduction
• Présentation
•
Introduction
Olivier Halligon
• Food Reporter
Food Reporter
• Objectif
• Base de la traduction
• Traduction auto de XIB
3
4. Traduction par la
méthode «standard»
Traduction par la méthode «standard»
• Ressources localisées
• Fichiers «strings»
• Limitations de cette méthode
4
5. Ressources localisées
Traduction par la méthode «standard»
• Un dossier «.lproj» par locale
• Locale = langue + région (en_US, en_UK)
• Dans le dossier .lproj
• Images
• XIB
• Textes
5
6. Fichiers «strings»
Traduction par la méthode «standard»
• 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
7. En pratique
Traduction par la méthode «standard»
• 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
8. Limitations de cette méthode
Traduction par la méthode «standard»
• 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
9. La traduction automatique
de votre interface
La traduction automatique de votre interface
• Principe
• Automatisation : éviter le glue code
• Aller plus loin
9
10. Principe
La traduction automatique de votre interface
• 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
11. Automatisation
La traduction automatique de votre interface
But : appeler automatiquement la méthode
awakeFromNib
• Sous-classer et surcharger
• Pas pratique, et lourd à mettre en place
• Catégories
• Pas fait pour, et aucune garantie
• Method Swizzling
11
12. Automatisation
La traduction automatique de votre interface
Method Swizzling : intervertir deux implémentations
[obj awakeFromNib]; awakeFromNib { ??? }
Avant -(void)myAwakeFromNib {
[obj myAwakeFromNib]; [self autoL10n];
[self awakeFromNib];
}
[obj awakeFromNib]; awakeFromNib { ??? }
Après
-(void)myAwakeFromNib {
[obj myAwakeFromNib]; [self autoL10n];
[self myAwakeFromNib];
}
12
13. Automatisation
La traduction automatique de votre interface
! Method awakeFromNib = class_getInstanceMethod([NSObject class], @selector(awakeFromNib));
! Method localizeNibObject = class_getInstanceMethod([NSObject class], @selector(localizeNibObject));
! method_exchangeImplementations(awakeFromNib, localizeNibObject);
Lorsqu’un objet recevera le message awakeFromNib,
c’est sa méthode localizeNibObject qui sera exécutée
#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
}
Cette méthode va appeler une méthode différente en fonction du type d’élément.
13
14. Automatisation
La traduction automatique de votre interface
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.
14
15. Aller plus loin
La traduction automatique de votre interface
• Personnalisation possible du code
• Vérifier les oublis de traduction
• Gérer les exceptions (chaînes fictives)
• Gérer les variantes singulier/pluriel
#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";
15
16. Les astuces
Les pièges à éviter
Les astuces, les 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
17. Impacts sur l’interface
Les astuces, les pièges à éviter
• Différentes tailles selon la langue
• sizeToFit Push
• Images à taille variable
• stretchableImageWithLeftCapWidth:topCapHeight:
• Tester !!
17
18. Intégration avec un SI
Les astuces, les pièges à éviter
• 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
19. Gérer l’ordre des
paramètres
Les astuces, les pièges à éviter
• 5 green apples
• NSLog(«%1$d %2$@ %3$@»,n,color,fruit)
• 5 pommes vertes
• NSLog(«%1$d %3$@ %2$@»,n,color,fruit)
19
20. Formattage des
nombres
Les astuces, les pièges à éviter
• NSNumberFormatter
• séparateur de décimales, de milliers
• monnaie (currency)
• Utiliser les versions localisées des méthodes
• localizedStringWithFormat
• localizedDescription
• localizedScannerWithString
• ...
20
21. Suivi de versions
Les astuces, les pièges à éviter
• 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
22. Conclusion
• Traduction d’application se fait en plusieurs
étapes
Conclusion
• 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