diff --git a/Makefile.in b/Makefile.in
index 3ce1f73320..519cf77147 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -581,6 +581,8 @@ ALL_BASE_HEADERS = \
wx/generic/fswatcher.h \
wx/secretstore.h \
wx/lzmastream.h \
+ wx/localedefs.h \
+ wx/uilocale.h \
$(BASE_PLATFORM_HDR) \
wx/fs_inet.h \
wx/protocol/file.h \
@@ -766,6 +768,8 @@ ALL_PORTS_BASE_HEADERS = \
wx/generic/fswatcher.h \
wx/secretstore.h \
wx/lzmastream.h \
+ wx/localedefs.h \
+ wx/uilocale.h \
wx/unix/app.h \
wx/unix/apptbase.h \
wx/unix/apptrait.h \
@@ -905,6 +909,7 @@ ALL_BASE_SOURCES = \
src/generic/fswatcherg.cpp \
src/common/secretstore.cpp \
src/common/lzmastream.cpp \
+ src/common/uilocale.cpp \
src/common/fdiodispatcher.cpp \
src/common/selectdispatcher.cpp \
src/unix/appunix.cpp \
@@ -924,6 +929,7 @@ ALL_BASE_SOURCES = \
src/unix/fswatcher_inotify.cpp \
src/unix/stdpaths.cpp \
src/unix/secretstore.cpp \
+ src/unix/uilocale.cpp \
src/msw/basemsw.cpp \
src/msw/crashrpt.cpp \
src/msw/debughlp.cpp \
@@ -944,6 +950,7 @@ ALL_BASE_SOURCES = \
src/msw/utilsexc.cpp \
src/msw/fswatcher.cpp \
src/msw/secretstore.cpp \
+ src/msw/uilocale.cpp \
$(BASE_OSX_SRC) \
src/common/event.cpp \
src/common/fs_mem.cpp \
@@ -1093,6 +1100,7 @@ MONODLL_OBJECTS = \
monodll_fswatcherg.o \
monodll_common_secretstore.o \
monodll_lzmastream.o \
+ monodll_common_uilocale.o \
$(__BASE_PLATFORM_SRC_OBJECTS) \
monodll_event.o \
monodll_fs_mem.o \
@@ -1235,6 +1243,7 @@ MONOLIB_OBJECTS = \
monolib_fswatcherg.o \
monolib_common_secretstore.o \
monolib_lzmastream.o \
+ monolib_common_uilocale.o \
$(__BASE_PLATFORM_SRC_OBJECTS_1) \
monolib_event.o \
monolib_fs_mem.o \
@@ -1365,6 +1374,7 @@ BASEDLL_OBJECTS = \
basedll_fswatcherg.o \
basedll_common_secretstore.o \
basedll_lzmastream.o \
+ basedll_common_uilocale.o \
$(__BASE_PLATFORM_SRC_OBJECTS_2) \
basedll_event.o \
basedll_fs_mem.o \
@@ -1477,6 +1487,7 @@ BASELIB_OBJECTS = \
baselib_fswatcherg.o \
baselib_common_secretstore.o \
baselib_lzmastream.o \
+ baselib_common_uilocale.o \
$(__BASE_PLATFORM_SRC_OBJECTS_3) \
baselib_event.o \
baselib_fs_mem.o \
@@ -2357,6 +2368,7 @@ COND_TOOLKIT_OSX_COCOA_BASE_OSX_SRC = \
src/osx/core/strconv_cf.cpp \
src/osx/cocoa/utils_base.mm \
src/osx/core/secretstore.cpp \
+ src/osx/core/uilocale.cpp \
src/common/fdiodispatcher.cpp \
src/common/selectdispatcher.cpp \
src/unix/appunix.cpp \
@@ -2382,6 +2394,7 @@ COND_TOOLKIT_OSX_IPHONE_BASE_OSX_SRC = \
src/osx/core/strconv_cf.cpp \
src/osx/cocoa/utils_base.mm \
src/osx/core/secretstore.cpp \
+ src/osx/core/uilocale.cpp \
src/common/fdiodispatcher.cpp \
src/common/selectdispatcher.cpp \
src/unix/appunix.cpp \
@@ -2421,7 +2434,8 @@ COND_TOOLKIT_COCOA_BASE_OSX_SRC = \
src/osx/core/evtloop_cf.cpp \
src/osx/core/strconv_cf.cpp \
src/osx/cocoa/utils_base.mm \
- src/osx/core/secretstore.cpp
+ src/osx/core/secretstore.cpp \
+ src/osx/core/uilocale.cpp
@COND_TOOLKIT_COCOA@BASE_OSX_SRC = $(COND_TOOLKIT_COCOA_BASE_OSX_SRC)
COND_TOOLKIT_GTK_BASE_OSX_SRC = \
src/common/fdiodispatcher.cpp \
@@ -2444,7 +2458,8 @@ COND_TOOLKIT_GTK_BASE_OSX_SRC = \
src/osx/core/evtloop_cf.cpp \
src/osx/core/strconv_cf.cpp \
src/osx/cocoa/utils_base.mm \
- src/osx/core/secretstore.cpp
+ src/osx/core/secretstore.cpp \
+ src/osx/core/uilocale.cpp
@COND_TOOLKIT_GTK@BASE_OSX_SRC = $(COND_TOOLKIT_GTK_BASE_OSX_SRC)
COND_TOOLKIT_X11_BASE_OSX_SRC = \
src/common/fdiodispatcher.cpp \
@@ -2467,7 +2482,8 @@ COND_TOOLKIT_X11_BASE_OSX_SRC = \
src/osx/core/evtloop_cf.cpp \
src/osx/core/strconv_cf.cpp \
src/osx/cocoa/utils_base.mm \
- src/osx/core/secretstore.cpp
+ src/osx/core/secretstore.cpp \
+ src/osx/core/uilocale.cpp
@COND_TOOLKIT_X11@BASE_OSX_SRC = $(COND_TOOLKIT_X11_BASE_OSX_SRC)
COND_TOOLKIT_MOTIF_BASE_OSX_SRC = \
src/common/fdiodispatcher.cpp \
@@ -2490,7 +2506,8 @@ COND_TOOLKIT_MOTIF_BASE_OSX_SRC = \
src/osx/core/evtloop_cf.cpp \
src/osx/core/strconv_cf.cpp \
src/osx/cocoa/utils_base.mm \
- src/osx/core/secretstore.cpp
+ src/osx/core/secretstore.cpp \
+ src/osx/core/uilocale.cpp
@COND_TOOLKIT_MOTIF@BASE_OSX_SRC = $(COND_TOOLKIT_MOTIF_BASE_OSX_SRC)
COND_TOOLKIT__BASE_OSX_SRC = \
src/common/fdiodispatcher.cpp \
@@ -2513,7 +2530,8 @@ COND_TOOLKIT__BASE_OSX_SRC = \
src/osx/core/evtloop_cf.cpp \
src/osx/core/strconv_cf.cpp \
src/osx/cocoa/utils_base.mm \
- src/osx/core/secretstore.cpp
+ src/osx/core/secretstore.cpp \
+ src/osx/core/uilocale.cpp
@COND_TOOLKIT_@BASE_OSX_SRC = $(COND_TOOLKIT__BASE_OSX_SRC)
COND_TOOLKIT_OSX_COCOA_BASE_OSX_HDR = \
wx/osx/core/cfdataref.h \
@@ -4259,6 +4277,7 @@ COND_PLATFORM_MACOSX_1___BASE_PLATFORM_SRC_OBJECTS = \
monodll_strconv_cf.o \
monodll_utils_base.o \
monodll_core_secretstore.o \
+ monodll_core_uilocale.o \
monodll_fdiodispatcher.o \
monodll_selectdispatcher.o \
monodll_appunix.o \
@@ -4296,7 +4315,8 @@ COND_PLATFORM_UNIX_1___BASE_PLATFORM_SRC_OBJECTS = \
monodll_unix_mimetype.o \
monodll_fswatcher_inotify.o \
monodll_unix_stdpaths.o \
- monodll_unix_secretstore.o
+ monodll_unix_secretstore.o \
+ monodll_unix_uilocale.o
@COND_PLATFORM_UNIX_1@__BASE_PLATFORM_SRC_OBJECTS = $(COND_PLATFORM_UNIX_1___BASE_PLATFORM_SRC_OBJECTS)
COND_PLATFORM_WIN32_1___BASE_PLATFORM_SRC_OBJECTS = \
monodll_basemsw.o \
@@ -4318,7 +4338,8 @@ COND_PLATFORM_WIN32_1___BASE_PLATFORM_SRC_OBJECTS = \
monodll_msw_utils.o \
monodll_utilsexc.o \
monodll_fswatcher.o \
- monodll_msw_secretstore.o
+ monodll_msw_secretstore.o \
+ monodll_msw_uilocale.o
@COND_PLATFORM_WIN32_1@__BASE_PLATFORM_SRC_OBJECTS = $(COND_PLATFORM_WIN32_1___BASE_PLATFORM_SRC_OBJECTS)
@COND_PLATFORM_WIN32_1@__BASE_AND_GUI_PLATFORM_SRC_OBJECTS \
@COND_PLATFORM_WIN32_1@ = monodll_msw_main.o monodll_volume.o
@@ -6252,6 +6273,7 @@ COND_PLATFORM_MACOSX_1___BASE_PLATFORM_SRC_OBJECTS_1 = \
monolib_strconv_cf.o \
monolib_utils_base.o \
monolib_core_secretstore.o \
+ monolib_core_uilocale.o \
monolib_fdiodispatcher.o \
monolib_selectdispatcher.o \
monolib_appunix.o \
@@ -6289,7 +6311,8 @@ COND_PLATFORM_UNIX_1___BASE_PLATFORM_SRC_OBJECTS_1 = \
monolib_unix_mimetype.o \
monolib_fswatcher_inotify.o \
monolib_unix_stdpaths.o \
- monolib_unix_secretstore.o
+ monolib_unix_secretstore.o \
+ monolib_unix_uilocale.o
@COND_PLATFORM_UNIX_1@__BASE_PLATFORM_SRC_OBJECTS_1 = $(COND_PLATFORM_UNIX_1___BASE_PLATFORM_SRC_OBJECTS_1)
COND_PLATFORM_WIN32_1___BASE_PLATFORM_SRC_OBJECTS_1 = \
monolib_basemsw.o \
@@ -6311,7 +6334,8 @@ COND_PLATFORM_WIN32_1___BASE_PLATFORM_SRC_OBJECTS_1 = \
monolib_msw_utils.o \
monolib_utilsexc.o \
monolib_fswatcher.o \
- monolib_msw_secretstore.o
+ monolib_msw_secretstore.o \
+ monolib_msw_uilocale.o
@COND_PLATFORM_WIN32_1@__BASE_PLATFORM_SRC_OBJECTS_1 = $(COND_PLATFORM_WIN32_1___BASE_PLATFORM_SRC_OBJECTS_1)
@COND_PLATFORM_WIN32_1@__BASE_AND_GUI_PLATFORM_SRC_OBJECTS_1 \
@COND_PLATFORM_WIN32_1@ = monolib_msw_main.o monolib_volume.o
@@ -8297,6 +8321,7 @@ COND_PLATFORM_MACOSX_1___BASE_PLATFORM_SRC_OBJECTS_2 = \
basedll_strconv_cf.o \
basedll_utils_base.o \
basedll_core_secretstore.o \
+ basedll_core_uilocale.o \
basedll_fdiodispatcher.o \
basedll_selectdispatcher.o \
basedll_appunix.o \
@@ -8334,7 +8359,8 @@ COND_PLATFORM_UNIX_1___BASE_PLATFORM_SRC_OBJECTS_2 = \
basedll_unix_mimetype.o \
basedll_fswatcher_inotify.o \
basedll_unix_stdpaths.o \
- basedll_unix_secretstore.o
+ basedll_unix_secretstore.o \
+ basedll_unix_uilocale.o
@COND_PLATFORM_UNIX_1@__BASE_PLATFORM_SRC_OBJECTS_2 = $(COND_PLATFORM_UNIX_1___BASE_PLATFORM_SRC_OBJECTS_2)
COND_PLATFORM_WIN32_1___BASE_PLATFORM_SRC_OBJECTS_2 = \
basedll_basemsw.o \
@@ -8356,7 +8382,8 @@ COND_PLATFORM_WIN32_1___BASE_PLATFORM_SRC_OBJECTS_2 = \
basedll_msw_utils.o \
basedll_utilsexc.o \
basedll_fswatcher.o \
- basedll_msw_secretstore.o
+ basedll_msw_secretstore.o \
+ basedll_msw_uilocale.o
@COND_PLATFORM_WIN32_1@__BASE_PLATFORM_SRC_OBJECTS_2 = $(COND_PLATFORM_WIN32_1___BASE_PLATFORM_SRC_OBJECTS_2)
@COND_PLATFORM_WIN32_1@__BASE_AND_GUI_PLATFORM_SRC_OBJECTS_2 \
@COND_PLATFORM_WIN32_1@ = basedll_main.o basedll_volume.o
@@ -8380,6 +8407,7 @@ COND_PLATFORM_MACOSX_1___BASE_PLATFORM_SRC_OBJECTS_3 = \
baselib_strconv_cf.o \
baselib_utils_base.o \
baselib_core_secretstore.o \
+ baselib_core_uilocale.o \
baselib_fdiodispatcher.o \
baselib_selectdispatcher.o \
baselib_appunix.o \
@@ -8417,7 +8445,8 @@ COND_PLATFORM_UNIX_1___BASE_PLATFORM_SRC_OBJECTS_3 = \
baselib_unix_mimetype.o \
baselib_fswatcher_inotify.o \
baselib_unix_stdpaths.o \
- baselib_unix_secretstore.o
+ baselib_unix_secretstore.o \
+ baselib_unix_uilocale.o
@COND_PLATFORM_UNIX_1@__BASE_PLATFORM_SRC_OBJECTS_3 = $(COND_PLATFORM_UNIX_1___BASE_PLATFORM_SRC_OBJECTS_3)
COND_PLATFORM_WIN32_1___BASE_PLATFORM_SRC_OBJECTS_3 = \
baselib_basemsw.o \
@@ -8439,7 +8468,8 @@ COND_PLATFORM_WIN32_1___BASE_PLATFORM_SRC_OBJECTS_3 = \
baselib_msw_utils.o \
baselib_utilsexc.o \
baselib_fswatcher.o \
- baselib_msw_secretstore.o
+ baselib_msw_secretstore.o \
+ baselib_msw_uilocale.o
@COND_PLATFORM_WIN32_1@__BASE_PLATFORM_SRC_OBJECTS_3 = $(COND_PLATFORM_WIN32_1___BASE_PLATFORM_SRC_OBJECTS_3)
@COND_PLATFORM_WIN32_1@__BASE_AND_GUI_PLATFORM_SRC_OBJECTS_3 \
@COND_PLATFORM_WIN32_1@ = baselib_main.o baselib_volume.o
@@ -15995,6 +16025,9 @@ monodll_common_secretstore.o: $(srcdir)/src/common/secretstore.cpp $(MONODLL_ODE
monodll_lzmastream.o: $(srcdir)/src/common/lzmastream.cpp $(MONODLL_ODEP)
$(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/common/lzmastream.cpp
+monodll_common_uilocale.o: $(srcdir)/src/common/uilocale.cpp $(MONODLL_ODEP)
+ $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/common/uilocale.cpp
+
monodll_unix_mimetype.o: $(srcdir)/src/unix/mimetype.cpp $(MONODLL_ODEP)
$(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/unix/mimetype.cpp
@@ -16007,6 +16040,9 @@ monodll_unix_stdpaths.o: $(srcdir)/src/unix/stdpaths.cpp $(MONODLL_ODEP)
monodll_unix_secretstore.o: $(srcdir)/src/unix/secretstore.cpp $(MONODLL_ODEP)
$(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/unix/secretstore.cpp
+monodll_unix_uilocale.o: $(srcdir)/src/unix/uilocale.cpp $(MONODLL_ODEP)
+ $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/unix/uilocale.cpp
+
monodll_basemsw.o: $(srcdir)/src/msw/basemsw.cpp $(MONODLL_ODEP)
$(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/msw/basemsw.cpp
@@ -16067,6 +16103,9 @@ monodll_fswatcher.o: $(srcdir)/src/msw/fswatcher.cpp $(MONODLL_ODEP)
monodll_msw_secretstore.o: $(srcdir)/src/msw/secretstore.cpp $(MONODLL_ODEP)
$(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/msw/secretstore.cpp
+monodll_msw_uilocale.o: $(srcdir)/src/msw/uilocale.cpp $(MONODLL_ODEP)
+ $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/msw/uilocale.cpp
+
monodll_core_mimetype.o: $(srcdir)/src/osx/core/mimetype.cpp $(MONODLL_ODEP)
$(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/osx/core/mimetype.cpp
@@ -16085,6 +16124,9 @@ monodll_utils_base.o: $(srcdir)/src/osx/cocoa/utils_base.mm $(MONODLL_ODEP)
monodll_core_secretstore.o: $(srcdir)/src/osx/core/secretstore.cpp $(MONODLL_ODEP)
$(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/osx/core/secretstore.cpp
+monodll_core_uilocale.o: $(srcdir)/src/osx/core/uilocale.cpp $(MONODLL_ODEP)
+ $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/osx/core/uilocale.cpp
+
monodll_fswatcher_fsevents.o: $(srcdir)/src/osx/fswatcher_fsevents.cpp $(MONODLL_ODEP)
$(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/osx/fswatcher_fsevents.cpp
@@ -21272,6 +21314,9 @@ monolib_common_secretstore.o: $(srcdir)/src/common/secretstore.cpp $(MONOLIB_ODE
monolib_lzmastream.o: $(srcdir)/src/common/lzmastream.cpp $(MONOLIB_ODEP)
$(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/common/lzmastream.cpp
+monolib_common_uilocale.o: $(srcdir)/src/common/uilocale.cpp $(MONOLIB_ODEP)
+ $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/common/uilocale.cpp
+
monolib_unix_mimetype.o: $(srcdir)/src/unix/mimetype.cpp $(MONOLIB_ODEP)
$(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/unix/mimetype.cpp
@@ -21284,6 +21329,9 @@ monolib_unix_stdpaths.o: $(srcdir)/src/unix/stdpaths.cpp $(MONOLIB_ODEP)
monolib_unix_secretstore.o: $(srcdir)/src/unix/secretstore.cpp $(MONOLIB_ODEP)
$(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/unix/secretstore.cpp
+monolib_unix_uilocale.o: $(srcdir)/src/unix/uilocale.cpp $(MONOLIB_ODEP)
+ $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/unix/uilocale.cpp
+
monolib_basemsw.o: $(srcdir)/src/msw/basemsw.cpp $(MONOLIB_ODEP)
$(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/msw/basemsw.cpp
@@ -21344,6 +21392,9 @@ monolib_fswatcher.o: $(srcdir)/src/msw/fswatcher.cpp $(MONOLIB_ODEP)
monolib_msw_secretstore.o: $(srcdir)/src/msw/secretstore.cpp $(MONOLIB_ODEP)
$(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/msw/secretstore.cpp
+monolib_msw_uilocale.o: $(srcdir)/src/msw/uilocale.cpp $(MONOLIB_ODEP)
+ $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/msw/uilocale.cpp
+
monolib_core_mimetype.o: $(srcdir)/src/osx/core/mimetype.cpp $(MONOLIB_ODEP)
$(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/osx/core/mimetype.cpp
@@ -21362,6 +21413,9 @@ monolib_utils_base.o: $(srcdir)/src/osx/cocoa/utils_base.mm $(MONOLIB_ODEP)
monolib_core_secretstore.o: $(srcdir)/src/osx/core/secretstore.cpp $(MONOLIB_ODEP)
$(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/osx/core/secretstore.cpp
+monolib_core_uilocale.o: $(srcdir)/src/osx/core/uilocale.cpp $(MONOLIB_ODEP)
+ $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/osx/core/uilocale.cpp
+
monolib_fswatcher_fsevents.o: $(srcdir)/src/osx/fswatcher_fsevents.cpp $(MONOLIB_ODEP)
$(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/osx/fswatcher_fsevents.cpp
@@ -26549,6 +26603,9 @@ basedll_common_secretstore.o: $(srcdir)/src/common/secretstore.cpp $(BASEDLL_ODE
basedll_lzmastream.o: $(srcdir)/src/common/lzmastream.cpp $(BASEDLL_ODEP)
$(CXXC) -c -o $@ $(BASEDLL_CXXFLAGS) $(srcdir)/src/common/lzmastream.cpp
+basedll_common_uilocale.o: $(srcdir)/src/common/uilocale.cpp $(BASEDLL_ODEP)
+ $(CXXC) -c -o $@ $(BASEDLL_CXXFLAGS) $(srcdir)/src/common/uilocale.cpp
+
basedll_unix_mimetype.o: $(srcdir)/src/unix/mimetype.cpp $(BASEDLL_ODEP)
$(CXXC) -c -o $@ $(BASEDLL_CXXFLAGS) $(srcdir)/src/unix/mimetype.cpp
@@ -26561,6 +26618,9 @@ basedll_unix_stdpaths.o: $(srcdir)/src/unix/stdpaths.cpp $(BASEDLL_ODEP)
basedll_unix_secretstore.o: $(srcdir)/src/unix/secretstore.cpp $(BASEDLL_ODEP)
$(CXXC) -c -o $@ $(BASEDLL_CXXFLAGS) $(srcdir)/src/unix/secretstore.cpp
+basedll_unix_uilocale.o: $(srcdir)/src/unix/uilocale.cpp $(BASEDLL_ODEP)
+ $(CXXC) -c -o $@ $(BASEDLL_CXXFLAGS) $(srcdir)/src/unix/uilocale.cpp
+
basedll_basemsw.o: $(srcdir)/src/msw/basemsw.cpp $(BASEDLL_ODEP)
$(CXXC) -c -o $@ $(BASEDLL_CXXFLAGS) $(srcdir)/src/msw/basemsw.cpp
@@ -26621,6 +26681,9 @@ basedll_fswatcher.o: $(srcdir)/src/msw/fswatcher.cpp $(BASEDLL_ODEP)
basedll_msw_secretstore.o: $(srcdir)/src/msw/secretstore.cpp $(BASEDLL_ODEP)
$(CXXC) -c -o $@ $(BASEDLL_CXXFLAGS) $(srcdir)/src/msw/secretstore.cpp
+basedll_msw_uilocale.o: $(srcdir)/src/msw/uilocale.cpp $(BASEDLL_ODEP)
+ $(CXXC) -c -o $@ $(BASEDLL_CXXFLAGS) $(srcdir)/src/msw/uilocale.cpp
+
basedll_core_mimetype.o: $(srcdir)/src/osx/core/mimetype.cpp $(BASEDLL_ODEP)
$(CXXC) -c -o $@ $(BASEDLL_CXXFLAGS) $(srcdir)/src/osx/core/mimetype.cpp
@@ -26639,6 +26702,9 @@ basedll_utils_base.o: $(srcdir)/src/osx/cocoa/utils_base.mm $(BASEDLL_ODEP)
basedll_core_secretstore.o: $(srcdir)/src/osx/core/secretstore.cpp $(BASEDLL_ODEP)
$(CXXC) -c -o $@ $(BASEDLL_CXXFLAGS) $(srcdir)/src/osx/core/secretstore.cpp
+basedll_core_uilocale.o: $(srcdir)/src/osx/core/uilocale.cpp $(BASEDLL_ODEP)
+ $(CXXC) -c -o $@ $(BASEDLL_CXXFLAGS) $(srcdir)/src/osx/core/uilocale.cpp
+
basedll_fswatcher_fsevents.o: $(srcdir)/src/osx/fswatcher_fsevents.cpp $(BASEDLL_ODEP)
$(CXXC) -c -o $@ $(BASEDLL_CXXFLAGS) $(srcdir)/src/osx/fswatcher_fsevents.cpp
@@ -27023,6 +27089,9 @@ baselib_common_secretstore.o: $(srcdir)/src/common/secretstore.cpp $(BASELIB_ODE
baselib_lzmastream.o: $(srcdir)/src/common/lzmastream.cpp $(BASELIB_ODEP)
$(CXXC) -c -o $@ $(BASELIB_CXXFLAGS) $(srcdir)/src/common/lzmastream.cpp
+baselib_common_uilocale.o: $(srcdir)/src/common/uilocale.cpp $(BASELIB_ODEP)
+ $(CXXC) -c -o $@ $(BASELIB_CXXFLAGS) $(srcdir)/src/common/uilocale.cpp
+
baselib_unix_mimetype.o: $(srcdir)/src/unix/mimetype.cpp $(BASELIB_ODEP)
$(CXXC) -c -o $@ $(BASELIB_CXXFLAGS) $(srcdir)/src/unix/mimetype.cpp
@@ -27035,6 +27104,9 @@ baselib_unix_stdpaths.o: $(srcdir)/src/unix/stdpaths.cpp $(BASELIB_ODEP)
baselib_unix_secretstore.o: $(srcdir)/src/unix/secretstore.cpp $(BASELIB_ODEP)
$(CXXC) -c -o $@ $(BASELIB_CXXFLAGS) $(srcdir)/src/unix/secretstore.cpp
+baselib_unix_uilocale.o: $(srcdir)/src/unix/uilocale.cpp $(BASELIB_ODEP)
+ $(CXXC) -c -o $@ $(BASELIB_CXXFLAGS) $(srcdir)/src/unix/uilocale.cpp
+
baselib_basemsw.o: $(srcdir)/src/msw/basemsw.cpp $(BASELIB_ODEP)
$(CXXC) -c -o $@ $(BASELIB_CXXFLAGS) $(srcdir)/src/msw/basemsw.cpp
@@ -27095,6 +27167,9 @@ baselib_fswatcher.o: $(srcdir)/src/msw/fswatcher.cpp $(BASELIB_ODEP)
baselib_msw_secretstore.o: $(srcdir)/src/msw/secretstore.cpp $(BASELIB_ODEP)
$(CXXC) -c -o $@ $(BASELIB_CXXFLAGS) $(srcdir)/src/msw/secretstore.cpp
+baselib_msw_uilocale.o: $(srcdir)/src/msw/uilocale.cpp $(BASELIB_ODEP)
+ $(CXXC) -c -o $@ $(BASELIB_CXXFLAGS) $(srcdir)/src/msw/uilocale.cpp
+
baselib_core_mimetype.o: $(srcdir)/src/osx/core/mimetype.cpp $(BASELIB_ODEP)
$(CXXC) -c -o $@ $(BASELIB_CXXFLAGS) $(srcdir)/src/osx/core/mimetype.cpp
@@ -27113,6 +27188,9 @@ baselib_utils_base.o: $(srcdir)/src/osx/cocoa/utils_base.mm $(BASELIB_ODEP)
baselib_core_secretstore.o: $(srcdir)/src/osx/core/secretstore.cpp $(BASELIB_ODEP)
$(CXXC) -c -o $@ $(BASELIB_CXXFLAGS) $(srcdir)/src/osx/core/secretstore.cpp
+baselib_core_uilocale.o: $(srcdir)/src/osx/core/uilocale.cpp $(BASELIB_ODEP)
+ $(CXXC) -c -o $@ $(BASELIB_CXXFLAGS) $(srcdir)/src/osx/core/uilocale.cpp
+
baselib_fswatcher_fsevents.o: $(srcdir)/src/osx/fswatcher_fsevents.cpp $(BASELIB_ODEP)
$(CXXC) -c -o $@ $(BASELIB_CXXFLAGS) $(srcdir)/src/osx/fswatcher_fsevents.cpp
diff --git a/build/bakefiles/files.bkl b/build/bakefiles/files.bkl
index ab4f770305..afa23f0bcc 100644
--- a/build/bakefiles/files.bkl
+++ b/build/bakefiles/files.bkl
@@ -115,6 +115,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
src/unix/fswatcher_inotify.cpp
src/unix/stdpaths.cpp
src/unix/secretstore.cpp
+ src/unix/uilocale.cpp
$(BASE_UNIX_AND_DARWIN_NOTWXMAC_HDR)
@@ -146,6 +147,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
src/msw/utilsexc.cpp
src/msw/fswatcher.cpp
src/msw/secretstore.cpp
+ src/msw/uilocale.cpp
src/msw/main.cpp
@@ -187,6 +189,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
src/osx/core/strconv_cf.cpp
src/osx/cocoa/utils_base.mm
src/osx/core/secretstore.cpp
+ src/osx/core/uilocale.cpp
wx/osx/core/cfdataref.h
@@ -561,6 +564,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
src/generic/fswatcherg.cpp
src/common/secretstore.cpp
src/common/lzmastream.cpp
+ src/common/uilocale.cpp
src/common/event.cpp
@@ -735,6 +739,8 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
wx/generic/fswatcher.h
wx/secretstore.h
wx/lzmastream.h
+ wx/localedefs.h
+ wx/uilocale.h
diff --git a/build/cmake/files.cmake b/build/cmake/files.cmake
index 3b90eda592..df46473e51 100644
--- a/build/cmake/files.cmake
+++ b/build/cmake/files.cmake
@@ -47,6 +47,7 @@ set(BASE_UNIX_SRC
src/unix/fswatcher_inotify.cpp
src/unix/secretstore.cpp
src/unix/stdpaths.cpp
+ src/unix/uilocale.cpp
)
set(BASE_UNIX_HDR
@@ -76,6 +77,7 @@ set(BASE_WIN32_SRC
src/msw/utils.cpp
src/msw/utilsexc.cpp
src/msw/fswatcher.cpp
+ src/msw/uilocale.cpp
)
set(BASE_AND_GUI_WIN32_SRC
@@ -114,6 +116,7 @@ set(BASE_COREFOUNDATION_SRC
src/osx/core/secretstore.cpp
src/osx/core/strconv_cf.cpp
src/osx/cocoa/utils_base.mm
+ src/osx/core/uilocale.cpp
)
set(BASE_COREFOUNDATION_HDR
@@ -475,6 +478,7 @@ set(BASE_CMN_SRC
src/common/fswatchercmn.cpp
src/generic/fswatcherg.cpp
src/common/lzmastream.cpp
+ src/common/uilocale.cpp
)
set(BASE_AND_GUI_CMN_SRC
@@ -651,6 +655,8 @@ set(BASE_CMN_HDR
wx/fswatcher.h
wx/generic/fswatcher.h
wx/lzmastream.h
+ wx/localedefs.h
+ wx/uilocale.h
)
set(NET_UNIX_SRC
diff --git a/build/files b/build/files
index 5c68b80c8d..eafe03673d 100644
--- a/build/files
+++ b/build/files
@@ -71,6 +71,7 @@ BASE_UNIX_SRC =
src/unix/fswatcher_inotify.cpp
src/unix/secretstore.cpp
src/unix/stdpaths.cpp
+ src/unix/uilocale.cpp
BASE_UNIX_HDR =
$(BASE_UNIX_AND_DARWIN_NOTWXMAC_HDR)
@@ -98,6 +99,7 @@ BASE_WIN32_SRC =
src/msw/stdpaths.cpp
src/msw/thread.cpp
src/msw/timer.cpp
+ src/msw/uilocale.cpp
src/msw/utils.cpp
src/msw/utilsexc.cpp
src/msw/fswatcher.cpp
@@ -139,6 +141,7 @@ BASE_COREFOUNDATION_SRC =
src/osx/core/evtloop_cf.cpp
src/osx/core/secretstore.cpp
src/osx/core/strconv_cf.cpp
+ src/osx/core/uilocale.cpp
src/osx/cocoa/utils_base.mm
BASE_COREFOUNDATION_HDR =
@@ -481,6 +484,7 @@ BASE_CMN_SRC =
src/common/tokenzr.cpp
src/common/translation.cpp
src/common/txtstrm.cpp
+ src/common/uilocale.cpp
src/common/unichar.cpp
src/common/uri.cpp
src/common/ustring.cpp
@@ -574,6 +578,7 @@ BASE_CMN_HDR =
wx/link.h
wx/list.h
wx/listimpl.cpp
+ wx/localedefs.h
wx/log.h
wx/longlong.h
wx/lzmastream.h
@@ -632,6 +637,7 @@ BASE_CMN_HDR =
wx/txtstrm.h
wx/typeinfo.h
wx/types.h
+ wx/uilocale.h
wx/unichar.h
wx/uri.h
wx/ustring.h
diff --git a/build/msw/makefile.gcc b/build/msw/makefile.gcc
index 4ed7edba02..fcb8ae9aa3 100644
--- a/build/msw/makefile.gcc
+++ b/build/msw/makefile.gcc
@@ -477,6 +477,7 @@ MONODLL_OBJECTS = \
$(OBJS)\monodll_fswatcherg.o \
$(OBJS)\monodll_common_secretstore.o \
$(OBJS)\monodll_lzmastream.o \
+ $(OBJS)\monodll_common_uilocale.o \
$(OBJS)\monodll_basemsw.o \
$(OBJS)\monodll_crashrpt.o \
$(OBJS)\monodll_debughlp.o \
@@ -497,6 +498,7 @@ MONODLL_OBJECTS = \
$(OBJS)\monodll_utilsexc.o \
$(OBJS)\monodll_fswatcher.o \
$(OBJS)\monodll_msw_secretstore.o \
+ $(OBJS)\monodll_msw_uilocale.o \
$(OBJS)\monodll_event.o \
$(OBJS)\monodll_fs_mem.o \
$(OBJS)\monodll_msgout.o \
@@ -633,6 +635,7 @@ MONOLIB_OBJECTS = \
$(OBJS)\monolib_fswatcherg.o \
$(OBJS)\monolib_common_secretstore.o \
$(OBJS)\monolib_lzmastream.o \
+ $(OBJS)\monolib_common_uilocale.o \
$(OBJS)\monolib_basemsw.o \
$(OBJS)\monolib_crashrpt.o \
$(OBJS)\monolib_debughlp.o \
@@ -653,6 +656,7 @@ MONOLIB_OBJECTS = \
$(OBJS)\monolib_utilsexc.o \
$(OBJS)\monolib_fswatcher.o \
$(OBJS)\monolib_msw_secretstore.o \
+ $(OBJS)\monolib_msw_uilocale.o \
$(OBJS)\monolib_event.o \
$(OBJS)\monolib_fs_mem.o \
$(OBJS)\monolib_msgout.o \
@@ -783,6 +787,7 @@ BASEDLL_OBJECTS = \
$(OBJS)\basedll_fswatcherg.o \
$(OBJS)\basedll_common_secretstore.o \
$(OBJS)\basedll_lzmastream.o \
+ $(OBJS)\basedll_common_uilocale.o \
$(OBJS)\basedll_basemsw.o \
$(OBJS)\basedll_crashrpt.o \
$(OBJS)\basedll_debughlp.o \
@@ -803,6 +808,7 @@ BASEDLL_OBJECTS = \
$(OBJS)\basedll_utilsexc.o \
$(OBJS)\basedll_fswatcher.o \
$(OBJS)\basedll_msw_secretstore.o \
+ $(OBJS)\basedll_msw_uilocale.o \
$(OBJS)\basedll_event.o \
$(OBJS)\basedll_fs_mem.o \
$(OBJS)\basedll_msgout.o \
@@ -914,6 +920,7 @@ BASELIB_OBJECTS = \
$(OBJS)\baselib_fswatcherg.o \
$(OBJS)\baselib_common_secretstore.o \
$(OBJS)\baselib_lzmastream.o \
+ $(OBJS)\baselib_common_uilocale.o \
$(OBJS)\baselib_basemsw.o \
$(OBJS)\baselib_crashrpt.o \
$(OBJS)\baselib_debughlp.o \
@@ -934,6 +941,7 @@ BASELIB_OBJECTS = \
$(OBJS)\baselib_utilsexc.o \
$(OBJS)\baselib_fswatcher.o \
$(OBJS)\baselib_msw_secretstore.o \
+ $(OBJS)\baselib_msw_uilocale.o \
$(OBJS)\baselib_event.o \
$(OBJS)\baselib_fs_mem.o \
$(OBJS)\baselib_msgout.o \
@@ -7144,6 +7152,9 @@ $(OBJS)\monodll_common_secretstore.o: ../../src/common/secretstore.cpp
$(OBJS)\monodll_lzmastream.o: ../../src/common/lzmastream.cpp
$(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $<
+$(OBJS)\monodll_common_uilocale.o: ../../src/common/uilocale.cpp
+ $(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $<
+
$(OBJS)\monodll_basemsw.o: ../../src/msw/basemsw.cpp
$(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $<
@@ -7204,6 +7215,9 @@ $(OBJS)\monodll_fswatcher.o: ../../src/msw/fswatcher.cpp
$(OBJS)\monodll_msw_secretstore.o: ../../src/msw/secretstore.cpp
$(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $<
+$(OBJS)\monodll_msw_uilocale.o: ../../src/msw/uilocale.cpp
+ $(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $<
+
$(OBJS)\monodll_event.o: ../../src/common/event.cpp
$(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $<
@@ -9712,6 +9726,9 @@ $(OBJS)\monolib_common_secretstore.o: ../../src/common/secretstore.cpp
$(OBJS)\monolib_lzmastream.o: ../../src/common/lzmastream.cpp
$(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $<
+$(OBJS)\monolib_common_uilocale.o: ../../src/common/uilocale.cpp
+ $(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $<
+
$(OBJS)\monolib_basemsw.o: ../../src/msw/basemsw.cpp
$(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $<
@@ -9772,6 +9789,9 @@ $(OBJS)\monolib_fswatcher.o: ../../src/msw/fswatcher.cpp
$(OBJS)\monolib_msw_secretstore.o: ../../src/msw/secretstore.cpp
$(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $<
+$(OBJS)\monolib_msw_uilocale.o: ../../src/msw/uilocale.cpp
+ $(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $<
+
$(OBJS)\monolib_event.o: ../../src/common/event.cpp
$(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $<
@@ -12280,6 +12300,9 @@ $(OBJS)\basedll_common_secretstore.o: ../../src/common/secretstore.cpp
$(OBJS)\basedll_lzmastream.o: ../../src/common/lzmastream.cpp
$(CXX) -c -o $@ $(BASEDLL_CXXFLAGS) $(CPPDEPS) $<
+$(OBJS)\basedll_common_uilocale.o: ../../src/common/uilocale.cpp
+ $(CXX) -c -o $@ $(BASEDLL_CXXFLAGS) $(CPPDEPS) $<
+
$(OBJS)\basedll_basemsw.o: ../../src/msw/basemsw.cpp
$(CXX) -c -o $@ $(BASEDLL_CXXFLAGS) $(CPPDEPS) $<
@@ -12340,6 +12363,9 @@ $(OBJS)\basedll_fswatcher.o: ../../src/msw/fswatcher.cpp
$(OBJS)\basedll_msw_secretstore.o: ../../src/msw/secretstore.cpp
$(CXX) -c -o $@ $(BASEDLL_CXXFLAGS) $(CPPDEPS) $<
+$(OBJS)\basedll_msw_uilocale.o: ../../src/msw/uilocale.cpp
+ $(CXX) -c -o $@ $(BASEDLL_CXXFLAGS) $(CPPDEPS) $<
+
$(OBJS)\basedll_event.o: ../../src/common/event.cpp
$(CXX) -c -o $@ $(BASEDLL_CXXFLAGS) $(CPPDEPS) $<
@@ -12625,6 +12651,9 @@ $(OBJS)\baselib_common_secretstore.o: ../../src/common/secretstore.cpp
$(OBJS)\baselib_lzmastream.o: ../../src/common/lzmastream.cpp
$(CXX) -c -o $@ $(BASELIB_CXXFLAGS) $(CPPDEPS) $<
+$(OBJS)\baselib_common_uilocale.o: ../../src/common/uilocale.cpp
+ $(CXX) -c -o $@ $(BASELIB_CXXFLAGS) $(CPPDEPS) $<
+
$(OBJS)\baselib_basemsw.o: ../../src/msw/basemsw.cpp
$(CXX) -c -o $@ $(BASELIB_CXXFLAGS) $(CPPDEPS) $<
@@ -12685,6 +12714,9 @@ $(OBJS)\baselib_fswatcher.o: ../../src/msw/fswatcher.cpp
$(OBJS)\baselib_msw_secretstore.o: ../../src/msw/secretstore.cpp
$(CXX) -c -o $@ $(BASELIB_CXXFLAGS) $(CPPDEPS) $<
+$(OBJS)\baselib_msw_uilocale.o: ../../src/msw/uilocale.cpp
+ $(CXX) -c -o $@ $(BASELIB_CXXFLAGS) $(CPPDEPS) $<
+
$(OBJS)\baselib_event.o: ../../src/common/event.cpp
$(CXX) -c -o $@ $(BASELIB_CXXFLAGS) $(CPPDEPS) $<
diff --git a/build/msw/makefile.vc b/build/msw/makefile.vc
index d8557a9f40..42d2c0634e 100644
--- a/build/msw/makefile.vc
+++ b/build/msw/makefile.vc
@@ -510,6 +510,7 @@ MONODLL_OBJECTS = \
$(OBJS)\monodll_fswatcherg.obj \
$(OBJS)\monodll_common_secretstore.obj \
$(OBJS)\monodll_lzmastream.obj \
+ $(OBJS)\monodll_common_uilocale.obj \
$(OBJS)\monodll_basemsw.obj \
$(OBJS)\monodll_crashrpt.obj \
$(OBJS)\monodll_debughlp.obj \
@@ -530,6 +531,7 @@ MONODLL_OBJECTS = \
$(OBJS)\monodll_utilsexc.obj \
$(OBJS)\monodll_fswatcher.obj \
$(OBJS)\monodll_msw_secretstore.obj \
+ $(OBJS)\monodll_msw_uilocale.obj \
$(OBJS)\monodll_event.obj \
$(OBJS)\monodll_fs_mem.obj \
$(OBJS)\monodll_msgout.obj \
@@ -675,6 +677,7 @@ MONOLIB_OBJECTS = \
$(OBJS)\monolib_fswatcherg.obj \
$(OBJS)\monolib_common_secretstore.obj \
$(OBJS)\monolib_lzmastream.obj \
+ $(OBJS)\monolib_common_uilocale.obj \
$(OBJS)\monolib_basemsw.obj \
$(OBJS)\monolib_crashrpt.obj \
$(OBJS)\monolib_debughlp.obj \
@@ -695,6 +698,7 @@ MONOLIB_OBJECTS = \
$(OBJS)\monolib_utilsexc.obj \
$(OBJS)\monolib_fswatcher.obj \
$(OBJS)\monolib_msw_secretstore.obj \
+ $(OBJS)\monolib_msw_uilocale.obj \
$(OBJS)\monolib_event.obj \
$(OBJS)\monolib_fs_mem.obj \
$(OBJS)\monolib_msgout.obj \
@@ -834,6 +838,7 @@ BASEDLL_OBJECTS = \
$(OBJS)\basedll_fswatcherg.obj \
$(OBJS)\basedll_common_secretstore.obj \
$(OBJS)\basedll_lzmastream.obj \
+ $(OBJS)\basedll_common_uilocale.obj \
$(OBJS)\basedll_basemsw.obj \
$(OBJS)\basedll_crashrpt.obj \
$(OBJS)\basedll_debughlp.obj \
@@ -854,6 +859,7 @@ BASEDLL_OBJECTS = \
$(OBJS)\basedll_utilsexc.obj \
$(OBJS)\basedll_fswatcher.obj \
$(OBJS)\basedll_msw_secretstore.obj \
+ $(OBJS)\basedll_msw_uilocale.obj \
$(OBJS)\basedll_event.obj \
$(OBJS)\basedll_fs_mem.obj \
$(OBJS)\basedll_msgout.obj \
@@ -977,6 +983,7 @@ BASELIB_OBJECTS = \
$(OBJS)\baselib_fswatcherg.obj \
$(OBJS)\baselib_common_secretstore.obj \
$(OBJS)\baselib_lzmastream.obj \
+ $(OBJS)\baselib_common_uilocale.obj \
$(OBJS)\baselib_basemsw.obj \
$(OBJS)\baselib_crashrpt.obj \
$(OBJS)\baselib_debughlp.obj \
@@ -997,6 +1004,7 @@ BASELIB_OBJECTS = \
$(OBJS)\baselib_utilsexc.obj \
$(OBJS)\baselib_fswatcher.obj \
$(OBJS)\baselib_msw_secretstore.obj \
+ $(OBJS)\baselib_msw_uilocale.obj \
$(OBJS)\baselib_event.obj \
$(OBJS)\baselib_fs_mem.obj \
$(OBJS)\baselib_msgout.obj \
@@ -7575,6 +7583,9 @@ $(OBJS)\monodll_common_secretstore.obj: ..\..\src\common\secretstore.cpp
$(OBJS)\monodll_lzmastream.obj: ..\..\src\common\lzmastream.cpp
$(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) ..\..\src\common\lzmastream.cpp
+$(OBJS)\monodll_common_uilocale.obj: ..\..\src\common\uilocale.cpp
+ $(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) ..\..\src\common\uilocale.cpp
+
$(OBJS)\monodll_basemsw.obj: ..\..\src\msw\basemsw.cpp
$(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) ..\..\src\msw\basemsw.cpp
@@ -7635,6 +7646,9 @@ $(OBJS)\monodll_fswatcher.obj: ..\..\src\msw\fswatcher.cpp
$(OBJS)\monodll_msw_secretstore.obj: ..\..\src\msw\secretstore.cpp
$(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) ..\..\src\msw\secretstore.cpp
+$(OBJS)\monodll_msw_uilocale.obj: ..\..\src\msw\uilocale.cpp
+ $(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) ..\..\src\msw\uilocale.cpp
+
$(OBJS)\monodll_event.obj: ..\..\src\common\event.cpp
$(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) ..\..\src\common\event.cpp
@@ -10143,6 +10157,9 @@ $(OBJS)\monolib_common_secretstore.obj: ..\..\src\common\secretstore.cpp
$(OBJS)\monolib_lzmastream.obj: ..\..\src\common\lzmastream.cpp
$(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) ..\..\src\common\lzmastream.cpp
+$(OBJS)\monolib_common_uilocale.obj: ..\..\src\common\uilocale.cpp
+ $(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) ..\..\src\common\uilocale.cpp
+
$(OBJS)\monolib_basemsw.obj: ..\..\src\msw\basemsw.cpp
$(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) ..\..\src\msw\basemsw.cpp
@@ -10203,6 +10220,9 @@ $(OBJS)\monolib_fswatcher.obj: ..\..\src\msw\fswatcher.cpp
$(OBJS)\monolib_msw_secretstore.obj: ..\..\src\msw\secretstore.cpp
$(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) ..\..\src\msw\secretstore.cpp
+$(OBJS)\monolib_msw_uilocale.obj: ..\..\src\msw\uilocale.cpp
+ $(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) ..\..\src\msw\uilocale.cpp
+
$(OBJS)\monolib_event.obj: ..\..\src\common\event.cpp
$(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) ..\..\src\common\event.cpp
@@ -12711,6 +12731,9 @@ $(OBJS)\basedll_common_secretstore.obj: ..\..\src\common\secretstore.cpp
$(OBJS)\basedll_lzmastream.obj: ..\..\src\common\lzmastream.cpp
$(CXX) /c /nologo /TP /Fo$@ $(BASEDLL_CXXFLAGS) ..\..\src\common\lzmastream.cpp
+$(OBJS)\basedll_common_uilocale.obj: ..\..\src\common\uilocale.cpp
+ $(CXX) /c /nologo /TP /Fo$@ $(BASEDLL_CXXFLAGS) ..\..\src\common\uilocale.cpp
+
$(OBJS)\basedll_basemsw.obj: ..\..\src\msw\basemsw.cpp
$(CXX) /c /nologo /TP /Fo$@ $(BASEDLL_CXXFLAGS) ..\..\src\msw\basemsw.cpp
@@ -12771,6 +12794,9 @@ $(OBJS)\basedll_fswatcher.obj: ..\..\src\msw\fswatcher.cpp
$(OBJS)\basedll_msw_secretstore.obj: ..\..\src\msw\secretstore.cpp
$(CXX) /c /nologo /TP /Fo$@ $(BASEDLL_CXXFLAGS) ..\..\src\msw\secretstore.cpp
+$(OBJS)\basedll_msw_uilocale.obj: ..\..\src\msw\uilocale.cpp
+ $(CXX) /c /nologo /TP /Fo$@ $(BASEDLL_CXXFLAGS) ..\..\src\msw\uilocale.cpp
+
$(OBJS)\basedll_event.obj: ..\..\src\common\event.cpp
$(CXX) /c /nologo /TP /Fo$@ $(BASEDLL_CXXFLAGS) ..\..\src\common\event.cpp
@@ -13056,6 +13082,9 @@ $(OBJS)\baselib_common_secretstore.obj: ..\..\src\common\secretstore.cpp
$(OBJS)\baselib_lzmastream.obj: ..\..\src\common\lzmastream.cpp
$(CXX) /c /nologo /TP /Fo$@ $(BASELIB_CXXFLAGS) ..\..\src\common\lzmastream.cpp
+$(OBJS)\baselib_common_uilocale.obj: ..\..\src\common\uilocale.cpp
+ $(CXX) /c /nologo /TP /Fo$@ $(BASELIB_CXXFLAGS) ..\..\src\common\uilocale.cpp
+
$(OBJS)\baselib_basemsw.obj: ..\..\src\msw\basemsw.cpp
$(CXX) /c /nologo /TP /Fo$@ $(BASELIB_CXXFLAGS) ..\..\src\msw\basemsw.cpp
@@ -13116,6 +13145,9 @@ $(OBJS)\baselib_fswatcher.obj: ..\..\src\msw\fswatcher.cpp
$(OBJS)\baselib_msw_secretstore.obj: ..\..\src\msw\secretstore.cpp
$(CXX) /c /nologo /TP /Fo$@ $(BASELIB_CXXFLAGS) ..\..\src\msw\secretstore.cpp
+$(OBJS)\baselib_msw_uilocale.obj: ..\..\src\msw\uilocale.cpp
+ $(CXX) /c /nologo /TP /Fo$@ $(BASELIB_CXXFLAGS) ..\..\src\msw\uilocale.cpp
+
$(OBJS)\baselib_event.obj: ..\..\src\common\event.cpp
$(CXX) /c /nologo /TP /Fo$@ $(BASELIB_CXXFLAGS) ..\..\src\common\event.cpp
diff --git a/build/msw/wx_base.vcxproj b/build/msw/wx_base.vcxproj
index 102a6974d7..16a1d225c1 100644
--- a/build/msw/wx_base.vcxproj
+++ b/build/msw/wx_base.vcxproj
@@ -605,6 +605,26 @@
$(IntDir)common_%(Filename).obj
+
+ $(IntDir)msw_%(Filename).obj
+ $(IntDir)msw_%(Filename).obj
+ $(IntDir)msw_%(Filename).obj
+ $(IntDir)msw_%(Filename).obj
+ $(IntDir)msw_%(Filename).obj
+ $(IntDir)msw_%(Filename).obj
+ $(IntDir)msw_%(Filename).obj
+ $(IntDir)msw_%(Filename).obj
+
+
+ $(IntDir)common_%(Filename).obj
+ $(IntDir)common_%(Filename).obj
+ $(IntDir)common_%(Filename).obj
+ $(IntDir)common_%(Filename).obj
+ $(IntDir)common_%(Filename).obj
+ $(IntDir)common_%(Filename).obj
+ $(IntDir)common_%(Filename).obj
+ $(IntDir)common_%(Filename).obj
+
@@ -823,6 +843,8 @@
+
+
diff --git a/build/msw/wx_base.vcxproj.filters b/build/msw/wx_base.vcxproj.filters
index 44e8f07935..33a96e5ef0 100644
--- a/build/msw/wx_base.vcxproj.filters
+++ b/build/msw/wx_base.vcxproj.filters
@@ -261,6 +261,9 @@
Common Sources
+
+ Common Sources
+
Common Sources
@@ -360,6 +363,9 @@
MSW Sources
+
+ MSW Sources
+
MSW Sources
@@ -598,6 +604,9 @@
Common Headers
+
+ Common Headers
+
Common Headers
@@ -859,6 +868,9 @@
Common Headers
+
+ Common Headers
+
Common Headers
diff --git a/build/msw/wx_vc8_base.vcproj b/build/msw/wx_vc8_base.vcproj
index 5708485856..feb02ea5e3 100644
--- a/build/msw/wx_vc8_base.vcproj
+++ b/build/msw/wx_vc8_base.vcproj
@@ -1249,6 +1249,74 @@
RelativePath="..\..\src\common\txtstrm.cpp"
>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1446,6 +1514,74 @@
RelativePath="..\..\src\msw\timer.cpp"
>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -2103,6 +2239,10 @@
RelativePath="..\..\include\wx\list.h"
>
+
+
@@ -2343,6 +2483,10 @@
RelativePath="..\..\include\wx\types.h"
>
+
+
diff --git a/build/msw/wx_vc9_base.vcproj b/build/msw/wx_vc9_base.vcproj
index 1accda8c00..33df8ce65f 100644
--- a/build/msw/wx_vc9_base.vcproj
+++ b/build/msw/wx_vc9_base.vcproj
@@ -1245,6 +1245,74 @@
RelativePath="..\..\src\common\txtstrm.cpp"
>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1442,6 +1510,74 @@
RelativePath="..\..\src\msw\timer.cpp"
>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -2099,6 +2235,10 @@
RelativePath="..\..\include\wx\list.h"
>
+
+
@@ -2339,6 +2479,10 @@
RelativePath="..\..\include\wx\types.h"
>
+
+
diff --git a/include/wx/dvrenderers.h b/include/wx/dvrenderers.h
index 85fcea0023..3b6857e971 100644
--- a/include/wx/dvrenderers.h
+++ b/include/wx/dvrenderers.h
@@ -527,6 +527,8 @@ public:
virtual wxSize GetSize() const wxOVERRIDE;
private:
+ wxString FormatDate() const;
+
wxDateTime m_date;
};
#else // !wxUSE_DATEPICKCTRL
diff --git a/include/wx/generic/spinctlg.h b/include/wx/generic/spinctlg.h
index db7162751a..594a4d02ed 100644
--- a/include/wx/generic/spinctlg.h
+++ b/include/wx/generic/spinctlg.h
@@ -430,8 +430,6 @@ private:
void DoSetDigitsAndUpdate(unsigned digits);
- wxString m_format;
-
wxDECLARE_DYNAMIC_CLASS(wxSpinCtrlDouble);
};
diff --git a/include/wx/intl.h b/include/wx/intl.h
index 2ce148dd54..866bcfbcac 100644
--- a/include/wx/intl.h
+++ b/include/wx/intl.h
@@ -13,19 +13,10 @@
#define _WX_INTL_H_
#include "wx/defs.h"
+#include "wx/localedefs.h"
#include "wx/string.h"
#include "wx/translation.h"
-// Make wxLayoutDirection enum available without need for wxUSE_INTL so wxWindow, wxApp
-// and other classes are not distrubed by wxUSE_INTL
-
-enum wxLayoutDirection
-{
- wxLayout_Default,
- wxLayout_LeftToRight,
- wxLayout_RightToLeft
-};
-
#if wxUSE_INTL
#include "wx/fontenc.h"
@@ -50,86 +41,6 @@ class WXDLLIMPEXP_FWD_BASE wxLanguageInfoArray;
// locale support
// ============================================================================
-// ----------------------------------------------------------------------------
-// wxLanguageInfo: encapsulates wxLanguage to OS native lang.desc.
-// translation information
-// ----------------------------------------------------------------------------
-
-struct WXDLLIMPEXP_BASE wxLanguageInfo
-{
- int Language; // wxLanguage id
- wxString CanonicalName; // Canonical name, e.g. fr_FR
-#ifdef __WINDOWS__
- wxUint32 WinLang, // Win32 language identifiers
- WinSublang;
-#endif // __WINDOWS__
- wxString Description; // human-readable name of the language
- wxLayoutDirection LayoutDirection;
-
-#ifdef __WINDOWS__
- // return the LCID corresponding to this language
- wxUint32 GetLCID() const;
-#endif // __WINDOWS__
-
- // return the locale name corresponding to this language usable with
- // setlocale() on the current system or empty string if this locale is not
- // supported
- wxString GetLocaleName() const;
-
- // Call setlocale() and return non-null value if it works for this language.
- //
- // This function is mostly for internal use, as changing locale involves
- // more than just calling setlocale() on some platforms, use wxLocale to
- // do everything that needs to be done instead of calling this method.
- const char* TrySetLocale() const;
-};
-
-// ----------------------------------------------------------------------------
-// wxLocaleCategory: the category of locale settings
-// ----------------------------------------------------------------------------
-
-enum wxLocaleCategory
-{
- // (any) numbers
- wxLOCALE_CAT_NUMBER,
-
- // date/time
- wxLOCALE_CAT_DATE,
-
- // monetary value
- wxLOCALE_CAT_MONEY,
-
- // default category for wxLocaleInfo values which only apply to a single
- // category (e.g. wxLOCALE_SHORT_DATE_FMT)
- wxLOCALE_CAT_DEFAULT,
-
- wxLOCALE_CAT_MAX
-};
-
-// ----------------------------------------------------------------------------
-// wxLocaleInfo: the items understood by wxLocale::GetInfo()
-// ----------------------------------------------------------------------------
-
-enum wxLocaleInfo
-{
- // the thousands separator (for wxLOCALE_CAT_NUMBER or MONEY)
- wxLOCALE_THOUSANDS_SEP,
-
- // the character used as decimal point (for wxLOCALE_CAT_NUMBER or MONEY)
- wxLOCALE_DECIMAL_POINT,
-
- // the stftime()-formats used for short/long date and time representations
- // (under some platforms short and long date formats are the same)
- //
- // NB: these elements should appear in this order, code in GetInfo() relies
- // on it
- wxLOCALE_SHORT_DATE_FMT,
- wxLOCALE_LONG_DATE_FMT,
- wxLOCALE_DATE_TIME_FMT,
- wxLOCALE_TIME_FMT
-
-};
-
// ----------------------------------------------------------------------------
// wxLocale: encapsulates all language dependent settings, including current
// message catalogs, date, time and currency formats (TODO) &c
@@ -145,6 +56,8 @@ enum wxLocaleInitFlags
#endif
};
+// NOTE: This class is deprecated, use wxUILocale and wxTranslations instead.
+
class WXDLLIMPEXP_BASE wxLocale
{
public:
diff --git a/include/wx/localedefs.h b/include/wx/localedefs.h
new file mode 100644
index 0000000000..d5b43b2eff
--- /dev/null
+++ b/include/wx/localedefs.h
@@ -0,0 +1,113 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name: wx/localedefs.h
+// Purpose: Definitions of common locale-related constants and structs.
+// Author: Vadim Zeitlin
+// Created: 2021-07-31 (extracted from wx/intl.h)
+// Copyright: (c) 2021 Vadim Zeitlin
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_LOCALEDEFS_H_
+#define _WX_LOCALEDEFS_H_
+
+// ----------------------------------------------------------------------------
+// wxLayoutDirection: used by wxWindow, wxDC etc
+// ----------------------------------------------------------------------------
+
+// Note that this one must be available even when wxUSE_INTL == 0 as it's used
+// outside of locale code too.
+
+enum wxLayoutDirection
+{
+ wxLayout_Default,
+ wxLayout_LeftToRight,
+ wxLayout_RightToLeft
+};
+
+#if wxUSE_INTL
+
+#include "wx/string.h"
+
+// ----------------------------------------------------------------------------
+// wxLocaleCategory: the category of locale settings
+// ----------------------------------------------------------------------------
+
+enum wxLocaleCategory
+{
+ // (any) numbers
+ wxLOCALE_CAT_NUMBER,
+
+ // date/time
+ wxLOCALE_CAT_DATE,
+
+ // monetary value
+ wxLOCALE_CAT_MONEY,
+
+ // default category for wxLocaleInfo values which only apply to a single
+ // category (e.g. wxLOCALE_SHORT_DATE_FMT)
+ wxLOCALE_CAT_DEFAULT,
+
+ wxLOCALE_CAT_MAX
+};
+
+// ----------------------------------------------------------------------------
+// wxLocaleInfo: the items understood by wxLocale::GetInfo()
+// ----------------------------------------------------------------------------
+
+enum wxLocaleInfo
+{
+ // the thousands separator (for wxLOCALE_CAT_NUMBER or MONEY)
+ wxLOCALE_THOUSANDS_SEP,
+
+ // the character used as decimal point (for wxLOCALE_CAT_NUMBER or MONEY)
+ wxLOCALE_DECIMAL_POINT,
+
+ // the stftime()-formats used for short/long date and time representations
+ // (under some platforms short and long date formats are the same)
+ //
+ // NB: these elements should appear in this order, code in GetInfo() relies
+ // on it
+ wxLOCALE_SHORT_DATE_FMT,
+ wxLOCALE_LONG_DATE_FMT,
+ wxLOCALE_DATE_TIME_FMT,
+ wxLOCALE_TIME_FMT
+
+};
+
+// ----------------------------------------------------------------------------
+// wxLanguageInfo: encapsulates wxLanguage to OS native lang.desc.
+// translation information
+// ----------------------------------------------------------------------------
+
+struct WXDLLIMPEXP_BASE wxLanguageInfo
+{
+ int Language; // wxLanguage id
+ wxString CanonicalName; // Canonical name, e.g. fr_FR
+#ifdef __WINDOWS__
+ wxUint32 WinLang, // Win32 language identifiers
+ WinSublang;
+#endif // __WINDOWS__
+ wxString Description; // human-readable name of the language
+ wxLayoutDirection LayoutDirection;
+
+#ifdef __WINDOWS__
+ // return the LCID corresponding to this language
+ wxUint32 GetLCID() const;
+#endif // __WINDOWS__
+
+ // return the locale name corresponding to this language usable with
+ // setlocale() on the current system or empty string if this locale is not
+ // supported
+ wxString GetLocaleName() const;
+
+ // Call setlocale() and return non-null value if it works for this language.
+ //
+ // This function is mostly for internal use, as changing locale involves
+ // more than just calling setlocale() on some platforms, use wxLocale to
+ // do everything that needs to be done instead of calling this method.
+ const char* TrySetLocale() const;
+};
+
+#endif // wxUSE_INTL
+
+#endif // _WX_LOCALEDEFS_H_
diff --git a/include/wx/msw/private/uilocale.h b/include/wx/msw/private/uilocale.h
new file mode 100644
index 0000000000..8684213610
--- /dev/null
+++ b/include/wx/msw/private/uilocale.h
@@ -0,0 +1,28 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name: wx/msw/private/uilocale.h
+// Purpose: MSW-specific locale-related helpers
+// Author: Vadim Zeitlin
+// Created: 2021-08-14
+// Copyright: (c) 2021 Vadim Zeitlin
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_MSW_PRIVATE_UILOCALE_H_
+#define _WX_MSW_PRIVATE_UILOCALE_H_
+
+#include "wx/msw/private.h" // Include to get LCID.
+
+#ifndef LOCALE_SNAME
+#define LOCALE_SNAME 0x5c
+#endif
+#ifndef LOCALE_CUSTOM_UI_DEFAULT
+#define LOCALE_CUSTOM_UI_DEFAULT 0x1400
+#endif
+
+// Use the specific LCID for the current thread.
+void wxUseLCID(LCID lcid);
+
+// This function is defined in src/common/intl.cpp
+wxString wxGetInfoFromLCID(LCID lcid, wxLocaleInfo index, wxLocaleCategory cat);
+
+#endif // _WX_MSW_PRIVATE_UILOCALE_H_
diff --git a/include/wx/numformatter.h b/include/wx/numformatter.h
index 24ab702ab7..5e0f795dbe 100644
--- a/include/wx/numformatter.h
+++ b/include/wx/numformatter.h
@@ -40,6 +40,13 @@ public:
int precision,
int style = Style_WithThousandsSep);
+ // Format the given number using one of the floating point formats and
+ // ensure that the result uses the correct decimal separator.
+ // Prefer using ToString() if possible, i.e. if format is "%g" or "%.Nf"
+ // which are supported by it directly.
+ static wxString Format(const wxString& format, double val);
+
+
// Parse a string representing a number, possibly with thousands separator.
//
// Return true on success and stores the result in the provided location
diff --git a/include/wx/private/localeset.h b/include/wx/private/localeset.h
new file mode 100644
index 0000000000..a977247d6b
--- /dev/null
+++ b/include/wx/private/localeset.h
@@ -0,0 +1,49 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name: wx/private/localeset.h
+// Purpose: Define helper wxLocaleSetter class.
+// Author: Vadim Zeitlin
+// Created: 2021-08-03 (extracted from tests/testprec.h)
+// Copyright: (c) 2021 Vadim Zeitlin
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_PRIVATE_LOCALESET_H_
+#define _WX_PRIVATE_LOCALESET_H_
+
+#include "wx/crt.h" // wxStrdupA()
+
+#include
+
+// Helper class setting the locale to the given one for its lifetime.
+class wxLocaleSetter
+{
+public:
+ wxLocaleSetter(const char *loc)
+ : m_locOld(wxStrdupA(setlocale(LC_ALL, NULL)))
+ {
+ setlocale(LC_ALL, loc);
+ }
+
+ ~wxLocaleSetter()
+ {
+ setlocale(LC_ALL, m_locOld);
+ free(m_locOld);
+ }
+
+private:
+ char * const m_locOld;
+
+ wxDECLARE_NO_COPY_CLASS(wxLocaleSetter);
+};
+
+// An even simpler helper for setting the locale to "C" one during its lifetime.
+class wxCLocaleSetter : private wxLocaleSetter
+{
+public:
+ wxCLocaleSetter() : wxLocaleSetter("C") { }
+
+private:
+ wxDECLARE_NO_COPY_CLASS(wxCLocaleSetter);
+};
+
+#endif // _WX_PRIVATE_LOCALESET_H_
diff --git a/include/wx/private/uilocale.h b/include/wx/private/uilocale.h
new file mode 100644
index 0000000000..bfa6f318ea
--- /dev/null
+++ b/include/wx/private/uilocale.h
@@ -0,0 +1,52 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name: wx/private/uilocale.h
+// Purpose: wxUILocaleImpl class declaration
+// Author: Vadim Zeitlin
+// Created: 2021-08-01
+// Copyright: (c) 2021 Vadim Zeitlin
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_PRIVATE_UILOCALE_H_
+#define _WX_PRIVATE_UILOCALE_H_
+
+#include "wx/localedefs.h"
+#include "wx/string.h"
+
+// ----------------------------------------------------------------------------
+// wxUILocaleImpl provides the implementation of public wxUILocale functions
+// ----------------------------------------------------------------------------
+
+class wxUILocaleImpl
+{
+public:
+ // This function is implemented in platform-specific code and returns the
+ // object used by default, i.e. if wxUILocale::UseDefault() is not called.
+ // This object corresponds to the traditional "C" locale.
+ //
+ // It should never return NULL.
+ static wxUILocaleImpl* CreateStdC();
+
+ // Similarly, this one returns the object corresponding to the default user
+ // locale settings which is used if wxUILocale::UseDefault() was called.
+ //
+ // It may return NULL in case of failure.
+ static wxUILocaleImpl* CreateUserDefault();
+
+ // This function exists only for wxLocale compatibility and sets the locale
+ // corresponding to the given language.
+ //
+ // The language passed to this function is a valid language, i.e. neither
+ // wxLANGUAGE_UNKNOWN nor wxLANGUAGE_DEFAULT.
+ //
+ // It may return NULL in case of failure.
+ static wxUILocaleImpl* CreateForLanguage(const wxLanguageInfo& info);
+
+ // Functions corresponding to wxUILocale ones.
+ virtual wxString GetName() const = 0;
+ virtual wxString GetInfo(wxLocaleInfo index, wxLocaleCategory cat) const = 0;
+
+ virtual ~wxUILocaleImpl() { }
+};
+
+#endif // _WX_PRIVATE_UILOCALE_H_
diff --git a/include/wx/uilocale.h b/include/wx/uilocale.h
new file mode 100644
index 0000000000..acae223190
--- /dev/null
+++ b/include/wx/uilocale.h
@@ -0,0 +1,84 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name: wx/uilocale.h
+// Purpose: wxUILocale class declaration.
+// Author: Vadim Zeitlin
+// Created: 2021-07-31
+// Copyright: (c) 2021 Vadim Zeitlin
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_UILOCALE_H_
+#define _WX_UILOCALE_H_
+
+#include "wx/defs.h"
+
+#if wxUSE_INTL
+
+#include "wx/localedefs.h"
+#include "wx/string.h"
+
+class wxUILocaleImpl;
+
+// ----------------------------------------------------------------------------
+// wxUILocale allows to use the default UI locale and get information about it
+// ----------------------------------------------------------------------------
+
+class WXDLLIMPEXP_BASE wxUILocale
+{
+public:
+ // Configure the UI to use the default user locale.
+ static bool UseDefault();
+
+ // Use the locale corresponding to the given language.
+ //
+ // This is a compatibility function used by wxWidgets itself, don't use it
+ // in the new code.
+ static bool UseLanguage(const wxLanguageInfo& info);
+
+ // Get the object corresponding to the currently used locale.
+ static const wxUILocale& GetCurrent();
+
+ // Get the platform-dependent name of the current locale.
+ wxString GetName() const;
+
+ // Query the locale for the specified information.
+ wxString GetInfo(wxLocaleInfo index,
+ wxLocaleCategory cat = wxLOCALE_CAT_DEFAULT) const;
+
+ // Note that this class is not supposed to be used polymorphically, hence
+ // its dtor is not virtual.
+ ~wxUILocale();
+
+private:
+ // Ctor is private, use static accessor to get objects of this class.
+ wxUILocale() : m_impl(NULL) { }
+
+ // Used by UseDefault().
+ //
+ // Note that this object takes ownership of the provided pointer and will
+ // delete it in dtor.
+ void SetImpl(wxUILocaleImpl* impl);
+
+
+ static wxUILocale ms_current;
+
+ wxUILocaleImpl* m_impl;
+
+ wxDECLARE_NO_COPY_CLASS(wxUILocale);
+};
+
+inline wxString wxGetUIDateFormat()
+{
+ return wxUILocale::GetCurrent().GetInfo(wxLOCALE_SHORT_DATE_FMT);
+}
+
+#else // !wxUSE_INTL
+
+inline wxString wxGetUIDateFormat()
+{
+ return wxString(wxS("%x"));
+}
+
+#endif // wxUSE_INTL/!wxUSE_INTL
+
+#endif // _WX_UILOCALE_H_
diff --git a/include/wx/unix/private/uilocale.h b/include/wx/unix/private/uilocale.h
new file mode 100644
index 0000000000..7a882810d0
--- /dev/null
+++ b/include/wx/unix/private/uilocale.h
@@ -0,0 +1,33 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name: wx/unix/private/uilocale.h
+// Purpose: Various locale-related helpers used under Unix systems only
+// Author: Vadim Zeitlin
+// Created: 2021-08-14 (extracted from src/common/intl.cpp)
+// Copyright: (c) 2021 Vadim Zeitlin
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _WX_UNIX_PRIVATE_UILOCALE_H_
+#define _WX_UNIX_PRIVATE_UILOCALE_H_
+
+#include "wx/string.h"
+
+// get just the language part ("en" in "en_GB")
+inline wxString ExtractLang(const wxString& langFull)
+{
+ return langFull.BeforeFirst('_');
+}
+
+// get everything else (including the leading '_')
+inline wxString ExtractNotLang(const wxString& langFull)
+{
+ size_t pos = langFull.find('_');
+ if ( pos != wxString::npos )
+ return langFull.substr(pos);
+ else
+ return wxString();
+}
+
+const char *wxSetlocaleTryAll(int c, const wxString& lc);
+
+#endif // _WX_UNIX_PRIVATE_UILOCALE_H_
diff --git a/interface/wx/intl.h b/interface/wx/intl.h
index 92902c1b7d..92d1bab62d 100644
--- a/interface/wx/intl.h
+++ b/interface/wx/intl.h
@@ -69,7 +69,7 @@ struct wxLanguageInfo
/**
The category of locale settings.
- @see wxLocale::GetInfo()
+ @see wxLocale::GetInfo(), wxUILocale::GetInfo()
*/
enum wxLocaleCategory
{
@@ -108,6 +108,8 @@ enum wxLocaleCategory
All of these values are used with @c wxLOCALE_CAT_DATE in wxLocale::GetInfo() or,
more typically, with @c wxLOCALE_CAT_DEFAULT as they only apply to a single category.
+
+ @see wxUILocale::GetInfo()
*/
enum wxLocaleInfo
{
@@ -116,6 +118,9 @@ enum wxLocaleInfo
This value can be used with either wxLOCALE_CAT_NUMBER or
wxLOCALE_CAT_MONEY categories.
+
+ By default, i.e. when wxLOCALE_CAT_DEFAULT is used, the separator for
+ numbers is returned.
*/
wxLOCALE_THOUSANDS_SEP,
@@ -124,6 +129,9 @@ enum wxLocaleInfo
This value can be used with either wxLOCALE_CAT_NUMBER or
wxLOCALE_CAT_MONEY categories.
+
+ By default, i.e. when wxLOCALE_CAT_DEFAULT is used, the decimal point
+ for numbers is returned.
*/
wxLOCALE_DECIMAL_POINT,
@@ -166,6 +174,13 @@ enum wxLocaleInfo
wxLocale class encapsulates all language-dependent settings and is a
generalization of the C locale concept.
+ @note While this class can still be used in wxMSW and wxGTK ports, it
+ doesn't work in wxOSX where it is impossible to change the application
+ UI locale after launching it. Worse, since macOS 11 (Big Sur), using
+ wxLocale can break application display due to bugs in C locale support
+ in macOS itself. Because of this, it is recommended to use wxUILocale
+ instead of this class for the applications targeting macOS.
+
In wxWidgets this class manages current locale. It also initializes and
activates wxTranslations object that manages message catalogs.
@@ -435,6 +450,9 @@ public:
/**
Get the values of a locale datum in the OS locale.
+ This function shouldn't be used in the new code, use
+ wxUILocale::GetInfo() instead.
+
This function is similar to GetInfo() and, in fact, identical to it
under non-MSW systems. Under MSW it differs from it when no locale had
been explicitly set: GetInfo() returns the values corresponding to the
diff --git a/interface/wx/numformatter.h b/interface/wx/numformatter.h
index 1479bae1c4..f635e2327d 100644
--- a/interface/wx/numformatter.h
+++ b/interface/wx/numformatter.h
@@ -8,11 +8,15 @@
/**
@class wxNumberFormatter
- Helper class for formatting and parsing numbers with thousands separators.
+ Formatting and parsing numbers using the current UI locale conventions,
+ including support for using the correct decimal point character and
+ thousands separators.
This class contains only static functions, so users must not create instances
but directly call the member functions.
+ @see wxUILocale
+
@since 2.9.2
@library{wxbase}
@@ -32,7 +36,7 @@ public:
/**
If this flag is given, thousands separators will be inserted in the
- number string representation as defined by the current locale.
+ number string representation as defined by the current UI locale.
*/
Style_WithThousandsSep = 0x01,
@@ -56,7 +60,7 @@ public:
Returns string representation of an integer number.
By default, the string will use thousands separators if appropriate for
- the current locale. This can be avoided by passing Style_None as @a
+ the current UI locale. This can be avoided by passing Style_None as @a
flags in which case the call to the function has exactly the same
effect as wxString::Format("%ld", val)
.
@@ -89,12 +93,22 @@ public:
static wxString
ToString(double val, int precision, int flags = Style_WithThousandsSep);
+ /**
+ Format the given number using one of the floating point formats and
+ ensure that the result uses the correct decimal separator.
+
+ Prefer using ToString() if possible, i.e. if format is "%g" or "%.Nf"
+ which are supported by it directly.
+
+ @since 3.1.6
+ */
+ static wxString Format(const wxString& format, double val);
/**
Parse a string representation of a number possibly including thousands
separators.
- These functions parse number representation in the current locale. On
+ These functions parse number representation in the current UI locale. On
success they return @true and store the result at the location pointed
to by @a val (which can't be @NULL), otherwise @false is returned.
@@ -114,7 +128,7 @@ public:
//@}
/**
- Get the decimal separator for the current locale.
+ Get the decimal separator for the current UI locale.
Decimal separators is always defined and we fall back to returning '.'
in case of an error.
@@ -123,14 +137,14 @@ public:
/**
Get the thousands separator if grouping of the digits is used by the
- current locale.
+ current UI locale.
The value returned in @a sep should be only used if the function
returns @true, otherwise no thousands separator should be used at all.
@param sep
Points to the variable receiving the thousands separator character
- if it is used by the current locale. May be @NULL if only the
+ if it is used by the current UI locale. May be @NULL if only the
function return value is needed.
*/
static bool GetThousandsSeparatorIfUsed(wxChar *sep);
diff --git a/interface/wx/uilocale.h b/interface/wx/uilocale.h
new file mode 100644
index 0000000000..de6bcc7550
--- /dev/null
+++ b/interface/wx/uilocale.h
@@ -0,0 +1,121 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name: wx/uilocale.h
+// Purpose: Interface of wxUILocale
+// Author: Vadim Zeitlin
+// Created: 2021-08-01
+// Copyright: (c) 2021 Vadim Zeitlin
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ Query and modify locale used for the UI by the current platform.
+
+ UI locale determines all culture-dependent conventions used in the user
+ interface, including numbers, currencies and dates formatting. It also
+ determines the language used by the native dialogs, such as wxFileDialog,
+ where different labels use the language corresponding to the current UI
+ locale.
+
+ The UI locale is, in general, different from C locale set by the standard
+ @c setlocale() function and affecting C standard library functions such as
+ @c printf(), @c scanf(), @c strftime() and many others. Unfortunately, the
+ relationship between C and UI locales is not the same depending on the
+ platform: with wxGTK they must be the same, but under macOS C locale must
+ not be changed, as doing this exposes bugs in the system. Because of this,
+ applications can't generally count on C locale being set to any particular
+ value and it is best to avoid using it, including implicitly via the
+ standard C functions, in portable code. Instead, consider using
+ wxNumberFormatter for parsing and formatting numbers according to the
+ current UI locale or wxString::FromCDouble() and wxString::ToCDouble()
+ functions for doing it always using period as decimal separator.
+
+ Localized applications should call wxUILocale::UseDefault() on startup to
+ explicitly indicate that they opt-in using the current UI locale, even if
+ this results in changing the global C locale, as is the case in wxGTK. Note
+ that some platforms (MSW and macOS) will use default user locale for their
+ standard dialogs even if this function is not called, but it is still
+ necessary to call it to use the correct number and date formats and to
+ avoid mixing messages in the user language with default formats not
+ corresponding to it.
+
+ Please also note that under macOS to really use the user locale, it must be
+ listed as a supported language in the application @c Info.plist file under
+ @c CFBundleLocalizations key.
+
+ Unlike wxLocale class, this class doesn't affect the translations used by
+ the application, see wxTranslations for doing this.
+
+ @library{wxbase}
+ @since 3.1.6
+ */
+class wxUILocale
+{
+public:
+ /**
+ Configure the UI to use the default user locale.
+
+ Localized applications should call this functions as early as possible
+ during the program startup, e.g. in the very beginning of the
+ overridden wxApp::OnInit().
+
+ Note that under most Unix systems (but not macOS) this function changes
+ the C locale to the locale specified by the environment variables and
+ so affects the results of calling C functions such as @c sprintf() etc
+ which can use comma, rather than period, as decimal separator. The
+ wxString::ToCDouble() and wxString::FromCDouble() functions can be used
+ for parsing and formatting floating point numbers using period as
+ decimal separator independently of the current locale.
+
+ @return @true on success or @false if the default locale couldn't be set
+ */
+ static bool UseDefault();
+
+ /**
+ Get the object corresponding to the currently used locale.
+
+ If UseDefault() had been called, this object corresponds to the default
+ user locale. Otherwise it corresponds to a generic locale similar to
+ "C" locale, i.e. always uses period as decimal separator and m/d/y date
+ format.
+ */
+ static const wxUILocale& GetCurrent();
+
+ /**
+ Get the platform-dependent name of the current locale.
+
+ This name can be used in diagnostic messages.
+ */
+ wxString GetName() const;
+
+ /**
+ Query the locale for the specified information.
+
+ This function returns the value of the locale-specific option specified
+ by the given @a index.
+
+ @param index
+ One of the elements of wxLocaleInfo enum.
+ @param cat
+ The category to use with the given index or wxLOCALE_CAT_DEFAULT if
+ the index can only apply to a single category.
+ @return
+ The option value or empty string if the function failed.
+ */
+ wxString GetInfo(wxLocaleInfo index,
+ wxLocaleCategory cat = wxLOCALE_CAT_DEFAULT) const;
+};
+
+/**
+ Return the format to use for formatting user-visible dates.
+
+ This is a simple wrapper function normally calling wxUILocale::GetInfo()
+ with wxLOCALE_SHORT_DATE_FMT argument, but which is also available when @c
+ wxUSE_INTL==0, i.e. support for internationalization is disabled at
+ compile-time, in which case it returns @c %x string, i.e. uses the current
+ C locale formatting rather than UI locale.
+
+ @see wxDateTime::Format()
+
+ @since 3.1.6
+ */
+wxString wxGetUIDateFormat();
diff --git a/samples/internat/internat.cpp b/samples/internat/internat.cpp
index 5502619b53..15f8319239 100644
--- a/samples/internat/internat.cpp
+++ b/samples/internat/internat.cpp
@@ -28,11 +28,17 @@
#include "wx/wx.h"
#endif
+#include "wx/calctrl.h"
#include "wx/intl.h"
#include "wx/file.h"
+#include "wx/grid.h"
#include "wx/log.h"
#include "wx/cmdline.h"
+#include "wx/numformatter.h"
#include "wx/platinfo.h"
+#include "wx/spinctrl.h"
+#include "wx/translation.h"
+#include "wx/uilocale.h"
#ifndef wxHAS_IMAGES_IN_RESOURCES
#include "../sample.xpm"
@@ -53,22 +59,29 @@
class MyApp: public wxApp
{
public:
- MyApp() { m_lang = wxLANGUAGE_UNKNOWN; }
+ MyApp() { m_setLocale = Locale_Ask; }
virtual void OnInitCmdLine(wxCmdLineParser& parser) wxOVERRIDE;
virtual bool OnCmdLineParsed(wxCmdLineParser& parser) wxOVERRIDE;
virtual bool OnInit() wxOVERRIDE;
protected:
- wxLanguage m_lang; // language specified by user
- wxLocale m_locale; // locale we'll be using
+ // Specifies whether we should use the current locale or not. By default we
+ // ask the user about it, but it's possible to override this using the
+ // command line options.
+ enum
+ {
+ Locale_Ask,
+ Locale_Set,
+ Locale_Skip
+ } m_setLocale;
};
// Define a new frame type
class MyFrame: public wxFrame
{
public:
- MyFrame(wxLocale& m_locale);
+ MyFrame();
public:
void OnTestLocaleAvail(wxCommandEvent& event);
@@ -80,14 +93,13 @@ public:
void OnPlay(wxCommandEvent& event);
void OnOpen(wxCommandEvent& event);
+ void OnSave(wxCommandEvent& event);
void OnTest1(wxCommandEvent& event);
void OnTest2(wxCommandEvent& event);
void OnTest3(wxCommandEvent& event);
void OnTestMsgBox(wxCommandEvent& event);
wxDECLARE_EVENT_TABLE();
-
- wxLocale& m_locale;
};
// ----------------------------------------------------------------------------
@@ -114,59 +126,6 @@ enum
INTERNAT_MACRO_9
};
-// language data
-static const wxLanguage langIds[] =
-{
- wxLANGUAGE_DEFAULT,
- wxLANGUAGE_FRENCH,
- wxLANGUAGE_ITALIAN,
- wxLANGUAGE_GERMAN,
- wxLANGUAGE_RUSSIAN,
- wxLANGUAGE_BULGARIAN,
- wxLANGUAGE_CZECH,
- wxLANGUAGE_POLISH,
- wxLANGUAGE_SWEDISH,
-#if wxUSE_UNICODE || defined(__WXMOTIF__)
- wxLANGUAGE_JAPANESE,
-#endif
-#if wxUSE_UNICODE
- wxLANGUAGE_GEORGIAN,
- wxLANGUAGE_ENGLISH,
- wxLANGUAGE_ENGLISH_US,
- wxLANGUAGE_ARABIC,
- wxLANGUAGE_ARABIC_EGYPT
-#endif
-};
-
-// note that it makes no sense to translate these strings, they are
-// shown before we set the locale anyhow
-const wxString langNames[] =
-{
- "System default",
- "French",
- "Italian",
- "German",
- "Russian",
- "Bulgarian",
- "Czech",
- "Polish",
- "Swedish",
-#if wxUSE_UNICODE || defined(__WXMOTIF__)
- "Japanese",
-#endif
-#if wxUSE_UNICODE
- "Georgian",
- "English",
- "English (U.S.)",
- "Arabic",
- "Arabic (Egypt)"
-#endif
-};
-
-// the arrays must be in sync
-wxCOMPILE_TIME_ASSERT( WXSIZEOF(langNames) == WXSIZEOF(langIds),
- LangArraysMismatch );
-
// ----------------------------------------------------------------------------
// wxWidgets macros
// ----------------------------------------------------------------------------
@@ -181,6 +140,7 @@ wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(INTERNAT_PLAY, MyFrame::OnPlay)
EVT_MENU(wxID_OPEN, MyFrame::OnOpen)
+ EVT_MENU(wxID_SAVE, MyFrame::OnSave)
EVT_MENU(INTERNAT_TEST_1, MyFrame::OnTest1)
EVT_MENU(INTERNAT_TEST_2, MyFrame::OnTest2)
EVT_MENU(INTERNAT_TEST_3, MyFrame::OnTest3)
@@ -198,11 +158,16 @@ wxIMPLEMENT_APP(MyApp);
// ----------------------------------------------------------------------------
// command line arguments handling
+
+static const char* OPTION_NO_LOCALE = "no-locale";
+static const char* OPTION_SET_LOCALE = "set-locale";
+
void MyApp::OnInitCmdLine(wxCmdLineParser& parser)
{
- parser.AddParam(_("locale"),
- wxCMD_LINE_VAL_STRING,
- wxCMD_LINE_PARAM_OPTIONAL);
+ parser.AddSwitch("n", OPTION_NO_LOCALE,
+ _("skip setting locale on startup"));
+ parser.AddSwitch("y", OPTION_SET_LOCALE,
+ _("do set locale on startup without asking"));
wxApp::OnInitCmdLine(parser);
}
@@ -212,17 +177,20 @@ bool MyApp::OnCmdLineParsed(wxCmdLineParser& parser)
if ( !wxApp::OnCmdLineParsed(parser) )
return false;
- if ( parser.GetParamCount() )
+ if ( parser.Found(OPTION_NO_LOCALE) )
{
- const wxString loc = parser.GetParam();
- const wxLanguageInfo * const lang = wxLocale::FindLanguageInfo(loc);
- if ( !lang )
+ m_setLocale = Locale_Skip;
+ }
+
+ if ( parser.Found(OPTION_SET_LOCALE) )
+ {
+ if ( m_setLocale == Locale_Skip )
{
- wxLogError(_("Locale \"%s\" is unknown."), loc);
- return false;
+ wxLogWarning("--%s option overrides --%s",
+ OPTION_SET_LOCALE, OPTION_NO_LOCALE);
}
- m_lang = static_cast(lang->Language);
+ m_setLocale = Locale_Set;
}
return true;
@@ -234,57 +202,75 @@ bool MyApp::OnInit()
if ( !wxApp::OnInit() )
return false;
- if ( m_lang == wxLANGUAGE_UNKNOWN )
+ // For demonstration purposes only, ask the user if they want to run the
+ // program using the current system language. In real programs, we would do
+ // it unconditionally for localized programs -- or never do it at all for
+ // the other ones.
+ const wxLanguageInfo* const
+ langInfo = wxLocale::GetLanguageInfo(wxLANGUAGE_DEFAULT);
+ const wxString
+ langDesc = langInfo ? langInfo->Description
+ : "the default system locale";
+
+ if ( m_setLocale == Locale_Ask )
{
- int lng = wxGetSingleChoiceIndex
- (
- _("Please choose language:"),
- _("Language"),
- WXSIZEOF(langNames),
- langNames
- );
- m_lang = lng == -1 ? wxLANGUAGE_DEFAULT : langIds[lng];
+ m_setLocale = wxMessageBox
+ (
+ wxString::Format
+ (
+ "Would you like to use the program in %s?",
+ langDesc
+ ),
+ "wxWidgets i18n (internat) sample",
+ wxYES_NO
+ ) == wxYES ? Locale_Set : Locale_Skip;
}
- // don't use wxLOCALE_LOAD_DEFAULT flag so that Init() doesn't return
- // false just because it failed to load wxstd catalog
- if ( !m_locale.Init(m_lang, wxLOCALE_DONT_LOAD_DEFAULT) )
+ if ( m_setLocale == Locale_Set )
{
- wxLogWarning(_("This language is not supported by the system."));
+ if ( !wxUILocale::UseDefault() )
+ {
+ wxLogWarning("Failed to initialize the default system locale.");
+ }
- // continue nevertheless
- }
- // normally this wouldn't be necessary as the catalog files would be found
- // in the default locations, but when the program is not installed the
- // catalogs are in the build directory where we wouldn't find them by
- // default
- wxLocale::AddCatalogLookupPathPrefix(".");
+ // Independently of whether we succeeded to set the locale or not, try
+ // to load the translations (for the default system language) here.
- // Initialize the catalogs we'll be using
- const wxLanguageInfo* pInfo = wxLocale::GetLanguageInfo(m_lang);
- if (!m_locale.AddCatalog("internat"))
- {
- wxLogError(_("Couldn't find/load the 'internat' catalog for locale '%s'."),
- pInfo ? pInfo->GetLocaleName() : _("unknown"));
- }
+ // normally this wouldn't be necessary as the catalog files would be found
+ // in the default locations, but when the program is not installed the
+ // catalogs are in the build directory where we wouldn't find them by
+ // default
+ wxFileTranslationsLoader::AddCatalogLookupPathPrefix(".");
- // Now try to add wxstd.mo so that loading "NOTEXIST.ING" file will produce
- // a localized error message:
- m_locale.AddCatalog("wxstd");
- // NOTE: it's not an error if we couldn't find it!
+ // Create the object for message translation and set it up for global use.
+ wxTranslations* const trans = new wxTranslations();
+ wxTranslations::Set(trans);
- // this catalog is installed in standard location on Linux systems and
- // shows that you may make use of the standard message catalogs as well
- //
- // if it's not installed on your system, it is just silently ignored
+ // Initialize the catalogs we'll be using.
+ if ( !trans->AddCatalog("internat") )
+ {
+ wxLogError(_("Couldn't find/load 'internat' catalog for %s."),
+ langDesc);
+ }
+
+ // Now try to add wxstd.mo so that loading "NOTEXIST.ING" file will produce
+ // a localized error message:
+ trans->AddCatalog("wxstd");
+ // NOTE: it's not an error if we couldn't find it!
+
+ // this catalog is installed in standard location on Linux systems and
+ // shows that you may make use of the standard message catalogs as well
+ //
+ // if it's not installed on your system, it is just silently ignored
#ifdef USE_COREUTILS_MO
- wxLocale::AddCatalogLookupPathPrefix("/usr/share/locale");
- g_loadedCoreutilsMO = m_locale.AddCatalog("coreutils");
+ wxFileTranslationsLoader::AddCatalogLookupPathPrefix("/usr/share/locale");
+ g_loadedCoreutilsMO = trans->AddCatalog("coreutils");
#endif // USE_COREUTILS_MO
+ }
// Create the main frame window
- MyFrame *frame = new MyFrame(m_locale);
+ MyFrame *frame = new MyFrame();
// Show the frame
frame->Show(true);
@@ -297,11 +283,10 @@ bool MyApp::OnInit()
// ----------------------------------------------------------------------------
// main frame constructor
-MyFrame::MyFrame(wxLocale& locale)
+MyFrame::MyFrame()
: wxFrame(NULL,
wxID_ANY,
- _("International wxWidgets App")),
- m_locale(locale)
+ _("International wxWidgets App"))
{
SetIcon(wxICON(sample));
@@ -316,6 +301,7 @@ MyFrame::MyFrame(wxLocale& locale)
wxMenu *test_menu = new wxMenu;
test_menu->Append(wxID_OPEN, _("&Open bogus file"), _("Shows a wxWidgets localized error message"));
+ test_menu->Append(wxID_SAVE, _("&Save dummy file"), _("Shows a localized standard dialog"));
test_menu->Append(INTERNAT_PLAY, _("&Play a game"), _("A little game; hint: 17 is a lucky number for many"));
test_menu->AppendSeparator();
test_menu->Append(INTERNAT_TEST_1, _("&1 _() (gettext)"), _("Tests the _() macro"));
@@ -360,13 +346,79 @@ MyFrame::MyFrame(wxLocale& locale)
// this demonstrates RTL support in wxStatusBar:
CreateStatusBar(1);
- // this demonstrates RTL layout mirroring for Arabic locales
+ wxPanel* const panel = new wxPanel(this);
+
+ wxSizer* const topSizer = new wxBoxSizer(wxVERTICAL);
+
+ // create controls showing the locale being used
+ topSizer->Add(new wxStaticText
+ (
+ panel,
+ wxID_ANY,
+ wxString::Format
+ (
+ _("Current UI locale: %s; C locale: %s"),
+ wxUILocale::GetCurrent().GetName(),
+ setlocale(LC_ALL, NULL)
+ )
+ ),
+ wxSizerFlags().Center().Border());
+
+ // create some controls affected by the locale
+
+ // this demonstrates RTL layout mirroring for Arabic locales and using
+ // locale-specific decimal separator in wxSpinCtrlDouble.
wxSizer *sizer = new wxBoxSizer(wxHORIZONTAL);
- sizer->Add(new wxStaticText(this, wxID_ANY, _("First")),
- wxSizerFlags().Border());
- sizer->Add(new wxStaticText(this, wxID_ANY, _("Second")),
- wxSizerFlags().Border());
- SetSizer(sizer);
+ sizer->Add(new wxStaticText(panel, wxID_ANY, _("Numeric input:")),
+ wxSizerFlags().Center().Border());
+
+ wxSpinCtrlDouble* const spin = new wxSpinCtrlDouble(panel, wxID_ANY);
+ spin->SetDigits(2);
+ spin->SetValue(12.34);
+ sizer->Add(spin, wxSizerFlags().Center().Border());
+
+ topSizer->Add(sizer, wxSizerFlags().Center());
+
+ // show that week days and months names are translated too
+ topSizer->Add(new wxCalendarCtrl(panel, wxID_ANY),
+ wxSizerFlags().Center().Border());
+
+ // another control using locale-specific number and date format
+ wxGrid* const grid = new wxGrid(panel, wxID_ANY,
+ wxDefaultPosition, wxDefaultSize,
+ wxBORDER_SIMPLE);
+ grid->CreateGrid(2, 2);
+ grid->HideRowLabels();
+
+ grid->SetColLabelValue(0, _("Number"));
+ grid->SetColFormatFloat(0);
+ grid->SetCellValue(0, 0, wxNumberFormatter::ToString(3.14159265, -1));
+
+ grid->SetColLabelValue(1, _("Date"));
+ grid->SetColFormatDate(1);
+ grid->SetCellValue(0, 1, "Today");
+
+ topSizer->Add(grid, wxSizerFlags().Center().Border());
+
+ // show the difference (in decimal and thousand separator, hence use a
+ // floating point number > 1000) between wxString::Format() and
+ // wxNumberFormatter: the former uses the current C locale, while the
+ // latter uses the UI locale
+ topSizer->Add(new wxStaticText
+ (
+ panel,
+ wxID_ANY,
+ wxString::Format
+ (
+ _("Number in UI locale: %s; in C locale: %.2f"),
+ wxNumberFormatter::ToString(1234567.89, 2),
+ 1234567.89
+ )
+ ),
+ wxSizerFlags().Center().Border());
+
+ panel->SetSizer(topSizer);
+ topSizer->SetSizeHints(this);
}
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event) )
@@ -376,20 +428,10 @@ void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event) )
void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{
- wxString localeInfo;
- wxString locale = m_locale.GetLocale();
- wxString sysname = m_locale.GetSysName();
- wxString canname = m_locale.GetCanonicalName();
-
- localeInfo.Printf(_("Language: %s\nSystem locale name: %s\nCanonical locale name: %s\n"),
- locale, sysname, canname );
-
wxMessageDialog dlg(
this,
- wxString(_("I18n sample\n(c) 1998, 1999 Vadim Zeitlin and Julian Smart"))
- + "\n\n"
- + localeInfo,
- _("About Internat"),
+ _("I18n sample\n(c) 1998, 1999 Vadim Zeitlin and Julian Smart"),
+ _("About Internat"),
wxOK | wxICON_INFORMATION
);
dlg.ShowModal();
@@ -510,6 +552,13 @@ void MyFrame::OnOpen(wxCommandEvent& WXUNUSED(event))
wxFile file("NOTEXIST.ING");
}
+void MyFrame::OnSave(wxCommandEvent& WXUNUSED(event))
+{
+ // show this file dialog just to check that the locale-specific elements in
+ // it (such as dates) follow the current locale convnetions
+ wxSaveFileSelector(_("Dummy file dialog"), ".ext", "dummy", this);
+}
+
void MyFrame::OnTest1(wxCommandEvent& WXUNUSED(event))
{
const wxString& title = _("Testing _() (gettext)");
diff --git a/src/common/datavcmn.cpp b/src/common/datavcmn.cpp
index 7d25c8fe2b..f17b761ffa 100644
--- a/src/common/datavcmn.cpp
+++ b/src/common/datavcmn.cpp
@@ -28,6 +28,8 @@
#include "wx/choice.h"
#include "wx/imaglist.h"
#include "wx/renderer.h"
+#include "wx/uilocale.h"
+
#if wxUSE_ACCESSIBILITY
#include "wx/access.h"
#endif // wxUSE_ACCESSIBILITY
@@ -1999,23 +2001,28 @@ bool wxDataViewDateRenderer::GetValue(wxVariant& value) const
return true;
}
+wxString wxDataViewDateRenderer::FormatDate() const
+{
+ return m_date.Format(wxGetUIDateFormat());
+}
+
#if wxUSE_ACCESSIBILITY
wxString wxDataViewDateRenderer::GetAccessibleDescription() const
{
- return m_date.FormatDate();
+ return FormatDate();
}
#endif // wxUSE_ACCESSIBILITY
bool wxDataViewDateRenderer::Render(wxRect cell, wxDC* dc, int state)
{
- wxString tmp = m_date.FormatDate();
+ wxString tmp = FormatDate();
RenderText( tmp, 0, cell, dc, state );
return true;
}
wxSize wxDataViewDateRenderer::GetSize() const
{
- return GetTextExtent(m_date.FormatDate());
+ return GetTextExtent(FormatDate());
}
#endif // (defined(wxHAS_GENERIC_DATAVIEWCTRL) || defined(__WXGTK__)) && wxUSE_DATEPICKCTRL
diff --git a/src/common/intl.cpp b/src/common/intl.cpp
index 6dc41e4b05..5f2a74788f 100644
--- a/src/common/intl.cpp
+++ b/src/common/intl.cpp
@@ -43,18 +43,6 @@
#include
#endif
-#ifdef __WIN32__
- #include "wx/dynlib.h"
- #include "wx/msw/private.h"
-
- #ifndef LOCALE_SNAME
- #define LOCALE_SNAME 0x5c
- #endif
- #ifndef LOCALE_CUSTOM_UI_DEFAULT
- #define LOCALE_CUSTOM_UI_DEFAULT 0x1400
- #endif
-#endif
-
#include "wx/file.h"
#include "wx/filename.h"
#include "wx/tokenzr.h"
@@ -63,13 +51,18 @@
#include "wx/apptrait.h"
#include "wx/stdpaths.h"
#include "wx/hashset.h"
+#include "wx/uilocale.h"
-#if defined(__WXOSX__)
+#ifdef __WIN32__
+ #include "wx/msw/private/uilocale.h"
+#elif defined(__WXOSX__)
#include "wx/osx/core/cfref.h"
#include "wx/osx/core/cfstring.h"
#include
#include
#include
+#elif defined(__UNIX__)
+ #include "wx/unix/private/uilocale.h"
#endif
// ----------------------------------------------------------------------------
@@ -88,31 +81,6 @@
static wxLocale *wxSetLocale(wxLocale *pLocale);
-namespace
-{
-
-#if defined(__UNIX__)
-
-// get just the language part ("en" in "en_GB")
-inline wxString ExtractLang(const wxString& langFull)
-{
- return langFull.BeforeFirst('_');
-}
-
-// get everything else (including the leading '_')
-inline wxString ExtractNotLang(const wxString& langFull)
-{
- size_t pos = langFull.find('_');
- if ( pos != wxString::npos )
- return langFull.substr(pos);
- else
- return wxString();
-}
-
-#endif // __UNIX__
-
-} // anonymous namespace
-
// ----------------------------------------------------------------------------
// wxLanguageInfo
// ----------------------------------------------------------------------------
@@ -396,89 +364,6 @@ bool wxLocale::DoCommonPostInit(bool success,
return success;
}
-#if defined(__UNIX__)
-
-// Helper of wxSetlocaleTryAll() below which tries setting the given locale
-// with and without UTF-8 suffix. Don't use this one directly.
-static const char *wxSetlocaleTryUTF8(int c, const wxString& lc)
-{
- const char *l = NULL;
-
- // NB: We prefer to set UTF-8 locale if it's possible and only fall back to
- // non-UTF-8 locale if it fails, but this is not necessary under the
- // supported macOS versions where xx_YY locales are just aliases to
- // xx_YY.UTF-8 anyhow.
-#if wxUSE_UNICODE && !defined(__WXMAC__)
- if ( !lc.empty() )
- {
- wxString buf(lc);
- wxString buf2;
- buf2 = buf + wxS(".UTF-8");
- l = wxSetlocale(c, buf2);
- if ( !l )
- {
- buf2 = buf + wxS(".utf-8");
- l = wxSetlocale(c, buf2);
- }
- if ( !l )
- {
- buf2 = buf + wxS(".UTF8");
- l = wxSetlocale(c, buf2);
- }
- if ( !l )
- {
- buf2 = buf + wxS(".utf8");
- l = wxSetlocale(c, buf2);
- }
- }
-
- // if we can't set UTF-8 locale, try non-UTF-8 one:
- if ( !l )
-#endif // wxUSE_UNICODE && !__WXMAC__
- l = wxSetlocale(c, lc);
-
- return l;
-}
-
-// Try setting all possible versions of the given locale, i.e. with and without
-// UTF-8 encoding, and with or without the "_territory" part.
-static const char *wxSetlocaleTryAll(int c, const wxString& lc)
-{
- const char* l = wxSetlocaleTryUTF8(c, lc);
- if ( !l )
- {
- const wxString& lcOnlyLang = ExtractLang(lc);
- if ( lcOnlyLang != lc )
- l = wxSetlocaleTryUTF8(c, lcOnlyLang);
- }
-
- return l;
-}
-
-#endif // __UNIX__
-
-#ifdef __WIN32__
-
-// Trivial wrapper for ::SetThreadUILanguage().
-//
-// TODO-XP: Drop this when we don't support XP any longer.
-static void wxMSWSetThreadUILanguage(LANGID langid)
-{
- // SetThreadUILanguage() is available on XP, but with unclear
- // behavior, so avoid calling it there.
- if ( wxGetWinVersion() >= wxWinVersion_Vista )
- {
- wxLoadedDLL dllKernel32(wxS("kernel32.dll"));
- typedef LANGID(WINAPI *SetThreadUILanguage_t)(LANGID);
- SetThreadUILanguage_t pfnSetThreadUILanguage = NULL;
- wxDL_INIT_FUNC(pfn, SetThreadUILanguage, dllKernel32);
- if (pfnSetThreadUILanguage)
- pfnSetThreadUILanguage(langid);
- }
-}
-
-#endif // __WIN32__
-
bool wxLocale::Init(int lang, int flags)
{
#if WXWIN_COMPATIBILITY_2_8
@@ -522,76 +407,19 @@ bool wxLocale::Init(int lang, int flags)
#if defined(__UNIX__) || defined(__WIN32__)
+ bool ok = lang == wxLANGUAGE_DEFAULT ? wxUILocale::UseDefault()
+ : wxUILocale::UseLanguage(*info);
+
+ // Under (non-Darwn) Unix wxUILocale already set the C locale, but under
+ // the other platforms we still have to do it here.
+#if defined(__WIN32__) || defined(__WXOSX__)
+
// We prefer letting the CRT to set its locale on its own when using
// default locale, as it does a better job of it than we do. We also have
// to do this when we didn't recognize the default language at all.
const char *retloc = lang == wxLANGUAGE_DEFAULT ? wxSetlocale(LC_ALL, "")
- : NULL;
+ : info->TrySetLocale();
-#if defined(__UNIX__)
- if ( !retloc )
- retloc = wxSetlocaleTryAll(LC_ALL, shortName);
-
- if ( !retloc )
- {
- // Some C libraries (namely glibc) still use old ISO 639,
- // so will translate the abbrev for them
- wxString localeAlt;
- const wxString& langOnly = ExtractLang(shortName);
- if ( langOnly == wxS("he") )
- localeAlt = wxS("iw") + ExtractNotLang(shortName);
- else if ( langOnly == wxS("id") )
- localeAlt = wxS("in") + ExtractNotLang(shortName);
- else if ( langOnly == wxS("yi") )
- localeAlt = wxS("ji") + ExtractNotLang(shortName);
- else if ( langOnly == wxS("nb") )
- localeAlt = wxS("no_NO");
- else if ( langOnly == wxS("nn") )
- localeAlt = wxS("no_NY");
-
- if ( !localeAlt.empty() )
- retloc = wxSetlocaleTryAll(LC_ALL, localeAlt);
- }
-
-#ifdef __AIX__
- // at least in AIX 5.2 libc is buggy and the string returned from
- // setlocale(LC_ALL) can't be passed back to it because it returns 6
- // strings (one for each locale category), i.e. for C locale we get back
- // "C C C C C C"
- //
- // this contradicts IBM own docs but this is not of much help, so just work
- // around it in the crudest possible manner
- char* p = const_cast(wxStrchr(retloc, ' '));
- if ( p )
- *p = '\0';
-#endif // __AIX__
-
-#elif defined(__WIN32__)
- if ( lang == wxLANGUAGE_DEFAULT )
- {
- ::SetThreadLocale(LOCALE_USER_DEFAULT);
- wxMSWSetThreadUILanguage(LANG_USER_DEFAULT);
-
- // CRT locale already set above.
- }
- else if ( info->WinLang == 0 )
- {
- wxLogWarning(wxS("Locale '%s' not supported by OS."), name);
-
- retloc = "C";
- }
- else // language supported by Windows
- {
- const wxUint32 lcid = info->GetLCID();
-
- // change locale used by Windows functions
- ::SetThreadLocale(lcid);
-
- wxMSWSetThreadUILanguage(LANGIDFROMLCID(lcid));
-
- // and also call setlocale() to change locale used by the CRT
- retloc = info->TrySetLocale();
- }
#if wxUSE_UNICODE && (defined(__VISUALC__) || defined(__MINGW32__))
// VC++ setlocale() (also used by Mingw) can't set locale to languages that
// can only be written using Unicode, therefore wxSetlocale() call fails
@@ -607,13 +435,15 @@ bool wxLocale::Init(int lang, int flags)
}
}
#endif // CRT not handling Unicode-only languages
-#else
- #error "Unsupported platform"
-#endif
+
+ if ( !retloc )
+ ok = false;
+
+#endif // __WIN32__
return DoCommonPostInit
(
- retloc != NULL,
+ ok,
name,
// wxLANGUAGE_DEFAULT needs to be passed to wxTranslations as ""
// for correct detection of user's preferred language(s)
@@ -648,9 +478,6 @@ inline bool wxGetNonEmptyEnvVar(const wxString& name, wxString* value)
size_t i = 0,
count = ms_languagesDB->GetCount();
-#if defined(__UNIX__)
- // first get the string identifying the language from the environment
- wxString langFull;
#ifdef __WXOSX__
wxCFRef userLocaleRef(CFLocaleCopyCurrent());
@@ -658,10 +485,34 @@ inline bool wxGetNonEmptyEnvVar(const wxString& name, wxString* value)
// az_Cyrl_AZ@calendar=buddhist;currency=JPY we just recreate the base info as expected by wx here
wxCFStringRef str(wxCFRetain((CFStringRef)CFLocaleGetValue(userLocaleRef, kCFLocaleLanguageCode)));
- langFull = str.AsString()+"_";
+ const wxString langPrefix = str.AsString() + "_";
+
str.reset(wxCFRetain((CFStringRef)CFLocaleGetValue(userLocaleRef, kCFLocaleCountryCode)));
- langFull += str.AsString();
-#else
+ const wxString langFull = langPrefix + str.AsString();
+
+ int langOnlyMatchIndex = wxNOT_FOUND;
+ for ( i = 0; i < count; i++ )
+ {
+ const wxString& fullname = ms_languagesDB->Item(i).CanonicalName;
+ if ( langFull == fullname )
+ {
+ // Exact match, no need to look any further.
+ break;
+ }
+
+ if ( fullname.StartsWith(langPrefix) )
+ {
+ // Matched just the language, keep looking, but we'll keep this if
+ // we don't find an exact match later.
+ langOnlyMatchIndex = i;
+ }
+ }
+
+ if ( i == count && langOnlyMatchIndex != wxNOT_FOUND )
+ i = langOnlyMatchIndex;
+#elif defined(__UNIX__)
+ // first get the string identifying the language from the environment
+ wxString langFull;
if (!wxGetNonEmptyEnvVar(wxS("LC_ALL"), &langFull) &&
!wxGetNonEmptyEnvVar(wxS("LC_MESSAGES"), &langFull) &&
!wxGetNonEmptyEnvVar(wxS("LANG"), &langFull))
@@ -670,8 +521,6 @@ inline bool wxGetNonEmptyEnvVar(const wxString& name, wxString* value)
return wxLANGUAGE_ENGLISH_US;
}
-#endif
-
// the language string has the following form
//
// lang[_LANG][.encoding][@modifier]
@@ -1118,8 +967,7 @@ wxLocale::~wxLocale()
}
#ifdef __WIN32__
- ::SetThreadLocale(m_oldLCID);
- wxMSWSetThreadUILanguage(LANGIDFROMLCID(m_oldLCID));
+ wxUseLCID(m_oldLCID);
#endif
}
@@ -1145,6 +993,13 @@ bool wxLocale::IsAvailable(int lang)
if ( !::IsValidLocale(info->GetLCID(), LCID_INSTALLED) )
return false;
+#elif defined(__WXOSX__)
+ CFLocaleRef
+ cfloc = CFLocaleCreate(kCFAllocatorDefault, wxCFStringRef(info->CanonicalName));
+ if ( !cfloc )
+ return false;
+
+ CFRelease(cfloc);
#elif defined(__UNIX__)
// Test if setting the locale works, then set it back.
@@ -1601,6 +1456,10 @@ wxString wxTranslateFromUnicodeFormat(const wxString& fmt)
#if defined(__WINDOWS__)
+// This function is also used by wxUILocaleImpl, so don't make it private.
+extern wxString
+wxGetInfoFromLCID(LCID lcid, wxLocaleInfo index, wxLocaleCategory cat);
+
namespace
{
@@ -1624,10 +1483,38 @@ LCTYPE GetLCTYPEFormatFromLocalInfo(wxLocaleInfo index)
return 0;
}
+// This private function additionally checks consistency of the decimal
+// separator settings between MSW and CRT.
wxString
-GetInfoFromLCID(LCID lcid,
- wxLocaleInfo index,
- wxLocaleCategory cat = wxLOCALE_CAT_DEFAULT)
+GetInfoFromLCID(LCID lcid, wxLocaleInfo index, wxLocaleCategory cat)
+{
+ const wxString str = wxGetInfoFromLCID(lcid, index, cat);
+
+ if ( !str.empty() && index == wxLOCALE_DECIMAL_POINT )
+ {
+ // As we get our decimal point separator from Win32 and not the
+ // CRT there is a possibility of mismatch between them and this
+ // can easily happen if the user code called setlocale()
+ // instead of using wxLocale to change the locale. And this can
+ // result in very strange bugs elsewhere in the code as the
+ // assumptions that formatted strings do use the decimal
+ // separator actually fail, so check for it here.
+ wxASSERT_MSG
+ (
+ wxString::Format("%.3f", 1.23).find(str) != wxString::npos,
+ "Decimal separator mismatch -- did you use setlocale()?"
+ "If so, use wxLocale to change the locale instead."
+ );
+ }
+
+ return str;
+}
+
+} // anonymous namespace
+
+// This function is also used by wxUILocaleImpl, so don't make it private.
+wxString
+wxGetInfoFromLCID(LCID lcid, wxLocaleInfo index, wxLocaleCategory cat)
{
wxString str;
@@ -1650,20 +1537,6 @@ GetInfoFromLCID(LCID lcid,
WXSIZEOF(buf)) )
{
str = buf;
-
- // As we get our decimal point separator from Win32 and not the
- // CRT there is a possibility of mismatch between them and this
- // can easily happen if the user code called setlocale()
- // instead of using wxLocale to change the locale. And this can
- // result in very strange bugs elsewhere in the code as the
- // assumptions that formatted strings do use the decimal
- // separator actually fail, so check for it here.
- wxASSERT_MSG
- (
- wxString::Format("%.3f", 1.23).find(str) != wxString::npos,
- "Decimal separator mismatch -- did you use setlocale()?"
- "If so, use wxLocale to change the locale instead."
- );
}
break;
@@ -1686,12 +1559,12 @@ GetInfoFromLCID(LCID lcid,
// alternate representation here)
{
const wxString
- datefmt = GetInfoFromLCID(lcid, wxLOCALE_SHORT_DATE_FMT);
+ datefmt = wxGetInfoFromLCID(lcid, wxLOCALE_SHORT_DATE_FMT, cat);
if ( datefmt.empty() )
break;
const wxString
- timefmt = GetInfoFromLCID(lcid, wxLOCALE_TIME_FMT);
+ timefmt = wxGetInfoFromLCID(lcid, wxLOCALE_TIME_FMT, cat);
if ( timefmt.empty() )
break;
@@ -1706,8 +1579,6 @@ GetInfoFromLCID(LCID lcid,
return str;
}
-} // anonymous namespace
-
/* static */
wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory cat)
{
@@ -1766,34 +1637,19 @@ wxString wxLocale::GetOSInfo(wxLocaleInfo index, wxLocaleCategory cat)
#elif defined(__WXOSX__)
-/* static */
-wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory WXUNUSED(cat))
+// This function is also used by wxUILocaleImpl, so don't make it private.
+extern wxString
+wxGetInfoFromCFLocale(CFLocaleRef cfloc, wxLocaleInfo index, wxLocaleCategory WXUNUSED(cat))
{
- CFLocaleRef userLocaleRefRaw;
- if ( wxGetLocale() )
- {
- userLocaleRefRaw = CFLocaleCreate
- (
- kCFAllocatorDefault,
- wxCFStringRef(wxGetLocale()->GetCanonicalName())
- );
- }
- else // no current locale, use the default one
- {
- userLocaleRefRaw = CFLocaleCopyCurrent();
- }
-
- wxCFRef userLocaleRef(userLocaleRefRaw);
-
CFStringRef cfstr = 0;
switch ( index )
{
case wxLOCALE_THOUSANDS_SEP:
- cfstr = (CFStringRef) CFLocaleGetValue(userLocaleRef, kCFLocaleGroupingSeparator);
+ cfstr = (CFStringRef) CFLocaleGetValue(cfloc, kCFLocaleGroupingSeparator);
break;
case wxLOCALE_DECIMAL_POINT:
- cfstr = (CFStringRef) CFLocaleGetValue(userLocaleRef, kCFLocaleDecimalSeparator);
+ cfstr = (CFStringRef) CFLocaleGetValue(cfloc, kCFLocaleDecimalSeparator);
break;
case wxLOCALE_SHORT_DATE_FMT:
@@ -1823,7 +1679,7 @@ wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory WXUNUSED(cat))
return wxString();
}
wxCFRef dateFormatter( CFDateFormatterCreate
- (NULL, userLocaleRef, dateStyle, timeStyle));
+ (NULL, cfloc, dateStyle, timeStyle));
wxCFStringRef cfs = wxCFRetain( CFDateFormatterGetFormat(dateFormatter ));
wxString format = wxTranslateFromUnicodeFormat(cfs.AsString());
// we always want full years
@@ -1840,6 +1696,28 @@ wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory WXUNUSED(cat))
return str.AsString();
}
+/* static */
+wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory cat)
+{
+ CFLocaleRef userLocaleRefRaw;
+ if ( wxGetLocale() )
+ {
+ userLocaleRefRaw = CFLocaleCreate
+ (
+ kCFAllocatorDefault,
+ wxCFStringRef(wxGetLocale()->GetCanonicalName())
+ );
+ }
+ else // no current locale, use the default one
+ {
+ userLocaleRefRaw = CFLocaleCopyCurrent();
+ }
+
+ wxCFRef userLocaleRef(userLocaleRefRaw);
+
+ return wxGetInfoFromCFLocale(userLocaleRef, index, cat);
+}
+
#else // !__WINDOWS__ && !__WXOSX__, assume generic POSIX
namespace
@@ -1935,22 +1813,34 @@ wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory cat)
switch ( index )
{
case wxLOCALE_THOUSANDS_SEP:
- if ( cat == wxLOCALE_CAT_NUMBER )
- return lc->thousands_sep;
- else if ( cat == wxLOCALE_CAT_MONEY )
- return lc->mon_thousands_sep;
+ switch ( cat )
+ {
+ case wxLOCALE_CAT_DEFAULT:
+ case wxLOCALE_CAT_NUMBER:
+ return lc->thousands_sep;
- wxFAIL_MSG( "invalid wxLocaleCategory" );
+ case wxLOCALE_CAT_MONEY:
+ return lc->mon_thousands_sep;
+
+ default:
+ wxFAIL_MSG( "invalid wxLocaleCategory" );
+ }
break;
case wxLOCALE_DECIMAL_POINT:
- if ( cat == wxLOCALE_CAT_NUMBER )
- return lc->decimal_point;
- else if ( cat == wxLOCALE_CAT_MONEY )
- return lc->mon_decimal_point;
+ switch ( cat )
+ {
+ case wxLOCALE_CAT_DEFAULT:
+ case wxLOCALE_CAT_NUMBER:
+ return lc->decimal_point;
- wxFAIL_MSG( "invalid wxLocaleCategory" );
+ case wxLOCALE_CAT_MONEY:
+ return lc->mon_decimal_point;
+
+ default:
+ wxFAIL_MSG( "invalid wxLocaleCategory" );
+ }
break;
case wxLOCALE_SHORT_DATE_FMT:
diff --git a/src/common/numformatter.cpp b/src/common/numformatter.cpp
index e57ab02335..c59ea520db 100644
--- a/src/common/numformatter.cpp
+++ b/src/common/numformatter.cpp
@@ -16,84 +16,7 @@
#include "wx/numformatter.h"
-#include "wx/intl.h"
-
-#include // for setlocale and LC_ALL
-
-// ----------------------------------------------------------------------------
-// local helpers
-// ----------------------------------------------------------------------------
-
-namespace
-{
-
-// Contains information about the locale which was used to initialize our
-// cached values of the decimal and thousands separators. Notice that it isn't
-// enough to store just wxLocale because the user code may call setlocale()
-// directly and storing just C locale string is not enough because we can use
-// the OS API directly instead of the CRT ones on some platforms. So just store
-// both.
-class LocaleId
-{
-public:
- LocaleId()
- {
-#if wxUSE_INTL
- m_wxloc = NULL;
-#endif // wxUSE_INTL
- m_cloc = NULL;
- }
-
- ~LocaleId()
- {
- Free();
- }
-
-#if wxUSE_INTL
- // Return true if this is the first time this function is called for this
- // object or if the program locale has changed since the last time it was
- // called. Otherwise just return false indicating that updating locale-
- // dependent information is not necessary.
- bool NotInitializedOrHasChanged()
- {
- wxLocale * const wxloc = wxGetLocale();
- const char * const cloc = setlocale(LC_ALL, NULL);
- if ( m_wxloc || m_cloc )
- {
- if ( m_wxloc == wxloc && strcmp(m_cloc, cloc) == 0 )
- return false;
-
- Free();
- }
- //else: Not initialized yet.
-
- m_wxloc = wxloc;
- m_cloc = wxCRT_StrdupA(cloc);
-
- return true;
- }
-#endif // wxUSE_INTL
-
-private:
- void Free()
- {
-#if wxUSE_INTL
- free(m_cloc);
-#endif // wxUSE_INTL
- }
-
-#if wxUSE_INTL
- // Non-owned pointer to wxLocale which was used.
- wxLocale *m_wxloc;
-#endif // wxUSE_INTL
-
- // Owned pointer to the C locale string.
- char *m_cloc;
-
- wxDECLARE_NO_COPY_CLASS(LocaleId);
-};
-
-} // anonymous namespace
+#include "wx/uilocale.h"
// ============================================================================
// wxNumberFormatter implementation
@@ -111,14 +34,10 @@ wxChar wxNumberFormatter::GetDecimalSeparator()
// concurrently from more than one thread so it's not a real problem.
static wxChar s_decimalSeparator = 0;
- // Remember the locale which was current when we initialized, we must redo
- // the initialization if the locale changed.
- static LocaleId s_localeUsedForInit;
-
- if ( s_localeUsedForInit.NotInitializedOrHasChanged() )
+ if ( !s_decimalSeparator )
{
const wxString
- s = wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER);
+ s = wxUILocale::GetCurrent().GetInfo(wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER);
if ( s.length() == 1 )
{
s_decimalSeparator = s[0];
@@ -141,12 +60,14 @@ bool wxNumberFormatter::GetThousandsSeparatorIfUsed(wxChar *sep)
{
#if wxUSE_INTL
static wxChar s_thousandsSeparator = 0;
- static LocaleId s_localeUsedForInit;
+ static bool s_thousandsSeparatorInitialized = false;
- if ( s_localeUsedForInit.NotInitializedOrHasChanged() )
+ if ( !s_thousandsSeparatorInitialized )
{
+ s_thousandsSeparatorInitialized = true;
+
const wxString
- s = wxLocale::GetInfo(wxLOCALE_THOUSANDS_SEP, wxLOCALE_CAT_NUMBER);
+ s = wxUILocale::GetCurrent().GetInfo(wxLOCALE_THOUSANDS_SEP, wxLOCALE_CAT_NUMBER);
if ( s.length() == 1 )
{
s_thousandsSeparator = s[0];
@@ -172,6 +93,21 @@ bool wxNumberFormatter::GetThousandsSeparatorIfUsed(wxChar *sep)
// Conversion to string and helpers
// ----------------------------------------------------------------------------
+namespace
+{
+
+void ReplaceSeparatorIfNecessary(wxString& s, wxChar sepOld, wxChar sepNew)
+{
+ if ( sepNew != sepOld )
+ {
+ const size_t posSep = s.find(sepOld);
+ if ( posSep != wxString::npos )
+ s[posSep] = sepNew;
+ }
+}
+
+} // anonymous namespace
+
wxString wxNumberFormatter::PostProcessIntString(wxString s, int style)
{
if ( style & Style_WithThousandsSep )
@@ -206,7 +142,9 @@ wxString wxNumberFormatter::ToString(wxULongLong_t val, int style)
wxString wxNumberFormatter::ToString(double val, int precision, int style)
{
- wxString s = wxString::FromDouble(val,precision);
+ wxString s = wxString::FromCDouble(val,precision);
+
+ ReplaceSeparatorIfNecessary(s, '.', GetDecimalSeparator());
if ( style & Style_WithThousandsSep )
AddThousandsSeparators(s);
@@ -217,6 +155,23 @@ wxString wxNumberFormatter::ToString(double val, int precision, int style)
return s;
}
+wxString wxNumberFormatter::Format(const wxString& format, double val)
+{
+ wxString s = wxString::Format(format, val);
+
+ const wxChar sep = GetDecimalSeparator();
+ if ( s.find(sep) == wxString::npos )
+ {
+ const wxChar other = sep == '.' ? ',' : '.';
+ const size_t posSep = s.find(other);
+ if ( posSep != wxString::npos )
+ s[posSep] = sep;
+ }
+ //else: it already uses the correct separator
+
+ return s;
+}
+
void wxNumberFormatter::AddThousandsSeparators(wxString& s)
{
// Thousands separators for numbers in scientific format are not relevant.
@@ -330,5 +285,6 @@ bool wxNumberFormatter::FromString(wxString s, wxULongLong_t *val)
bool wxNumberFormatter::FromString(wxString s, double *val)
{
RemoveThousandsSeparators(s);
- return s.ToDouble(val);
+ ReplaceSeparatorIfNecessary(s, GetDecimalSeparator(), '.');
+ return s.ToCDouble(val);
}
diff --git a/src/common/uilocale.cpp b/src/common/uilocale.cpp
new file mode 100644
index 0000000000..4843f823e5
--- /dev/null
+++ b/src/common/uilocale.cpp
@@ -0,0 +1,102 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name: src/common/uilocale.cpp
+// Purpose: wxUILocale implementation
+// Author: Vadim Zeitlin
+// Created: 2021-07-31
+// Copyright: (c) 2021 Vadim Zeitlin
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+// for compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#if wxUSE_INTL
+
+#include "wx/uilocale.h"
+
+#include "wx/private/uilocale.h"
+
+// ----------------------------------------------------------------------------
+// global variables
+// ----------------------------------------------------------------------------
+
+// This static global variable doesn't need to be protected from concurrent
+// access as it's only supposed to be used from the UI thread.
+/* static */
+wxUILocale wxUILocale::ms_current;
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+/* static */
+bool wxUILocale::UseDefault()
+{
+ // We don't attempt to optimize this function by checking whether
+ // ms_current is already set to the user default locale, as we're
+ // supposed to be called just once during the program lifetime anyhow.
+
+ wxUILocaleImpl* const impl = wxUILocaleImpl::CreateUserDefault();
+ if ( !impl )
+ return false;
+
+ ms_current.SetImpl(impl);
+
+ return true;
+}
+
+/* static */
+bool wxUILocale::UseLanguage(const wxLanguageInfo& info)
+{
+ wxUILocaleImpl* const impl = wxUILocaleImpl::CreateForLanguage(info);
+ if ( !impl )
+ return false;
+
+ ms_current.SetImpl(impl);
+
+ return true;
+}
+
+/* static */
+const wxUILocale& wxUILocale::GetCurrent()
+{
+ // We initialize it on demand.
+ if ( !ms_current.m_impl )
+ {
+ ms_current.SetImpl(wxUILocaleImpl::CreateStdC());
+ }
+
+ return ms_current;
+}
+
+void wxUILocale::SetImpl(wxUILocaleImpl* impl)
+{
+ delete m_impl;
+
+ m_impl = impl;
+}
+
+wxString wxUILocale::GetName() const
+{
+ return m_impl->GetName();
+}
+
+wxString wxUILocale::GetInfo(wxLocaleInfo index, wxLocaleCategory cat) const
+{
+ return m_impl->GetInfo(index, cat);
+}
+
+wxUILocale::~wxUILocale()
+{
+ delete m_impl;
+}
+
+#endif // wxUSE_INTL
diff --git a/src/generic/gridctrl.cpp b/src/generic/gridctrl.cpp
index 8ba3582b2c..4c526f81b5 100644
--- a/src/generic/gridctrl.cpp
+++ b/src/generic/gridctrl.cpp
@@ -25,8 +25,10 @@
#include "wx/checkbox.h"
#endif // WX_PRECOMP
+#include "wx/numformatter.h"
#include "wx/tokenzr.h"
#include "wx/renderer.h"
+#include "wx/uilocale.h"
#include "wx/generic/private/grid.h"
#include "wx/private/window.h"
@@ -159,7 +161,7 @@ wxGridCellDateRenderer::wxGridCellDateRenderer(const wxString& outformat)
{
if ( outformat.empty() )
{
- m_oformat = "%x"; // Localized date representation.
+ m_oformat = wxGetUIDateFormat();
}
else
{
@@ -839,7 +841,7 @@ wxString wxGridCellFloatRenderer::GetString(const wxGrid& grid, int row, int col
else
{
text = table->GetValue(row, col);
- hasDouble = text.ToDouble(&val);
+ hasDouble = wxNumberFormatter::FromString(text, &val);
}
if ( hasDouble )
@@ -877,8 +879,7 @@ wxString wxGridCellFloatRenderer::GetString(const wxGrid& grid, int row, int col
m_format += wxT('f');
}
- text.Printf(m_format, val);
-
+ text = wxNumberFormatter::Format(m_format, val);
}
//else: text already contains the string
diff --git a/src/generic/grideditors.cpp b/src/generic/grideditors.cpp
index 6cdce725eb..96832ee9de 100644
--- a/src/generic/grideditors.cpp
+++ b/src/generic/grideditors.cpp
@@ -29,12 +29,14 @@
#include "wx/listbox.h"
#endif
+#include "wx/numformatter.h"
#include "wx/valnum.h"
#include "wx/textfile.h"
#include "wx/spinctrl.h"
#include "wx/tokenzr.h"
#include "wx/renderer.h"
#include "wx/datectrl.h"
+#include "wx/uilocale.h"
#include "wx/generic/gridsel.h"
#include "wx/generic/grideditors.h"
@@ -997,7 +999,7 @@ void wxGridCellFloatEditor::BeginEdit(int row, int col, wxGrid* grid)
const wxString value = table->GetValue(row, col);
if ( !value.empty() )
{
- if ( !value.ToDouble(&m_value) )
+ if ( !wxNumberFormatter::FromString(value, &m_value) )
{
wxFAIL_MSG( wxT("this cell doesn't have float value") );
return;
@@ -1018,7 +1020,7 @@ bool wxGridCellFloatEditor::EndEdit(int WXUNUSED(row),
double value;
if ( !text.empty() )
{
- if ( !text.ToDouble(&value) )
+ if ( !wxNumberFormatter::FromString(text, &value) )
return false;
}
else // new value is empty string
@@ -1060,20 +1062,9 @@ void wxGridCellFloatEditor::Reset()
void wxGridCellFloatEditor::StartingKey(wxKeyEvent& event)
{
int keycode = event.GetKeyCode();
- char tmpbuf[2];
- tmpbuf[0] = (char) keycode;
- tmpbuf[1] = '\0';
- wxString strbuf(tmpbuf, *wxConvCurrent);
-
-#if wxUSE_INTL
- bool is_decimal_point = ( strbuf ==
- wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER) );
-#else
- bool is_decimal_point = ( strbuf == wxT(".") );
-#endif
if ( wxIsdigit(keycode) || keycode == '+' || keycode == '-'
- || is_decimal_point )
+ || keycode == wxNumberFormatter::GetDecimalSeparator() )
{
wxGridCellTextEditor::StartingKey(event);
@@ -1197,7 +1188,7 @@ wxString wxGridCellFloatEditor::GetString()
m_format += wxT('f');
}
- return wxString::Format(m_format, m_value);
+ return wxNumberFormatter::Format(m_format, m_value);
}
bool wxGridCellFloatEditor::IsAcceptedKey(wxKeyEvent& event)
@@ -1207,17 +1198,10 @@ bool wxGridCellFloatEditor::IsAcceptedKey(wxKeyEvent& event)
const int keycode = event.GetKeyCode();
if ( wxIsascii(keycode) )
{
-#if wxUSE_INTL
- const wxString decimalPoint =
- wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER);
-#else
- const wxString decimalPoint(wxT('.'));
-#endif
-
// accept digits, 'e' as in '1e+6', also '-', '+', and '.'
if ( wxIsdigit(keycode) ||
tolower(keycode) == 'e' ||
- keycode == decimalPoint ||
+ keycode == wxNumberFormatter::GetDecimalSeparator() ||
keycode == '+' ||
keycode == '-' )
{
@@ -1869,7 +1853,7 @@ wxGridCellDateEditor::wxGridCellDateEditor(const wxString& format)
void wxGridCellDateEditor::SetParameters(const wxString& params)
{
if ( params.empty() )
- m_format = "%x";
+ m_format = wxGetUIDateFormat();
else
m_format = params;
}
diff --git a/src/generic/spinctlg.cpp b/src/generic/spinctlg.cpp
index 7e87d1937a..0dc60a9102 100644
--- a/src/generic/spinctlg.cpp
+++ b/src/generic/spinctlg.cpp
@@ -41,6 +41,7 @@ wxIMPLEMENT_DYNAMIC_CLASS(wxSpinDoubleEvent, wxNotifyEvent);
#if wxUSE_SPINBTN
+#include "wx/numformatter.h"
#include "wx/valnum.h"
#include "wx/valtext.h"
@@ -764,12 +765,12 @@ void wxSpinCtrlDouble::DoSendEvent()
bool wxSpinCtrlDouble::DoTextToValue(const wxString& text, double *val)
{
- return text.ToDouble(val);
+ return wxNumberFormatter::FromString(text, val);
}
wxString wxSpinCtrlDouble::DoValueToText(double val)
{
- return wxString::Format(m_format, val);
+ return wxNumberFormatter::ToString(val, m_digits);
}
void wxSpinCtrlDouble::SetIncrement(double inc)
@@ -812,8 +813,6 @@ void wxSpinCtrlDouble::DoSetDigitsAndUpdate(unsigned digits)
void wxSpinCtrlDouble::DoSetDigits(unsigned digits)
{
m_digits = digits;
-
- m_format.Printf(wxT("%%0.%ulf"), digits);
}
void wxSpinCtrlDouble::ResetTextValidator()
diff --git a/src/msw/uilocale.cpp b/src/msw/uilocale.cpp
new file mode 100644
index 0000000000..6916fefe52
--- /dev/null
+++ b/src/msw/uilocale.cpp
@@ -0,0 +1,141 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name: src/msw/uilocale.cpp
+// Purpose: wxUILocale implementation for MSW
+// Author: Vadim Zeitlin
+// Created: 2021-07-31
+// Copyright: (c) 2021 Vadim Zeitlin
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+// for compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#if wxUSE_INTL
+
+#include "wx/private/uilocale.h"
+
+#include "wx/msw/private/uilocale.h"
+
+#include "wx/dynlib.h"
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// helper functions
+// ----------------------------------------------------------------------------
+
+namespace
+{
+
+// Trivial wrapper for ::SetThreadUILanguage().
+//
+// TODO-XP: Drop this when we don't support XP any longer.
+static void wxMSWSetThreadUILanguage(LANGID langid)
+{
+ // SetThreadUILanguage() is available on XP, but with unclear
+ // behavior, so avoid calling it there.
+ if ( wxGetWinVersion() >= wxWinVersion_Vista )
+ {
+ wxLoadedDLL dllKernel32(wxS("kernel32.dll"));
+ typedef LANGID(WINAPI *SetThreadUILanguage_t)(LANGID);
+ SetThreadUILanguage_t pfnSetThreadUILanguage = NULL;
+ wxDL_INIT_FUNC(pfn, SetThreadUILanguage, dllKernel32);
+ if (pfnSetThreadUILanguage)
+ pfnSetThreadUILanguage(langid);
+ }
+}
+
+} // anonymous namespace
+
+void wxUseLCID(LCID lcid)
+{
+ ::SetThreadLocale(lcid);
+
+ wxMSWSetThreadUILanguage(LANGIDFROMLCID(lcid));
+}
+
+// ----------------------------------------------------------------------------
+// wxUILocale implementation for MSW
+// ----------------------------------------------------------------------------
+
+// TODO-XP: Replace this with an implementation using GetLocaleInfoEx() when we
+// don't support XP any longer.
+class wxUILocaleImplLCID : public wxUILocaleImpl
+{
+public:
+ explicit wxUILocaleImplLCID(LCID lcid)
+ : m_lcid(lcid)
+ {
+ wxUseLCID(lcid);
+ }
+
+ wxString GetName() const wxOVERRIDE
+ {
+ wxChar buf[256];
+ buf[0] = wxT('\0');
+
+ // Try using newer constant available since Vista which produces names
+ // more similar to the other platforms.
+ if ( wxGetWinVersion() >= wxWinVersion_Vista )
+ {
+ ::GetLocaleInfo(m_lcid, LOCALE_SNAME, buf, WXSIZEOF(buf));
+ }
+ else // TODO-XP: Drop this branch.
+ {
+ // This name constant is available under all systems, including
+ // pre-Vista ones.
+ ::GetLocaleInfo(m_lcid, LOCALE_SENGLANGUAGE, buf, WXSIZEOF(buf));
+ }
+
+ return buf;
+ }
+
+ wxString GetInfo(wxLocaleInfo index, wxLocaleCategory cat) const wxOVERRIDE
+ {
+ return wxGetInfoFromLCID(m_lcid, index, cat);
+ }
+
+private:
+ const LCID m_lcid;
+
+ wxDECLARE_NO_COPY_CLASS(wxUILocaleImplLCID);
+};
+
+/* static */
+wxUILocaleImpl* wxUILocaleImpl::CreateStdC()
+{
+ // There is no LCID for "C" locale, but US English is basically the same.
+ LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
+ return new wxUILocaleImplLCID(lcid);
+}
+
+/* static */
+wxUILocaleImpl* wxUILocaleImpl::CreateUserDefault()
+{
+ return new wxUILocaleImplLCID(LOCALE_USER_DEFAULT);
+}
+
+/* static */
+wxUILocaleImpl* wxUILocaleImpl::CreateForLanguage(const wxLanguageInfo& info)
+{
+ if ( info.WinLang == 0 )
+ {
+ wxLogWarning(wxS("Locale '%s' not supported by OS."), info.Description);
+
+ return NULL;
+ }
+
+ return new wxUILocaleImplLCID(info.GetLCID());
+}
+
+#endif // wxUSE_INTL
diff --git a/src/osx/core/uilocale.cpp b/src/osx/core/uilocale.cpp
new file mode 100644
index 0000000000..96a0058f5a
--- /dev/null
+++ b/src/osx/core/uilocale.cpp
@@ -0,0 +1,103 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name: src/osx/core/uilocale.cpp
+// Purpose: wxUILocale implementation for macOS
+// Author: Vadim Zeitlin
+// Created: 2021-08-01
+// Copyright: (c) 2021 Vadim Zeitlin
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+// for compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#if wxUSE_INTL
+
+#include "wx/private/uilocale.h"
+
+#include "wx/osx/core/cfref.h"
+#include "wx/osx/core/cfstring.h"
+
+#include
+#include
+
+extern wxString
+wxGetInfoFromCFLocale(CFLocaleRef cfloc, wxLocaleInfo index, wxLocaleCategory cat);
+
+namespace
+{
+
+// ----------------------------------------------------------------------------
+// wxUILocale implementation using Core Foundation
+// ----------------------------------------------------------------------------
+
+class wxUILocaleImplCF : public wxUILocaleImpl
+{
+public:
+ explicit wxUILocaleImplCF(const wxCFRef& cfloc)
+ : m_cfloc(cfloc)
+ {
+ }
+
+ static wxUILocaleImplCF* Create(const wxString& name)
+ {
+ CFLocaleRef cfloc = CFLocaleCreate(kCFAllocatorDefault, wxCFStringRef(name));
+ if ( !cfloc )
+ return NULL;
+
+ return new wxUILocaleImplCF(cfloc);
+ }
+
+ wxString GetName() const wxOVERRIDE;
+ wxString GetInfo(wxLocaleInfo index, wxLocaleCategory cat) const wxOVERRIDE;
+
+private:
+ wxCFRef m_cfloc;
+
+ wxDECLARE_NO_COPY_CLASS(wxUILocaleImplCF);
+};
+
+} // anonymous namespace
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+wxString
+wxUILocaleImplCF::GetName() const
+{
+ return wxCFStringRef::AsString(CFLocaleGetIdentifier(m_cfloc));
+}
+
+wxString
+wxUILocaleImplCF::GetInfo(wxLocaleInfo index, wxLocaleCategory cat) const
+{
+ return wxGetInfoFromCFLocale(m_cfloc, index, cat);
+}
+
+/* static */
+wxUILocaleImpl* wxUILocaleImpl::CreateStdC()
+{
+ return wxUILocaleImplCF::Create("C");
+}
+
+/* static */
+wxUILocaleImpl* wxUILocaleImpl::CreateUserDefault()
+{
+ return new wxUILocaleImplCF(CFLocaleCopyCurrent());
+}
+
+/* static */
+wxUILocaleImpl* wxUILocaleImpl::CreateForLanguage(const wxLanguageInfo& info)
+{
+ return wxUILocaleImplCF::Create(info.CanonicalName);
+}
+
+#endif // wxUSE_INTL
diff --git a/src/unix/uilocale.cpp b/src/unix/uilocale.cpp
new file mode 100644
index 0000000000..f4b86fa0a0
--- /dev/null
+++ b/src/unix/uilocale.cpp
@@ -0,0 +1,186 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name: src/unix/uilocale.cpp
+// Purpose: wxUILocale implementation for Unix systems
+// Author: Vadim Zeitlin
+// Created: 2021-08-01
+// Copyright: (c) 2021 Vadim Zeitlin
+// Licence: wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+// for compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#if wxUSE_INTL
+
+#include "wx/private/uilocale.h"
+
+#include "wx/unix/private/uilocale.h"
+
+#include "wx/intl.h"
+
+#include
+
+namespace
+{
+
+// ----------------------------------------------------------------------------
+// wxUILocale implementation using standard Unix/C functions
+// ----------------------------------------------------------------------------
+
+class wxUILocaleImplUnix : public wxUILocaleImpl
+{
+public:
+ // Locale argument may be NULL to not change it at all.
+ explicit wxUILocaleImplUnix(const char* locale);
+
+ wxString GetName() const wxOVERRIDE;
+ wxString GetInfo(wxLocaleInfo index, wxLocaleCategory cat) const wxOVERRIDE;
+
+private:
+ wxDECLARE_NO_COPY_CLASS(wxUILocaleImplUnix);
+};
+
+} // anonymous namespace
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// Helper of wxSetlocaleTryAll() below which tries setting the given locale
+// with and without UTF-8 suffix. Don't use this one directly.
+static const char *wxSetlocaleTryUTF8(int c, const wxString& lc)
+{
+ const char *l = NULL;
+
+ // NB: We prefer to set UTF-8 locale if it's possible and only fall back to
+ // non-UTF-8 locale if it fails, but this is not necessary under the
+ // supported macOS versions where xx_YY locales are just aliases to
+ // xx_YY.UTF-8 anyhow.
+#if wxUSE_UNICODE && !defined(__WXMAC__)
+ if ( !lc.empty() )
+ {
+ wxString buf(lc);
+ wxString buf2;
+ buf2 = buf + wxS(".UTF-8");
+ l = wxSetlocale(c, buf2);
+ if ( !l )
+ {
+ buf2 = buf + wxS(".utf-8");
+ l = wxSetlocale(c, buf2);
+ }
+ if ( !l )
+ {
+ buf2 = buf + wxS(".UTF8");
+ l = wxSetlocale(c, buf2);
+ }
+ if ( !l )
+ {
+ buf2 = buf + wxS(".utf8");
+ l = wxSetlocale(c, buf2);
+ }
+ }
+
+ // if we can't set UTF-8 locale, try non-UTF-8 one:
+ if ( !l )
+#endif // wxUSE_UNICODE && !__WXMAC__
+ l = wxSetlocale(c, lc);
+
+ return l;
+}
+
+// Try setting all possible versions of the given locale, i.e. with and without
+// UTF-8 encoding, and with or without the "_territory" part.
+const char *wxSetlocaleTryAll(int c, const wxString& lc)
+{
+ const char* l = wxSetlocaleTryUTF8(c, lc);
+ if ( !l )
+ {
+ const wxString& lcOnlyLang = ExtractLang(lc);
+ if ( lcOnlyLang != lc )
+ l = wxSetlocaleTryUTF8(c, lcOnlyLang);
+ }
+
+ return l;
+}
+
+// ----------------------------------------------------------------------------
+// wxUILocale implementation for Unix
+// ----------------------------------------------------------------------------
+
+wxUILocaleImplUnix::wxUILocaleImplUnix(const char* locale)
+{
+ if ( locale )
+ setlocale(LC_ALL, locale);
+}
+
+wxString
+wxUILocaleImplUnix::GetName() const
+{
+ return wxString::FromAscii(setlocale(LC_ALL, NULL));
+}
+
+wxString
+wxUILocaleImplUnix::GetInfo(wxLocaleInfo index, wxLocaleCategory cat) const
+{
+ // Currently we rely on the user code not calling setlocale() itself, so
+ // that the current locale is still the same as was set in the ctor.
+ //
+ // If this assumption turns out to be wrong, we could use wxLocaleSetter to
+ // temporarily change the locale here (maybe only if setlocale(NULL) result
+ // differs from the expected one).
+ return wxLocale::GetInfo(index, cat);
+}
+
+/* static */
+wxUILocaleImpl* wxUILocaleImpl::CreateStdC()
+{
+ return new wxUILocaleImplUnix(NULL);
+}
+
+/* static */
+wxUILocaleImpl* wxUILocaleImpl::CreateUserDefault()
+{
+ return new wxUILocaleImplUnix("");
+}
+
+/* static */
+wxUILocaleImpl* wxUILocaleImpl::CreateForLanguage(const wxLanguageInfo& info)
+{
+ // Set the locale before creating the wxUILocaleImplUnix object in order to
+ // check if we succeed in doing it.
+
+ const wxString& shortName = info.CanonicalName;
+
+ if ( !wxSetlocaleTryAll(LC_ALL, shortName) )
+ {
+ // Some C libraries (namely glibc) still use old ISO 639,
+ // so will translate the abbrev for them
+ wxString localeAlt;
+ const wxString& langOnly = ExtractLang(shortName);
+ if ( langOnly == wxS("he") )
+ localeAlt = wxS("iw") + ExtractNotLang(shortName);
+ else if ( langOnly == wxS("id") )
+ localeAlt = wxS("in") + ExtractNotLang(shortName);
+ else if ( langOnly == wxS("yi") )
+ localeAlt = wxS("ji") + ExtractNotLang(shortName);
+ else if ( langOnly == wxS("nb") )
+ localeAlt = wxS("no_NO");
+ else if ( langOnly == wxS("nn") )
+ localeAlt = wxS("no_NY");
+
+ if ( localeAlt.empty() || !wxSetlocaleTryAll(LC_ALL, localeAlt) )
+ return NULL;
+ }
+
+ return new wxUILocaleImplUnix(NULL);
+}
+
+#endif // wxUSE_INTL
diff --git a/tests/controls/textctrltest.cpp b/tests/controls/textctrltest.cpp
index 5bf21bff22..a5283f3fce 100644
--- a/tests/controls/textctrltest.cpp
+++ b/tests/controls/textctrltest.cpp
@@ -33,6 +33,8 @@
#include "wx/stopwatch.h"
#endif
+#include "wx/private/localeset.h"
+
#include "textentrytest.h"
#include "testableframe.h"
#include "asserthelper.h"
@@ -295,7 +297,7 @@ void TextCtrlTestCase::StreamInput()
#ifndef __WXOSX__
{
// Ensure we use decimal point and not a comma.
- LocaleSetter setCLocale("C");
+ wxCLocaleSetter setCLocale;
*m_text << "stringinput"
<< 10
diff --git a/tests/datetime/datetimetest.cpp b/tests/datetime/datetimetest.cpp
index 8ecf70f2c6..0a03babc54 100644
--- a/tests/datetime/datetimetest.cpp
+++ b/tests/datetime/datetimetest.cpp
@@ -22,6 +22,8 @@
#include "wx/wxcrt.h" // for wxStrstr()
+#include "wx/private/localeset.h"
+
// to test Today() meaningfully we must be able to change the system date which
// is not usually the case, but if we're under Win32 we can try it -- define
// the macro below to do it
@@ -1304,7 +1306,7 @@ void DateTimeTestCase::TestDateTimeParse()
// the test strings here use "PM" which is not available in all locales so
// we need to use "C" locale for them
- CLocaleSetter cloc;
+ wxCLocaleSetter cloc;
wxDateTime dt;
for ( size_t n = 0; n < WXSIZEOF(parseTestDates); n++ )
diff --git a/tests/filename/filenametest.cpp b/tests/filename/filenametest.cpp
index a650deff7e..3134bbe53d 100644
--- a/tests/filename/filenametest.cpp
+++ b/tests/filename/filenametest.cpp
@@ -22,6 +22,8 @@
#include "wx/stdpaths.h"
#include "wx/scopeguard.h"
+#include "wx/private/localeset.h"
+
#ifdef __WINDOWS__
#include "wx/msw/registry.h"
#include "wx/msw/wrapshl.h"
@@ -493,7 +495,7 @@ TEST_CASE("wxFileName::GetHumanReadable", "[filename]")
{ "304 KB", 304351, 0, wxSIZE_CONV_SI },
};
- CLocaleSetter loc; // we want to use "C" locale for LC_NUMERIC
+ wxCLocaleSetter loc; // we want to use "C" locale for LC_NUMERIC
// so that regardless of the system's locale
// the decimal point used by GetHumanReadableSize()
// is always '.'
diff --git a/tests/intl/intltest.cpp b/tests/intl/intltest.cpp
index c19628b4c0..d6db0c8a56 100644
--- a/tests/intl/intltest.cpp
+++ b/tests/intl/intltest.cpp
@@ -18,6 +18,7 @@
#endif // WX_PRECOMP
#include "wx/intl.h"
+#include "wx/uilocale.h"
#if wxUSE_INTL
@@ -239,4 +240,17 @@ TEST_CASE("wxLocale::Default", "[locale]")
#endif // wxUSE_UNICODE
+// This test doesn't run by default as it only works in locales using decimal
+// point as separator, which doesn't need to be the case.
+TEST_CASE("wxUILocale::GetInfo", "[.][uilocale]")
+{
+ REQUIRE( wxUILocale::UseDefault() );
+
+ const wxUILocale& loc = wxUILocale::GetCurrent();
+
+ WARN( "Using locale " << loc.GetName() );
+
+ CHECK( loc.GetInfo(wxLOCALE_DECIMAL_POINT) == "." );
+}
+
#endif // wxUSE_INTL
diff --git a/tests/mbconv/mbconvtest.cpp b/tests/mbconv/mbconvtest.cpp
index 8306759fb0..53309c4b60 100644
--- a/tests/mbconv/mbconvtest.cpp
+++ b/tests/mbconv/mbconvtest.cpp
@@ -22,6 +22,8 @@
#include "wx/txtstrm.h"
#include "wx/mstream.h"
+#include "wx/private/localeset.h"
+
#if defined wxHAVE_TCHAR_SUPPORT && !defined HAVE_WCHAR_H
#define HAVE_WCHAR_H
#endif
@@ -1106,7 +1108,7 @@ void MBConvTestCase::LibcTests()
// supposed to use the same CRT -- no idea why and unfortunately gdb is too
// flaky to debug it)
#ifdef __VISUALC__
- LocaleSetter loc("English_United States.1252");
+ wxLocaleSetter loc("English_United States.1252");
wxMBConvLibc convLibc;
TestCoder(
diff --git a/tests/strings/vsnprintf.cpp b/tests/strings/vsnprintf.cpp
index 53f48c3e2e..f1fa10f99f 100644
--- a/tests/strings/vsnprintf.cpp
+++ b/tests/strings/vsnprintf.cpp
@@ -24,6 +24,7 @@
#include "wx/wxchar.h"
#endif // WX_PRECOMP
+#include "wx/private/localeset.h"
// NOTE: for more info about the specification of wxVsnprintf() behaviour you can
// refer to the following page of the GNU libc manual:
@@ -85,10 +86,10 @@ wxUnsafeSnprintf(T *buf, size_t len, const wxChar *fmt, ...)
// Explicitly set C locale to avoid check failures when running on machines
// with a locale where the decimal point is not '.'
-class VsnprintfTestCase : CLocaleSetter
+class VsnprintfTestCase : wxCLocaleSetter
{
public:
- VsnprintfTestCase() : CLocaleSetter() { }
+ VsnprintfTestCase() : wxCLocaleSetter() { }
protected:
template
diff --git a/tests/testprec.h b/tests/testprec.h
index 1dcaa0a289..ef38886526 100644
--- a/tests/testprec.h
+++ b/tests/testprec.h
@@ -148,38 +148,6 @@ extern bool IsAutomaticTest();
extern bool IsRunningUnderXVFB();
-// Helper class setting the locale to the given one for its lifetime.
-class LocaleSetter
-{
-public:
- LocaleSetter(const char *loc)
- : m_locOld(wxStrdupA(setlocale(LC_ALL, NULL)))
- {
- setlocale(LC_ALL, loc);
- }
-
- ~LocaleSetter()
- {
- setlocale(LC_ALL, m_locOld);
- free(m_locOld);
- }
-
-private:
- char * const m_locOld;
-
- wxDECLARE_NO_COPY_CLASS(LocaleSetter);
-};
-
-// An even simpler helper for setting the locale to "C" one during its lifetime.
-class CLocaleSetter : private LocaleSetter
-{
-public:
- CLocaleSetter() : LocaleSetter("C") { }
-
-private:
- wxDECLARE_NO_COPY_CLASS(CLocaleSetter);
-};
-
#if wxUSE_GUI
// Return true if the UI tests are enabled, used by WXUISIM_TEST().