updated i18n sample, french translations are now in the "fr" subdirectory.
Added some documentation in readme.txt. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@1399 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -78,9 +78,18 @@ public:
|
|||||||
// returns locale name
|
// returns locale name
|
||||||
const char *GetLocale() const { return m_strLocale; }
|
const char *GetLocale() const { return m_strLocale; }
|
||||||
|
|
||||||
|
// add a prefix to the catalog lookup path: the message catalog files will be
|
||||||
|
// looked up under prefix/<lang>/LC_MESSAGES, prefix/LC_MESSAGES and prefix
|
||||||
|
// (in this order).
|
||||||
|
//
|
||||||
|
// This only applies to subsequent invocations of AddCatalog()!
|
||||||
|
static void AddCatalogLookupPathPrefix(const wxString& prefix);
|
||||||
|
|
||||||
// add a catalog: it's searched for in standard places (current directory
|
// add a catalog: it's searched for in standard places (current directory
|
||||||
// first, system one after). It will be used for message lookup by
|
// first, system one after), but the you may prepend additional directories to
|
||||||
// GetString().
|
// the search path with AddCatalogLookupPathPrefix().
|
||||||
|
//
|
||||||
|
// The loaded catalog will be used for message lookup by GetString().
|
||||||
//
|
//
|
||||||
// Returns 'true' if it was successfully loaded
|
// Returns 'true' if it was successfully loaded
|
||||||
bool AddCatalog(const char *szDomain);
|
bool AddCatalog(const char *szDomain);
|
||||||
|
BIN
samples/internat/fr/internat.mo
Normal file
BIN
samples/internat/fr/internat.mo
Normal file
Binary file not shown.
77
samples/internat/fr/internat.po
Normal file
77
samples/internat/fr/internat.po
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
# Message catalog file template for the wxWindows i18n sample
|
||||||
|
# Copyright (C) 1999 wxWindows development team
|
||||||
|
# Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
|
||||||
|
#
|
||||||
|
#: internat.cpp:146
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: wxWindows 2.0 i18n sample\n"
|
||||||
|
"POT-Creation-Date: 1999-01-13 18:19+0100\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=CHARSET\n"
|
||||||
|
"Content-Transfer-Encoding: ENCODING\n"
|
||||||
|
|
||||||
|
#: internat.cpp:98
|
||||||
|
msgid "International wxWindows App"
|
||||||
|
msgstr "Application wxWindows internationale"
|
||||||
|
|
||||||
|
#: internat.cpp:105
|
||||||
|
msgid "&About..."
|
||||||
|
msgstr "&A propos..."
|
||||||
|
|
||||||
|
#: internat.cpp:107
|
||||||
|
msgid "E&xit"
|
||||||
|
msgstr "&Quitter"
|
||||||
|
|
||||||
|
#: internat.cpp:110
|
||||||
|
msgid "&Open bogus file"
|
||||||
|
msgstr "&Ouvrir un fichier"
|
||||||
|
|
||||||
|
#: internat.cpp:111
|
||||||
|
msgid "&Play a game"
|
||||||
|
msgstr "&Jouer"
|
||||||
|
|
||||||
|
#: internat.cpp:114
|
||||||
|
msgid "&File"
|
||||||
|
msgstr "&Fichier"
|
||||||
|
|
||||||
|
#: internat.cpp:115
|
||||||
|
msgid "&Test"
|
||||||
|
msgstr "&Test"
|
||||||
|
|
||||||
|
#: internat.cpp:138
|
||||||
|
msgid "I18n sample\n"
|
||||||
|
"<22> 1998, 1999 Vadim Zeitlin and Julian Smart"
|
||||||
|
msgstr "Exemple d'i18n\n"
|
||||||
|
"<22> 1998, 1999 Vadim Zeitlin et Julian Smart"
|
||||||
|
|
||||||
|
#: internat.cpp:139
|
||||||
|
msgid "About Internat"
|
||||||
|
msgstr "A propos d'Internat"
|
||||||
|
|
||||||
|
#: internat.cpp:144
|
||||||
|
msgid "Enter your number:"
|
||||||
|
msgstr "Entrez votre num<75>ro:"
|
||||||
|
|
||||||
|
#: internat.cpp:145
|
||||||
|
msgid "Try to guess my number!"
|
||||||
|
msgstr "Essayez de d<>viner mon num<75>ro!"
|
||||||
|
|
||||||
|
#: internat.cpp:150
|
||||||
|
msgid "You've probably entered an invalid number."
|
||||||
|
msgstr "Vous avez probablement entr<74> un nombre invalide."
|
||||||
|
|
||||||
|
#: internat.cpp:154
|
||||||
|
msgid "Bad luck! try again..."
|
||||||
|
msgstr "Pas de chance! essayez encore..."
|
||||||
|
|
||||||
|
#: internat.cpp:158
|
||||||
|
msgid "Congratulations! you've won. Here is the magic phrase:"
|
||||||
|
msgstr "F<>licitations! vouz avez gagn<67>. Voil<69> la phrase magique:"
|
||||||
|
|
||||||
|
#: internat.cpp:162
|
||||||
|
msgid "Result"
|
||||||
|
msgstr "Resultat"
|
Binary file not shown.
131
samples/internat/fr/wxstd.po
Normal file
131
samples/internat/fr/wxstd.po
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
# Message catalog file template for the wxWindows i18n sample
|
||||||
|
# Copyright (C) 1999 wxWindows development team
|
||||||
|
# Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: wxWindows 2.0 i18n sample\n"
|
||||||
|
"POT-Creation-Date: 1999-01-13 18:19+0100\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=CHARSET\n"
|
||||||
|
"Content-Transfer-Encoding: ENCODING\n"
|
||||||
|
|
||||||
|
#: file.cpp:182 hello.cpp:38
|
||||||
|
#, fuzzy, c-format
|
||||||
|
msgid "can't create file '%s'"
|
||||||
|
msgstr "impossible de cr<63>er le fichier '%s'"
|
||||||
|
|
||||||
|
#: file.cpp:213
|
||||||
|
#, c-format
|
||||||
|
msgid "can't open file '%s'"
|
||||||
|
msgstr "impossible d'ouvrir le fichier '%s'"
|
||||||
|
|
||||||
|
#: file.cpp:227
|
||||||
|
#, c-format
|
||||||
|
msgid "can't close file descriptor %d"
|
||||||
|
msgstr "impossible de fermer le descripteur %d"
|
||||||
|
|
||||||
|
#: file.cpp:244
|
||||||
|
#, c-format
|
||||||
|
msgid "can't read from file descriptor %d"
|
||||||
|
msgstr "impossible de lire <20> partir de descripteur %d"
|
||||||
|
|
||||||
|
#: file.cpp:258
|
||||||
|
#, c-format
|
||||||
|
msgid "can't write to file descriptor %d"
|
||||||
|
msgstr "impossible d'<27>crire sur le descripteur %d"
|
||||||
|
|
||||||
|
#: file.cpp:271
|
||||||
|
#, c-format
|
||||||
|
msgid "can't flush file descriptor %d"
|
||||||
|
msgstr "impossible de mettre <20> jour le descripteur %d"
|
||||||
|
|
||||||
|
#: file.cpp:308
|
||||||
|
#, c-format
|
||||||
|
msgid "can't seek on file descriptor %d"
|
||||||
|
msgstr "impossible de changer la position sur le descripteur %d"
|
||||||
|
|
||||||
|
#: file.cpp:322
|
||||||
|
#, c-format
|
||||||
|
msgid "can't get seek position on file descriptor %d"
|
||||||
|
msgstr "impossible d'obtenir la position courante sur le descripteur %d"
|
||||||
|
|
||||||
|
#: file.cpp:355
|
||||||
|
#, c-format
|
||||||
|
msgid "can't find length of file on file descriptor %d"
|
||||||
|
msgstr "impossible de trouver la taille du fichier ouvert sur le descripteur %d"
|
||||||
|
|
||||||
|
#: intl.cpp:139
|
||||||
|
#, c-format
|
||||||
|
msgid "catalog file for domain '%s' not found."
|
||||||
|
msgstr "impossible de trouver le catalogue de messages pour le domaine '%s'."
|
||||||
|
|
||||||
|
#: intl.cpp:177
|
||||||
|
#, c-format
|
||||||
|
msgid "'%s' is not a valid message catalog."
|
||||||
|
msgstr "'%s' n'est pas un catalogue de messages valid."
|
||||||
|
|
||||||
|
#: intl.cpp:330 intl.cpp:334
|
||||||
|
#, c-format
|
||||||
|
msgid "locale '%s' can not be set."
|
||||||
|
msgstr "impossible de passer <20> locale '%s'."
|
||||||
|
|
||||||
|
#: intl.cpp:431 intl.cpp:435
|
||||||
|
#, c-format
|
||||||
|
msgid "string '%s' not found in domain '%s' for locale '%s'."
|
||||||
|
msgstr "cha<68>ne '%s' n'a pas <20>t<EFBFBD> trouv<75>e dans le domaine '%s' pour le locale '%s'."
|
||||||
|
|
||||||
|
#: intl.cpp:434 intl.cpp:438
|
||||||
|
#, c-format
|
||||||
|
msgid "string '%s' not found in locale '%s'."
|
||||||
|
msgstr "cha<68>ne '%s' n'a pas <20>t<EFBFBD> trouv<75>e dans le locale '%s'."
|
||||||
|
|
||||||
|
#: log.cpp:104
|
||||||
|
#, c-format
|
||||||
|
msgid " (error %ld: %s)"
|
||||||
|
msgstr " (erreur %ld: %s)"
|
||||||
|
|
||||||
|
#: log.cpp:165
|
||||||
|
msgid "Debug: "
|
||||||
|
msgstr "Debug: "
|
||||||
|
|
||||||
|
#: log.cpp:171
|
||||||
|
msgid "Fatal error: "
|
||||||
|
msgstr "Erreur fatale: "
|
||||||
|
|
||||||
|
#: log.cpp:172
|
||||||
|
msgid "Program aborted.\n"
|
||||||
|
msgstr "Programme abandonn<6E>.\n"
|
||||||
|
|
||||||
|
#: log.cpp:177
|
||||||
|
msgid "Error: "
|
||||||
|
msgstr "Erreur: "
|
||||||
|
|
||||||
|
#: log.cpp:181
|
||||||
|
msgid "Warning: "
|
||||||
|
msgstr "Attention: "
|
||||||
|
|
||||||
|
#: log.cpp:268
|
||||||
|
#, c-format
|
||||||
|
msgid "Assert failed in file %s at line %d"
|
||||||
|
msgstr "Assertion est fausse dans le fichier %s <20> la ligne %d"
|
||||||
|
|
||||||
|
#: file.cpp:303
|
||||||
|
msgid "unknown seek origin"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "looking for catalog '%s' in path '%s'."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: intl.cpp:378
|
||||||
|
msgid "no message catalog list"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "OK"
|
||||||
|
msgstr "OK"
|
||||||
|
|
||||||
|
msgid "Cancel"
|
||||||
|
msgstr "Annuler"
|
@@ -54,7 +54,7 @@ public:
|
|||||||
void OnAbout(wxCommandEvent& event);
|
void OnAbout(wxCommandEvent& event);
|
||||||
void OnPlay(wxCommandEvent& event);
|
void OnPlay(wxCommandEvent& event);
|
||||||
void OnOpen(wxCommandEvent& event);
|
void OnOpen(wxCommandEvent& event);
|
||||||
bool OnClose(void) { return TRUE; }
|
bool OnClose() { return TRUE; }
|
||||||
|
|
||||||
DECLARE_EVENT_TABLE()
|
DECLARE_EVENT_TABLE()
|
||||||
};
|
};
|
||||||
@@ -80,11 +80,34 @@ IMPLEMENT_APP(MyApp)
|
|||||||
|
|
||||||
|
|
||||||
// `Main program' equivalent, creating windows and returning main app frame
|
// `Main program' equivalent, creating windows and returning main app frame
|
||||||
bool MyApp::OnInit(void)
|
bool MyApp::OnInit()
|
||||||
{
|
{
|
||||||
// Initialize the catalogs we'll be using
|
// set the language to use
|
||||||
m_locale.Init("french", "fr", "C");
|
const char *language = NULL;
|
||||||
|
const char *langid = NULL;
|
||||||
|
switch ( argc )
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
// ignore the other args, fall through
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
language = argv[1];
|
||||||
|
langid = argv[2];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
language = argv[1];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
language = "french";
|
||||||
|
langid = "fr";
|
||||||
|
};
|
||||||
|
|
||||||
|
// there are very few systems right now which support locales other than "C"
|
||||||
|
m_locale.Init(language, langid, "C");
|
||||||
|
|
||||||
|
// Initialize the catalogs we'll be using
|
||||||
/* not needed any more, done in wxLocale ctor
|
/* not needed any more, done in wxLocale ctor
|
||||||
m_locale.AddCatalog("wxstd"); // 1) for library messages
|
m_locale.AddCatalog("wxstd"); // 1) for library messages
|
||||||
*/
|
*/
|
||||||
@@ -95,14 +118,15 @@ bool MyApp::OnInit(void)
|
|||||||
m_locale.AddCatalog("fileutils"); // 3) and another just for testing
|
m_locale.AddCatalog("fileutils"); // 3) and another just for testing
|
||||||
|
|
||||||
// Create the main frame window
|
// Create the main frame window
|
||||||
MyFrame *frame = new MyFrame((wxFrame *) NULL, _("International wxWindows App"), 50, 50, 150, 40);
|
MyFrame *frame = new MyFrame((wxFrame *) NULL, _("International wxWindows App"),
|
||||||
|
50, 50, 250, 40);
|
||||||
|
|
||||||
// Give it an icon
|
// Give it an icon
|
||||||
frame->SetIcon(wxICON(mondrian));
|
frame->SetIcon(wxICON(mondrian));
|
||||||
|
|
||||||
// Make a menubar
|
// Make a menubar
|
||||||
wxMenu *file_menu = new wxMenu;
|
wxMenu *file_menu = new wxMenu;
|
||||||
file_menu->Append(MINIMAL_ABOUT, _("&About"));
|
file_menu->Append(MINIMAL_ABOUT, _("&About..."));
|
||||||
file_menu->AppendSeparator();
|
file_menu->AppendSeparator();
|
||||||
file_menu->Append(MINIMAL_QUIT, _("E&xit"));
|
file_menu->Append(MINIMAL_QUIT, _("E&xit"));
|
||||||
|
|
||||||
@@ -135,7 +159,8 @@ void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event) )
|
|||||||
|
|
||||||
void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
|
void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
|
||||||
{
|
{
|
||||||
wxMessageDialog(this, _("I18n sample\n<EFBFBD> Vadim Zeitlin & Julian Smart"),
|
wxMessageDialog(this, _("I18n sample\n"
|
||||||
|
"<EFBFBD> 1998, 1999 Vadim Zeitlin and Julian Smart"),
|
||||||
_("About Internat"), wxOK | wxICON_INFORMATION).ShowModal();
|
_("About Internat"), wxOK | wxICON_INFORMATION).ShowModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,18 +169,21 @@ void MyFrame::OnPlay(wxCommandEvent& WXUNUSED(event))
|
|||||||
wxString str = wxGetTextFromUser(_("Enter your number:"),
|
wxString str = wxGetTextFromUser(_("Enter your number:"),
|
||||||
_("Try to guess my number!"),
|
_("Try to guess my number!"),
|
||||||
"", this);
|
"", this);
|
||||||
|
if ( str.IsEmpty() )
|
||||||
|
return;
|
||||||
|
|
||||||
int num;
|
int num;
|
||||||
sscanf(str, "%d", &num);
|
sscanf(str, "%d", &num);
|
||||||
if ( num == 0 )
|
if ( num == 0 )
|
||||||
str = _("you've probably entered an invalid number.");
|
str = _("You've probably entered an invalid number.");
|
||||||
else if ( num == 9 ) // this message is not translated (not in catalog)
|
else if ( num == 9 ) // this message is not translated (not in catalog)
|
||||||
str = _("you've found a bug in this program!");
|
str = "You've found a bug in this program!";
|
||||||
else if ( num != 17 ) // a more implicit way to write _()
|
else if ( num != 17 ) // a more implicit way to write _()
|
||||||
str = wxGetTranslation("bad luck! try again...");
|
str = wxGetTranslation("Bad luck! try again...");
|
||||||
else {
|
else {
|
||||||
str.Empty();
|
str.Empty();
|
||||||
// string must be split in two -- otherwise the translation won't be found
|
// string must be split in two -- otherwise the translation won't be found
|
||||||
str << _("congratulations! you've won. Here is the magic phrase:")
|
str << _("Congratulations! you've won. Here is the magic phrase:")
|
||||||
<< _("cannot create fifo `%s'");
|
<< _("cannot create fifo `%s'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Binary file not shown.
@@ -1,74 +0,0 @@
|
|||||||
# SOME DESCRIPTIVE TITLE.
|
|
||||||
# Copyright (C) YEAR Free Software Foundation, Inc.
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
||||||
#
|
|
||||||
#: hello.cpp:44
|
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
|
||||||
"POT-Creation-Date: 1997-12-19 17:46+0100\n"
|
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=CHARSET\n"
|
|
||||||
"Content-Transfer-Encoding: ENCODING\n"
|
|
||||||
|
|
||||||
#: hello.cpp:31 hello.cpp:38
|
|
||||||
msgid "bad luck! try again..."
|
|
||||||
msgstr "pas de chance! essayez encore..."
|
|
||||||
|
|
||||||
#: hello.cpp:23 hello.cpp:24
|
|
||||||
#, c-format
|
|
||||||
msgid "usage: %s <number>"
|
|
||||||
msgstr "syntaxe: %s <nombre>"
|
|
||||||
|
|
||||||
#: hello.cpp:29 hello.cpp:34
|
|
||||||
msgid "you've probably entered an invalid number."
|
|
||||||
msgstr "vous avez du entrer un nombre invalide."
|
|
||||||
|
|
||||||
#: hello.cpp:33 hello.cpp:40
|
|
||||||
msgid "congratulations! you've won. Here is the magic phrase:"
|
|
||||||
msgstr "felicitations! vous avez gagne. Voici la phrase magique:"
|
|
||||||
|
|
||||||
#: hello.cpp:17
|
|
||||||
msgid "wxstd"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: hello.cpp:18
|
|
||||||
msgid "hello"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: hello.cpp:19
|
|
||||||
msgid "fileutils"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: hello.cpp:20
|
|
||||||
msgid "french"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: hello.cpp:20
|
|
||||||
msgid "fr"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: hello.cpp:20
|
|
||||||
msgid "C"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: hello.cpp:27
|
|
||||||
msgid "nosuchfi.le"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: hello.cpp:36
|
|
||||||
msgid "You've found a bug in this program!"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: hello.cpp:43
|
|
||||||
#, c-format
|
|
||||||
msgid "cannot create fifo `%s'"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: hello.cpp:43
|
|
||||||
msgid "foo"
|
|
||||||
msgstr ""
|
|
82
samples/internat/readme.txt
Normal file
82
samples/internat/readme.txt
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
This is the README file for the internationalization sample for wxWindows 2.0.
|
||||||
|
|
||||||
|
Q. What does this stupid program do?
|
||||||
|
A. It demonstrates how to translate all program messages to a foreign language.
|
||||||
|
In any program using wxWindows there is going to be 3 kinds of messages: the
|
||||||
|
messages from the program itself, the messages from the wxWindows library and
|
||||||
|
the messages from the system (e.g. system error messages). This program
|
||||||
|
translates the first 2 kinds of messages but the system messages will be only
|
||||||
|
translated if your system supports it.
|
||||||
|
|
||||||
|
Brief usage summary: "Test|File" tries to open a non existing file (provoking
|
||||||
|
system error message), "Test|Play" shows a message box asking for a number.
|
||||||
|
Hint: try some special values like 9 and 17.
|
||||||
|
|
||||||
|
Q. Why the error message when I try to open a non existing file is only partly
|
||||||
|
translated?
|
||||||
|
A. Your system doesn't have the translation in the language you use, sorry.
|
||||||
|
|
||||||
|
Q. Why the message when I enter '9' is not translated?
|
||||||
|
A. This is on purpose: the corresponding string wasn't enclosed in _() macro and
|
||||||
|
so didn't get into the message catalog when it was created using xgettext.
|
||||||
|
|
||||||
|
Q. Why the message when I enter '17' is only partly translated?
|
||||||
|
A. This will only work under some versions of Linux, don't worry if the second
|
||||||
|
half of the sentence is not translated.
|
||||||
|
|
||||||
|
Q. I don't speak french, what about translations to <language>?
|
||||||
|
A. Please write them - see the next question. French is chosen by default
|
||||||
|
because it's the only translation which is currently available. To test
|
||||||
|
translations to the other languages please run the sample with 2 command line
|
||||||
|
arguments: the full language name and the name of the directory where the
|
||||||
|
message catalogs for this language are (will be taken as 2 first letters of
|
||||||
|
the language name if only 1 argument is given).
|
||||||
|
|
||||||
|
Q. How to do translations to other language?
|
||||||
|
A. First of all, you will need the GNU gettext tools (see the next question).
|
||||||
|
After you've probably installed them, type the following (example is for Unix
|
||||||
|
and you should do exactly the same under Windows).
|
||||||
|
|
||||||
|
# all translations forgiven language should be in a separate directory.
|
||||||
|
# Please use the standard abbreviation for the language names!
|
||||||
|
mkdir <language>
|
||||||
|
cd <language>
|
||||||
|
|
||||||
|
# generate the .po file for the program itself
|
||||||
|
# see `xgettext --help' for options, "-C" is important!
|
||||||
|
xgettext -C -o internat.po ../internat.cpp
|
||||||
|
|
||||||
|
# .po file for wxWindows might be generated in the same way, but for now just
|
||||||
|
# take this one...
|
||||||
|
cp ../wxstd.po .
|
||||||
|
|
||||||
|
# now edit the files and do translate strings (this isn't done by gettext)
|
||||||
|
# you can use another editor if you wish :-)
|
||||||
|
vi internat.po wxstd.po
|
||||||
|
|
||||||
|
# create the message catalog files
|
||||||
|
msgfmt -o internat.mo internat.po
|
||||||
|
msgfmt -o wxstd.mo wxstd.po
|
||||||
|
|
||||||
|
# run the sample to test it
|
||||||
|
cd ..
|
||||||
|
./$OSTYPE/internat <language> <langid>
|
||||||
|
|
||||||
|
Q. How to get the gettext tools?
|
||||||
|
A. For Unix, you should be able to get the source distribution of any GNU mirror
|
||||||
|
(see www.gnu.org for a start). gettext() version 0.10 is buggy, try to get at
|
||||||
|
least version strictly greater than 0.10. gettext RPMs can be downloaded from
|
||||||
|
the standard locations for Linux. For Windows, you can get the precompiled
|
||||||
|
binaries from wxWindows web page.
|
||||||
|
|
||||||
|
Q. What's i18n?
|
||||||
|
A. Count the number of letters in the word "internationalization".
|
||||||
|
|
||||||
|
Q. Where to send comments,
|
||||||
|
additional translations,
|
||||||
|
flames,
|
||||||
|
money?
|
||||||
|
A. To Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>,
|
||||||
|
wxWindows list <wxwin-developers@wx.dent.med.uni-muenchen.de>,
|
||||||
|
/dev/null (platform-dependent),
|
||||||
|
wxWindows dev team Suiss banc account.
|
@@ -21,103 +21,102 @@ msgstr ""
|
|||||||
#: file.cpp:182 hello.cpp:38
|
#: file.cpp:182 hello.cpp:38
|
||||||
#, fuzzy, c-format
|
#, fuzzy, c-format
|
||||||
msgid "can't create file '%s'"
|
msgid "can't create file '%s'"
|
||||||
msgstr "impossible de cr<63>er le fichier '%s'"
|
msgstr ""
|
||||||
|
|
||||||
#: file.cpp:213
|
#: file.cpp:213
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "can't open file '%s'"
|
msgid "can't open file '%s'"
|
||||||
msgstr "impossible d'ouvrir le fichier '%s'"
|
msgstr ""
|
||||||
|
|
||||||
#: file.cpp:227
|
#: file.cpp:227
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "can't close file descriptor %d"
|
msgid "can't close file descriptor %d"
|
||||||
msgstr "impossible de fermer le descripteur %d"
|
msgstr ""
|
||||||
|
|
||||||
#: file.cpp:244
|
#: file.cpp:244
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "can't read from file descriptor %d"
|
msgid "can't read from file descriptor %d"
|
||||||
msgstr "impossible de lire <20> partir de descripteur %d"
|
msgstr ""
|
||||||
|
|
||||||
#: file.cpp:258
|
#: file.cpp:258
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "can't write to file descriptor %d"
|
msgid "can't write to file descriptor %d"
|
||||||
msgstr "impossible d'<27>crire sur le descripteur %d"
|
msgstr ""
|
||||||
|
|
||||||
#: file.cpp:271
|
#: file.cpp:271
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "can't flush file descriptor %d"
|
msgid "can't flush file descriptor %d"
|
||||||
msgstr "impossible de mettre <20> jour le descripteur %d"
|
msgstr ""
|
||||||
|
|
||||||
#: file.cpp:308
|
#: file.cpp:308
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "can't seek on file descriptor %d"
|
msgid "can't seek on file descriptor %d"
|
||||||
msgstr "impossible de changer la position sur le descripteur %d"
|
msgstr ""
|
||||||
|
|
||||||
#: file.cpp:322
|
#: file.cpp:322
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "can't get seek position on file descriptor %d"
|
msgid "can't get seek position on file descriptor %d"
|
||||||
msgstr "impossible d'obtenir la position courante sur le descripteur %d"
|
msgstr ""
|
||||||
|
|
||||||
#: file.cpp:355
|
#: file.cpp:355
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "can't find length of file on file descriptor %d"
|
msgid "can't find length of file on file descriptor %d"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"impossible de trouver la taille du fichier ouvert sur le descripteur %d"
|
|
||||||
|
|
||||||
#: intl.cpp:139
|
#: intl.cpp:139
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "catalog file for domain '%s' not found."
|
msgid "catalog file for domain '%s' not found."
|
||||||
msgstr "impossible de trouver le catalogue de messages pour le domaine '%s'."
|
msgstr ""
|
||||||
|
|
||||||
#: intl.cpp:177
|
#: intl.cpp:177
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "'%s' is not a valid message catalog."
|
msgid "'%s' is not a valid message catalog."
|
||||||
msgstr "'%s' n'est pas un catalogue de messages valid."
|
msgstr ""
|
||||||
|
|
||||||
#: intl.cpp:330 intl.cpp:334
|
#: intl.cpp:330 intl.cpp:334
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "locale '%s' can not be set."
|
msgid "locale '%s' can not be set."
|
||||||
msgstr "impossible de passer <20> locale '%s'."
|
msgstr ""
|
||||||
|
|
||||||
#: intl.cpp:431 intl.cpp:435
|
#: intl.cpp:431 intl.cpp:435
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "string '%s' not found in domain '%s' for locale '%s'."
|
msgid "string '%s' not found in domain '%s' for locale '%s'."
|
||||||
msgstr "cha<EFBFBD>ne '%s' n'a pas <20>t<EFBFBD> trouv<75> dans le domaine '%s' pour le locale '%s'."
|
msgstr ""
|
||||||
|
|
||||||
#: intl.cpp:434 intl.cpp:438
|
#: intl.cpp:434 intl.cpp:438
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "string '%s' not found in locale '%s'."
|
msgid "string '%s' not found in locale '%s'."
|
||||||
msgstr "cha<EFBFBD>ne '%s' n'a pas <20>t<EFBFBD> trouv<75> dans le locale '%s'."
|
msgstr ""
|
||||||
|
|
||||||
#: log.cpp:104
|
#: log.cpp:104
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid " (error %ld: %s)"
|
msgid " (error %ld: %s)"
|
||||||
msgstr " (erreur %ld: %s)"
|
msgstr ""
|
||||||
|
|
||||||
#: log.cpp:165
|
#: log.cpp:165
|
||||||
msgid "Debug: "
|
msgid "Debug: "
|
||||||
msgstr "Debug: "
|
msgstr ""
|
||||||
|
|
||||||
#: log.cpp:171
|
#: log.cpp:171
|
||||||
msgid "Fatal error: "
|
msgid "Fatal error: "
|
||||||
msgstr "Erreur fatale: "
|
msgstr ""
|
||||||
|
|
||||||
#: log.cpp:172
|
#: log.cpp:172
|
||||||
msgid "Program aborted.\n"
|
msgid "Program aborted.\n"
|
||||||
msgstr "Programme abandonn<6E>.\n"
|
msgstr ""
|
||||||
|
|
||||||
#: log.cpp:177
|
#: log.cpp:177
|
||||||
msgid "Error: "
|
msgid "Error: "
|
||||||
msgstr "Erreur: "
|
msgstr ""
|
||||||
|
|
||||||
#: log.cpp:181
|
#: log.cpp:181
|
||||||
msgid "Warning: "
|
msgid "Warning: "
|
||||||
msgstr "Attention: "
|
msgstr ""
|
||||||
|
|
||||||
#: log.cpp:268
|
#: log.cpp:268
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Assert failed in file %s at line %d"
|
msgid "Assert failed in file %s at line %d"
|
||||||
msgstr "Assertion est fausse dans le fichier %s <20> la ligne %d"
|
msgstr ""
|
||||||
|
|
||||||
#: file.cpp:303
|
#: file.cpp:303
|
||||||
msgid "unknown seek origin"
|
msgid "unknown seek origin"
|
||||||
@@ -129,3 +128,9 @@ msgstr ""
|
|||||||
#: intl.cpp:378
|
#: intl.cpp:378
|
||||||
msgid "no message catalog list"
|
msgid "no message catalog list"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "OK"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Cancel"
|
||||||
|
msgstr ""
|
||||||
|
@@ -148,6 +148,13 @@ private:
|
|||||||
char *m_pszName; // name of the domain
|
char *m_pszName; // name of the domain
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// global variables
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// the list of the directories to search for message catalog files
|
||||||
|
static wxArrayString s_searchPrefixes;
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// implementation
|
// implementation
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -197,42 +204,77 @@ wxMsgCatalog::~wxMsgCatalog()
|
|||||||
wxDELETEA(m_pszName);
|
wxDELETEA(m_pszName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// small class to suppress the translation erros until exit from current scope
|
||||||
class NoTransErr
|
class NoTransErr
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NoTransErr() { wxSuppressTransErrors(); }
|
NoTransErr() { wxSuppressTransErrors(); }
|
||||||
~NoTransErr() { wxRestoreTransErrors(); }
|
~NoTransErr() { wxRestoreTransErrors(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// return all directories to search for given prefix
|
||||||
|
static wxString GetAllMsgCatalogSubdirs(const char *prefix,
|
||||||
|
const char *lang)
|
||||||
|
{
|
||||||
|
wxString searchPath;
|
||||||
|
|
||||||
|
// search first in prefix/fr/LC_MESSAGES, then in prefix/fr and finally in
|
||||||
|
// prefix (assuming the language is 'fr')
|
||||||
|
searchPath << prefix << FILE_SEP_PATH << lang << FILE_SEP_PATH
|
||||||
|
<< "LC_MESSAGES" << PATH_SEP
|
||||||
|
<< prefix << FILE_SEP_PATH << lang << PATH_SEP
|
||||||
|
<< prefix << PATH_SEP;
|
||||||
|
|
||||||
|
return searchPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// construct the search path for the given language
|
||||||
|
static wxString GetFullSearchPath(const char *lang)
|
||||||
|
{
|
||||||
|
wxString searchPath;
|
||||||
|
|
||||||
|
// first take the entries explicitly added by the program
|
||||||
|
size_t count = s_searchPrefixes.Count();
|
||||||
|
for ( size_t n = 0; n < count; n++ )
|
||||||
|
{
|
||||||
|
searchPath << GetAllMsgCatalogSubdirs(s_searchPrefixes[n], lang)
|
||||||
|
<< PATH_SEP;
|
||||||
|
}
|
||||||
|
|
||||||
|
// then take the current directory
|
||||||
|
// FIXME it should be the directory of the executable
|
||||||
|
searchPath << GetAllMsgCatalogSubdirs(".", lang) << PATH_SEP;
|
||||||
|
|
||||||
|
// and finally add some standard ones
|
||||||
|
searchPath
|
||||||
|
<< GetAllMsgCatalogSubdirs("/usr/share/locale", lang) << PATH_SEP
|
||||||
|
<< GetAllMsgCatalogSubdirs("/usr/lib/locale", lang) << PATH_SEP
|
||||||
|
<< GetAllMsgCatalogSubdirs("/usr/local/share/locale", lang);
|
||||||
|
|
||||||
|
return searchPath;
|
||||||
|
}
|
||||||
|
|
||||||
// open disk file and read in it's contents
|
// open disk file and read in it's contents
|
||||||
bool wxMsgCatalog::Load(const char *szDirPrefix, const char *szName)
|
bool wxMsgCatalog::Load(const char *szDirPrefix, const char *szName)
|
||||||
{
|
{
|
||||||
// search order (assume language 'foo') is
|
// FIXME VZ: I forgot the exact meaning of LC_PATH - anyone to remind me?
|
||||||
// 1) $LC_PATH/foo/LC_MESSAGES (if LC_PATH set)
|
#if 0
|
||||||
// 2) ./foo/LC_MESSAGES
|
|
||||||
// 3) ./foo
|
|
||||||
// 4) . (Added by JACS)
|
|
||||||
//
|
|
||||||
// under UNIX we search also in:
|
|
||||||
// 5) /usr/share/locale/foo/LC_MESSAGES (Linux)
|
|
||||||
// 6) /usr/lib/locale/foo/LC_MESSAGES (Solaris)
|
|
||||||
#define MSG_PATH FILE_SEP_PATH + "LC_MESSAGES" PATH_SEP
|
|
||||||
|
|
||||||
wxString strPath("");
|
|
||||||
const char *pszLcPath = getenv("LC_PATH");
|
const char *pszLcPath = getenv("LC_PATH");
|
||||||
if ( pszLcPath != NULL )
|
if ( pszLcPath != NULL )
|
||||||
strPath += pszLcPath + wxString(szDirPrefix) + MSG_PATH; // (1)
|
strPath += pszLcPath + wxString(szDirPrefix) + MSG_PATH;
|
||||||
|
#endif // 0
|
||||||
|
|
||||||
// NB: '<<' is unneeded between too literal strings:
|
wxString searchPath = GetFullSearchPath(szDirPrefix);
|
||||||
// they are concatenated at compile time
|
const char *sublocale = strchr(szDirPrefix, '_');
|
||||||
strPath += "./" + wxString(szDirPrefix) + MSG_PATH // (2)
|
if ( sublocale )
|
||||||
+ "./" + szDirPrefix + FILE_SEP_PATH + PATH_SEP // (3)
|
{
|
||||||
+ "." + PATH_SEP
|
// also add just base locale name: for things like "fr_BE" (belgium
|
||||||
#ifdef __UNIX__
|
// french) we should use "fr" if no belgium specific message catalogs
|
||||||
"/usr/share/locale/" + szDirPrefix + MSG_PATH // (5)
|
// exist
|
||||||
"/usr/lib/locale/" + szDirPrefix + MSG_PATH // (6)
|
searchPath << GetFullSearchPath(wxString(szDirPrefix).
|
||||||
#endif //UNIX
|
Left((size_t)(sublocale - szDirPrefix)))
|
||||||
;
|
<< PATH_SEP;
|
||||||
|
}
|
||||||
|
|
||||||
wxString strFile = szName;
|
wxString strFile = szName;
|
||||||
strFile += MSGCATALOG_EXTENSION;
|
strFile += MSGCATALOG_EXTENSION;
|
||||||
@@ -244,10 +286,10 @@ bool wxMsgCatalog::Load(const char *szDirPrefix, const char *szName)
|
|||||||
NoTransErr noTransErr;
|
NoTransErr noTransErr;
|
||||||
|
|
||||||
wxLogVerbose(_("looking for catalog '%s' in path '%s'."),
|
wxLogVerbose(_("looking for catalog '%s' in path '%s'."),
|
||||||
szName, strPath.c_str());
|
szName, searchPath.c_str());
|
||||||
|
|
||||||
wxString strFullName;
|
wxString strFullName;
|
||||||
if ( !wxFindFileInPath(&strFullName, strPath, strFile) ) {
|
if ( !wxFindFileInPath(&strFullName, searchPath, strFile) ) {
|
||||||
wxLogWarning(_("catalog file for domain '%s' not found."), szName);
|
wxLogWarning(_("catalog file for domain '%s' not found."), szName);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@@ -384,8 +426,8 @@ bool wxLocale::Init(const char *szName,
|
|||||||
// the short name will be used to look for catalog files as well,
|
// the short name will be used to look for catalog files as well,
|
||||||
// so we need something here
|
// so we need something here
|
||||||
if ( m_strShort.IsEmpty() ) {
|
if ( m_strShort.IsEmpty() ) {
|
||||||
// #### I don't know how these 2 letter abbreviations are formed,
|
// FIXME I don't know how these 2 letter abbreviations are formed,
|
||||||
// this wild guess is almost surely wrong
|
// this wild guess is surely wrong
|
||||||
m_strShort = wxToLower(szLocale[0]) + wxToLower(szLocale[1]);
|
m_strShort = wxToLower(szLocale[0]) + wxToLower(szLocale[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -401,20 +443,29 @@ bool wxLocale::Init(const char *szName,
|
|||||||
return bOk;
|
return bOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxLocale::AddCatalogLookupPathPrefix(const wxString& prefix)
|
||||||
|
{
|
||||||
|
if ( s_searchPrefixes.Index(prefix) == NOT_FOUND )
|
||||||
|
{
|
||||||
|
s_searchPrefixes.Add(prefix);
|
||||||
|
}
|
||||||
|
//else: already have it
|
||||||
|
}
|
||||||
|
|
||||||
// clean up
|
// clean up
|
||||||
wxLocale::~wxLocale()
|
wxLocale::~wxLocale()
|
||||||
{
|
{
|
||||||
// free memory
|
// free memory
|
||||||
wxMsgCatalog *pTmpCat;
|
wxMsgCatalog *pTmpCat;
|
||||||
while ( m_pMsgCat != NULL ) {
|
while ( m_pMsgCat != NULL ) {
|
||||||
pTmpCat = m_pMsgCat;
|
pTmpCat = m_pMsgCat;
|
||||||
m_pMsgCat = m_pMsgCat->m_pNext;
|
m_pMsgCat = m_pMsgCat->m_pNext;
|
||||||
delete pTmpCat;
|
delete pTmpCat;
|
||||||
}
|
}
|
||||||
|
|
||||||
// restore old locale
|
// restore old locale
|
||||||
wxSetLocale(m_pOldLocale);
|
wxSetLocale(m_pOldLocale);
|
||||||
setlocale(LC_ALL, m_pszOldLocale);
|
setlocale(LC_ALL, m_pszOldLocale);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the translation of given string in current locale
|
// get the translation of given string in current locale
|
||||||
@@ -444,16 +495,27 @@ const char *wxLocale::GetString(const char *szOrigString,
|
|||||||
|
|
||||||
if ( pszTrans == NULL ) {
|
if ( pszTrans == NULL ) {
|
||||||
if ( wxIsLoggingTransErrors() ) {
|
if ( wxIsLoggingTransErrors() ) {
|
||||||
// suppress further error messages
|
// suppress further error messages if we're not debugging: this avoids
|
||||||
// (do it before LogWarning to prevent infinite recursion!)
|
// flooding the user with messages about each and every missing string if,
|
||||||
|
// for example, a whole catalog file is missing.
|
||||||
|
|
||||||
|
// do it before calling LogWarning to prevent infinite recursion!
|
||||||
|
#ifdef __WXDEBUG__
|
||||||
|
NoTransErr noTransErr;
|
||||||
|
#else // !debug
|
||||||
wxSuppressTransErrors();
|
wxSuppressTransErrors();
|
||||||
|
#endif // debug/!debug
|
||||||
|
|
||||||
if ( szDomain != NULL )
|
if ( szDomain != NULL )
|
||||||
|
{
|
||||||
wxLogWarning(_("string '%s' not found in domain '%s' for locale '%s'."),
|
wxLogWarning(_("string '%s' not found in domain '%s' for locale '%s'."),
|
||||||
szOrigString, szDomain, m_strLocale.c_str());
|
szOrigString, szDomain, m_strLocale.c_str());
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
wxLogWarning(_("string '%s' not found in locale '%s'."),
|
wxLogWarning(_("string '%s' not found in locale '%s'."),
|
||||||
szOrigString, m_strLocale.c_str());
|
szOrigString, m_strLocale.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return szOrigString;
|
return szOrigString;
|
||||||
|
Reference in New Issue
Block a user