Pentru a putea vota, modifica pagini sau abona la modificările unei pagini trebuie să fiți autentificați. Cu această ocazie scăpați și de acest mesaj deranjant.

Localizarea în Visual C: Diferență între versiuni

De la l10n.ro
Salt la: navigare, căutare
m (New page: == Introducere == Dupa 7 ani de zile am putut să renunţ la suportul pentru Win9x şi am început portarea aplicaţiei, scrisă în MFC, pe Unicode. Acum pot sa recomand oricui vrea sa ...)
 
(Cum convertesc dintr-un string în altul)
 
(Nu s-au afișat 18 versiuni intermediare efectuate de alți 3 utilizatori)
Linia 1: Linia 1:
 
== Introducere ==
 
== Introducere ==
Dupa 7 ani de zile am putut să renunţ la suportul pentru Win9x şi am început portarea aplicaţiei, scrisă în MFC, pe Unicode.  
+
Am în mentenanţă o aplicaţie MFC, veche de 7 ani şi de curând am putut să renunţ la suportul pentru Win9x şi am început trecerea aplicaţiei la Unicode.  
  
Acum pot sa recomand oricui vrea sa internationalizeze/localizeze să folosească libraria gettext din urmatoarele motive:
+
Acum pot recomand oricui vrea, să internaţionalizeze/localizeze, să folosească librăria gettext din următoarele motive:
 
* mentenanţa fişierelor de localizare este incomparabil mai uşoară
 
* mentenanţa fişierelor de localizare este incomparabil mai uşoară
 
* există orice fel de unelte de localizare pentru fişiere gettext (.PO)
 
* există orice fel de unelte de localizare pentru fişiere gettext (.PO)
 
* poate fi folosită şi în aplicaţii comerciale (este LGPL)
 
* poate fi folosită şi în aplicaţii comerciale (este LGPL)
  
== Faza 1 - trecerea la unicode... fără a renuţa la versiunea veche! ==
+
== Trecerea aplicației la Unicode ==
Unii o pot considera inutila dar experienta mea spune ca merita sa renunti la Win9x si sa treci la unicode.  
+
Unii o pot considera inutilă, dar experienţa mea spune că merită să renunţi la Win9x și să treci la Unicode. Cel puțin, scapi de problema codepage-urilor.
  
Incepeti prin a inlocui tipurile de date si accesele la functii cu urmatoarele. Aceasta faza nu vă va 'strica' aplicaţia şi veţi putea să faceţi build-uri separate.
+
Începeţi prin a înlocui tipurile de date și apelurile la funcții cu următoarele alternative, care de fapt sunt toate macro-uri, care se compilează diferit, în funcție de target. Această fază nu vă va 'strica' aplicaţia şi veţi putea să faceţi build-uri separate.
 +
 
 +
Nu uitați să faceți un branch separat înainte de a începe, s-ar putea să dureze de 3X mai mult decât credeți, acum depinde de când și de cine a fost scrisă aplicația inițial.
  
 
<pre>
 
<pre>
char   _TCHAR
+
char       _TCHAR
 
LPSTR      LPTSTR
 
LPSTR      LPTSTR
 
LPCSTR      LPCTSTR
 
LPCSTR      LPCTSTR
Linia 28: Linia 30:
 
sscanf      _stscanf
 
sscanf      _stscanf
 
wsprintf    _tcs
 
wsprintf    _tcs
atoi   _tstoi
+
atoi       _tstoi
itoa   itot
+
itoa       _itot_s
sscanf   _stscanf
+
sscanf     _stscanf
 
vsprintf    _vstprintf
 
vsprintf    _vstprintf
fopen   _tfopen
+
fopen       _tfopen
 
fputs      _fputs
 
fputs      _fputs
fclose   _tfclose
+
fclose     _tfclose
 
</pre>
 
</pre>
  
 
<source lang="c">
 
<source lang="c">
/* Cum Bill cam uită să ducă treaba la bun sfârşit a uitat de (w)sprintf aşa că adăugaţi şi asta într-un H*/
+
/* Cum Bill cam uită să ducă treaba la bun sfârşit, a uitat de (w)sprintf aşa că adăugaţi şi asta într-un H*/
 
#ifdef UNICODE
 
#ifdef UNICODE
 
#define _tsprintf wsprintf
 
#define _tsprintf wsprintf
Linia 49: Linia 51:
  
 
=== Ceva mai puţin evident despre ..prinf(...) ===
 
=== Ceva mai puţin evident despre ..prinf(...) ===
funcţiile din gama printf pot primi ca parametrii atât char, w_char cât şi t_char aşa că **trebuie** ajutate să-şi dea sema ce primesc
+
Funcţiile din gama printf, pot primi ca parametrii atât char, w_char cât şi t_char aşa că **trebuie** ajutate să-şi dea seama ce primesc
 
<pre>
 
<pre>
 
Apel                  build unicode          build ne-unicode        alias
 
Apel                  build unicode          build ne-unicode        alias
Linia 59: Linia 61:
 
</pre>
 
</pre>
  
== Cum convertesc dintr-un string in altul ==
+
== Cum convertesc dintr-un string în altul ==
Puteti folosi niste macrocomenzi gen:
+
Puteți folosi niște macrocomenzi gen:
 +
 
 
<pre>
 
<pre>
W2A
+
W2A(...) și CW2A(...)
CA2T - const ANSI to TCHAR
+
A2T(...) și CA2T(...)
 +
T2A(...) și CT2A(...)
 
</pre>
 
</pre>
Nu uitati ca întorc un buffer static deci trebuie copiaţi valoarea dacă nu o folosiţi imediat.
+
 
 +
* C - constant
 +
* W - Wide
 +
* T - TCHAR (Adica W în unicode și A în rest)
 +
* A - ASCII
 +
 
 +
Nu uitați că ''nu le puteți folosi oricum'', deoarece fac niște hack-uri cam nasoale. Dacă vreți le folosiți citiți '''neapărat''' înainte
 +
* http://codexpert.ro/forum/viewtopic.php?f=23&t=149&p=650&hilit=CW2A#p650
 +
* http://codexpert.ro/forum/viewtopic.php?f=14&t=416&p=2426&hilit=ct2a#p2426
  
 
== Gettext ==
 
== Gettext ==
Descarcati:
+
 
 +
=== Gettext functions and comments ===
 +
<source lang=cpp>
 +
// Translators: This is a text that is going to be used by translators in order to translate the next term corectly.
 +
print(_("Code"));
 +
 
 +
// This is how we MUST use printf syntax in order to be able to translate corectly the programs.
 +
// This syntax permits the changing the order of the parameters.
 +
printf("'%2$d' us tge 2th parameter and '%1$s' is the first one.", param1, param2);
 +
 
 +
// SYntax
 +
// _(...) este doar un macro care se expandeaza la gettext(...)
 +
// dgettext
 +
// dcgettext
 +
char * ngettext (const char *msgid_singular, const char *msgid2_plural, unsigned long int n); // For plural
 +
char * dngettext (const char *domain, const char *msgid1_singular, const char *msgid2_plural, unsigned long int n); //
 +
char * dcngettext (const char *domain, const char *msgid1, const char *msgid2, unsigned long int n, int category); //
 +
// Formatting with positions
 +
fprintf "%2$d %1$d" // (POSIX but not C 99)
 +
// printf, vfprintf, sprintf, vsprintf, fwprintf, wprintf, swprintf, vswprintf
 +
</source>
 +
 
 +
=== ... ===
 +
 
 +
Descărcaţi:
 
* <tt>gettext-runtime</tt> (ex: ftp://ftp-stud.fht-esslingen.de/pub/Mirrors/ftp.gnu.org/gettext)
 
* <tt>gettext-runtime</tt> (ex: ftp://ftp-stud.fht-esslingen.de/pub/Mirrors/ftp.gnu.org/gettext)
 
* <tt>libiconv</tt> (ex: ftp://ftp-stud.fht-esslingen.de/pub/Mirrors/ftp.gnu.org/libiconv)
 
* <tt>libiconv</tt> (ex: ftp://ftp-stud.fht-esslingen.de/pub/Mirrors/ftp.gnu.org/libiconv)
  
Ar trebui sa stiti ca implicit gettext intoarce textele in UTF-8 ceea ce este foarte bine, mai putin pentru Windows care foloseste in modul Unicode (UTF16-LE), asa ca trebuie sa le convertiti la runtime (oricum e suficient de rapida conversia).
+
Ar trebui să ştiţi că, implicit, gettext întoarce textele în UTF-8, ceea ce este foarte bine, mai puţin pentru Windows, care foloseşte în modul Unicode (UTF16-LE), aşa că trebuie le convertiţi la runtime (oricum e suficient de rapidă conversia).
  
 
<source lang="cpp">
 
<source lang="cpp">
Linia 85: Linia 121:
  
 
== Extragerea textelor ==
 
== Extragerea textelor ==
Extragerea textelor din fisierele .C si .CPP este extrem de usoara folosing <tt>xgettext</tt>, dar cand veti ajunge la fisierele <tt>.RC</tt> o sa descoperiti ca nu sunt suportate. Din fericire dupa multe incercari nereusite am gasit singur o solutie simpla
+
Extragerea textelor din fişierele .C si .CPP este extrem de uşoară, folosind <tt>xgettext</tt>, dar când veţi ajunge la fişierele <tt>.RC</tt>, o să descoperiţi că nu sunt suportate. Din fericire, după multe încercări nereuşite, am găsit singur o soluţie simplă
  
 
<source lang="bash">xgettext --from-code=UTF-8 --add-comments --omit-header --no-location \
 
<source lang="bash">xgettext --from-code=UTF-8 --add-comments --omit-header --no-location \
Linia 92: Linia 128:
 
</source>
 
</source>
  
Sau pe scurt: intrucat sintaxa Tcl e destul de compatibila cu cea din .RC, folosind keyword-urile respective obtinei un parser de .RC in xgettext. Cool?... o sa trimit si un mail ca sa modifice sa recunoasca fisierele rc direct.
+
Sau pe scurt: întrucât sintaxa Tcl e destul de compatibilă cu cea din .RC, folosind keyword-urile respective, obţineţi un parser de .RC în xgettext. Cool?... o trimit şi un mail ca modifice să recunoască fişierele rc direct.
  
[[Category:Tutorial]]
 
  
== Legături ==
+
 
 +
== [[Legături|Legături]] ==
 
* http://www.gnu.org/software/gettext/ - de citit cu atenţie
 
* http://www.gnu.org/software/gettext/ - de citit cu atenţie
* http://taossa.com/index.php/2007/01/09/string-theory-for-windows/ - cum se lucreaza cu siruri in windows
+
* http://taossa.com/index.php/2007/01/09/string-theory-for-windows/ - cum se lucrează cu şiruri în Windows
  
 
--[[User:Admin|sorin]]
 
--[[User:Admin|sorin]]
 +
 +
[[Categorie:Tutorial]]
 +
[[Categorie:Programare]]

Versiunea curentă din 22 noiembrie 2009 08:07

Introducere

Am în mentenanţă o aplicaţie MFC, veche de 7 ani şi de curând am putut să renunţ la suportul pentru Win9x şi am început trecerea aplicaţiei la Unicode.

Acum pot să recomand oricui vrea, să internaţionalizeze/localizeze, să folosească librăria gettext din următoarele motive:

  • mentenanţa fişierelor de localizare este incomparabil mai uşoară
  • există orice fel de unelte de localizare pentru fişiere gettext (.PO)
  • poate fi folosită şi în aplicaţii comerciale (este LGPL)

Trecerea aplicației la Unicode

Unii o pot considera inutilă, dar experienţa mea spune că merită să renunţi la Win9x și să treci la Unicode. Cel puțin, scapi de problema codepage-urilor.

Începeţi prin a înlocui tipurile de date și apelurile la funcții cu următoarele alternative, care de fapt sunt toate macro-uri, care se compilează diferit, în funcție de target. Această fază nu vă va 'strica' aplicaţia şi veţi putea să faceţi build-uri separate.

Nu uitați să faceți un branch separat înainte de a începe, s-ar putea să dureze de 3X mai mult decât credeți, acum depinde de când și de cine a fost scrisă aplicația inițial.

char        _TCHAR
LPSTR       LPTSTR
LPCSTR      LPCTSTR

strlen      _tcslen
strcpy      _tcscpy 
strcmp      _tcscmp
strncmp     _tcsmcmp
stricmp     _tcsicmp
strchr      _tcschr
strncmp     _tcsncmp
sprintf     _tsprintf /* Vezi mai jos */
strstr      _tcsstr
sscanf      _stscanf
wsprintf    _tcs
atoi        _tstoi
itoa        _itot_s
sscanf      _stscanf
vsprintf    _vstprintf
fopen       _tfopen
fputs       _fputs
fclose      _tfclose
/* Cum Bill cam uită să ducă treaba la bun sfârşit, a uitat de (w)sprintf aşa că adăugaţi şi asta într-un H*/
#ifdef UNICODE
#define _tsprintf wsprintf
#define tstring wstring
#else
#define _tsprintf sprintf
#define tstring string
#endif

Ceva mai puţin evident despre ..prinf(...)

Funcţiile din gama printf, pot primi ca parametrii atât char, w_char cât şi t_char aşa că **trebuie** ajutate să-şi dea seama ce primesc

Apel                  build unicode          build ne-unicode        alias
--------------------------------------------------------------------------------
sprintf "%s"          LPWSTR                 LPSTR                   normal
sprintf "%S"          LPSTR          LPWSTR                  inverse  
sprintf "%hs"         LPSTR                  LPSTR                   single-byte
sprintf "&ls"         LPWSTR                 LPWSTR                  double-byte

Cum convertesc dintr-un string în altul

Puteți folosi niște macrocomenzi gen:

W2A(...) și CW2A(...)
A2T(...) și CA2T(...)
T2A(...) și CT2A(...)
  • C - constant
  • W - Wide
  • T - TCHAR (Adica W în unicode și A în rest)
  • A - ASCII

Nu uitați că nu le puteți folosi oricum, deoarece fac niște hack-uri cam nasoale. Dacă vreți să le folosiți citiți neapărat înainte

Gettext

Gettext functions and comments

// Translators: This is a text that is going to be used by translators in order to translate the next term corectly.
print(_("Code"));

// This is how we MUST use printf syntax in order to be able to translate corectly the programs.
// This syntax permits the changing the order of the parameters.
printf("'%2$d' us tge 2th parameter and '%1$s' is the first one.", param1, param2);

// SYntax
// _(...) este doar un macro care se expandeaza la gettext(...)
// dgettext
// dcgettext
char * ngettext (const char *msgid_singular, const char *msgid2_plural, unsigned long int n); // For plural
char * dngettext (const char *domain, const char *msgid1_singular, const char *msgid2_plural, unsigned long int n); // 
char * dcngettext (const char *domain, const char *msgid1, const char *msgid2, unsigned long int n, int category); //
// Formatting with positions
fprintf "%2$d %1$d" // (POSIX but not C 99)
// printf, vfprintf, sprintf, vsprintf, fwprintf, wprintf, swprintf, vswprintf

...

Descărcaţi:

Ar trebui să ştiţi că, implicit, gettext întoarce textele în UTF-8, ceea ce este foarte bine, mai puţin pentru Windows, care foloseşte în modul Unicode (UTF16-LE), aşa că trebuie să le convertiţi la runtime (oricum e suficient de rapidă conversia).

#include "../contrib/gettext-runtime/include/libintl.h"

CString strDomain=CString(textdomain("myproject")); // if you put "" will default to "messages"
CString strBinded = CString(bindtextdomain("myproject","d:\\dev\\pbxtools\\src\\debug\\locale\\")); // put you path here

// later
AfxMessageBox(_("Hello World!"), (UINT)MB_OK, (UINT)0);

Extragerea textelor

Extragerea textelor din fişierele .C si .CPP este extrem de uşoară, folosind xgettext, dar când veţi ajunge la fişierele .RC, o să descoperiţi că nu sunt suportate. Din fericire, după multe încercări nereuşite, am găsit singur o soluţie simplă

xgettext --from-code=UTF-8 --add-comments --omit-header --no-location \
--keyword=MENUITEM --keyword=LTEXT --keyword=DEFPUSHBUTTON --keyword=PUSHBUTTON --keyword=CAPTION \
--language=Tcl -o resources.po project.rc

Sau pe scurt: întrucât sintaxa Tcl e destul de compatibilă cu cea din .RC, folosind keyword-urile respective, obţineţi un parser de .RC în xgettext. Cool?... o să trimit şi un mail ca să modifice să recunoască fişierele rc direct.


Legături

--sorin