Domanda

Voglio localizzare un programma che ho già scritto .. È abbastanza grande (quasi 50k righe) e idealmente voglio un sistema che mi permetta (il programmatore) di fare il minor lavoro possibile, e senza grandi cambiamenti al programma - se possibile nessuno.

Ho guardato gettext () e mi è piaciuto molto, ma non mi è chiaro come tradurrebbe stringhe come queste:

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

che sono MOLTO comuni nel mio programma. Qui sostituendo " Rosso " con gettext (" Red ") ovviamente non funzionerebbe.

Quindi ho pensato di fare qualcosa come OutputFunction (gettext (Colors [Id])), ma come posso ottenere un elenco di stringhe da localizzare? Dubito che qualsiasi programma sia abbastanza intelligente da riuscire a ottenere "Rosso", "Blu", "Giallo" da quello in un elenco da localizzare staticamente.

Dato che è fondamentalmente un server, non è necessario modificare la lingua senza ricompilare (posso compilarla per ogni lingua supportata senza problemi o fastidi importanti), ho pensato a constexpr di C ++ 0x, che sarebbe perfezionare! Funzionerebbe in array / etc e otterrei facilmente un elenco di stringhe da localizzare in fase di compilazione .. Peccato che nessun compilatore lo abbia ancora implementato.

Cambiare tutte le stringhe in un ID non è un'opzione poiché richiederebbe una grande quantità di lavoro da parte mia e soprattutto la creazione di un nuovo ID per ogni nuova stringa sarebbe fastidiosamente infernale. Lo stesso vale per convertire tutti gli array come quello sopra in qualcos'altro.

Quindi, qualche idea? : /

È stato utile?

Soluzione 2

Dopo aver giocato un sacco con gettext () e xgettext, penso di aver trovato un modo me stesso (scusate qualcuno ma non mi è piaciuto il vostro approccio. Devono esserci centinaia di array come questo e dovrei importare tutto di loro in main (), c'è molto lavoro esterno e molto lavoro extra: /).

Ad ogni modo, è così che penso che possa teoricamente essere fatto (non ho ancora provato a tradurre effettivamente ma non vedo perché non funzionerebbe)

Due # definisci:

#define _ gettext
#define __(x) x

Quindi usi _ per tradurre effettivamente e __ per contrassegnare semplicemente le stringhe come " da tradurre " ;:

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

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

Quindi esegui:

xgettext -k_ -k__ *.cpp

E ottieni il seguente file .po:

#: 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 ""

Quindi, usi __ (o qualsiasi altro nome, non importa davvero) come una funzione fittizia " per far sapere a xgettext che la stringa deve essere tradotta e _ per chiamare effettivamente gettext ().

Se chiami _ con una stringa, anche la stringa verrà contrassegnata per essere tradotta, se la chiami con una variabile, un array, qualunque cosa sembri essere semplicemente ignorata da xgettext.

Grande! Ora tutto ciò che devo fare è passare attraverso 5 trilioni di file e aggiungere caratteri di sottolineatura, come se fossi una scimmia: /

Altri suggerimenti

Per il tuo esempio specifico, potrei provare qualcosa del tipo:

// 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 chiama gettext su ogni input e scrive un output. Penso che potrebbe essere implementato proprio come una chiamata a std :: transform. E potresti evitare il parametro size con un po 'di trucco con i template.

Un'altra opzione è quella di chiamare gettext nel punto in cui una delle stringhe di colore sta per essere utilizzata (visualizzata o aggiunta a una stringa per la visualizzazione). Ciò significa cambiare più codice, ma non richiede che main () traduca ogni serie di stringhe nel programma prima di fare qualsiasi cosa che possa usarle.

Se non vuoi fare il lavoro in main, puoi farlo nel codice che usa le stringhe, qualcosa del genere:

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

O se la tua app è multithread, considera pthread_once o l'equivalente nell'API thread che usi.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top