Bonnes pratiques de traduction
muqaddar
Administrateur
Hello,
Je venais voir si il y avait des bonnes habitudes à prendre sur les chaà®nes côté traductions.
Vous êtes plutôt:
J'avais pris l'habitude de mettre un "k", comme NSLocalizedString(@kNewProduct, @"");
mais ça peut être un problème sur les chaà®nes sans majuscule NSLocalizedString(@kproduct, @""); qui sont peu lisibles.
Par contre j'aimais bien l'idée de voir ce "k" tout de suite dans l'app, afin que la chaà®ne non traduite nous saute aux yeux.
Je venais voir si il y avait des bonnes habitudes à prendre sur les chaà®nes côté traductions.
Vous êtes plutôt:
NSLocalizedString(@"NewProduct", @"");<br />NSLocalizedString(@"New Product", @"");<br />NSLocalizedString(@"kNewProduct", @"");<br />NSLocalizedString(@"New_Product", @"");
J'avais pris l'habitude de mettre un "k", comme NSLocalizedString(@kNewProduct, @"");
mais ça peut être un problème sur les chaà®nes sans majuscule NSLocalizedString(@kproduct, @""); qui sont peu lisibles.
Par contre j'aimais bien l'idée de voir ce "k" tout de suite dans l'app, afin que la chaà®ne non traduite nous saute aux yeux.
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
C'est une partie d'un de mes localizable.strings.
Enfin c'est assez vieux, maintenant je met plutôt "TITLE_" en préfixe. (OK, c'est un léger changement )
En fait l'intérêt c'est surtout de préciser au futur traducteur le genre de chaque morceau à traduire.
Par exemple, pour des actions je fais:
Comme ça il sait que ça fait partie des actions.. histoire qu'il n'y ait pas de quiproquo dans certaines langues..
Surtout pas de constantes, ça ferait bien trop lourd à gérer je trouve.. D'ailleurs tu t'es planté je pense dans tes exemples.. le "kMachinChose" ne devrait pas avoir les double-quote vu que c'est une constante.. enfin si tu as voulu le faire passer pour une constante.. sinon je trouve ça bizarre de mettre @kMachinChose... C'est plutôt NSString *const kMachinChose = @MachinChose; (enfin c'est ce que je fais)
k étant le k de Key.
L'inconvénient avec ta méthode c'est que tu n'indiques pas au traducteur les minuscules et majuscules dans la clé. Tu me diras si tu files le fichier en anglais il verra ce qu'on a fait dans la valeur.
Bref tout ceci a beaucoup d'avantages :
- des fichiers .strings proprement organisés, aérés, et facilement navigables depuis Xcode avec le menu
- des constantes organisées par groupes
- une facilité pour détecter les clés manquantes dans certaines langues, une détection aisiée des constantes qui n'ont pas de traduction
- une meilleure compréhension et lisibilité
Par contre en dehors des chaà®nes localisables, par exemple pour mon code quand j'ai une constante à définir pour indiquer par exemple je sais pas, la durée d'une animation, là je la déclare (directement dans le code donc) souvent avec un k au début de son nom genre [tt]const float kAnimationDuration = 2.0f;[/tt].
J'utilise aussi la macro _T() qui est pratique.
Je vais utiliser MARK également pour classer.
Merci pour tous ces détails.
Ainsi si j'avais suivi cette idée j'aurais nommé mes clés "[tt]feed.nearby.cell.nbrates.%d[/tt]" plutôt que juste "[tt]feed.nearby.cell.nbrates[/tt]" ou "[tt]locationChooser.location.%@[/tt]" plutôt que "[tt]locationChooser.location.format[/tt]".
Et comme ça en les utilisant avec on a une cohérence dans la chaà®ne de format, retrouvant que je dois m'attendre à un "[tt]%@[/tt]" dans la chaà®ne traduite quelle que soit la langue, et donc ce qui attend un argument de type [tt]NSString[/tt] à suivre dans ma macro.
Du coup je risque pas d'oublier que j'ai un argument à mettre quand j'utilise cette chaà®ne (au risque d'avoir un crash au runtime si l'argument en question n'est pas mis dans mon code) et je ne risque pas de mettre un nombre au lieu d'une chaà®ne ou vice-versa.
Si je prévoyais un affichage en coordonnées GPS à la place d'afficher l'adresse, j'aurais pu alors avoir une autre clé par exemple et en l'utilisant dans mon code, le nom de la clé m'aurait rappelé que je devais passer 2 float en paramètre après cette clé pour que ça marche (et pas une NSString ou quoi que ce soit d'autre)
Bon il se trouve que j'ai pas gardé l'astuce car j'ai pas pris l'habitude de l'utiliser et qu'il n'est plus trop temps de remplacer toutes mes clés dans mon fichier pour coller à cette idée.
Mais je la trouvais sympa pour rendre le code à la fois plus "sûr" via ce "rappel" et plus lisible car le code continuait à ressembler à un "format à la printf" et on comprenais en lisant le code pourquoi après le nom de la clé on passait des entiers ou des float ou des NSString... faudrait que je la remette au goût du jour tiens.
Par exemple, je n'ai pas besoin de traduire les pluriels à la volée.
Bien sûr je nomme mes clés en conséquence, faut pas être concon comme tu dis. Si c'est un texte générique genre "OK" ou "Annuler" ou un texte qui sera forcément le même à différents endroits dans l'application bah je vais pas nommer ma clé "feed.nearby.cell.nbnotes" mais "restaurant.nbnotes" plutôt, si c'est générique à tous les restaurants.
Mais dans certains cas (pas mal en fait dans mon contexte) je l'ai séparé/dupliqué et j'ai bien fait, parce que en français j'affiche le même texte à 3 endroits dans l'appli... mais en anglais les textes sont différents, parce que le texte en anglais est plus long et que dans le 2e contexte où je l'utilise il ne rentre pas car n'a pas la place donc je vais mettre sa version abrégée. Et ce n'est qu'un exemple.
Bref faut être cohérent.
- Bien sûr si tu utilises exactement le même texte à plusieurs endroits dans l'appli, tu ne vas pas répéter la clé. Mais évidemment faut pas être concon, pour reprendre ton expression : dans ce cas il est évident que tu ne vas pas nommer ta clé un truc comme "feed.nearby.cell.notes" mais "restaurant.notes", bref toujours avec le même principe de notation URL-inversée mais en adaptant le contexte de nommage, ça va de soit.
- D'ailleurs, dans mes nommages, j'ai un "package" de clés qui commence par "generic." aussi pour tous les textes génériques (OK, Annuler, ...)
- Mais si tu utilises un texte spécifique dans plusieurs endroits, même si c'est le même texte en français dans les 2 endroits, ce n'est pas toujours judicieux d'utiliser la même clé. D'une part parce que dans une autre langue selon le contexte la formulation ne sera pas pareil (déjà eu le cas plusieurs fois), d'autre part parce que parfois dans certains contextes un texte en espagnol ou allemand rentre et dans un autre il faut l'abréger, et enfin parce qu'ainsi si tu veux modifier le texte utilisé pour à cet endroit ça risque pas d'avoir un effet de bord et modifier le texte à l'autre endroit (ça m'est déjà arrivé aussi, j'ai voulu changer une traduction de "%d notes" en "%d notes ont été postées", ce qui remplissait mieux l'écran et était plus joli... sauf que j'avais oublié que j'utilisais la même clé ailleurs et que dans cet autre endroit le texte ne rentrais pas...
Si tu utilises une clé que tu utiliseras aussi ailleurs car elle est générique, tu la nommes en conséquence.
Si tu utilises une clé spécifique et que tu sais que le texte sera utilisé explicitement à un endroit précis dans l'app, tu la nommes en conséquence.
Faut pas être concon
Quand je dis plus tard, c'est dans une version ultérieur, donc tu le sais pas au moment où tu écriras ton feed.nearby.cell.nbrates.
Ca ne m'est de toute façon jamais arrivé il me semble, malgré toutes les versions et évolutions qu'on a faites depuis le début de FR. Et si ça m'arrivait je préfère avoir tous les avantages de ma méthode et un truc proprement organisé qui ne risque pas de faire des effets de bord (en modifiant le texte d'une clé qui se trouve être utilisée en fait à plein d'endroits différents*) et occasionnellement avoir à faire un rechercher/remplacer (oh mon Dieu ça prend 5s) qu'à l'inverse avoir des clés génériques qui n'ont pas trop de cohérence dans leur nommage et qu'on risque d'utiliser à mauvais escient dans des contextes séparés là où ça risque de poser pb* et d'avoir des traductions décontextualisées.
*Car j'espère que tu es un minimum consciencieux et que si tu modifies la valeur d'une clé tu penses à vérifier tous les effets de bord, en particulier que dans toutes les langues le nouveau texte ne dépasse pas et tienne toujours dans ta fenêtre... quoique sur Mac tu as peut-être moins le cas avec les fenêtres redimentionnables mais sur iOS surtout sur iPhone ça fait partie des choses qu'il faut vérifier avec la taille d'écran fixe et limitée)
Or si cette clé est utilisée dans les 150 écrans de ton appli faut penser à passer partout...! Et vérifier que partout où elle est utilisée elle ne dépasse pas.
Alors qu'avec des clés spécifiques tu sais tout de suite où tu dois repasser dans tes écrans pour vérifier, et tu n'as pas de risque de dépendances
En tout cas je tenterai ta méthode dans mon prochain projet, parce que ça me plaà®t beaucoup, même si c'est moins "évident" pour le traducteur.. mais normalement la phrase lui suffit, et si y'a un contexte particulier les commentaires sont là pour ça
Alors qu'avec "nbnotes" il sait pas trop s'il faut écrire "%d notes" ou "%d notes dans ce restaurant" ou "%d notes sur ce plat" ou quoi, avec "restaurant.nbnotes" il sait que c'est le nombre de notes d'un resto, et si c'est pas une clé générique mais spécifique comme "feed.nearby.restaurant.nbnotes" il sait que c'est un nombre de notes d'un des restaurants affichés dans le feed "Nearby" ("A proximité"), d'autant que ça l'est rappellé autant dans le commentaire "MARK: " que j'ai au dessus que dans le commentaire à côté de ma clé en fin de la ligne.
C'est aussi pour ça que j'aime cette notation, elle aide aussi le traducteur à re-situer le contexte dans lequel est utilisée la chaà®ne (parce que sinon une clé "done" il faut traduire ça par "Terminé", "Valider", "OK" ou "Fini" ?) ce qui donne de meilleures traductions.
Quand je vois des traductions foireuses dans certains jeux ou applis où tu vois que le mot a été traduit hors contexte et que du coup ç'en est risible (et tu finis par comprendre ce que ça veux dire seulement parce que tu vois à quel mot en anglais peut correspondre ce mot que tu vois en français, et comprend alors les traductions alternatives et ce qu'ils voulaient vraiment dire), raison de plus pour aider le traducteur en lui donnant encore plus d'indices sur le contexte dans lequel est utilisé ton texte !
https://github.com/Cocoanetics/DTLocalizableStringScanner
Non testé.
J'aime pas genstrings car d'une part je n'aime pas trop le format de fichier .strings qu'il génère (mais bon encore ça va on peut toujours ajuster après) mais surtout parce que c'est une plaie de faire des mises à jour de fichiers par ce biais...
Et puis bon de toute façon il n'est pas trop compatible avec des usages plus poussés de la traduction comme les miens :
Bref, genstring pourrait être une bonne idée à la base, bien pour débuter au tout début avec un projet simpliste et quand on ne génère les fichiers .string qu'à la toute fin du projet, mais autrement il n'est vraiment pas adapté. Je connais d'ailleurs personne qui l'utilise, même s'ils connaissent son existence.
Un ";" ou un " qui manque... et patatra Xcode nous signale une erreur mais ne précise JAMAIS la ligne.
Y-a-til une astuce pour la trouver car ça devient vite un enfer avec un fichier à 500 lignes ?
Merci pour cette astuce !
Sinon, rien de moins artisanal avec Xcode ?
Moi c'est comme ça que je fais en tout cas.
[font=arial,helvetica,sans-serif] J'ai vraiment été désagréablement surpris quand j'ai voulu faire des mises à jour la 1ère fois avec genstrings. Du coup je l'utilise pour la première génération, après je fais tout à la main.
Ca me parait vraiment intéressant ton système de macros. Utilises-tu "localizedStringForKey:value:table:" dans ta macro ?
Comment gères-tu les mises à jours ?
C'est toujours un problème de trouver un système pratique pour faire traduire juste les mises à jours sans passer des heures (10aines de minutes) à fusionner les fichiers après coup.[/font]
Une autre chose qui est difficile à faire c'est de donner du contexte aux traducteurs. Les commentaires sont souvent insuffisants si le traducteur ne peut pas utiliser l'app. En plus quand tu es en train d'écrire du code, tu n'as pas la tête à te lancer dans des explications pour les traducteurs.
Je cherche toujours le système idéal qui permettrait aux traducteurs de voir les chaà®nes dans le contexte de l'app sans avoir à utiliser l'app.
Et pour le contexte, c'est pour ça que j'utilise une notation à la "URL-inversée" qui aide encore un peu à comprendre le contexte, même si c'est pas idéal. Mais au moins comme ça quand je fais une version OTA à mon traducteur, il peut voir clairement où il manque des clés et quel est leur nom complet.
Mais _userInfo est déclarée @private et je ne sais pas y acceder!!! Y a t-il une solution?
Je vais ajouter une vérification des .strings dans mon logiciel Localise.