]> git.saurik.com Git - wxWidgets.git/blame - samples/internat/internat.cpp
add SetCharIncludes and SetCharExcludes utilities to wxTextValidator; use iterators...
[wxWidgets.git] / samples / internat / internat.cpp
CommitLineData
c801d85f
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: internat.cpp
c7f3b78b 3// Purpose: Demonstrates internationalisation (i18n) support
c801d85f
KB
4// Author: Vadim Zeitlin/Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
6aa89a22 8// Copyright: (c) Julian Smart
c7f3b78b 9// Licence: wxWindows license
c801d85f
KB
10/////////////////////////////////////////////////////////////////////////////
11
017fcf32
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
c801d85f
KB
19
20// For compilers that support precompilation, includes "wx/wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24#pragma hdrstop
25#endif
26
27#ifndef WX_PRECOMP
3a331275 28 #include "wx/wx.h"
c801d85f
KB
29#endif
30
31#include "wx/intl.h"
c7f3b78b 32#include "wx/file.h"
c801d85f 33#include "wx/log.h"
3a331275 34#include "wx/cmdline.h"
c801d85f 35
618f2efa 36#if defined(__WXGTK__) || defined(__WXX11__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXMGL__)
47908e25
RR
37#include "mondrian.xpm"
38#endif
39
017fcf32
VZ
40// ----------------------------------------------------------------------------
41// private classes
42// ----------------------------------------------------------------------------
43
c801d85f
KB
44// Define a new application type
45class MyApp: public wxApp
46{
47public:
3a331275
VZ
48 MyApp() { m_lang = wxLANGUAGE_UNKNOWN; }
49
50 virtual void OnInitCmdLine(wxCmdLineParser& parser);
51 virtual bool OnCmdLineParsed(wxCmdLineParser& parser);
aec18ff7 52 virtual bool OnInit();
c7f3b78b 53
c801d85f 54protected:
3a331275
VZ
55 wxLanguage m_lang; // language specified by user
56 wxLocale m_locale; // locale we'll be using
c801d85f
KB
57};
58
59// Define a new frame type
60class MyFrame: public wxFrame
aec18ff7 61{
c7f3b78b 62public:
017fcf32 63 MyFrame(wxLocale& m_locale);
c7f3b78b
VZ
64
65public:
cec5ffc4 66 void OnTestLocaleAvail(wxCommandEvent& event);
aec18ff7 67 void OnAbout(wxCommandEvent& event);
cec5ffc4
VZ
68 void OnQuit(wxCommandEvent& event);
69
aec18ff7
MB
70 void OnPlay(wxCommandEvent& event);
71 void OnOpen(wxCommandEvent& event);
849a28d0
VS
72 void OnTest1(wxCommandEvent& event);
73 void OnTest2(wxCommandEvent& event);
74 void OnTest3(wxCommandEvent& event);
f13880a9 75
aec18ff7
MB
76 DECLARE_EVENT_TABLE()
77
78 wxLocale& m_locale;
c801d85f
KB
79};
80
017fcf32
VZ
81// ----------------------------------------------------------------------------
82// constants
83// ----------------------------------------------------------------------------
84
c801d85f 85// ID for the menu commands
c7f3b78b
VZ
86enum
87{
cec5ffc4
VZ
88 INTERNAT_TEST = wxID_HIGHEST + 1,
89 INTERNAT_PLAY,
849a28d0
VS
90 INTERNAT_TEST_1,
91 INTERNAT_TEST_2,
6ea0cc70 92 INTERNAT_TEST_3
c7f3b78b 93};
c801d85f 94
79b4079f
VZ
95// language data
96static const wxLanguage langIds[] =
97{
98 wxLANGUAGE_DEFAULT,
99 wxLANGUAGE_FRENCH,
7a90a4db 100 wxLANGUAGE_ITALIAN,
79b4079f
VZ
101 wxLANGUAGE_GERMAN,
102 wxLANGUAGE_RUSSIAN,
103 wxLANGUAGE_BULGARIAN,
104 wxLANGUAGE_CZECH,
105 wxLANGUAGE_POLISH,
106 wxLANGUAGE_SWEDISH,
107#if wxUSE_UNICODE || defined(__WXMOTIF__)
108 wxLANGUAGE_JAPANESE,
109#endif
110#if wxUSE_UNICODE
111 wxLANGUAGE_GEORGIAN,
112 wxLANGUAGE_ENGLISH,
978af864
VZ
113 wxLANGUAGE_ENGLISH_US,
114 wxLANGUAGE_ARABIC,
115 wxLANGUAGE_ARABIC_EGYPT
79b4079f
VZ
116#endif
117};
118
119// note that it makes no sense to translate these strings, they are
120// shown before we set the locale anyhow
121const wxString langNames[] =
122{
bf2d9237
FM
123 "System default",
124 "French",
125 "Italian",
126 "German",
127 "Russian",
128 "Bulgarian",
129 "Czech",
130 "Polish",
131 "Swedish",
79b4079f 132#if wxUSE_UNICODE || defined(__WXMOTIF__)
bf2d9237 133 "Japanese",
79b4079f
VZ
134#endif
135#if wxUSE_UNICODE
bf2d9237
FM
136 "Georgian",
137 "English",
138 "English (U.S.)",
139 "Arabic",
140 "Arabic (Egypt)"
79b4079f
VZ
141#endif
142};
143
144// the arrays must be in sync
145wxCOMPILE_TIME_ASSERT( WXSIZEOF(langNames) == WXSIZEOF(langIds),
146 LangArraysMismatch );
147
017fcf32 148// ----------------------------------------------------------------------------
be5a51fb 149// wxWidgets macros
017fcf32
VZ
150// ----------------------------------------------------------------------------
151
c801d85f 152BEGIN_EVENT_TABLE(MyFrame, wxFrame)
cec5ffc4 153 EVT_MENU(INTERNAT_TEST, MyFrame::OnTestLocaleAvail)
aec18ff7 154 EVT_MENU(wxID_ABOUT, MyFrame::OnAbout)
cec5ffc4
VZ
155 EVT_MENU(wxID_EXIT, MyFrame::OnQuit)
156
157 EVT_MENU(INTERNAT_PLAY, MyFrame::OnPlay)
6ea0cc70 158 EVT_MENU(wxID_OPEN, MyFrame::OnOpen)
849a28d0
VS
159 EVT_MENU(INTERNAT_TEST_1, MyFrame::OnTest1)
160 EVT_MENU(INTERNAT_TEST_2, MyFrame::OnTest2)
161 EVT_MENU(INTERNAT_TEST_3, MyFrame::OnTest3)
c801d85f
KB
162END_EVENT_TABLE()
163
164IMPLEMENT_APP(MyApp)
165
017fcf32
VZ
166// ============================================================================
167// implementation
168// ============================================================================
169
170// ----------------------------------------------------------------------------
171// MyApp
172// ----------------------------------------------------------------------------
c801d85f 173
3a331275
VZ
174// command line arguments handling
175void MyApp::OnInitCmdLine(wxCmdLineParser& parser)
c801d85f 176{
3a331275
VZ
177 parser.AddParam(_("locale"),
178 wxCMD_LINE_VAL_STRING,
179 wxCMD_LINE_PARAM_OPTIONAL);
45e6e6f8 180
3a331275
VZ
181 wxApp::OnInitCmdLine(parser);
182}
017fcf32 183
3a331275
VZ
184bool MyApp::OnCmdLineParsed(wxCmdLineParser& parser)
185{
186 if ( !wxApp::OnCmdLineParsed(parser) )
187 return false;
188
189 if ( parser.GetParamCount() )
aec18ff7 190 {
3a331275
VZ
191 const wxString loc = parser.GetParam();
192 const wxLanguageInfo * const lang = wxLocale::FindLanguageInfo(loc);
193 if ( !lang )
194 {
195 wxLogError(_("Locale \"%s\" is unknown."), loc);
196 return false;
197 }
198
81d3348a 199 m_lang = static_cast<wxLanguage>(lang->Language);
017fcf32
VZ
200 }
201
3a331275
VZ
202 return true;
203}
204
205// `Main program' equivalent, creating windows and returning main app frame
206bool MyApp::OnInit()
207{
208 if ( !wxApp::OnInit() )
209 return false;
210
211 if ( m_lang == wxLANGUAGE_UNKNOWN )
017fcf32 212 {
3a331275
VZ
213 int lng = wxGetSingleChoiceIndex
214 (
215 _("Please choose language:"),
216 _("Language"),
217 WXSIZEOF(langNames),
218 langNames
219 );
220 m_lang = lng == -1 ? wxLANGUAGE_DEFAULT : langIds[lng];
017fcf32
VZ
221 }
222
6f011443
VZ
223 // don't use wxLOCALE_LOAD_DEFAULT flag so that Init() doesn't return
224 // false just because it failed to load wxstd catalog
225 if ( !m_locale.Init(m_lang, wxLOCALE_CONV_ENCODING) )
346f4231 226 {
6f011443 227 wxLogWarning(_("This language is not supported by the system."));
3a331275 228
6f011443 229 // continue nevertheless
346f4231 230 }
aec18ff7 231
89611d4d
VZ
232 // normally this wouldn't be necessary as the catalog files would be found
233 // in the default locations, but when the program is not installed the
234 // catalogs are in the build directory where we wouldn't find them by
235 // default
7256e9b6 236 wxLocale::AddCatalogLookupPathPrefix(".");
017fcf32 237
aec18ff7 238 // Initialize the catalogs we'll be using
7256e9b6 239 if (!m_locale.AddCatalog("internat"))
f00204d3 240 wxLogError(_("Couldn't find/load the 'internat' catalog."));
017fcf32 241
7256e9b6
FM
242 // Now try to add wxstd.mo so that loading "NOTEXIST.ING" file will produce
243 // a localized error message:
244 m_locale.AddCatalog("wxstd.mo");
245 // NOTE: it's not an error if we couldn't find it!
246
017fcf32
VZ
247 // this catalog is installed in standard location on Linux systems and
248 // shows that you may make use of the standard message catalogs as well
249 //
250 // if it's not installed on your system, it is just silently ignored
8e97b17b 251#ifdef __LINUX__
aec18ff7 252 {
017fcf32 253 wxLogNull noLog;
bf2d9237 254 m_locale.AddCatalog("fileutils");
aec18ff7 255 }
8e97b17b 256#endif
aec18ff7
MB
257
258 // Create the main frame window
017fcf32 259 MyFrame *frame = new MyFrame(m_locale);
aec18ff7
MB
260
261 // Give it an icon
262 frame->SetIcon(wxICON(mondrian));
263
264 // Make a menubar
265 wxMenu *file_menu = new wxMenu;
cec5ffc4
VZ
266 file_menu->Append(INTERNAT_TEST, _("&Test locale availability...\tCtrl-T"));
267 file_menu->AppendSeparator();
aec18ff7
MB
268 file_menu->Append(wxID_ABOUT, _("&About..."));
269 file_menu->AppendSeparator();
f13880a9 270 file_menu->Append(wxID_EXIT, _("E&xit"));
aec18ff7
MB
271
272 wxMenu *test_menu = new wxMenu;
6ea0cc70 273 test_menu->Append(wxID_OPEN, _("&Open bogus file"));
cec5ffc4 274 test_menu->Append(INTERNAT_PLAY, _("&Play a game"));
849a28d0
VS
275 test_menu->AppendSeparator();
276 test_menu->Append(INTERNAT_TEST_1, _("&1 _() (gettext)"));
277 test_menu->Append(INTERNAT_TEST_2, _("&2 _N() (ngettext)"));
4c3590e4 278 test_menu->Append(INTERNAT_TEST_3, _("&3 wxTRANSLATE() (gettext_noop)"));
aec18ff7
MB
279
280 wxMenuBar *menu_bar = new wxMenuBar;
281 menu_bar->Append(file_menu, _("&File"));
282 menu_bar->Append(test_menu, _("&Test"));
283 frame->SetMenuBar(menu_bar);
284
285 // Show the frame
f13880a9 286 frame->Show(true);
aec18ff7
MB
287 SetTopWindow(frame);
288
f13880a9 289 return true;
c801d85f
KB
290}
291
017fcf32
VZ
292// ----------------------------------------------------------------------------
293// MyFrame
294// ----------------------------------------------------------------------------
295
296// main frame constructor
297MyFrame::MyFrame(wxLocale& locale)
298 : wxFrame(NULL,
f13880a9
WS
299 wxID_ANY,
300 _("International wxWidgets App")),
017fcf32 301 m_locale(locale)
c7f3b78b 302{
978af864
VZ
303 // this demonstrates RTL layout mirroring for Arabic locales
304 wxSizer *sizer = new wxBoxSizer(wxHORIZONTAL);
305 sizer->Add(new wxStaticText(this, wxID_ANY, _("First")),
306 wxSizerFlags().Border());
307 sizer->Add(new wxStaticText(this, wxID_ANY, _("Second")),
308 wxSizerFlags().Border());
309 SetSizer(sizer);
c7f3b78b 310}
c801d85f 311
bd7d06f2 312void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event) )
c801d85f 313{
f13880a9 314 Close(true);
c801d85f
KB
315}
316
bd7d06f2 317void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
c801d85f 318{
aec18ff7 319 wxString localeInfo;
2b5f62a0
VZ
320 wxString locale = m_locale.GetLocale();
321 wxString sysname = m_locale.GetSysName();
322 wxString canname = m_locale.GetCanonicalName();
323
f13880a9 324 localeInfo.Printf(_("Language: %s\nSystem locale name:\n%s\nCanonical locale name: %s\n"),
2b5f62a0 325 locale.c_str(), sysname.c_str(), canname.c_str() );
aec18ff7 326
925e9792
WS
327 wxMessageDialog dlg(
328 this,
329 wxString(_("I18n sample\n(c) 1998, 1999 Vadim Zeitlin and Julian Smart"))
7256e9b6 330 + "\n\n"
925e9792
WS
331 + localeInfo,
332 _("About Internat"),
333 wxOK | wxICON_INFORMATION
334 );
335 dlg.ShowModal();
c801d85f
KB
336}
337
bd7d06f2 338void MyFrame::OnPlay(wxCommandEvent& WXUNUSED(event))
c7f3b78b 339{
085c26ac
VZ
340 wxString str = wxGetTextFromUser
341 (
342 _("Enter your number:"),
343 _("Try to guess my number!"),
344 wxEmptyString,
345 this
346 );
347
348 if ( str.empty() )
349 {
350 // cancelled
351 return;
352 }
aec18ff7 353
085c26ac
VZ
354 long num;
355 if ( !str.ToLong(&num) || num < 0 )
356 {
aec18ff7 357 str = _("You've probably entered an invalid number.");
085c26ac
VZ
358 }
359 else if ( num == 9 )
360 {
361 // this message is not translated (not in catalog) because we used _T()
362 // and not _() around it
2b5f62a0 363 str = _T("You've found a bug in this program!");
085c26ac
VZ
364 }
365 else if ( num == 17 )
aec18ff7 366 {
085c26ac
VZ
367 str.clear();
368
369 // string must be split in two -- otherwise the translation would't be
370 // found
aec18ff7
MB
371 str << _("Congratulations! you've won. Here is the magic phrase:")
372 << _("cannot create fifo `%s'");
373 }
085c26ac
VZ
374 else
375 {
376 // this is a more implicit way to write _() but note that if you use it
377 // you must ensure that the strings get extracted in the message
bf2d9237
FM
378 // catalog as by default xgettext won't do it; it only knows of _(),
379 // not of wxTRANSLATE(). As internat's readme.txt says you should thus
380 // call xgettext with -kwxTRANSLATE.
7256e9b6
FM
381 str = wxGetTranslation(wxTRANSLATE("Bad luck! try again..."));
382
383 // note also that if we want 'str' to contain a localized string
384 // we need to use wxGetTranslation explicitely as wxTRANSLATE just
385 // tells xgettext to extract the string but has no effect on the
386 // runtime of the program!
085c26ac 387 }
aec18ff7
MB
388
389 wxMessageBox(str, _("Result"), wxOK | wxICON_INFORMATION);
c7f3b78b
VZ
390}
391
cec5ffc4
VZ
392void MyFrame::OnTestLocaleAvail(wxCommandEvent& WXUNUSED(event))
393{
394 static wxString s_locale;
395 wxString locale = wxGetTextFromUser
396 (
397 _("Enter the locale to test"),
398 wxGetTextFromUserPromptStr,
399 s_locale,
400 this
401 );
402 if ( locale.empty() )
403 return;
404
405 s_locale = locale;
406 const wxLanguageInfo * const info = wxLocale::FindLanguageInfo(s_locale);
407 if ( !info )
408 {
409 wxLogError(_("Locale \"%s\" is unknown."), s_locale.c_str());
410 return;
411 }
412
413 if ( wxLocale::IsAvailable(info->Language) )
414 wxLogMessage(_("Locale \"%s\" is available."), s_locale.c_str());
415 else
416 wxLogWarning(_("Locale \"%s\" is not available."), s_locale.c_str());
417}
418
419void MyFrame::OnOpen(wxCommandEvent& WXUNUSED(event))
c7f3b78b 420{
849a28d0 421 // open a bogus file -- the error message should be also translated if
7256e9b6
FM
422 // you've got wxstd.mo somewhere in the search path (see MyApp::OnInit)
423 wxFile file("NOTEXIST.ING");
071cc2be 424}
085c26ac 425
849a28d0
VS
426void MyFrame::OnTest1(wxCommandEvent& WXUNUSED(event))
427{
7256e9b6
FM
428 const wxString& title = _("Testing _() (gettext)");
429
430 // NOTE: using the wxTRANSLATE() macro here we won't show a localized
431 // string in the text entry dialog; we'll simply show the un-translated
432 // string; however if the user press "ok" without altering the text,
433 // since the "default value" string has been extracted by xgettext
434 // the wxGetTranslation call later will manage to return a localized
435 // string
849a28d0 436 wxTextEntryDialog d(this, _("Please enter text to translate"),
7256e9b6 437 title, wxTRANSLATE("default value"));
bf2d9237 438
849a28d0
VS
439 if (d.ShowModal() == wxID_OK)
440 {
f13880a9
WS
441 wxString v = d.GetValue();
442 wxString s(title);
bf2d9237
FM
443 s << "\n" << v << " -> "
444 << wxGetTranslation(v.c_str()) << "\n";
f13880a9 445 wxMessageBox(s);
849a28d0
VS
446 }
447}
448
449void MyFrame::OnTest2(wxCommandEvent& WXUNUSED(event))
450{
7256e9b6 451 const wxString& title = _("Testing _N() (ngettext)");
849a28d0 452 wxTextEntryDialog d(this,
f13880a9 453 _("Please enter range for plural forms of \"n files deleted\" phrase"),
bf2d9237
FM
454 title, "0-10");
455
849a28d0
VS
456 if (d.ShowModal() == wxID_OK)
457 {
f13880a9 458 int first, last;
bf2d9237 459 wxSscanf(d.GetValue(), "%d-%d", &first, &last);
f13880a9 460 wxString s(title);
bf2d9237 461 s << "\n";
f13880a9 462 for (int n = first; n <= last; ++n)
849a28d0 463 {
bf2d9237 464 s << n << " " <<
15d06954 465 wxPLURAL("file deleted", "files deleted", n) <<
bf2d9237 466 "\n";
f13880a9 467 }
849a28d0
VS
468 wxMessageBox(s);
469 }
470}
471
472void MyFrame::OnTest3(wxCommandEvent& WXUNUSED(event))
473{
ad4814e7 474 const char* lines[] =
849a28d0 475 {
f13880a9
WS
476 wxTRANSLATE("line 1"),
477 wxTRANSLATE("line 2"),
478 wxTRANSLATE("line 3"),
849a28d0 479 };
bf2d9237 480
4c3590e4 481 wxString s(_("Testing wxTRANSLATE() (gettext_noop)"));
bf2d9237 482 s << "\n";
849a28d0
VS
483 for (size_t i = 0; i < WXSIZEOF(lines); ++i)
484 {
bf2d9237 485 s << lines[i] << " -> " << wxGetTranslation(lines[i]) << "\n";
849a28d0
VS
486 }
487 wxMessageBox(s);
488}
489
490