Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

UTF-8, UCS-4, Unicode, wchar_t, std::string et std::wstring

9 réponses
Avatar
spam
Salut,

Avant toute chose, mon objectif : supporter tous les langues dans le
jeu Wormux (www.wormux.org, clone libre de Worms). Je voudrais
utiliser un conteneur STL si possible.

Je voudrais savoir s'il existe une solution simple et portable pour
utiliser les codes Unicode comme charset dans un programme. J'ai pas
mal lu sur ce sujet, mais je n'ai pas trouvé *la* solution. A ce que
j'ai compris, il existe principalement les encodages suivants :
- UTF-8 : Caractère codé sur une longueur variant de 1 à 6 octets.
Complexifie énormément l'accès aléatoire, la suppression à l'intérieur
d'une chaîne, etc. Solution courament choisie sous Linux
- UCS-4 (ou "UCS-32" ?) : Chaque caractère est codé sur 4 octets.
C'est la solution optimale (niveau CPU, pas mémoire) pour l'Unicode
4.0 (ou 4.1) car on peut rentrer tous les caractères dans 32 bits et
90% des processeurs actuels travaillent en 32 bits.
- UCS-2 (ou "UCS-16" ?) : Solution adoptée pour les Windows 95/98/Me.
On n'a accès qu'aux premiers 65536 caractères
- UTF-16 : Amélioration de l'UCS-2 sur Windows 2000/XP.

Maintenant, à ce que j'ai compris, le type "wchat_t" a une taille de 2
octets sous Windows ... pour raison historique (Windows 95 et son
UCS-2), alors que sous Unix on a directement 4 octets. De là, la
classe std::wstring travaille en UCS-2 ou UCS-4.

Je suis toujours bon jusque là ?
---
Maintenant, que faut-il faire pour avoir un std::wstring en UCS-4 à
tous les coups ? "typedef std::basic_string<uint32> mon_string_ucs4;"
?
---
Après ça se complique encore avec les caractères composés, comme é (e
accent aigu) = e + accent aigu (deux glyphes Unicode) ...

@+ Haypo

9 réponses

Avatar
Christophe de VIENNE
Victor STINNER wrote:
Salut,

Avant toute chose, mon objectif : supporter tous les langues dans le
jeu Wormux (www.wormux.org, clone libre de Worms). Je voudrais
utiliser un conteneur STL si possible.

Je voudrais savoir s'il existe une solution simple et portable pour
utiliser les codes Unicode comme charset dans un programme.


Personnellement, j'utiliserais UTF-8, gettext et si les manipulations de
chaines précises sont nécessaires, Glib::ustring qui propose la même
interface que std::string mais en tenant compte de l'encodage utf-8.

Ces choix se basent surtout sur les techno que je connais, et qui me
semble assez simple d'accès et portables, ils sont donc subjectifs.

A+

Christophe


--
Christophe de Vienne

Avatar
kanze
(Victor STINNER) wrote in message news:...

Avant toute chose, mon objectif : supporter tous les langues dans le
jeu Wormux (www.wormux.org, clone libre de Worms). Je voudrais
utiliser un conteneur STL si possible.

Je voudrais savoir s'il existe une solution simple et portable pour
utiliser les codes Unicode comme charset dans un programme.


Ca depend un peu des caracteres dont tu as besoin, et ce que tu entends
par " portable ". Dans l'absolu, " portable " et " affichage " sont
des contradictions -- pour commencer, tu ne peux pas afficher des
caracteres qui ne sont pas presentent dans la police utilisee, a
moins d'afficher tout en mode graphique (et alors, il n'y a rien
de portable).

J'ai pas
mal lu sur ce sujet, mais je n'ai pas trouvé *la* solution.


Parce qu'il n'y en a pas. A l'etat actuel, le probleme est
encore mal decerne ; il serait plus correct de parler d'autant
de problemes qu'il y a d'applications. Avec chacun sa propre
solution.

A ce que
j'ai compris, il existe principalement les encodages suivants :
- UTF-8 : Caractère codé sur une longueur variant de 1 à 6 octets.
Complexifie énormément l'accès aléatoire, la suppression à l'intérieur
d'une chaîne, etc. Solution courament choisie sous Linux


Surtout, solution adoptee par l'Internet, et plus generalement
pour la communication entre des ordinateurs. C'est aussi la solution
adoptee par quelque systemes pour l'enregistrement de texte dans
des fichiers.

Certains qui developpent sous Linux travaille dans cette direction.
Mais pour l'instant, la situation sous Linux est que chaque application
fait ce qu'elle veut.

- UCS-4 (ou "UCS-32" ?) : Chaque caractère est codé sur 4 octets.
C'est la solution optimale (niveau CPU, pas mémoire) pour l'Unicode
4.0 (ou 4.1) car on peut rentrer tous les caractères dans 32 bits et
90% des processeurs actuels travaillent en 32 bits.


La meilleur solution du point de vue technique, c'est certainement
UTF-8 en extern, et UCS-4 (ou UTF-32, ce qui revient au meme) en
intern. Certaines applications Linux (et Solaris ou HP/UX) l'ont
adopte, mais c'est loin d'etre universel. Sauf sous Plan 9.

- UCS-2 (ou "UCS-16" ?) : Solution adoptée pour les Windows 95/98/Me.
On n'a accès qu'aux premiers 65536 caractères
- UTF-16 : Amélioration de l'UCS-2 sur Windows 2000/XP.


C'est un peu plus complexe que ca. Historiquement, jusqu'a la version
3.1 (je crois) Unicode etait un code de 16 bits. Et on pretait
pas vraiment d'attention a la difference entre des UCS et des UTF,
c-a-d entre l'encodage et sa representation. C'est alors que Windows
a adopte Unicode, et on pourrait bien parler de UCS-2, voire pour
les formats externes (fichiers, etc.) UTF-16LE. Java s'est fait
avoir de la meme facon, mais le format extern est UTF-16BE.

Chez Unix, la situation est plus variee -- le systeme en fait impose
relativement peu, et beaucoup depend de l'application.

Maintenant, à ce que j'ai compris, le type "wchat_t" a une taille de 2
octets sous Windows ... pour raison historique (Windows 95 et son
UCS-2), alors que sous Unix on a directement 4 octets. De là, la
classe std::wstring travaille en UCS-2 ou UCS-4.


C'est beaucoup plus complique, et tous les systemes supportent
plusieurs solutions, pour des raisons historiques. Windows natif
est la plus homogene, avec UTF-16 intern, et UTF-16LE extern. En
supposant wchar_t, evidemment -- Windows supporte aussi char, avec
une variete d'encodages.

Sous Unix, AIX est tres proche de la solution Windows, sauf que le
format extern est UTF-16BE. Ce n'est pas etonnant -- IBM s'est
ralie a Java, et ce sont les conventions de Java. Solaris et HP/UX
ont un wchar_t de 32 bits, mais supportent par defaut des encodages
plus anciens -- je crois qu'ils ont aussi des locales qui supportent
Unicode, mais je ne les ai pas essaye. Extern, la tendance est vers
UTF-8, mais pour l'instant, on a surtout des declarations d'intention
que du support concret. Linux, c'est a peu mieux -- il n'y a pas
des encodages perimes a considerer, par exemple. Et le support au
niveau C est un peu plus avance que chez Solaris ou HP/UX. Mais
seulement un peu.

Je suis toujours bon jusque là ?

Maintenant, que faut-il faire pour avoir un std::wstring en UCS-4 à
tous les coups ? "typedef std::basic_string<uint32> mon_string_ucs4;"
?


Ce n'est pas si simple. Parce que std::basic_string exige plusieurs
parametres ; le deuxieme, par defaut, serait std::char_traits<uint32>.
Qui n'est pas defini par la norme -- il peut ne pas exister. (En fait,
et g++ et VC++ le fournir. Avec des definitions incompatible en ce qui
concerne les types non-signes.)

J'ai fait quelques experiences, que tu pourrais voir a ma site
(www.gabi-soft.fr). Mais mon but etait de fournir un type complet,
avec toute la fonctionalite. Et j'ai appris des choses depuis.
Tout depend de ce que tu veux faire avec les chaines, mais dans
certains cas, quelque chose du genre :

struct UTF32Traits { ... } ;
typedef std::basic_string< uint32, UTF32Traits > UTF32String ;

La definition de UTF32Traits est un peu longue, mais assez simple,
SAUF en ce qui concerne les types de position dans un fichier.

Pour la reste, il va falloir aussi que tu definisses un certain nombre
de facettes, selon ce que tu veux faire (mais au moins des facettes
de codecvt). Ce qui est loin d'etre evident.

Aussi, il n'y a pas de constantes de chaine pour ton nouveau
type de chaine. Et pas de conversion implicite entre char[] ou
wchar[] vers ton nouveau type.

Après ça se complique encore avec les caractères composés, comme é (e
accent aigu) = e + accent aigu (deux glyphes Unicode) ...


Unicode parle longuement sur les differentes representations
possibles d'un seul caractere, et comment les traiter. Voir a leur
site.

Et enfin, n'oublis surtout pas que l'affichage est independant
du C++. Il faut s'assurer que la police utilisee a l'affichage
utilise le meme encodage que ton programme, et autant que je sache,
il n'y a aucune solution portable pour ca.

--
James Kanze

Avatar
spam
wrote in message news:...
Ca depend un peu des caracteres dont tu as besoin,


Euh ... Et bien dans l'immédiat, j'aimerai pouvoir afficher des
chaînes en français, anglais, allemand, espagnol, polonais, hongrois
et portugais. Il me faut donc les lettres utilisées dans ces langues.

et ce que tu entends par " portable "


Que ça fonctionne sous Windows, Linux, FreeBSD, et ce, sur n'importe
quelle architecture (Big Endian / Little Endian, avec registres
internes du CPU en 32 ou 64 bits).

Dans l'absolu, " portable " et " affichage " sont
des contradictions -- pour commencer, tu ne peux pas afficher des
caracteres qui ne sont pas presentent dans la police utilisee,


Oui, c'est sûr. Je pense utiliser des polices TTF relativement
complètes (ex: une pour toutes les langues européennes, une autre pour
le chinois, etc.).

a moins d'afficher tout en mode graphique (et alors, il n'y a rien
de portable).


Je ne travaille qu'en mode graphique, ou presque (quelques messages
dans la console, comme "chargement du jeu ..." (messages localisés !).

La meilleur solution du point de vue technique, c'est certainement
UTF-8 en extern, et UCS-4 (ou UTF-32, ce qui revient au meme) en
intern. Certaines applications Linux (et Solaris ou HP/UX) l'ont
adopte, mais c'est loin d'etre universel. Sauf sous Plan 9.


Je pense que je vais m'orienter vers cette solution (UCS-4 en interne,
UTF-8 en externe). Question bête au passage : l'UTF-8 est-il dépendant
de l' "endianess" (BE/LE) ? Je ne pense pas, mais on ne sait jamais.

C'est un peu plus complexe que ca. Historiquement, (...)


Merci pour les rappels histoire, c'est intéressant et utile pour
comprendre la situation (le chaos :-)) actuelle.

Maintenant, que faut-il faire pour avoir un std::wstring en UCS-4 à
tous les coups ? "typedef std::basic_string<uint32> mon_string_ucs4;"
?


Ce n'est pas si simple. Parce que std::basic_string exige plusieurs
parametres ; le deuxieme, par defaut, serait std::char_traits<uint32>.
Qui n'est pas defini par la norme (...)


Pas de blague, il n'existe pas un type / une librairie qui offre de
l'UCS-4 pour le C++ ???

Pour la reste, il va falloir aussi que tu definisses un certain nombre
de facettes, selon ce que tu veux faire (mais au moins des facettes
de codecvt). Ce qui est loin d'etre evident.


Ben euh, c'est beaucoup de concaténations de chaînes. Dans notre jeu,
on se contente d'afficher des chaînes, c'est pas un éditeur de texte
:-D

Et enfin, n'oublis surtout pas que l'affichage est independant
du C++. Il faut s'assurer que la police utilisee a l'affichage
utilise le meme encodage que ton programme, et autant que je sache,
il n'y a aucune solution portable pour ca.


Disons que je vais commencer par résoudre le problème du stockage
interne des caractères. Après on verra pour l'affichage :-)

Notre jeu, Wormux(.org) pour rappel, utilise la librairie ClanLib. Or
cette dernière ne semble pas encore supporter autre chose que "char*",
donc c'est pas gagné ...

@+ Haypo


Avatar
James Kanze
(Victor STINNER) writes:

|> wrote in message
|> news:...
|> > Ca depend un peu des caracteres dont tu as besoin,

|> Euh ... Et bien dans l'immédiat, j'aimerai pouvoir afficher des
|> chaînes en français, anglais, allemand, espagnol, polonais, hongrois
|> et portugais. Il me faut donc les lettres utilisées dans ces
|> langues.

Alors, il doit y avoir une solution assez simple. Dans la pratique, si
on se limite aux caractères *alphabétiques* des langues modernes, UTF-16
et UTF-32 sont identique, à part la taille du caractère.

Si on doit traduire en chinois ou japonais, il faut savoir quelque chose
sur le vocabulaire utilisé. Pour les caractères les plus fréquents,
UTF-16 et UTF-32 sont aussi identiques, mais ça n'est pas vrai pour tous
les caractères.

|> > et ce que tu entends par " portable "

|> Que ça fonctionne sous Windows, Linux, FreeBSD, et ce, sur n'importe
|> quelle architecture (Big Endian / Little Endian, avec registres
|> internes du CPU en 32 ou 64 bits).

En somme, des systèmes assez semblables.

|> > Dans l'absolu, " portable " et " affichage " sont des
|> > contradictions -- pour commencer, tu ne peux pas afficher des
|> > caracteres qui ne sont pas presentent dans la police utilisee,

|> Oui, c'est sûr. Je pense utiliser des polices TTF relativement
|> complètes (ex: une pour toutes les langues européennes, une autre
|> pour le chinois, etc.).

|> > a moins d'afficher tout en mode graphique (et alors, il n'y a rien
|> > de portable).

|> Je ne travaille qu'en mode graphique, ou presque (quelques messages
|> dans la console, comme "chargement du jeu ..." (messages localisés
|> !).

Quand je disais en mode graphique, je voulais dire que tu génères
toi-même les caractères, plutôt que d'utiliser une police déjà installée
sur la machine.

|> > La meilleur solution du point de vue technique, c'est certainement
|> > UTF-8 en extern, et UCS-4 (ou UTF-32, ce qui revient au meme) en
|> > intern. Certaines applications Linux (et Solaris ou HP/UX) l'ont
|> > adopte, mais c'est loin d'etre universel. Sauf sous Plan 9.

|> Je pense que je vais m'orienter vers cette solution (UCS-4 en
|> interne, UTF-8 en externe). Question bête au passage : l'UTF-8
|> est-il dépendant de l' "endianess" (BE/LE) ? Je ne pense pas, mais
|> on ne sait jamais.

Non. C'est d'ailleurs une des raisons pourquoi on l'utilise en externe.

|> > C'est un peu plus complexe que ca. Historiquement, (...)

|> Merci pour les rappels histoire, c'est intéressant et utile pour
|> comprendre la situation (le chaos :-)) actuelle.

|> > > Maintenant, que faut-il faire pour avoir un std::wstring en
|> > > UCS-4 à tous les coups ? "typedef std::basic_string<uint32>
|> > > mon_string_ucs4;" ?

|> > Ce n'est pas si simple. Parce que std::basic_string exige
|> > plusieurs parametres ; le deuxieme, par defaut, serait
|> > std::char_traits<uint32>. Qui n'est pas defini par la norme (...)

|> Pas de blague, il n'existe pas un type / une librairie qui offre de
|> l'UCS-4 pour le C++ ???

Pas à ce que je sache.

Pour les cibles qui t'intéresse, et selon le vocabulaire utilisé dans
les messages à afficher, peut-être aussi pour toute langue moderne, tu
n'as besoin que du sous-ensemble UCS-2 de UCS-4. Alors, pour les
plateformes qui t'intéressent, je vois deux solutions « simples » :

- Toutes les plateformes en question ont des locales où on supporte
soit UCS-2 (sizeof(wchar_t) == 2) soit UCS-4 (sizeof(wchar_t) == 4).
S'il ne s'agit que de l'affichage, std::wstring, des constantes de
chaîne du type L"...", et la police qu'il faut fait l'affaire. Ce
n'est pas la peine de chercher plus loin.

- Sinon, il y a la bibliothèque ICU
(http://oss.software.ibm.com/icu/index.html) pour C. C'est du
UTF-16, et non du UCS-4, mais au moins d'avoir réelement besoin des
caractères non présents en UCS-2, ça revient au même. Et c'est très
complet. En écrire un wrapper C++ ne doit pas poser de gros
problèmes.

|> > Pour la reste, il va falloir aussi que tu definisses un certain
|> > nombre de facettes, selon ce que tu veux faire (mais au moins des
|> > facettes de codecvt). Ce qui est loin d'etre evident.

|> Ben euh, c'est beaucoup de concaténations de chaînes. Dans notre
|> jeu, on se contente d'afficher des chaînes, c'est pas un éditeur de
|> texte :-D

C'est ce que j'imaginais. Mais j'imagine aussi que les chaînes peuvent
comporter des nombres ; il te faudrait alors num_punct au moins.

Je soupçonne fort que std::wstring te suffira, puisque tu es très limité
dans les caractères nécessaires et dans les systèmes ciblés. Le tout,
c'est de vérifier qu'il y a un locale qui fait ce que tu veux. (La
dernière fois que j'ai régardé, g++ était très faible en ce qui
concernait le support pour les locales. Mais je sais qu'ils travaillent
ardemment dessus, et c'est probable que la situation s'est déjà
nettement améliorée.) Sinon, je crois que ICU est plus qu'il ne te faut.

|> > Et enfin, n'oublis surtout pas que l'affichage est independant du
|> > C++. Il faut s'assurer que la police utilisee a l'affichage
|> > utilise le meme encodage que ton programme, et autant que je
|> > sache, il n'y a aucune solution portable pour ca.

|> Disons que je vais commencer par résoudre le problème du stockage
|> interne des caractères. Après on verra pour l'affichage :-)

|> Notre jeu, Wormux(.org) pour rappel, utilise la librairie ClanLib.
|> Or cette dernière ne semble pas encore supporter autre chose que
|> "char*", donc c'est pas gagné ...

Tu peux mettre de l'UTF-8 dans des char[]. Traite la bibliothèque comme
un élément « externe ».

--
James Kanze
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
Avatar
Christophe de VIENNE
James Kanze wrote:
- Sinon, il y a la bibliothèque ICU
(http://oss.software.ibm.com/icu/index.html) pour C. C'est du
UTF-16, et non du UCS-4, mais au moins d'avoir réelement besoin des
caractères non présents en UCS-2, ça revient au même. Et c'est très
complet. En écrire un wrapper C++ ne doit pas poser de gros
problèmes.


ICU4C comporte déjà un wrapper C++ qui utilise, si je ne me trompe, la
version C pure.

A+

Christophe

--
Christophe de Vienne

Avatar
drkm
James Kanze writes:

(Victor STINNER) writes:


[...]

- Sinon, il y a la bibliothèque ICU
(http://oss.software.ibm.com/icu/index.html) pour C. C'est du
UTF-16, et non du UCS-4, mais au moins d'avoir réelement besoin des
caractères non présents en UCS-2, ça revient au même. Et c'est très
complet. En écrire un wrapper C++ ne doit pas poser de gros
problèmes.


Je ne sais pas s'il s'agit de deux implémentations distinctes, s'il
s'agit d'un wrapper C++ autour d'une bibliothèque C, ou une
bibliothèque C utilisant la bibliothèque C++, mais il y a déjà des
APIs C et C++. Et Java, également. Non ?

[...]

|> Notre jeu, Wormux(.org) pour rappel, utilise la librairie ClanLib.
|> Or cette dernière ne semble pas encore supporter autre chose que
|> "char*", donc c'est pas gagné ...

Tu peux mettre de l'UTF-8 dans des char[]. Traite la bibliothèque comme
un élément « externe ».


Que veux-tu dire par là ?

--drkm, en recherche d'un stage : http://www.fgeorges.org/ipl/stage.html

Avatar
James Kanze
drkm writes:

|> James Kanze writes:

|> > (Victor STINNER) writes:

|> [...]

|> > - Sinon, il y a la bibliothèque ICU
|> > (http://oss.software.ibm.com/icu/index.html) pour C. C'est du
|> > UTF-16, et non du UCS-4, mais au moins d'avoir réelement besoin des
|> > caractères non présents en UCS-2, ça revient au même. Et c'est très
|> > complet. En écrire un wrapper C++ ne doit pas poser de gros
|> > problèmes.

|> Je ne sais pas s'il s'agit de deux implémentations distinctes,
|> s'il s'agit d'un wrapper C++ autour d'une bibliothèque C, ou une
|> bibliothèque C utilisant la bibliothèque C++, mais il y a déjà des
|> APIs C et C++. Et Java, également. Non ?

En Java en tout cas -- le code a vue le jour parce que IBM trouvait que
le traitement Java de Unicode n'était pas suffisant. Je n'avais pas
prêté attention au wrapper C++ existant ; quand j'avais régardé en
détail (il y a quelques années), je ne l'avais pas rémarqué.

|> [...]

|> > |> Notre jeu, Wormux(.org) pour rappel, utilise la librairie
|> > |> ClanLib. Or cette dernière ne semble pas encore supporter
|> > |> autre chose que "char*", donc c'est pas gagné ...

|> > Tu peux mettre de l'UTF-8 dans des char[]. Traite la bibliothèque
|> > comme un élément « externe ».

|> Que veux-tu dire par là ?

Que quand il a à manipuler du texte dans son propre code, il se sert des
wchar_t et/ou ce que veut ICU, mais que quand il interface avec la
bibliothèque, il convertit en UTF-8, comme s'il s'agissait de sortir
vers l'extérieur.

--
James Kanze
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
Avatar
spam
James Kanze wrote in message news:...
- Toutes les plateformes en question ont des locales où on supporte
soit UCS-2 (sizeof(wchar_t) == 2) soit UCS-4 (sizeof(wchar_t) == 4).
S'il ne s'agit que de l'affichage, std::wstring, des constantes de
chaîne du type L"...", et la police qu'il faut fait l'affaire. Ce
n'est pas la peine de chercher plus loin.


Au fait, j'utilise largement gettext dans mon programme, c'est grâve
docteur ??? Ca prend du char* en entrée, et ça donne du char* en
sortie. Dois-je comprendre "UTF-8" en sortie si on lui demande
poliment ? (en touchant aux locales)

Du code du style :
std::cout << Format(_("Player %s died."), player.nane.c_str()) <<
std::endl;

Le prototype de la fonction Format étant :
std::string Format (char*, ...);

C'est ma version C++ de printf. Je n'utilise pas de std::ostringstream
pour pouvoir internationnaliser le jeu.

@+ Haypo

Avatar
kanze
(Victor STINNER) wrote in message
news:...
James Kanze wrote in message
news:...
- Toutes les plateformes en question ont des locales où on supporte
soit UCS-2 (sizeof(wchar_t) == 2) soit UCS-4 (sizeof(wchar_t) == 4).
S'il ne s'agit que de l'affichage, std::wstring, des constantes de
chaîne du type L"...", et la police qu'il faut fait l'affaire. Ce
n'est pas la peine de chercher plus loin.


Au fait, j'utilise largement gettext dans mon programme, c'est grâve
docteur ???


Ça dépend. Autant que je sache, cette fonction n'existe pas sous
Windows. Elle ne fait pas partie de la norme Posix non plus, ni de
l'Open System, bien que je l'ai toujours trouvé sur des plateformes Unix
(Solaris, etc.). Si tu vises la portabilité, c'est grave.

Ca prend du char* en entrée, et ça donne du char* en sortie. Dois-je
comprendre "UTF-8" en sortie si on lui demande poliment ? (en touchant
aux locales)


Je ne sais pas. Je *crois* qu'elle renvoie simplement ce qu'elle trouve
dans un fichier, ou le paramètre même, si elle ne trouve pas d'entrée
qui convient. Alors, si tu mets de UTF-8 dans le fichier, elle renvoie
le UTF-8. A priori, si le locale est UTF-8 (c-à-d que le nom du locale
se termine en .UTF-8, par exemple fr_FR.UTF-8), je m'attendrais à ce que
le texte renvoyé par gettext soit en UTF-8. Mais je ne crois pas qu'il y
a quoique ce soit qui l'enforce -- c'est à toi de jouer avec ce que tu
mets dans le fichier .po. que tu donne à msgfmt.

Note que dans la mésure où les messages sont dans un fichier, c'est
normal qu'ils soient en char, et non en wchar_t. En général, on ne met
jamais du wchar_t dans un fichier -- à cause des problèmes de l'ordre
des octets, et de la taille même de wchar_t. (Il existe des systèmes où
des char n'ont pas 8 bits, aussi, mais dans la pratique, dans beaucoup
de cas, on n'est pas obligé à ce niveau de portabilité.)

Du code du style :
std::cout << Format(_("Player %s died."), player.nane.c_str()) <<
std::endl;

Le prototype de la fonction Format étant :
std::string Format (char*, ...);

C'est ma version C++ de printf.


Tu pourrais jeter un oeil à GB_Format (sur ma site) ou boost::format ;
les deux implémentent tout le formattage utile de printf, avec les
extensions Open System pour les paramètres positionnels. (Le mien
implémente vraiment tout le formattage, celui de boost laisse tomber
quelques options qui ne sert pour ainsi dire jamais. En revanche, celui
de boost est templaté sur le type de caractère -- si tu veux passer un
jour en wchar_t, le mien ne le supporte pas. Le mien est probablement
plus portable, aussi, mais je n'ai pas vérifié partout.)

Dans le temps, j'avais une interface portable pour une équivalent de
gettext aussi -- malheureusement, je n'ai pas eu le temps de le
maintenir, et c'est un peu tombé du côté. Mais à ta place, j'écrirai
quelque chose du semblable -- une interface définie par toi, avec une
implémentation qui se sert de gettext, si c'est disponible, ou d'autre
chose, si il ne l'est pas. (Il existe une facette std::message dans la
bibliothèque standard, mais d'après mon expérience, les implémentations
de std::locale et des facettes ne sont pas toujours aussi complètes
qu'on voudrait. Aussi, il manque souvent de la documentation comment
créer et installer des catalogues de messages -- il se peut qu'il te
soit plus simple d'implémenter tout toi-même, selon tes besoins, que de
gérer 36 façons différentes de générer et d'installer tes messages.)

Je n'utilise pas de std::ostringstream pour pouvoir internationnaliser
le jeu.


Tout à fait. Les ostream ne se prêtent pas à l'internationalisation ;
c'en est une faiblesse connue. C'est pourquoi j'ai implémenté GB_Format
(il y a dix ans, dans sa première version).

--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34