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