Question

Je veux localiser un programme que j'ai déjà écrit. Il est assez volumineux (presque 50 000 lignes) et, idéalement, je veux un système qui me permette (au programmeur) de faire le moins de travail possible, sans modifications majeures du programme - si possible aucun.

J'ai regardé gettext () et l'ai beaucoup aimé, mais je ne vois pas comment cela traduirait des chaînes telles que celles-ci:

const char *Colors[] = {
 { "Red" },
 { "Blue" },
 { "Yellow" },
 ....
};

qui sont TRÈS répandus dans mon programme. Remplacez ici " Red " avec gettext ("Red") ne fonctionnerait évidemment pas.

Alors j'ai pensé faire quelque chose comme OutputFunction (gettext (Colors [Id])), mais comment puis-je obtenir une liste de chaînes à localiser? Je doute qu'un programme soit suffisamment intelligent pour pouvoir obtenir les symboles "Rouge", "Bleu", "Jaune". à partir de cela dans une liste à localiser de manière statique.

Etant donné qu’il s’agit d’un serveur, il n’est pas nécessaire de changer de langue sans recompiler (je peux le compiler pour chaque langue prise en charge sans problème majeur ni gêne), j’ai pensé au constexpr de C ++ 0x, qui serait parfait! Cela fonctionnerait dans les tableaux / etc et j'aurais facilement une liste de chaînes à localiser au moment de la compilation. Dommage qu’aucun compilateur ne l’ait encore implémenté.

Remplacer toutes les chaînes par un identifiant n’est pas une option, cela nécessiterait un travail énorme de ma part. Créer un nouvel identifiant pour chaque nouvelle chaîne serait particulièrement ennuyant. Il en va de même pour la conversion de tous les tableaux, comme celui ci-dessus, en quelque chose d'autre.

Alors, des idées? : /

Était-ce utile?

La solution 2

Après avoir beaucoup joué avec gettext () et xgettext, je pense avoir trouvé le moyen de le faire moi-même (désolé un par un mais je n’ai pas aimé votre approche. Il doit y avoir des centaines de tableaux comme celui-ci et d’entre eux dans main (), c’est beaucoup d’externes et beaucoup de travail supplémentaire: /).

Quoi qu'il en soit, voici comment je pense que cela peut théoriquement être fait (je n'ai pas encore essayé de traduire, mais je ne vois pas pourquoi cela ne fonctionnerait pas)

Deux # définitions:

#define _ gettext
#define __(x) x

Vous utilisez ensuite _ pour traduire et __ simplement marquer les chaînes comme "à traduire":

const char *Colors[] = {
 { __("Red") },
 { __("Blue") },
 { __("Yellow") },
 ....
};

void PrintColor(int id) {
    cout << _("The color is: ") << _(Colors[id]);
}

Ensuite, vous lancez:

xgettext -k_ -k__ *.cpp

Et vous obtenez le fichier .po suivant:

#: test.cpp:2
msgid "Red"
msgstr ""

#: test.cpp:3
msgid "Blue"
msgstr ""

#: test.cpp:4
msgid "Yellow"
msgstr ""

#: test.cpp:9
msgid "The color is: "
msgstr ""

Donc, vous utilisez __ (ou tout autre nom, cela n'a pas d'importance) en tant que "fonction fictive". simplement laisser xgettext savoir que la chaîne doit être traduite et _ appeler réellement gettext ().

Si vous appelez _ avec une chaîne, celle-ci sera également marquée comme si elle devait être traduite. Si vous l'appelez avec une variable, un tableau, quoi que ce soit, elle apparaît simplement ignorée par xgettext.

Génial! Il ne me reste plus qu'à parcourir 5 trillions de fichiers et y ajouter des traits de soulignement, comme si j'étais un singe: /

Autres conseils

Pour votre exemple spécifique, je pourrais essayer quelque chose comme:

// presumably globals
const char *Colors_en[] = {
 { "Red" },
 { "Blue" },
 { "Yellow" },
 ....
};
const char *Colors[] = {0};

// in main()
gettextarray(Colors_en, Colors, sizeof(Colors_en) / sizeof(char*));

gettextarray appelle gettext sur chaque entrée et écrit une sortie. Je pense que cela pourrait être implémenté comme un appel à std :: transform. Et vous pouvez éviter le paramètre de taille avec un peu de ruse dans les modèles.

Une autre option consiste à appeler gettext au point où l’une des chaînes de couleur est sur le point d’être utilisée (affichée ou ajoutée à une chaîne pour l’affichage). Cela signifie changer plus de code, mais ne nécessite pas que main () traduise chaque ensemble de chaînes du programme avant de faire quoi que ce soit qui pourrait les utiliser.

Si vous ne voulez pas faire le travail dans main, vous pouvez le faire dans le code qui utilise les chaînes, quelque chose comme ceci:

if (Colors[0] == 0)
  gettextarray(Colors_en, Colors, sizeof(Colors_en) / sizeof(char*));

Ou si votre application est multithread, considérez pthread_once ou son équivalent dans l'API de thread que vous utilisez.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top