]> git.saurik.com Git - wxWidgets.git/blame - samples/internat/internat.cpp
fixing infinite recursion for rotated text, introduced in cleanup r57915
[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{
123 _T("System default"),
124 _T("French"),
7a90a4db 125 _T("Italian"),
79b4079f
VZ
126 _T("German"),
127 _T("Russian"),
128 _T("Bulgarian"),
129 _T("Czech"),
130 _T("Polish"),
131 _T("Swedish"),
132#if wxUSE_UNICODE || defined(__WXMOTIF__)
133 _T("Japanese"),
134#endif
135#if wxUSE_UNICODE
136 _T("Georgian"),
137 _T("English"),
978af864
VZ
138 _T("English (U.S.)"),
139 _T("Arabic"),
140 _T("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
236 wxLocale::AddCatalogLookupPathPrefix(wxT("."));
017fcf32 237
aec18ff7 238 // Initialize the catalogs we'll be using
f00204d3
FM
239 if (!m_locale.AddCatalog(wxT("internat")))
240 wxLogError(_("Couldn't find/load the 'internat' catalog."));
017fcf32
VZ
241
242 // this catalog is installed in standard location on Linux systems and
243 // shows that you may make use of the standard message catalogs as well
244 //
245 // if it's not installed on your system, it is just silently ignored
8e97b17b 246#ifdef __LINUX__
aec18ff7 247 {
017fcf32
VZ
248 wxLogNull noLog;
249 m_locale.AddCatalog(_T("fileutils"));
aec18ff7 250 }
8e97b17b 251#endif
aec18ff7
MB
252
253 // Create the main frame window
017fcf32 254 MyFrame *frame = new MyFrame(m_locale);
aec18ff7
MB
255
256 // Give it an icon
257 frame->SetIcon(wxICON(mondrian));
258
259 // Make a menubar
260 wxMenu *file_menu = new wxMenu;
cec5ffc4
VZ
261 file_menu->Append(INTERNAT_TEST, _("&Test locale availability...\tCtrl-T"));
262 file_menu->AppendSeparator();
aec18ff7
MB
263 file_menu->Append(wxID_ABOUT, _("&About..."));
264 file_menu->AppendSeparator();
f13880a9 265 file_menu->Append(wxID_EXIT, _("E&xit"));
aec18ff7
MB
266
267 wxMenu *test_menu = new wxMenu;
6ea0cc70 268 test_menu->Append(wxID_OPEN, _("&Open bogus file"));
cec5ffc4 269 test_menu->Append(INTERNAT_PLAY, _("&Play a game"));
849a28d0
VS
270 test_menu->AppendSeparator();
271 test_menu->Append(INTERNAT_TEST_1, _("&1 _() (gettext)"));
272 test_menu->Append(INTERNAT_TEST_2, _("&2 _N() (ngettext)"));
4c3590e4 273 test_menu->Append(INTERNAT_TEST_3, _("&3 wxTRANSLATE() (gettext_noop)"));
aec18ff7
MB
274
275 wxMenuBar *menu_bar = new wxMenuBar;
276 menu_bar->Append(file_menu, _("&File"));
277 menu_bar->Append(test_menu, _("&Test"));
278 frame->SetMenuBar(menu_bar);
279
280 // Show the frame
f13880a9 281 frame->Show(true);
aec18ff7
MB
282 SetTopWindow(frame);
283
f13880a9 284 return true;
c801d85f
KB
285}
286
017fcf32
VZ
287// ----------------------------------------------------------------------------
288// MyFrame
289// ----------------------------------------------------------------------------
290
291// main frame constructor
292MyFrame::MyFrame(wxLocale& locale)
293 : wxFrame(NULL,
f13880a9
WS
294 wxID_ANY,
295 _("International wxWidgets App")),
017fcf32 296 m_locale(locale)
c7f3b78b 297{
978af864
VZ
298 // this demonstrates RTL layout mirroring for Arabic locales
299 wxSizer *sizer = new wxBoxSizer(wxHORIZONTAL);
300 sizer->Add(new wxStaticText(this, wxID_ANY, _("First")),
301 wxSizerFlags().Border());
302 sizer->Add(new wxStaticText(this, wxID_ANY, _("Second")),
303 wxSizerFlags().Border());
304 SetSizer(sizer);
c7f3b78b 305}
c801d85f 306
bd7d06f2 307void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event) )
c801d85f 308{
f13880a9 309 Close(true);
c801d85f
KB
310}
311
bd7d06f2 312void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
c801d85f 313{
aec18ff7 314 wxString localeInfo;
2b5f62a0
VZ
315 wxString locale = m_locale.GetLocale();
316 wxString sysname = m_locale.GetSysName();
317 wxString canname = m_locale.GetCanonicalName();
318
f13880a9 319 localeInfo.Printf(_("Language: %s\nSystem locale name:\n%s\nCanonical locale name: %s\n"),
2b5f62a0 320 locale.c_str(), sysname.c_str(), canname.c_str() );
aec18ff7 321
925e9792
WS
322 wxMessageDialog dlg(
323 this,
324 wxString(_("I18n sample\n(c) 1998, 1999 Vadim Zeitlin and Julian Smart"))
325 + wxT("\n\n")
326 + localeInfo,
327 _("About Internat"),
328 wxOK | wxICON_INFORMATION
329 );
330 dlg.ShowModal();
c801d85f
KB
331}
332
bd7d06f2 333void MyFrame::OnPlay(wxCommandEvent& WXUNUSED(event))
c7f3b78b 334{
085c26ac
VZ
335 wxString str = wxGetTextFromUser
336 (
337 _("Enter your number:"),
338 _("Try to guess my number!"),
339 wxEmptyString,
340 this
341 );
342
343 if ( str.empty() )
344 {
345 // cancelled
346 return;
347 }
aec18ff7 348
085c26ac
VZ
349 long num;
350 if ( !str.ToLong(&num) || num < 0 )
351 {
aec18ff7 352 str = _("You've probably entered an invalid number.");
085c26ac
VZ
353 }
354 else if ( num == 9 )
355 {
356 // this message is not translated (not in catalog) because we used _T()
357 // and not _() around it
2b5f62a0 358 str = _T("You've found a bug in this program!");
085c26ac
VZ
359 }
360 else if ( num == 17 )
aec18ff7 361 {
085c26ac
VZ
362 str.clear();
363
364 // string must be split in two -- otherwise the translation would't be
365 // found
aec18ff7
MB
366 str << _("Congratulations! you've won. Here is the magic phrase:")
367 << _("cannot create fifo `%s'");
368 }
085c26ac
VZ
369 else
370 {
371 // this is a more implicit way to write _() but note that if you use it
372 // you must ensure that the strings get extracted in the message
373 // catalog as by default xgettext won't do it (it only knows of _(),
374 // not wxGetTranslation())
375 str = wxGetTranslation(_T("Bad luck! try again..."));
376 }
aec18ff7
MB
377
378 wxMessageBox(str, _("Result"), wxOK | wxICON_INFORMATION);
c7f3b78b
VZ
379}
380
cec5ffc4
VZ
381void MyFrame::OnTestLocaleAvail(wxCommandEvent& WXUNUSED(event))
382{
383 static wxString s_locale;
384 wxString locale = wxGetTextFromUser
385 (
386 _("Enter the locale to test"),
387 wxGetTextFromUserPromptStr,
388 s_locale,
389 this
390 );
391 if ( locale.empty() )
392 return;
393
394 s_locale = locale;
395 const wxLanguageInfo * const info = wxLocale::FindLanguageInfo(s_locale);
396 if ( !info )
397 {
398 wxLogError(_("Locale \"%s\" is unknown."), s_locale.c_str());
399 return;
400 }
401
402 if ( wxLocale::IsAvailable(info->Language) )
403 wxLogMessage(_("Locale \"%s\" is available."), s_locale.c_str());
404 else
405 wxLogWarning(_("Locale \"%s\" is not available."), s_locale.c_str());
406}
407
408void MyFrame::OnOpen(wxCommandEvent& WXUNUSED(event))
c7f3b78b 409{
849a28d0
VS
410 // open a bogus file -- the error message should be also translated if
411 // you've got wxstd.mo somewhere in the search path
aec18ff7 412 wxFile file(wxT("NOTEXIST.ING"));
071cc2be 413}
085c26ac 414
849a28d0
VS
415void MyFrame::OnTest1(wxCommandEvent& WXUNUSED(event))
416{
79478afa 417 const wxString title = _("Testing _() (gettext)");
849a28d0 418 wxTextEntryDialog d(this, _("Please enter text to translate"),
f13880a9 419 title, wxTRANSLATE("default value"));
849a28d0
VS
420 if (d.ShowModal() == wxID_OK)
421 {
f13880a9
WS
422 wxString v = d.GetValue();
423 wxString s(title);
424 s << _T("\n") << v << _T(" -> ")
425 << wxGetTranslation(v.c_str()) << _T("\n");
426 wxMessageBox(s);
849a28d0
VS
427 }
428}
429
430void MyFrame::OnTest2(wxCommandEvent& WXUNUSED(event))
431{
79478afa 432 const wxString title = _("Testing _N() (ngettext)");
849a28d0 433 wxTextEntryDialog d(this,
f13880a9
WS
434 _("Please enter range for plural forms of \"n files deleted\" phrase"),
435 title, _T("0-10"));
849a28d0
VS
436 if (d.ShowModal() == wxID_OK)
437 {
f13880a9
WS
438 int first, last;
439 wxSscanf(d.GetValue(), _T("%d-%d"), &first, &last);
440 wxString s(title);
441 s << _T("\n");
442 for (int n = first; n <= last; ++n)
849a28d0 443 {
f13880a9 444 s << n << _T(" ") <<
15d06954 445 wxPLURAL("file deleted", "files deleted", n) <<
552973e0 446 _T("\n");
f13880a9 447 }
849a28d0
VS
448 wxMessageBox(s);
449 }
450}
451
452void MyFrame::OnTest3(wxCommandEvent& WXUNUSED(event))
453{
ad4814e7 454 const char* lines[] =
849a28d0 455 {
f13880a9
WS
456 wxTRANSLATE("line 1"),
457 wxTRANSLATE("line 2"),
458 wxTRANSLATE("line 3"),
849a28d0 459 };
4c3590e4 460 wxString s(_("Testing wxTRANSLATE() (gettext_noop)"));
849a28d0
VS
461 s << _T("\n");
462 for (size_t i = 0; i < WXSIZEOF(lines); ++i)
463 {
f13880a9 464 s << lines[i] << _T(" -> ") << wxGetTranslation(lines[i]) << _T("\n");
849a28d0
VS
465 }
466 wxMessageBox(s);
467}
468
469