Enhance wxUILocale and wxLocaleIdent
Many improvements and fixes to wxUILocale: - Add wxUILocale method for retrieving wxLocaleIdent identifier, localized names, layout direction. - Add wxLocaleIdent attributes, getter, and setter for platform-dependent tags under Windows: extension, sort order. - Modify method wxLocaleIdent::FromTag to support not only BCP 47-like tags, but also platform-dependent syntax. - Modify method wxLocaleIdent::GetTag to allow specifying the tag type. - Update internat sample to better show using wxUILocale. - Update German and French message catalogs for internat sample (German fully translated, French msgIds only). - Introduced wxUILocaleImplStdC under Windows, because locale "en-US" is not equivalent to the C locale. - Adjust wxLocale class to restore previous wxUILocale in the destructor. - Implement wxLocale::GetInfo method through wxUILocale methods. - Removed LCID dependency in wxLocale. - Move the implementation of some static wxUILocale methods from intl.cpp to uilocale.cpp. Co-authored-by: Vadim Zeitlin <vadim@wxwidgets.org> Closes #2615.
This commit is contained in:
@@ -270,6 +270,7 @@ private:
|
|||||||
m_strShort; // short name for the locale
|
m_strShort; // short name for the locale
|
||||||
int m_language; // this locale wxLanguage value
|
int m_language; // this locale wxLanguage value
|
||||||
|
|
||||||
|
wxString m_oldUILocale; // previous wxUILocale name
|
||||||
const char *m_pszOldLocale; // previous locale from setlocale()
|
const char *m_pszOldLocale; // previous locale from setlocale()
|
||||||
wxLocale *m_pOldLocale; // previous wxLocale
|
wxLocale *m_pOldLocale; // previous wxLocale
|
||||||
#ifdef __WIN32__
|
#ifdef __WIN32__
|
||||||
|
|||||||
@@ -32,6 +32,31 @@ enum wxLayoutDirection
|
|||||||
// wxLocaleCategory: the category of locale settings
|
// wxLocaleCategory: the category of locale settings
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
enum wxLocaleTagType
|
||||||
|
{
|
||||||
|
// Default (tag as given or else same as wxLOCALE_TAGTYPE_SYSTEM)
|
||||||
|
wxLOCALE_TAGTYPE_DEFAULT,
|
||||||
|
|
||||||
|
// Default type of the system (platform-dependent)
|
||||||
|
wxLOCALE_TAGTYPE_SYSTEM,
|
||||||
|
|
||||||
|
// BCP47-like type: <language>[-<script>][-<region>][-<modifier>]
|
||||||
|
wxLOCALE_TAGTYPE_BCP47,
|
||||||
|
|
||||||
|
// macOS type: <language>[-<script>][_<region>]
|
||||||
|
wxLOCALE_TAGTYPE_MACOS,
|
||||||
|
|
||||||
|
// POSIX type: <language>_<region>[.<charset>][@{<scriptalias>|<modifier>}]
|
||||||
|
wxLOCALE_TAGTYPE_POSIX,
|
||||||
|
|
||||||
|
// Windows type: <language>[-<script>][-<region>][-<extension>][_<sortorder>]
|
||||||
|
wxLOCALE_TAGTYPE_WINDOWS
|
||||||
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxLocaleCategory: the category of locale settings
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
enum wxLocaleCategory
|
enum wxLocaleCategory
|
||||||
{
|
{
|
||||||
// (any) numbers
|
// (any) numbers
|
||||||
@@ -74,6 +99,27 @@ enum wxLocaleInfo
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxLocaleName: the items understood by wxLocale::GetLocalizedName()
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
enum wxLocaleName
|
||||||
|
{
|
||||||
|
wxLOCALE_NAME_LOCALE,
|
||||||
|
wxLOCALE_NAME_LANGUAGE,
|
||||||
|
wxLOCALE_NAME_COUNTRY
|
||||||
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxLocaleForm: the forms of names understood by wxLocale::GetLocalizedName()
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
enum wxLocaleForm
|
||||||
|
{
|
||||||
|
wxLOCALE_FORM_NATIVE,
|
||||||
|
wxLOCALE_FORM_ENGLISH
|
||||||
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxLanguageInfo: encapsulates wxLanguage to OS native lang.desc.
|
// wxLanguageInfo: encapsulates wxLanguage to OS native lang.desc.
|
||||||
// translation information
|
// translation information
|
||||||
|
|||||||
@@ -63,6 +63,11 @@ public:
|
|||||||
// work, so it just falls back on CreateStdC() if it fails to create it.
|
// work, so it just falls back on CreateStdC() if it fails to create it.
|
||||||
static wxUILocaleImpl* CreateForLanguage(const wxLanguageInfo& info);
|
static wxUILocaleImpl* CreateForLanguage(const wxLanguageInfo& info);
|
||||||
|
|
||||||
|
// This function retrieves a list of preferred UI languages.
|
||||||
|
// The list is in the order of preference, if it has more than one entry.
|
||||||
|
// The entries contain platform-dependent identifiers.
|
||||||
|
static wxVector<wxString> GetPreferredUILanguages();
|
||||||
|
|
||||||
// Use this locale in the UI.
|
// Use this locale in the UI.
|
||||||
//
|
//
|
||||||
// This is not implemented for all platforms, notably not for Mac where the
|
// This is not implemented for all platforms, notably not for Mac where the
|
||||||
@@ -72,7 +77,10 @@ public:
|
|||||||
|
|
||||||
// Functions corresponding to wxUILocale ones.
|
// Functions corresponding to wxUILocale ones.
|
||||||
virtual wxString GetName() const = 0;
|
virtual wxString GetName() const = 0;
|
||||||
|
virtual wxLocaleIdent GetLocaleId() const = 0;
|
||||||
virtual wxString GetInfo(wxLocaleInfo index, wxLocaleCategory cat) const = 0;
|
virtual wxString GetInfo(wxLocaleInfo index, wxLocaleCategory cat) const = 0;
|
||||||
|
virtual wxString GetLocalizedName(wxLocaleName name, wxLocaleForm form) const = 0;
|
||||||
|
virtual wxLayoutDirection GetLayoutDirection() const = 0;
|
||||||
virtual int CompareStrings(const wxString& lhs, const wxString& rhs,
|
virtual int CompareStrings(const wxString& lhs, const wxString& rhs,
|
||||||
int flags) const = 0;
|
int flags) const = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#include "wx/localedefs.h"
|
#include "wx/localedefs.h"
|
||||||
#include "wx/string.h"
|
#include "wx/string.h"
|
||||||
|
#include "wx/vector.h"
|
||||||
|
|
||||||
class wxUILocaleImpl;
|
class wxUILocaleImpl;
|
||||||
|
|
||||||
@@ -56,12 +57,20 @@ public:
|
|||||||
// Set modifier (only supported under Unix)
|
// Set modifier (only supported under Unix)
|
||||||
wxLocaleIdent& Modifier(const wxString& modifier);
|
wxLocaleIdent& Modifier(const wxString& modifier);
|
||||||
|
|
||||||
|
// Set extension (only supported under Windows)
|
||||||
|
wxLocaleIdent& Extension(const wxString& extension);
|
||||||
|
|
||||||
|
// Set sort order (only supported under Windows)
|
||||||
|
wxLocaleIdent& SortOrder(const wxString& sortorder);
|
||||||
|
|
||||||
// Accessors for the individual fields.
|
// Accessors for the individual fields.
|
||||||
const wxString& GetLanguage() const { return m_language; }
|
const wxString& GetLanguage() const { return m_language; }
|
||||||
const wxString& GetRegion() const { return m_region; }
|
const wxString& GetRegion() const { return m_region; }
|
||||||
const wxString& GetScript() const { return m_script; }
|
const wxString& GetScript() const { return m_script; }
|
||||||
const wxString& GetCharset() const { return m_charset; }
|
const wxString& GetCharset() const { return m_charset; }
|
||||||
const wxString& GetModifier() const { return m_modifier; }
|
const wxString& GetModifier() const { return m_modifier; }
|
||||||
|
const wxString& GetExtension() const { return m_extension; }
|
||||||
|
const wxString& GetSortorder() const { return m_sortorder; }
|
||||||
|
|
||||||
// Construct platform dependent name
|
// Construct platform dependent name
|
||||||
wxString GetName() const;
|
wxString GetName() const;
|
||||||
@@ -69,7 +78,7 @@ public:
|
|||||||
// Get the language tag: for the objects created with FromTag() returns the
|
// Get the language tag: for the objects created with FromTag() returns the
|
||||||
// string passed to it directly, otherwise reconstructs this string from
|
// string passed to it directly, otherwise reconstructs this string from
|
||||||
// the components.
|
// the components.
|
||||||
wxString GetTag() const;
|
wxString GetTag(wxLocaleTagType tagType = wxLOCALE_TAGTYPE_DEFAULT) const;
|
||||||
|
|
||||||
// Empty locale identifier is invalid. at least Language() must be called.
|
// Empty locale identifier is invalid. at least Language() must be called.
|
||||||
bool IsEmpty() const
|
bool IsEmpty() const
|
||||||
@@ -85,6 +94,8 @@ private:
|
|||||||
wxString m_script;
|
wxString m_script;
|
||||||
wxString m_charset;
|
wxString m_charset;
|
||||||
wxString m_modifier;
|
wxString m_modifier;
|
||||||
|
wxString m_extension;
|
||||||
|
wxString m_sortorder;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -97,11 +108,11 @@ public:
|
|||||||
// Configure the UI to use the default user locale.
|
// Configure the UI to use the default user locale.
|
||||||
static bool UseDefault();
|
static bool UseDefault();
|
||||||
|
|
||||||
// Use the locale corresponding to the given language.
|
// Use the locale corresponding to the given POSIX locale, e.g. "de_DE.UTF-8".
|
||||||
//
|
//
|
||||||
// This is a compatibility function used by wxWidgets itself, don't use it
|
// This is a compatibility function used by wxWidgets itself, don't use it
|
||||||
// in the new code.
|
// in the new code.
|
||||||
static bool UseLanguage(const wxLanguageInfo& info);
|
static bool UseLocaleName(const wxString& localeName);
|
||||||
|
|
||||||
// Get the object corresponding to the currently used locale.
|
// Get the object corresponding to the currently used locale.
|
||||||
static const wxUILocale& GetCurrent();
|
static const wxUILocale& GetCurrent();
|
||||||
@@ -126,10 +137,19 @@ public:
|
|||||||
// Get the platform-dependent name of the current locale.
|
// Get the platform-dependent name of the current locale.
|
||||||
wxString GetName() const;
|
wxString GetName() const;
|
||||||
|
|
||||||
|
// Get the locale id from which the current locale was instantiated.
|
||||||
|
wxLocaleIdent GetLocaleId() const;
|
||||||
|
|
||||||
// Query the locale for the specified information.
|
// Query the locale for the specified information.
|
||||||
wxString GetInfo(wxLocaleInfo index,
|
wxString GetInfo(wxLocaleInfo index,
|
||||||
wxLocaleCategory cat = wxLOCALE_CAT_DEFAULT) const;
|
wxLocaleCategory cat = wxLOCALE_CAT_DEFAULT) const;
|
||||||
|
|
||||||
|
// Query the locale for the specified localized name.
|
||||||
|
wxString GetLocalizedName(wxLocaleName name, wxLocaleForm form) const;
|
||||||
|
|
||||||
|
// Query the layout direction of the current locale.
|
||||||
|
wxLayoutDirection GetLayoutDirection() const;
|
||||||
|
|
||||||
// Compares two strings in the order defined by this locale.
|
// Compares two strings in the order defined by this locale.
|
||||||
int CompareStrings(const wxString& lhs, const wxString& rhs,
|
int CompareStrings(const wxString& lhs, const wxString& rhs,
|
||||||
int flags = wxCompare_CaseSensitive) const;
|
int flags = wxCompare_CaseSensitive) const;
|
||||||
@@ -142,6 +162,10 @@ public:
|
|||||||
// Return wxLANGUAGE_UNKNOWN if language-guessing algorithm failed
|
// Return wxLANGUAGE_UNKNOWN if language-guessing algorithm failed
|
||||||
static int GetSystemLanguage();
|
static int GetSystemLanguage();
|
||||||
|
|
||||||
|
// Try to retrieve a list of user's (or OS's) preferred UI languages.
|
||||||
|
// Return empty list if language-guessing algorithm failed
|
||||||
|
static wxVector<wxString> GetPreferredUILanguages();
|
||||||
|
|
||||||
// Retrieve the language info struct for the given language
|
// Retrieve the language info struct for the given language
|
||||||
//
|
//
|
||||||
// Returns NULL if no info found, pointer must *not* be deleted by caller
|
// Returns NULL if no info found, pointer must *not* be deleted by caller
|
||||||
@@ -162,6 +186,13 @@ public:
|
|||||||
// Returns NULL if no info found, pointer must *not* be deleted by caller
|
// Returns NULL if no info found, pointer must *not* be deleted by caller
|
||||||
static const wxLanguageInfo* FindLanguageInfo(const wxString& locale);
|
static const wxLanguageInfo* FindLanguageInfo(const wxString& locale);
|
||||||
|
|
||||||
|
// Find the language for the given locale string which may be either a
|
||||||
|
// canonical ISO 2 letter language code ("xx"), a language code followed by
|
||||||
|
// the country code ("xx_XX") or a Windows full language name ("Xxxxx...")
|
||||||
|
//
|
||||||
|
// Returns NULL if no info found, pointer must *not* be deleted by caller
|
||||||
|
static const wxLanguageInfo* FindLanguageInfo(const wxLocaleIdent& locId);
|
||||||
|
|
||||||
// Add custom language to the list of known languages.
|
// Add custom language to the list of known languages.
|
||||||
// Notes: 1) wxLanguageInfo contains platform-specific data
|
// Notes: 1) wxLanguageInfo contains platform-specific data
|
||||||
// 2) must be called before Init to have effect
|
// 2) must be called before Init to have effect
|
||||||
|
|||||||
@@ -90,6 +90,34 @@ struct wxLanguageInfo
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
The type of a locale tag.
|
||||||
|
|
||||||
|
@see wxLocaleIdent::GetTag()
|
||||||
|
@since 3.1.6
|
||||||
|
*/
|
||||||
|
enum wxLocaleTagType
|
||||||
|
{
|
||||||
|
/// Default (tag as given or else same as wxLOCALE_TAGTYPE_SYSTEM)
|
||||||
|
wxLOCALE_TAGTYPE_DEFAULT,
|
||||||
|
|
||||||
|
/// Default type of the system (platform-dependent).
|
||||||
|
wxLOCALE_TAGTYPE_SYSTEM,
|
||||||
|
|
||||||
|
/// BCP47-like type: <language>[-<script>][-<region>][-<modifier>].
|
||||||
|
wxLOCALE_TAGTYPE_BCP47,
|
||||||
|
|
||||||
|
/// macOS type: <language>[-<script>][_<region>].
|
||||||
|
wxLOCALE_TAGTYPE_MACOS,
|
||||||
|
|
||||||
|
/// POSIX type: <language>_<region>[.<charset>][@{<scriptalias>|<modifier>}].
|
||||||
|
wxLOCALE_TAGTYPE_POSIX,
|
||||||
|
|
||||||
|
/// Windows type: <language>[-<script>][-<region>][-<extension>][_<sortorder>].
|
||||||
|
wxLOCALE_TAGTYPE_WINDOWS
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The category of locale settings.
|
The category of locale settings.
|
||||||
|
|
||||||
@@ -192,6 +220,50 @@ enum wxLocaleInfo
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
The values understood by wxUILocale::GetLocalizedName().
|
||||||
|
|
||||||
|
The corresponding strings can be used to display the information in the UI.
|
||||||
|
|
||||||
|
@since 3.1.6
|
||||||
|
|
||||||
|
@see wxUILocale::GetLocalizedName()
|
||||||
|
*/
|
||||||
|
enum wxLocaleName
|
||||||
|
{
|
||||||
|
/// Display name of a locale.
|
||||||
|
wxLOCALE_NAME_LOCALE,
|
||||||
|
|
||||||
|
/// Display name of the language of a locale.
|
||||||
|
wxLOCALE_NAME_LANGUAGE,
|
||||||
|
|
||||||
|
/// Display name of the country/region of a locale.
|
||||||
|
wxLOCALE_NAME_COUNTRY
|
||||||
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxLocaleForm: the forms of names understood by wxLocale::GetLocalizedName()
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
The values understood by wxUILocale::GetLocalizedName().
|
||||||
|
|
||||||
|
The values specify the form of a localized name.
|
||||||
|
|
||||||
|
@since 3.1.6
|
||||||
|
|
||||||
|
@see wxUILocale::GetLocalizedName()
|
||||||
|
*/
|
||||||
|
enum wxLocaleForm
|
||||||
|
{
|
||||||
|
/// Name should be returned in the language of the locale itself.
|
||||||
|
wxLOCALE_FORM_NATIVE,
|
||||||
|
|
||||||
|
/// Name should be returned in English.
|
||||||
|
wxLOCALE_FORM_ENGLISH
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@class wxLocale
|
@class wxLocale
|
||||||
|
|
||||||
|
|||||||
@@ -162,6 +162,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
wxString GetName() const;
|
wxString GetName() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the locale id from which the current locale was instantiated.
|
||||||
|
*/
|
||||||
|
wxLocaleIdent GetLocaleId() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Query the locale for the specified information.
|
Query the locale for the specified information.
|
||||||
|
|
||||||
@@ -179,6 +184,26 @@ public:
|
|||||||
wxString GetInfo(wxLocaleInfo index,
|
wxString GetInfo(wxLocaleInfo index,
|
||||||
wxLocaleCategory cat = wxLOCALE_CAT_DEFAULT) const;
|
wxLocaleCategory cat = wxLOCALE_CAT_DEFAULT) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Query the locale for the specified localized name.
|
||||||
|
|
||||||
|
@param name
|
||||||
|
One of the elements of wxLocaleName enum.
|
||||||
|
@param form
|
||||||
|
The representation form requested.
|
||||||
|
@return
|
||||||
|
The localized name value or empty string if the function failed.
|
||||||
|
*/
|
||||||
|
wxString GetLocalizedName(wxLocaleName name, wxLocaleForm form) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Query the layout direction of the current locale.
|
||||||
|
|
||||||
|
@return
|
||||||
|
The layout direction or wxLayout_Default if the function failed.
|
||||||
|
*/
|
||||||
|
wxLayoutDirection GetLayoutDirection() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Return true if locale is supported on the current system.
|
Return true if locale is supported on the current system.
|
||||||
|
|
||||||
@@ -210,6 +235,18 @@ public:
|
|||||||
*/
|
*/
|
||||||
static const wxLanguageInfo* FindLanguageInfo(const wxString& locale);
|
static const wxLanguageInfo* FindLanguageInfo(const wxString& locale);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function may be used to find the language description structure for the
|
||||||
|
given locale, specified as a locale identifier.
|
||||||
|
|
||||||
|
Returns the information for the given language or @NULL if this language
|
||||||
|
is unknown. Note that even if the returned pointer is valid, the caller
|
||||||
|
should @e not delete it.
|
||||||
|
|
||||||
|
@see GetLanguageInfo()
|
||||||
|
*/
|
||||||
|
static const wxLanguageInfo* FindLanguageInfo(const wxLocaleIdent& localeId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns a pointer to wxLanguageInfo structure containing information about
|
Returns a pointer to wxLanguageInfo structure containing information about
|
||||||
the given language or @NULL if this language is unknown. Note that even if
|
the given language or @NULL if this language is unknown. Note that even if
|
||||||
@@ -274,7 +311,7 @@ wxString wxGetUIDateFormat();
|
|||||||
|
|
||||||
There are two possible ways to construct wxLocaleIdent:
|
There are two possible ways to construct wxLocaleIdent:
|
||||||
|
|
||||||
- You can either use fromTag() to create it from a string in the form
|
- You can either use FromTag() to create it from a string in the form
|
||||||
@code language ["-" script] ["-" region] @endcode, corresponding to
|
@code language ["-" script] ["-" region] @endcode, corresponding to
|
||||||
the subset of BCP 47 (https://www.rfc-editor.org/rfc/bcp/bcp47.txt)
|
the subset of BCP 47 (https://www.rfc-editor.org/rfc/bcp/bcp47.txt)
|
||||||
syntax.
|
syntax.
|
||||||
@@ -308,7 +345,39 @@ class wxLocaleIdent
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
Return the locale identifier corresponding to the given BCP 47-like tag.
|
Return the locale identifier corresponding to the given locale tag.
|
||||||
|
|
||||||
|
This method accepts locale tags in various formats:
|
||||||
|
|
||||||
|
- BCP-47,
|
||||||
|
- Windows,
|
||||||
|
- POSIX, and
|
||||||
|
- macOS.
|
||||||
|
|
||||||
|
See section 2.01 of https://www.rfc-editor.org/rfc/bcp/bcp47.txt for the
|
||||||
|
full BCP-47 syntax. Here we fully support just the subset we're interested in:
|
||||||
|
|
||||||
|
- Normal language tags (not private use or grandfathered ones),
|
||||||
|
- Script, and
|
||||||
|
- Region.
|
||||||
|
|
||||||
|
Additionally platform-specific tags are supported:
|
||||||
|
|
||||||
|
- Extensions (without validity checks) (Windows only),
|
||||||
|
- Sortorder (Windows only)
|
||||||
|
- Charset (POSIX only), and
|
||||||
|
- Modifier (POSIX only).
|
||||||
|
|
||||||
|
Only language, script, and region are supported across all platforms.
|
||||||
|
The script tag is mapped to the modifier tag for POSIX platforms.
|
||||||
|
The script tag takes precedence, if a modifier is also specified.
|
||||||
|
|
||||||
|
The following tag syntax is accepted:
|
||||||
|
|
||||||
|
BCP-47: <language>[-<script>][-<region>][-<extension>]
|
||||||
|
Windows: <language>[-<script>][-<region>][-<extension>][_<sortorder>]
|
||||||
|
POSIX: <language>[_<region>][.<charset>][@<modifier>]
|
||||||
|
macOS: <language>[-<script>][_<region>]
|
||||||
|
|
||||||
The string must contain at least the language part (2 or 3 ASCII
|
The string must contain at least the language part (2 or 3 ASCII
|
||||||
letters) and may contain script and region separated by dashes, i.e.
|
letters) and may contain script and region separated by dashes, i.e.
|
||||||
@@ -363,7 +432,9 @@ public:
|
|||||||
/**
|
/**
|
||||||
Set script.
|
Set script.
|
||||||
|
|
||||||
Note that script value is currently ignored under Unix systems.
|
Note that under Unix systems the script value is currently mapped
|
||||||
|
to the modifier attribute using the script alias name, if the latter
|
||||||
|
is known. Otherwise it is ignored.
|
||||||
|
|
||||||
Return reference to `this` for method chaining.
|
Return reference to `this` for method chaining.
|
||||||
|
|
||||||
@@ -391,15 +462,46 @@ public:
|
|||||||
|
|
||||||
Note that this value is only used under Unix systems and simply ignored
|
Note that this value is only used under Unix systems and simply ignored
|
||||||
under the other ones.
|
under the other ones.
|
||||||
|
Note that under Unix systems the modifier value may represent a script
|
||||||
|
value. If the value corresponds to a valid script alias it is mapped
|
||||||
|
to the associated script tag.
|
||||||
|
|
||||||
Return reference to `this` for method chaining.
|
Return reference to `this` for method chaining.
|
||||||
|
|
||||||
@param modifier
|
@param modifier
|
||||||
Modifier is defined by ISO/IEC 15897.
|
Modifier is a free-form text string.
|
||||||
It is a semi-colon separated list of identifiers, or name=value pairs.
|
|
||||||
*/
|
*/
|
||||||
wxLocaleIdent& Modifier(const wxString& modifier);
|
wxLocaleIdent& Modifier(const wxString& modifier);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Set extension.
|
||||||
|
|
||||||
|
Note that this value is only used under Windows systems and simply ignored
|
||||||
|
under the other ones.
|
||||||
|
|
||||||
|
Return reference to @this for method chaining.
|
||||||
|
|
||||||
|
@param extension
|
||||||
|
Extension identifiers allow to support custom Windows locales.
|
||||||
|
They are usually not portable, not even from one Windows system
|
||||||
|
to the other.
|
||||||
|
*/
|
||||||
|
wxLocaleIdent& Extension(const wxString& extension);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Set sortorder.
|
||||||
|
|
||||||
|
Note that this value is only used under Windows systems and simply ignored
|
||||||
|
under the other ones.
|
||||||
|
|
||||||
|
Return reference to @this for method chaining.
|
||||||
|
|
||||||
|
@param sortorder
|
||||||
|
Sortorder identifiers are defined in the Windows Development documentation:
|
||||||
|
https://docs.microsoft.com/en-us/windows/win32/intl/sort-order-identifiers.
|
||||||
|
*/
|
||||||
|
wxLocaleIdent& Sortorder(const wxString& sortorder);
|
||||||
|
|
||||||
/// Return the language part of the locale identifier.
|
/// Return the language part of the locale identifier.
|
||||||
const wxString& GetLanguage() const;
|
const wxString& GetLanguage() const;
|
||||||
|
|
||||||
@@ -415,15 +517,36 @@ public:
|
|||||||
/// Return the modifier part of the locale identifier.
|
/// Return the modifier part of the locale identifier.
|
||||||
const wxString& GetModifier() const;
|
const wxString& GetModifier() const;
|
||||||
|
|
||||||
|
/// Return the extension part of the locale identifier.
|
||||||
|
const wxString& GetExtension() const;
|
||||||
|
|
||||||
|
/// Return the sortorder part of the locale identifier.
|
||||||
|
const wxString& GetSortorder() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Construct platform dependent name.
|
Construct platform dependent name.
|
||||||
Format:
|
Format:
|
||||||
Windows: \<language\>-\<script\>-\<REGION\>
|
Windows: \<language\>-\<script\>-\<REGION\>-\<extension\>_\<sortorder\>
|
||||||
Unix: \<language\>_\<REGION\>.\<charset\>@\<modifier\>
|
Unix: \<language\>_\<REGION\>.\<charset\>@\{\<modifier\>\|\<scriptalias\>\}
|
||||||
MacOS: \<language\>-\<script\>_\<REGION\>
|
MacOS: \<language\>-\<script\>_\<REGION\>
|
||||||
*/
|
*/
|
||||||
wxString GetName() const;
|
wxString GetName() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Construct name in specified format.
|
||||||
|
Format:
|
||||||
|
Default: name as used in wxLocaleIdent::FromTag() or system format
|
||||||
|
System: name in platform-dependent format
|
||||||
|
Windows: \<language\>-\<script\>-\<REGION\>-\<extension\>_\<sortorder\>
|
||||||
|
Unix: \<language\>_\<REGION\>.\<charset\>@\<modifier\>
|
||||||
|
MacOS: \<language\>-\<script\>_\<REGION\>
|
||||||
|
BCP 47: \<language\>-\<script\>-\<REGION\>-\<extension\>
|
||||||
|
|
||||||
|
@param tagType
|
||||||
|
Value from wxLocaleTagType enum.
|
||||||
|
*/
|
||||||
|
wxString GetTag(wxLocaleTagType tagType = wxLOCALE_TAGTYPE_DEFAULT) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Check if the locale is empty.
|
Check if the locale is empty.
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@@ -5,8 +5,8 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"POT-Creation-Date: 2021-11-11 23:05+0100\n"
|
"POT-Creation-Date: 2021-12-10 10:06+0100\n"
|
||||||
"PO-Revision-Date: 2021-11-11 23:09+0100\n"
|
"PO-Revision-Date: 2021-12-10 10:15+0100\n"
|
||||||
"Last-Translator: Ulrich Telle <ulrich@telle-online.eu>\n"
|
"Last-Translator: Ulrich Telle <ulrich@telle-online.eu>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
"Language: de\n"
|
"Language: de\n"
|
||||||
@@ -103,37 +103,37 @@ msgstr "Testet die Übersetzung der Schaltflächen im Hinweisfenster"
|
|||||||
|
|
||||||
#: internat.cpp:316
|
#: internat.cpp:316
|
||||||
msgid "item"
|
msgid "item"
|
||||||
msgstr "Eintrag"
|
msgstr "Eintrag ohne Kontext"
|
||||||
|
|
||||||
#: internat.cpp:317
|
#: internat.cpp:317
|
||||||
msgctxt "context_1"
|
msgctxt "context_1"
|
||||||
msgid "item"
|
msgid "item"
|
||||||
msgstr "Eintrag A"
|
msgstr "Eintrag Kontext 1"
|
||||||
|
|
||||||
#: internat.cpp:318
|
#: internat.cpp:318
|
||||||
msgctxt "context_2"
|
msgctxt "context_2"
|
||||||
msgid "item"
|
msgid "item"
|
||||||
msgstr "Eintrag B"
|
msgstr "Eintrag Kontext 2"
|
||||||
|
|
||||||
#: internat.cpp:319 internat.cpp:320
|
#: internat.cpp:319 internat.cpp:320
|
||||||
msgid "sing"
|
msgid "sing"
|
||||||
msgid_plural "plur"
|
msgid_plural "plur"
|
||||||
msgstr[0] "Einzahl"
|
msgstr[0] "Einzahl ohne Kontext"
|
||||||
msgstr[1] "Mehrzahl"
|
msgstr[1] "Mehrzahl ohne Kontext"
|
||||||
|
|
||||||
#: internat.cpp:321 internat.cpp:322
|
#: internat.cpp:321 internat.cpp:322
|
||||||
msgctxt "context_1"
|
msgctxt "context_1"
|
||||||
msgid "sing"
|
msgid "sing"
|
||||||
msgid_plural "plur"
|
msgid_plural "plur"
|
||||||
msgstr[0] "Einzahl A"
|
msgstr[0] "Einzahl Kontext 1"
|
||||||
msgstr[1] "Mehrzahl A"
|
msgstr[1] "Mehrzahl Kontext 1"
|
||||||
|
|
||||||
#: internat.cpp:323 internat.cpp:324
|
#: internat.cpp:323 internat.cpp:324
|
||||||
msgctxt "context_2"
|
msgctxt "context_2"
|
||||||
msgid "sing"
|
msgid "sing"
|
||||||
msgid_plural "plur"
|
msgid_plural "plur"
|
||||||
msgstr[0] "Einzahl B"
|
msgstr[0] "Einzahl Kontext 2"
|
||||||
msgstr[1] "Mehrzahl B"
|
msgstr[1] "Mehrzahl Kontext 2"
|
||||||
|
|
||||||
#: internat.cpp:328
|
#: internat.cpp:328
|
||||||
msgid "Show coreutils &help"
|
msgid "Show coreutils &help"
|
||||||
@@ -161,24 +161,34 @@ msgstr "&Hilfe"
|
|||||||
msgid "Current UI locale: %s; C locale: %s"
|
msgid "Current UI locale: %s; C locale: %s"
|
||||||
msgstr "Aktuelles UI Gebietsschema: %s; C Gebietsschema: %s"
|
msgstr "Aktuelles UI Gebietsschema: %s; C Gebietsschema: %s"
|
||||||
|
|
||||||
#: internat.cpp:372
|
#: internat.cpp:373
|
||||||
|
#, c-format
|
||||||
|
msgid "UI locale name in English: %s"
|
||||||
|
msgstr "Name des UI Gebietsschema auf Englisch: %s"
|
||||||
|
|
||||||
|
#: internat.cpp:385
|
||||||
|
#, c-format
|
||||||
|
msgid "... and in the locale language: %s"
|
||||||
|
msgstr "… und in der Sprache des Gebietsschemas: %s"
|
||||||
|
|
||||||
|
#: internat.cpp:396
|
||||||
msgid "Numeric input:"
|
msgid "Numeric input:"
|
||||||
msgstr "Numerische Eingabe:"
|
msgstr "Numerische Eingabe:"
|
||||||
|
|
||||||
#: internat.cpp:393
|
#: internat.cpp:417
|
||||||
msgid "Number"
|
msgid "Number"
|
||||||
msgstr "Zahl"
|
msgstr "Zahl"
|
||||||
|
|
||||||
#: internat.cpp:397
|
#: internat.cpp:421
|
||||||
msgid "Date"
|
msgid "Date"
|
||||||
msgstr "Datum"
|
msgstr "Datum"
|
||||||
|
|
||||||
#: internat.cpp:413
|
#: internat.cpp:437
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Number in UI locale: %s; in C locale: %.2f"
|
msgid "Number in UI locale: %s; in C locale: %.2f"
|
||||||
msgstr "Zahl im UI Gebietsschema: %s; im C Gebietsschema: %.2f"
|
msgstr "Zahl im UI Gebietsschema: %s; im C Gebietsschema: %.2f"
|
||||||
|
|
||||||
#: internat.cpp:433
|
#: internat.cpp:457
|
||||||
msgid ""
|
msgid ""
|
||||||
"I18n sample\n"
|
"I18n sample\n"
|
||||||
"(c) 1998, 1999 Vadim Zeitlin and Julian Smart"
|
"(c) 1998, 1999 Vadim Zeitlin and Julian Smart"
|
||||||
@@ -186,108 +196,111 @@ msgstr ""
|
|||||||
"I18n Beispiel\n"
|
"I18n Beispiel\n"
|
||||||
"© 1998, 1999 Vadim Zeitlin und Julian Smart"
|
"© 1998, 1999 Vadim Zeitlin und Julian Smart"
|
||||||
|
|
||||||
#: internat.cpp:434
|
#: internat.cpp:458
|
||||||
msgid "About Internat"
|
msgid "About Internat"
|
||||||
msgstr "Über Internat"
|
msgstr "Über Internat"
|
||||||
|
|
||||||
#: internat.cpp:467
|
#: internat.cpp:491
|
||||||
msgid "Enter your number:"
|
msgid "Enter your number:"
|
||||||
msgstr "Geben Sie eine Zahl ein:"
|
msgstr "Geben Sie eine Zahl ein:"
|
||||||
|
|
||||||
#: internat.cpp:468
|
#: internat.cpp:492
|
||||||
msgid "Try to guess my number!"
|
msgid "Try to guess my number!"
|
||||||
msgstr "Versuchen Sie, die Zahl zu raten!"
|
msgstr "Versuchen Sie, die Zahl zu raten!"
|
||||||
|
|
||||||
#: internat.cpp:482
|
#: internat.cpp:506
|
||||||
msgid "You've probably entered an invalid number."
|
msgid "You've probably entered an invalid number."
|
||||||
msgstr "Sie haben wahrscheinlich eine ungültige Zahl eingegeben."
|
msgstr "Sie haben wahrscheinlich eine ungültige Zahl eingegeben."
|
||||||
|
|
||||||
#: internat.cpp:496
|
#: internat.cpp:520
|
||||||
msgid "Congratulations! you've won. Here is the magic phrase:"
|
msgid "Congratulations! you've won. Here is the magic phrase:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Herzlichen Glückwunsch! Sie haben gewonnen. Hier ist der magische Satz:"
|
"Herzlichen Glückwunsch! Sie haben gewonnen. Hier ist der magische Satz:"
|
||||||
|
|
||||||
#: internat.cpp:497
|
#: internat.cpp:521
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "cannot create fifo `%s'"
|
msgid "cannot create fifo `%s'"
|
||||||
msgstr "Fifo `%s' kann nicht erzeugt werden"
|
msgstr "Fifo `%s' kann nicht erzeugt werden"
|
||||||
|
|
||||||
#: internat.cpp:506
|
#: internat.cpp:530
|
||||||
msgid "Bad luck! try again..."
|
msgid "Bad luck! try again..."
|
||||||
msgstr "Pech gehabt! Versuchen Sie es noch einmal..."
|
msgstr "Pech gehabt! Versuchen Sie es noch einmal..."
|
||||||
|
|
||||||
#: internat.cpp:514
|
#: internat.cpp:538
|
||||||
msgid "Result"
|
msgid "Result"
|
||||||
msgstr "Ergebnis"
|
msgstr "Ergebnis"
|
||||||
|
|
||||||
#: internat.cpp:522
|
#: internat.cpp:546
|
||||||
msgid "Enter the locale to test"
|
msgid "Enter the locale to test"
|
||||||
msgstr "Geben Sie das zu testende Gebietsschema ein"
|
msgstr "Geben Sie das zu testende Gebietsschema ein"
|
||||||
|
|
||||||
#: internat.cpp:534
|
#: internat.cpp:562
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Locale \"%s\" is unknown."
|
msgid ""
|
||||||
msgstr "Gebietsschema \"%s\" ist unbekannt."
|
"Locale \"%s\" is available.\n"
|
||||||
|
"Identifier: %s; Layout: %s\n"
|
||||||
|
"English name: %s\n"
|
||||||
|
"Localized name: %s"
|
||||||
|
msgstr ""
|
||||||
|
"Gebietsschema \"%s\" ist verfügbar.\n"
|
||||||
|
"Identifikator: %s; Layout: %s\n"
|
||||||
|
"Englischer Name: %s\n"
|
||||||
|
"Lokaler Name: %s"
|
||||||
|
|
||||||
#: internat.cpp:540
|
#: internat.cpp:569
|
||||||
#, c-format
|
|
||||||
msgid "Locale \"%s\" is available."
|
|
||||||
msgstr "Gebietsschema \"%s\" ist verfügbar."
|
|
||||||
|
|
||||||
#: internat.cpp:544
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Locale \"%s\" is not available."
|
msgid "Locale \"%s\" is not available."
|
||||||
msgstr "Gebietsschema \"%s\" ist nicht verfügbar."
|
msgstr "Gebietsschema \"%s\" ist nicht verfügbar."
|
||||||
|
|
||||||
#: internat.cpp:559
|
#: internat.cpp:584
|
||||||
msgid "Dummy file dialog"
|
msgid "Dummy file dialog"
|
||||||
msgstr "Dummy-Datei-Dialog"
|
msgstr "Dummy-Datei-Dialog"
|
||||||
|
|
||||||
#: internat.cpp:564
|
#: internat.cpp:589
|
||||||
msgid "Testing _() (gettext)"
|
msgid "Testing _() (gettext)"
|
||||||
msgstr "Test von _() (gettext)"
|
msgstr "Test von _() (gettext)"
|
||||||
|
|
||||||
#: internat.cpp:572
|
#: internat.cpp:597
|
||||||
msgid "Please enter text to translate"
|
msgid "Please enter text to translate"
|
||||||
msgstr "Bitte geben Sie einen zu übersetzenden Text ein"
|
msgstr "Bitte geben Sie einen zu übersetzenden Text ein"
|
||||||
|
|
||||||
#: internat.cpp:573
|
#: internat.cpp:598
|
||||||
msgid "default value"
|
msgid "default value"
|
||||||
msgstr "Default-Wert"
|
msgstr "Default-Wert"
|
||||||
|
|
||||||
#: internat.cpp:587
|
#: internat.cpp:612
|
||||||
msgid "Testing _N() (ngettext)"
|
msgid "Testing _N() (ngettext)"
|
||||||
msgstr "Test von _N() (ngettext)"
|
msgstr "Test von _N() (ngettext)"
|
||||||
|
|
||||||
#: internat.cpp:589
|
#: internat.cpp:614
|
||||||
msgid "Please enter range for plural forms of \"n files deleted\" phrase"
|
msgid "Please enter range for plural forms of \"n files deleted\" phrase"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Bitte geben Sie einen Bereich für Pluralformen des Satzes \"n Dateien "
|
"Bitte geben Sie einen Bereich für Pluralformen des Satzes \"n Dateien "
|
||||||
"gelöscht\" ein"
|
"gelöscht\" ein"
|
||||||
|
|
||||||
#: internat.cpp:601
|
#: internat.cpp:626
|
||||||
msgid "file deleted"
|
msgid "file deleted"
|
||||||
msgid_plural "files deleted"
|
msgid_plural "files deleted"
|
||||||
msgstr[0] "Datei gelöscht"
|
msgstr[0] "Datei gelöscht"
|
||||||
msgstr[1] "Dateien gelöscht"
|
msgstr[1] "Dateien gelöscht"
|
||||||
|
|
||||||
#: internat.cpp:612
|
#: internat.cpp:637
|
||||||
msgid "line 1"
|
msgid "line 1"
|
||||||
msgstr "Zeile 1"
|
msgstr "Zeile 1"
|
||||||
|
|
||||||
#: internat.cpp:613
|
#: internat.cpp:638
|
||||||
msgid "line 2"
|
msgid "line 2"
|
||||||
msgstr "Zeile 2"
|
msgstr "Zeile 2"
|
||||||
|
|
||||||
#: internat.cpp:614
|
#: internat.cpp:639
|
||||||
msgid "line 3"
|
msgid "line 3"
|
||||||
msgstr "Zeile 3"
|
msgstr "Zeile 3"
|
||||||
|
|
||||||
#: internat.cpp:617
|
#: internat.cpp:642
|
||||||
msgid "Testing wxTRANSLATE() (gettext_noop)"
|
msgid "Testing wxTRANSLATE() (gettext_noop)"
|
||||||
msgstr "Test von wxTRANSLATE() (gettext_noop)"
|
msgstr "Test von wxTRANSLATE() (gettext_noop)"
|
||||||
|
|
||||||
#: internat.cpp:630
|
#: internat.cpp:655
|
||||||
msgid ""
|
msgid ""
|
||||||
"Are the labels of the buttons in this message box translated into the "
|
"Are the labels of the buttons in this message box translated into the "
|
||||||
"current locale language?"
|
"current locale language?"
|
||||||
@@ -295,10 +308,18 @@ msgstr ""
|
|||||||
"Wurden die Beschriftungen der Schaltflächen in diesem Hinweisfenster in die "
|
"Wurden die Beschriftungen der Schaltflächen in diesem Hinweisfenster in die "
|
||||||
"Sprache des aktuellen Gebietsschemas übersetzt?"
|
"Sprache des aktuellen Gebietsschemas übersetzt?"
|
||||||
|
|
||||||
#: internat.cpp:632
|
#: internat.cpp:657
|
||||||
msgid "wxWidgets i18n sample"
|
msgid "wxWidgets i18n sample"
|
||||||
msgstr "wxWidgets I18n Beispiel"
|
msgstr "wxWidgets I18n Beispiel"
|
||||||
|
|
||||||
#: internat.cpp:637
|
#: internat.cpp:662
|
||||||
msgid "Please report the details of your platform to us."
|
msgid "Please report the details of your platform to us."
|
||||||
msgstr "Bitte teilen Sie uns über die Details Ihrer Plattform mit."
|
msgstr "Bitte teilen Sie uns über die Details Ihrer Plattform mit."
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
#~ msgid "Locale \"%s\" is unknown."
|
||||||
|
#~ msgstr "Gebietsschema \"%s\" ist unbekannt."
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
#~ msgid "Locale \"%s\" is available."
|
||||||
|
#~ msgstr "Gebietsschema \"%s\" ist verfügbar."
|
||||||
|
|||||||
Binary file not shown.
@@ -5,101 +5,310 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: wxWindows 2.0 i18n sample\n"
|
"Project-Id-Version: wxWindows 2.0 i18n sample\n"
|
||||||
"POT-Creation-Date: 1999-01-13 18:19+0100\n"
|
"POT-Creation-Date: 2021-12-10 10:11+0100\n"
|
||||||
"PO-Revision-Date: 2016-09-20 19:38+0200\n"
|
"PO-Revision-Date: 2021-12-10 10:12+0100\n"
|
||||||
"Last-Translator: Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>\n"
|
"Last-Translator: Ulrich Telle <ulrich@telle-online.eu>\n"
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=utf-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
"Language: fr\n"
|
"Language: fr\n"
|
||||||
"X-Generator: Poedit 1.8.7\n"
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||||
|
"X-Generator: Poedit 3.0\n"
|
||||||
|
"X-Poedit-KeywordsList: _;wxTRANSLATE;wxPLURAL:1,2;wxGETTEXT_IN_CONTEXT:1c,2;"
|
||||||
|
"wxGETTEXT_IN_CONTEXT_PLURAL:1c,2,3\n"
|
||||||
|
"X-Poedit-Basepath: ..\n"
|
||||||
|
"X-Poedit-SearchPath-0: internat.cpp\n"
|
||||||
|
|
||||||
|
#: internat.cpp:168
|
||||||
|
msgid "skip setting locale on startup"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:170
|
||||||
|
msgid "do set locale on startup without asking"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:253
|
||||||
|
#, c-format
|
||||||
|
msgid "Couldn't find/load 'internat' catalog for %s."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:289
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "International wxWindows App"
|
||||||
|
msgid "International wxWidgets App"
|
||||||
|
msgstr "Application wxWindows internationale"
|
||||||
|
|
||||||
|
#: internat.cpp:295
|
||||||
|
msgid "&Test locale availability...\tCtrl-T"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:300
|
||||||
|
msgid "E&xit"
|
||||||
|
msgstr "&Quitter"
|
||||||
|
|
||||||
|
#: internat.cpp:303
|
||||||
|
msgid "&Open bogus file"
|
||||||
|
msgstr "&Ouvrir un fichier"
|
||||||
|
|
||||||
|
#: internat.cpp:303
|
||||||
|
msgid "Shows a wxWidgets localized error message"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:304
|
||||||
|
msgid "&Save dummy file"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:304
|
||||||
|
msgid "Shows a localized standard dialog"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:305
|
||||||
|
msgid "&Play a game"
|
||||||
|
msgstr "&Jouer"
|
||||||
|
|
||||||
|
#: internat.cpp:305
|
||||||
|
msgid "A little game; hint: 17 is a lucky number for many"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:307
|
||||||
|
msgid "&1 _() (gettext)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:307
|
||||||
|
msgid "Tests the _() macro"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:308
|
||||||
|
msgid "&2 _N() (ngettext)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:308
|
||||||
|
msgid "Tests the _N() macro"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:309
|
||||||
|
msgid "&3 wxTRANSLATE() (gettext_noop)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:309
|
||||||
|
msgid "Tests the wxTRANSLATE() macro"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:310
|
||||||
|
msgid "&Message box test"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:311
|
||||||
|
msgid "Tests message box buttons labels translation"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:316
|
||||||
msgid "item"
|
msgid "item"
|
||||||
msgstr "Item without context"
|
msgstr "Item without context"
|
||||||
|
|
||||||
|
#: internat.cpp:317
|
||||||
msgctxt "context_1"
|
msgctxt "context_1"
|
||||||
msgid "item"
|
msgid "item"
|
||||||
msgstr "Item in context 1"
|
msgstr "Item in context 1"
|
||||||
|
|
||||||
|
#: internat.cpp:318
|
||||||
msgctxt "context_2"
|
msgctxt "context_2"
|
||||||
msgid "item"
|
msgid "item"
|
||||||
msgstr "Item in context 2"
|
msgstr "Item in context 2"
|
||||||
|
|
||||||
|
#: internat.cpp:319 internat.cpp:320
|
||||||
msgid "sing"
|
msgid "sing"
|
||||||
msgid_plural "plur"
|
msgid_plural "plur"
|
||||||
msgstr[0] "Singular form without context"
|
msgstr[0] "Singular form without context"
|
||||||
msgstr[1] "Plural form without context"
|
msgstr[1] "Plural form without context"
|
||||||
|
|
||||||
|
#: internat.cpp:321 internat.cpp:322
|
||||||
msgctxt "context_1"
|
msgctxt "context_1"
|
||||||
msgid "sing"
|
msgid "sing"
|
||||||
msgid_plural "plur"
|
msgid_plural "plur"
|
||||||
msgstr[0] "Singular form in context 1"
|
msgstr[0] "Singular form in context 1"
|
||||||
msgstr[1] "Plural form in context 1"
|
msgstr[1] "Plural form in context 1"
|
||||||
|
|
||||||
|
#: internat.cpp:323 internat.cpp:324
|
||||||
msgctxt "context_2"
|
msgctxt "context_2"
|
||||||
msgid "sing"
|
msgid "sing"
|
||||||
msgid_plural "plur"
|
msgid_plural "plur"
|
||||||
msgstr[0] "Singular form in context 2"
|
msgstr[0] "Singular form in context 2"
|
||||||
msgstr[1] "Plural form in context 2"
|
msgstr[1] "Plural form in context 2"
|
||||||
|
|
||||||
#: internat.cpp:98
|
#: internat.cpp:328
|
||||||
msgid "International wxWindows App"
|
msgid "Show coreutils &help"
|
||||||
msgstr "Application wxWindows internationale"
|
msgstr ""
|
||||||
|
|
||||||
#: internat.cpp:105
|
#: internat.cpp:331
|
||||||
msgid "&About"
|
msgid "&About"
|
||||||
msgstr "&A propos"
|
msgstr "&A propos"
|
||||||
|
|
||||||
#: internat.cpp:107
|
#: internat.cpp:336
|
||||||
msgid "E&xit"
|
|
||||||
msgstr "&Quitter"
|
|
||||||
|
|
||||||
#: internat.cpp:110
|
|
||||||
msgid "&Open bogus file"
|
|
||||||
msgstr "&Ouvrir un fichier"
|
|
||||||
|
|
||||||
#: internat.cpp:111
|
|
||||||
msgid "&Play a game"
|
|
||||||
msgstr "&Jouer"
|
|
||||||
|
|
||||||
#: internat.cpp:115
|
|
||||||
msgid "&Test"
|
msgid "&Test"
|
||||||
msgstr "&Test"
|
msgstr "&Test"
|
||||||
|
|
||||||
#: internat.cpp:138
|
#: internat.cpp:337
|
||||||
|
msgid "&Macro"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:343
|
||||||
|
msgctxt "standard Windows menu"
|
||||||
|
msgid "&Help"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:360
|
||||||
|
#, c-format
|
||||||
|
msgid "Current UI locale: %s; C locale: %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:373
|
||||||
|
#, c-format
|
||||||
|
msgid "UI locale name in English: %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:385
|
||||||
|
#, c-format
|
||||||
|
msgid "... and in the locale language: %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:396
|
||||||
|
msgid "Numeric input:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:417
|
||||||
|
msgid "Number"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:421
|
||||||
|
msgid "Date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:437
|
||||||
|
#, c-format
|
||||||
|
msgid "Number in UI locale: %s; in C locale: %.2f"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:457
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid ""
|
||||||
|
#| "I18n sample\n"
|
||||||
|
#| "© 1998, 1999 Vadim Zeitlin and Julian Smart"
|
||||||
msgid ""
|
msgid ""
|
||||||
"I18n sample\n"
|
"I18n sample\n"
|
||||||
"© 1998, 1999 Vadim Zeitlin and Julian Smart"
|
"(c) 1998, 1999 Vadim Zeitlin and Julian Smart"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Exemple d'i18n\n"
|
"Exemple d'i18n\n"
|
||||||
"© 1998, 1999 Vadim Zeitlin et Julian Smart"
|
"© 1998, 1999 Vadim Zeitlin et Julian Smart"
|
||||||
|
|
||||||
#: internat.cpp:139
|
#: internat.cpp:458
|
||||||
msgid "About Internat"
|
msgid "About Internat"
|
||||||
msgstr "A propos d'Internat"
|
msgstr "A propos d'Internat"
|
||||||
|
|
||||||
#: internat.cpp:144
|
#: internat.cpp:491
|
||||||
msgid "Enter your number:"
|
msgid "Enter your number:"
|
||||||
msgstr "Entrez votre numéro:"
|
msgstr "Entrez votre numéro:"
|
||||||
|
|
||||||
#: internat.cpp:145
|
#: internat.cpp:492
|
||||||
msgid "Try to guess my number!"
|
msgid "Try to guess my number!"
|
||||||
msgstr "Essayez de déviner mon numéro!"
|
msgstr "Essayez de déviner mon numéro!"
|
||||||
|
|
||||||
#: internat.cpp:150
|
#: internat.cpp:506
|
||||||
msgid "You've probably entered an invalid number."
|
msgid "You've probably entered an invalid number."
|
||||||
msgstr "Vous avez probablement entré un nombre invalide."
|
msgstr "Vous avez probablement entré un nombre invalide."
|
||||||
|
|
||||||
#: internat.cpp:154
|
#: internat.cpp:520
|
||||||
msgid "Bad luck! try again..."
|
|
||||||
msgstr "Pas de chance! essayez encore..."
|
|
||||||
|
|
||||||
#: internat.cpp:158
|
|
||||||
msgid "Congratulations! you've won. Here is the magic phrase:"
|
msgid "Congratulations! you've won. Here is the magic phrase:"
|
||||||
msgstr "Félicitations! vouz avez gagné. Voilà la phrase magique:"
|
msgstr "Félicitations! vouz avez gagné. Voilà la phrase magique:"
|
||||||
|
|
||||||
#: internat.cpp:162
|
#: internat.cpp:521
|
||||||
|
#, c-format
|
||||||
|
msgid "cannot create fifo `%s'"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:530
|
||||||
|
msgid "Bad luck! try again..."
|
||||||
|
msgstr "Pas de chance! essayez encore..."
|
||||||
|
|
||||||
|
#: internat.cpp:538
|
||||||
msgid "Result"
|
msgid "Result"
|
||||||
msgstr "Resultat"
|
msgstr "Resultat"
|
||||||
|
|
||||||
|
#: internat.cpp:546
|
||||||
|
msgid "Enter the locale to test"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:562
|
||||||
|
#, c-format
|
||||||
|
msgid ""
|
||||||
|
"Locale \"%s\" is available.\n"
|
||||||
|
"Identifier: %s; Layout: %s\n"
|
||||||
|
"English name: %s\n"
|
||||||
|
"Localized name: %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:569
|
||||||
|
#, c-format
|
||||||
|
msgid "Locale \"%s\" is not available."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:584
|
||||||
|
msgid "Dummy file dialog"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:589
|
||||||
|
msgid "Testing _() (gettext)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:597
|
||||||
|
msgid "Please enter text to translate"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:598
|
||||||
|
msgid "default value"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:612
|
||||||
|
msgid "Testing _N() (ngettext)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:614
|
||||||
|
msgid "Please enter range for plural forms of \"n files deleted\" phrase"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:626
|
||||||
|
msgid "file deleted"
|
||||||
|
msgid_plural "files deleted"
|
||||||
|
msgstr[0] ""
|
||||||
|
msgstr[1] ""
|
||||||
|
|
||||||
|
#: internat.cpp:637
|
||||||
|
msgid "line 1"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:638
|
||||||
|
msgid "line 2"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:639
|
||||||
|
msgid "line 3"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:642
|
||||||
|
msgid "Testing wxTRANSLATE() (gettext_noop)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:655
|
||||||
|
msgid ""
|
||||||
|
"Are the labels of the buttons in this message box translated into the "
|
||||||
|
"current locale language?"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:657
|
||||||
|
msgid "wxWidgets i18n sample"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: internat.cpp:662
|
||||||
|
msgid "Please report the details of your platform to us."
|
||||||
|
msgstr ""
|
||||||
|
|||||||
@@ -364,6 +364,30 @@ MyFrame::MyFrame()
|
|||||||
),
|
),
|
||||||
wxSizerFlags().Center().Border());
|
wxSizerFlags().Center().Border());
|
||||||
|
|
||||||
|
topSizer->Add(new wxStaticText
|
||||||
|
(
|
||||||
|
panel,
|
||||||
|
wxID_ANY,
|
||||||
|
wxString::Format
|
||||||
|
(
|
||||||
|
_("UI locale name in English: %s"),
|
||||||
|
wxUILocale::GetCurrent().GetLocalizedName(wxLOCALE_NAME_LOCALE, wxLOCALE_FORM_ENGLISH)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
wxSizerFlags().Center().Border());
|
||||||
|
|
||||||
|
topSizer->Add(new wxStaticText
|
||||||
|
(
|
||||||
|
panel,
|
||||||
|
wxID_ANY,
|
||||||
|
wxString::Format
|
||||||
|
(
|
||||||
|
_("... and in the locale language: %s"),
|
||||||
|
wxUILocale::GetCurrent().GetLocalizedName(wxLOCALE_NAME_LOCALE, wxLOCALE_FORM_NATIVE)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
wxSizerFlags().Center().Border());
|
||||||
|
|
||||||
// create some controls affected by the locale
|
// create some controls affected by the locale
|
||||||
|
|
||||||
// this demonstrates RTL layout mirroring for Arabic locales and using
|
// this demonstrates RTL layout mirroring for Arabic locales and using
|
||||||
@@ -528,16 +552,17 @@ void MyFrame::OnTestLocaleAvail(wxCommandEvent& WXUNUSED(event))
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
s_locale = locale;
|
s_locale = locale;
|
||||||
const wxLanguageInfo * const info = wxLocale::FindLanguageInfo(s_locale);
|
|
||||||
if ( !info )
|
|
||||||
{
|
|
||||||
wxLogError(_("Locale \"%s\" is unknown."), s_locale);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( wxLocale::IsAvailable(info->Language) )
|
wxUILocale uiLocale = wxUILocale::FromTag(s_locale);
|
||||||
|
if (uiLocale.IsSupported())
|
||||||
{
|
{
|
||||||
wxLogMessage(_("Locale \"%s\" is available."), s_locale);
|
wxLayoutDirection layout = uiLocale.GetLayoutDirection();
|
||||||
|
wxString strLayout = (layout == wxLayout_RightToLeft) ? "RTL" : "LTR";
|
||||||
|
wxString strLocale = uiLocale.GetLocalizedName(wxLOCALE_NAME_LOCALE, wxLOCALE_FORM_NATIVE);
|
||||||
|
wxLogMessage(_("Locale \"%s\" is available.\nIdentifier: %s; Layout: %s\nEnglish name: %s\nLocalized name: %s"),
|
||||||
|
s_locale, uiLocale.GetName(), strLayout,
|
||||||
|
uiLocale.GetLocalizedName(wxLOCALE_NAME_LOCALE, wxLOCALE_FORM_ENGLISH),
|
||||||
|
uiLocale.GetLocalizedName(wxLOCALE_NAME_LOCALE, wxLOCALE_FORM_NATIVE));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -166,24 +166,14 @@ const char* wxLanguageInfo::TrySetLocale() const
|
|||||||
|
|
||||||
wxString wxLanguageInfo::GetLocaleName() const
|
wxString wxLanguageInfo::GetLocaleName() const
|
||||||
{
|
{
|
||||||
const char* const orig = wxSetlocale(LC_ALL, NULL);
|
wxString localeId = CanonicalRef.empty() ? CanonicalName : CanonicalRef;
|
||||||
|
wxUILocale uiLocale = wxUILocale::FromTag(localeId);
|
||||||
const char* const ret = TrySetLocale();
|
wxString localeName = uiLocale.IsSupported() ? uiLocale.GetName() : wxString();
|
||||||
wxString retval;
|
return localeName;
|
||||||
if ( ret )
|
|
||||||
{
|
|
||||||
// Note that we must copy the returned value before calling setlocale()
|
|
||||||
// again as the string "ret" points to can (and, at least under Linux
|
|
||||||
// with glibc, actually always will) be changed by this call.
|
|
||||||
retval = ret;
|
|
||||||
wxSetlocale(LC_ALL, orig);
|
|
||||||
}
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxUILocale / wxLocale
|
// wxUILocale
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
static wxLanguageInfos gs_languagesDB;
|
static wxLanguageInfos gs_languagesDB;
|
||||||
@@ -217,233 +207,6 @@ void wxUILocale::DestroyLanguagesDB()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
|
|
||||||
#if defined(__UNIX__) && !defined(__WXOSX__)
|
|
||||||
// Small helper function: get the value of the given environment variable and
|
|
||||||
// return true only if the variable was found and has non-empty value.
|
|
||||||
inline bool wxGetNonEmptyEnvVar(const wxString& name, wxString* value)
|
|
||||||
{
|
|
||||||
return wxGetEnv(name, value) && !value->empty();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // anonymous namespace
|
|
||||||
|
|
||||||
/*static*/
|
|
||||||
int wxUILocale::GetSystemLanguage()
|
|
||||||
{
|
|
||||||
CreateLanguagesDB();
|
|
||||||
|
|
||||||
// init i to avoid compiler warning
|
|
||||||
size_t i = 0,
|
|
||||||
count = gs_languagesDB.size();
|
|
||||||
|
|
||||||
#ifdef __WXOSX__
|
|
||||||
wxCFRef<CFLocaleRef> userLocaleRef(CFLocaleCopyCurrent());
|
|
||||||
|
|
||||||
// because the locale identifier (kCFLocaleIdentifier) is formatted a little bit differently, eg
|
|
||||||
// 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)));
|
|
||||||
const wxString langPrefix = str.AsString() + "_";
|
|
||||||
|
|
||||||
str.reset(wxCFRetain((CFStringRef)CFLocaleGetValue(userLocaleRef, kCFLocaleCountryCode)));
|
|
||||||
const wxString langFull = langPrefix + str.AsString();
|
|
||||||
|
|
||||||
int langOnlyMatchIndex = wxNOT_FOUND;
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
const wxString& fullname = gs_languagesDB[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))
|
|
||||||
{
|
|
||||||
// no language specified, treat it as English
|
|
||||||
return wxLANGUAGE_ENGLISH_US;
|
|
||||||
}
|
|
||||||
|
|
||||||
// the language string has the following form
|
|
||||||
//
|
|
||||||
// lang[_LANG][.encoding][@modifier]
|
|
||||||
//
|
|
||||||
// (see environ(5) in the Open Unix specification)
|
|
||||||
//
|
|
||||||
// where lang is the primary language, LANG is a sublang/territory,
|
|
||||||
// encoding is the charset to use and modifier "allows the user to select
|
|
||||||
// a specific instance of localization data within a single category"
|
|
||||||
//
|
|
||||||
// for example, the following strings are valid:
|
|
||||||
// fr
|
|
||||||
// fr_FR
|
|
||||||
// de_DE.iso88591
|
|
||||||
// de_DE@euro
|
|
||||||
// de_DE.iso88591@euro
|
|
||||||
|
|
||||||
// for now we don't use the encoding, although we probably should (doing
|
|
||||||
// translations of the msg catalogs on the fly as required) (TODO)
|
|
||||||
//
|
|
||||||
// we need the modified for languages like Valencian: ca_ES@valencia
|
|
||||||
// though, remember it
|
|
||||||
wxString modifier;
|
|
||||||
size_t posModifier = langFull.find_first_of(wxS("@"));
|
|
||||||
if (posModifier != wxString::npos)
|
|
||||||
modifier = langFull.Mid(posModifier);
|
|
||||||
|
|
||||||
size_t posEndLang = langFull.find_first_of(wxS("@."));
|
|
||||||
if (posEndLang != wxString::npos)
|
|
||||||
{
|
|
||||||
langFull.Truncate(posEndLang);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (langFull == wxS("C") || langFull == wxS("POSIX"))
|
|
||||||
{
|
|
||||||
// default C locale is English too
|
|
||||||
return wxLANGUAGE_ENGLISH_US;
|
|
||||||
}
|
|
||||||
|
|
||||||
// do we have just the language (or sublang too)?
|
|
||||||
const bool justLang = langFull.find('_') == wxString::npos;
|
|
||||||
|
|
||||||
// 0. Make sure the lang is according to latest ISO 639
|
|
||||||
// (this is necessary because glibc uses iw and in instead
|
|
||||||
// of he and id respectively).
|
|
||||||
|
|
||||||
// the language itself (second part is the dialect/sublang)
|
|
||||||
wxString langOrig = ExtractLang(langFull);
|
|
||||||
|
|
||||||
wxString lang;
|
|
||||||
if (langOrig == wxS("iw"))
|
|
||||||
lang = wxS("he");
|
|
||||||
else if (langOrig == wxS("in"))
|
|
||||||
lang = wxS("id");
|
|
||||||
else if (langOrig == wxS("ji"))
|
|
||||||
lang = wxS("yi");
|
|
||||||
else if (langOrig == wxS("no_NO"))
|
|
||||||
lang = wxS("nb_NO");
|
|
||||||
else if (langOrig == wxS("no_NY"))
|
|
||||||
lang = wxS("nn_NO");
|
|
||||||
else if (langOrig == wxS("no"))
|
|
||||||
lang = wxS("nb_NO");
|
|
||||||
else
|
|
||||||
lang = langOrig;
|
|
||||||
|
|
||||||
// did we change it?
|
|
||||||
if (lang != langOrig)
|
|
||||||
{
|
|
||||||
langFull = lang + ExtractNotLang(langFull);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1. Try to find the language either as is:
|
|
||||||
// a) With modifier if set
|
|
||||||
if (!modifier.empty())
|
|
||||||
{
|
|
||||||
wxString langFullWithModifier = langFull + modifier;
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
if (gs_languagesDB[i].CanonicalName == langFullWithModifier)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// b) Without modifier
|
|
||||||
if (modifier.empty() || i == count)
|
|
||||||
{
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
if (gs_languagesDB[i].CanonicalName == langFull)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. If langFull is of the form xx_YY, try to find xx:
|
|
||||||
if (i == count && !justLang)
|
|
||||||
{
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
if (ExtractLang(gs_languagesDB[i].CanonicalName) == lang)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. If langFull is of the form xx, try to find any xx_YY record:
|
|
||||||
if (i == count && justLang)
|
|
||||||
{
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
if (ExtractLang(gs_languagesDB[i].CanonicalName) == langFull)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (i == count)
|
|
||||||
{
|
|
||||||
// In addition to the format above, we also can have full language
|
|
||||||
// names in LANG env var - for example, SuSE is known to use
|
|
||||||
// LANG="german" - so check for use of non-standard format and try to
|
|
||||||
// find the name in verbose description.
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
if (gs_languagesDB[i].Description.CmpNoCase(langFull) == 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#elif defined(__WIN32__)
|
|
||||||
const LANGID langid = ::GetUserDefaultUILanguage();
|
|
||||||
if (langid != LOCALE_CUSTOM_UI_DEFAULT)
|
|
||||||
{
|
|
||||||
wxUint32 lang = PRIMARYLANGID(langid);
|
|
||||||
wxUint32 sublang = SUBLANGID(langid);
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
if (gs_languagesDB[i].WinLang == lang &&
|
|
||||||
gs_languagesDB[i].WinSublang == sublang)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//else: leave wxlang == wxLANGUAGE_UNKNOWN
|
|
||||||
#endif // Unix/Win32
|
|
||||||
|
|
||||||
if (i < count)
|
|
||||||
{
|
|
||||||
// we did find a matching entry, use it
|
|
||||||
return gs_languagesDB[i].Language;
|
|
||||||
}
|
|
||||||
|
|
||||||
// no info about this language in the database
|
|
||||||
return wxLANGUAGE_UNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
void wxUILocale::AddLanguage(const wxLanguageInfo& info)
|
void wxUILocale::AddLanguage(const wxLanguageInfo& info)
|
||||||
{
|
{
|
||||||
@@ -451,95 +214,6 @@ void wxUILocale::AddLanguage(const wxLanguageInfo& info)
|
|||||||
gs_languagesDB.push_back(info);
|
gs_languagesDB.push_back(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
|
||||||
const wxLanguageInfo* wxUILocale::GetLanguageInfo(int lang)
|
|
||||||
{
|
|
||||||
CreateLanguagesDB();
|
|
||||||
|
|
||||||
// calling GetLanguageInfo(wxLANGUAGE_DEFAULT) is a natural thing to do, so
|
|
||||||
// make it work
|
|
||||||
if (lang == wxLANGUAGE_DEFAULT)
|
|
||||||
lang = GetSystemLanguage();
|
|
||||||
|
|
||||||
if (lang == wxLANGUAGE_UNKNOWN)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
const size_t count = gs_languagesDB.size();
|
|
||||||
for (size_t i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
if (gs_languagesDB[i].Language == lang)
|
|
||||||
return &gs_languagesDB[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* static */
|
|
||||||
wxString wxUILocale::GetLanguageName(int lang)
|
|
||||||
{
|
|
||||||
wxString string;
|
|
||||||
|
|
||||||
if (lang == wxLANGUAGE_DEFAULT || lang == wxLANGUAGE_UNKNOWN)
|
|
||||||
return string;
|
|
||||||
|
|
||||||
const wxLanguageInfo* info = GetLanguageInfo(lang);
|
|
||||||
if (info)
|
|
||||||
string = info->Description;
|
|
||||||
|
|
||||||
return string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* static */
|
|
||||||
wxString wxUILocale::GetLanguageCanonicalName(int lang)
|
|
||||||
{
|
|
||||||
wxString string;
|
|
||||||
|
|
||||||
if (lang == wxLANGUAGE_DEFAULT || lang == wxLANGUAGE_UNKNOWN)
|
|
||||||
return string;
|
|
||||||
|
|
||||||
const wxLanguageInfo* info = GetLanguageInfo(lang);
|
|
||||||
if (info)
|
|
||||||
string = info->CanonicalName;
|
|
||||||
|
|
||||||
return string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* static */
|
|
||||||
const wxLanguageInfo* wxUILocale::FindLanguageInfo(const wxString& locale)
|
|
||||||
{
|
|
||||||
CreateLanguagesDB();
|
|
||||||
|
|
||||||
const wxLanguageInfo* infoRet = NULL;
|
|
||||||
|
|
||||||
const size_t count = gs_languagesDB.size();
|
|
||||||
for (size_t i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
const wxLanguageInfo* info = &gs_languagesDB[i];
|
|
||||||
|
|
||||||
if (wxStricmp(locale, info->CanonicalName) == 0 ||
|
|
||||||
wxStricmp(locale, info->Description) == 0)
|
|
||||||
{
|
|
||||||
// exact match, stop searching
|
|
||||||
infoRet = info;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wxStricmp(locale, info->CanonicalName.BeforeFirst(wxS('_'))) == 0)
|
|
||||||
{
|
|
||||||
// a match -- but maybe we'll find an exact one later, so continue
|
|
||||||
// looking
|
|
||||||
//
|
|
||||||
// OTOH, maybe we had already found a language match and in this
|
|
||||||
// case don't overwrite it because the entry for the default
|
|
||||||
// country always appears first in gs_languagesDB
|
|
||||||
if (!infoRet)
|
|
||||||
infoRet = info;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return infoRet;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxLocale
|
// wxLocale
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -629,9 +303,25 @@ bool wxLocale::Init(const wxString& name,
|
|||||||
|
|
||||||
DoInit(name, strShort, wxLANGUAGE_UNKNOWN);
|
DoInit(name, strShort, wxLANGUAGE_UNKNOWN);
|
||||||
|
|
||||||
const bool ret = wxSetlocale(LC_ALL, szLocale) != NULL;
|
#if defined(__UNIX__) || defined(__WIN32__)
|
||||||
|
const wxString oldUILocale = wxUILocale::GetCurrent().GetName();
|
||||||
|
bool ok = wxUILocale::UseLocaleName(szLocale);
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
m_oldUILocale = oldUILocale;
|
||||||
|
}
|
||||||
|
|
||||||
return DoCommonPostInit(ret, szLocale, shortName, bLoadDefault);
|
// 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__)
|
||||||
|
ok = wxSetlocale(LC_ALL, szLocale) != NULL;
|
||||||
|
#endif // __WIN32__
|
||||||
|
|
||||||
|
#else
|
||||||
|
bool ok = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return DoCommonPostInit(ok, szLocale, shortName, bLoadDefault);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxLocale::DoInit(const wxString& name,
|
void wxLocale::DoInit(const wxString& name,
|
||||||
@@ -740,7 +430,7 @@ bool wxLocale::Init(int lang, int flags)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
name = info->Description;
|
name = info->Description;
|
||||||
shortName = info->CanonicalName;
|
shortName = info->CanonicalRef.empty() ? info->CanonicalName : info->CanonicalRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
DoInit(name, shortName, lang);
|
DoInit(name, shortName, lang);
|
||||||
@@ -748,9 +438,14 @@ bool wxLocale::Init(int lang, int flags)
|
|||||||
// Set the locale:
|
// Set the locale:
|
||||||
|
|
||||||
#if defined(__UNIX__) || defined(__WIN32__)
|
#if defined(__UNIX__) || defined(__WIN32__)
|
||||||
|
const wxString oldUILocale = wxUILocale::GetCurrent().GetName();
|
||||||
|
|
||||||
bool ok = lang == wxLANGUAGE_DEFAULT ? wxUILocale::UseDefault()
|
bool ok = lang == wxLANGUAGE_DEFAULT ? wxUILocale::UseDefault()
|
||||||
: wxUILocale::UseLanguage(*info);
|
: wxUILocale::UseLocaleName(shortName);
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
m_oldUILocale = oldUILocale;
|
||||||
|
}
|
||||||
|
|
||||||
// Under (non-Darwn) Unix wxUILocale already set the C locale, but under
|
// Under (non-Darwn) Unix wxUILocale already set the C locale, but under
|
||||||
// the other platforms we still have to do it here.
|
// the other platforms we still have to do it here.
|
||||||
@@ -1015,15 +710,17 @@ wxLocale::~wxLocale()
|
|||||||
// restore old locale pointer
|
// restore old locale pointer
|
||||||
wxSetLocale(m_pOldLocale);
|
wxSetLocale(m_pOldLocale);
|
||||||
|
|
||||||
|
// and old current wxUILocale
|
||||||
|
if (!m_oldUILocale.empty())
|
||||||
|
{
|
||||||
|
wxUILocale::UseLocaleName(m_oldUILocale);
|
||||||
|
}
|
||||||
|
|
||||||
if ( m_pszOldLocale )
|
if ( m_pszOldLocale )
|
||||||
{
|
{
|
||||||
wxSetlocale(LC_ALL, m_pszOldLocale);
|
wxSetlocale(LC_ALL, m_pszOldLocale);
|
||||||
free(const_cast<char *>(m_pszOldLocale));
|
free(const_cast<char *>(m_pszOldLocale));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __WIN32__
|
|
||||||
wxUseLCID(m_oldLCID);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1041,51 +738,10 @@ bool wxLocale::IsAvailable(int lang)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__WIN32__)
|
wxString localeTag = info->CanonicalRef.empty() ? info->LocaleTag : info->CanonicalRef;
|
||||||
if ( !info->WinLang )
|
wxUILocale uiLocale(wxLocaleIdent::FromTag(localeTag));
|
||||||
return false;
|
|
||||||
|
|
||||||
if ( !::IsValidLocale(info->GetLCID(), LCID_INSTALLED) )
|
return uiLocale.IsSupported();
|
||||||
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.
|
|
||||||
char * const oldLocale = wxStrdupA(setlocale(LC_ALL, NULL));
|
|
||||||
|
|
||||||
wxLocaleIdent locId;
|
|
||||||
wxString region;
|
|
||||||
locId.Language(info->CanonicalName.BeforeFirst('_', ®ion));
|
|
||||||
if ( !region.empty() )
|
|
||||||
{
|
|
||||||
// We never have encoding in our canonical names, but we can have
|
|
||||||
// modifiers, so take them into account.
|
|
||||||
wxString mod;
|
|
||||||
locId.Region(region.BeforeFirst('@', &mod));
|
|
||||||
|
|
||||||
if ( !mod.empty() )
|
|
||||||
locId.Modifier(mod);
|
|
||||||
}
|
|
||||||
|
|
||||||
const bool available = wxSetlocaleTryAll(LC_ALL, locId);
|
|
||||||
|
|
||||||
// restore the original locale
|
|
||||||
wxSetlocale(LC_ALL, oldLocale);
|
|
||||||
|
|
||||||
free(oldLocale);
|
|
||||||
|
|
||||||
if ( !available )
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1578,38 +1234,6 @@ LCTYPE wxGetLCTYPEFormatFromLocalInfo(wxLocaleInfo index)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
|
|
||||||
// This private function additionally checks consistency of the decimal
|
|
||||||
// separator settings between MSW and CRT.
|
|
||||||
wxString
|
|
||||||
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.
|
// This function is also used by wxUILocaleImpl, so don't make it private.
|
||||||
wxString
|
wxString
|
||||||
wxGetInfoFromLCID(LCID lcid, wxLocaleInfo index, wxLocaleCategory cat)
|
wxGetInfoFromLCID(LCID lcid, wxLocaleInfo index, wxLocaleCategory cat)
|
||||||
@@ -1680,35 +1304,13 @@ wxGetInfoFromLCID(LCID lcid, wxLocaleInfo index, wxLocaleCategory cat)
|
|||||||
/* static */
|
/* static */
|
||||||
wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory cat)
|
wxString wxLocale::GetInfo(wxLocaleInfo index, wxLocaleCategory cat)
|
||||||
{
|
{
|
||||||
if ( !wxGetLocale() )
|
return wxUILocale::GetCurrent().GetInfo(index, cat);
|
||||||
{
|
|
||||||
// wxSetLocale() hadn't been called yet of failed, hence CRT must be
|
|
||||||
// using "C" locale -- but check it to detect bugs that would happen if
|
|
||||||
// this were not the case.
|
|
||||||
wxASSERT_MSG( strcmp(setlocale(LC_ALL, NULL), "C") == 0,
|
|
||||||
wxS("You probably called setlocale() directly instead ")
|
|
||||||
wxS("of using wxLocale and now there is a ")
|
|
||||||
wxS("mismatch between C/C++ and Windows locale.\n")
|
|
||||||
wxS("Things are going to break, please only change ")
|
|
||||||
wxS("locale by creating wxLocale objects to avoid this!") );
|
|
||||||
|
|
||||||
|
|
||||||
// Return the hard coded values for C locale. This is really the right
|
|
||||||
// thing to do as there is no LCID we can use in the code below in this
|
|
||||||
// case, even LOCALE_INVARIANT is not quite the same as C locale (the
|
|
||||||
// only difference is that it uses %Y instead of %y in the date format
|
|
||||||
// but this difference is significant enough).
|
|
||||||
return wxGetStdCLocaleInfo(index, cat);
|
|
||||||
}
|
|
||||||
|
|
||||||
// wxSetLocale() succeeded and so thread locale was set together with CRT one.
|
|
||||||
return GetInfoFromLCID(::GetThreadLocale(), index, cat);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
wxString wxLocale::GetOSInfo(wxLocaleInfo index, wxLocaleCategory cat)
|
wxString wxLocale::GetOSInfo(wxLocaleInfo index, wxLocaleCategory cat)
|
||||||
{
|
{
|
||||||
return GetInfoFromLCID(::GetThreadLocale(), index, cat);
|
return wxUILocale::GetCurrent().GetInfo(index, cat);
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(__WXOSX__)
|
#elif defined(__WXOSX__)
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include "wx/uilocale.h"
|
#include "wx/uilocale.h"
|
||||||
|
|
||||||
#include "wx/arrstr.h"
|
#include "wx/arrstr.h"
|
||||||
|
#include "wx/intl.h"
|
||||||
|
|
||||||
#ifndef __WINDOWS__
|
#ifndef __WINDOWS__
|
||||||
#include "wx/language.h"
|
#include "wx/language.h"
|
||||||
@@ -30,6 +31,35 @@
|
|||||||
|
|
||||||
#include "wx/private/uilocale.h"
|
#include "wx/private/uilocale.h"
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// helper functions
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
const char* validCharsAlpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
|
const char* validCharsAlnum = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||||
|
const char* validCharsModExt = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-";
|
||||||
|
const char* validCharsTag = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.@";
|
||||||
|
|
||||||
|
// Handle special case "ca-ES-valencia"
|
||||||
|
// Sync attributes modifier and extension
|
||||||
|
inline void CheckLanguageVariant(wxLocaleIdent& locId)
|
||||||
|
{
|
||||||
|
if (locId.GetModifier().IsSameAs("valencia"))
|
||||||
|
{
|
||||||
|
locId.Extension(locId.GetModifier());
|
||||||
|
}
|
||||||
|
else if (locId.GetExtension().IsSameAs("valencia") && locId.GetModifier().empty())
|
||||||
|
{
|
||||||
|
locId.Modifier(locId.GetExtension());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// global variables
|
// global variables
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -50,27 +80,97 @@ wxUILocale wxUILocale::ms_current;
|
|||||||
/* static */
|
/* static */
|
||||||
wxLocaleIdent wxLocaleIdent::FromTag(const wxString& tag)
|
wxLocaleIdent wxLocaleIdent::FromTag(const wxString& tag)
|
||||||
{
|
{
|
||||||
|
// This method accepts tags in various formats: BCP47, Windows, POSIX, and macOS.
|
||||||
|
//
|
||||||
// See section 2.01 of https://www.rfc-editor.org/rfc/bcp/bcp47.txt for the
|
// See section 2.01 of https://www.rfc-editor.org/rfc/bcp/bcp47.txt for the
|
||||||
// full syntax. Here we fully support just the subset we're interested in:
|
// full syntax. Here we fully support just the subset we're interested in:
|
||||||
//
|
//
|
||||||
// - Normal language tags (not private use or grandfathered ones).
|
// - Normal language tags (not private use or grandfathered ones).
|
||||||
// - Only script and region, but not the extensions or extlangs.
|
// - Script and region.
|
||||||
|
//
|
||||||
|
// Additionally platform-specific tags are supported:
|
||||||
|
// - Extensions (without validity checks) (Windows only).
|
||||||
|
// - Charset and modifier (POSIX only)
|
||||||
|
//
|
||||||
|
// Only language, script, and region are supported across all platforms.
|
||||||
|
// The script tag is mapped to the modifier for POSIX platforms.
|
||||||
|
// The script tag takes precedence, if a modifier is also specified.
|
||||||
|
//
|
||||||
|
// The following tag syntax is accepted:
|
||||||
|
// BCP47: language[-script][-region][-extension]
|
||||||
|
// Windows: language[-script][-region][-extension][_sortorder]
|
||||||
|
// POSIX: language[_region][.charset][@modifier]
|
||||||
|
// macOS: language[-script][_region]
|
||||||
|
|
||||||
// Language tags must always use ASCII.
|
// Locale tags must always use alphanumeric characters and certain special characters "-_.@"
|
||||||
if ( tag != tag.ToAscii() )
|
if (tag.find_first_not_of(validCharsTag) != wxString::npos)
|
||||||
|
{
|
||||||
|
wxFAIL_MSG("tag contains invalid characters (not alphanumeric) or invalid delimiters");
|
||||||
return wxLocaleIdent();
|
return wxLocaleIdent();
|
||||||
|
}
|
||||||
|
|
||||||
const wxArrayString& parts = wxSplit(tag, '-', '\0');
|
wxLocaleIdent locId;
|
||||||
|
|
||||||
|
// 1. Handle platform-dependent cases
|
||||||
|
|
||||||
|
// 1a. Check for modifier in POSIX tag
|
||||||
|
wxString tagRest;
|
||||||
|
wxString tagMain = tag.BeforeFirst('@', &tagRest);
|
||||||
|
if (!tagRest.empty())
|
||||||
|
{
|
||||||
|
// POSIX modifier found
|
||||||
|
wxString script = wxUILocale::GetScriptNameFromAlias(tagRest);
|
||||||
|
if (!script.empty())
|
||||||
|
locId.Script(script);
|
||||||
|
else
|
||||||
|
locId.Modifier(tagRest);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxASSERT_MSG(tag.find('@') == wxString::npos, "modifier delimiter found, but modifier is empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1b. Check for charset in POSIX tag
|
||||||
|
tagMain = tagMain.BeforeFirst('.', &tagRest);
|
||||||
|
if (!tagRest.empty())
|
||||||
|
{
|
||||||
|
// POSIX charset found
|
||||||
|
locId.Charset(tagRest);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxASSERT_MSG(tagMain.find('.') == wxString::npos, "charset delimiter found, but charset is empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1c. Check for sort order in Windows tag
|
||||||
|
//
|
||||||
|
// Make sure we don't extract the region identifier erroneously as a sortorder identifier
|
||||||
|
wxString tagTemp = tagMain.BeforeFirst('_', &tagRest);
|
||||||
|
if (tagRest.length() > 4 && locId.m_modifier.empty() && locId.m_charset.empty())
|
||||||
|
{
|
||||||
|
// Windows sortorder found
|
||||||
|
locId.SortOrder(tagRest);
|
||||||
|
tagMain = tagTemp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Handle remaining tag identifier as being BCP47-like
|
||||||
|
|
||||||
|
// Now that special POSIX attributes have been handled
|
||||||
|
// POSIX specific delimiters must no longer be present
|
||||||
|
wxASSERT_MSG(tagMain.find_first_of(".@") == wxString::npos, "tag contains invalid delimiters");
|
||||||
|
|
||||||
|
// Replace '_' separators by '-' to simplify further processing
|
||||||
|
tagMain.Replace("_", "-");
|
||||||
|
|
||||||
|
const wxArrayString& parts = wxSplit(tagMain, '-', '\0');
|
||||||
wxArrayString::const_iterator it = parts.begin();
|
wxArrayString::const_iterator it = parts.begin();
|
||||||
if ( it == parts.end() )
|
if ( it == parts.end() )
|
||||||
return wxLocaleIdent();
|
return wxLocaleIdent();
|
||||||
|
|
||||||
// We have at least the language, so we'll return a valid object.
|
// We have at least the language, so we'll return a valid object.
|
||||||
wxLocaleIdent locId;
|
locId.m_language = (*it).Lower();
|
||||||
locId.m_language = *it;
|
|
||||||
|
|
||||||
// Also store the full string, so that the platforms that support BCP 47
|
// Also store the full string.
|
||||||
// natively can use it instead of reconstructing the string from our fields.
|
|
||||||
locId.m_tag = tag;
|
locId.m_tag = tag;
|
||||||
|
|
||||||
if ( ++it == parts.end() )
|
if ( ++it == parts.end() )
|
||||||
@@ -103,82 +203,209 @@ wxLocaleIdent wxLocaleIdent::FromTag(const wxString& tag)
|
|||||||
case 2:
|
case 2:
|
||||||
case 3:
|
case 3:
|
||||||
// Either an ISO 3166-1 or UN M.49 region code.
|
// Either an ISO 3166-1 or UN M.49 region code.
|
||||||
locId.m_region = *it;
|
locId.m_region = (*it).Upper();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
// Must be an ISO 15924 script.
|
// Must be an ISO 15924 script.
|
||||||
locId.m_script = *it;
|
wxASSERT_MSG(locId.m_script.empty(), "script already set");
|
||||||
|
locId.m_script = (*it).Left(1).Upper() + (*it).Mid(2).Lower();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// This looks to be completely invalid.
|
// This looks to be completely invalid.
|
||||||
|
wxFAIL_MSG("invalid code length, script or region code expected");
|
||||||
return wxLocaleIdent();
|
return wxLocaleIdent();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we got the language and the region, we can't parse anything else
|
// Check whether we have got the region above.
|
||||||
// (variants, extensions, private use) anyhow.
|
// If not, we must have got the script. So, check if we have the region, too.
|
||||||
if ( !locId.m_region.empty() )
|
if (++it == parts.end())
|
||||||
|
{
|
||||||
|
CheckLanguageVariant(locId);
|
||||||
return locId;
|
return locId;
|
||||||
|
}
|
||||||
|
|
||||||
// Otherwise we must have got the script above, so check if we have the
|
if (locId.m_region.empty())
|
||||||
// region too.
|
{
|
||||||
if ( ++it == parts.end() )
|
switch (it->length())
|
||||||
return locId;
|
|
||||||
|
|
||||||
switch ( it->length() )
|
|
||||||
{
|
{
|
||||||
case 2:
|
case 2:
|
||||||
case 3:
|
case 3:
|
||||||
locId.m_region = *it;
|
locId.m_region = (*it).Upper(); ++it;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is still anything to parse (variants, extensions, private use),
|
||||||
|
// we assign it to the extension.
|
||||||
|
if (it != parts.end())
|
||||||
|
{
|
||||||
|
wxString custom = *it;
|
||||||
|
while (++it != parts.end())
|
||||||
|
{
|
||||||
|
custom << "-" << *it;
|
||||||
|
}
|
||||||
|
locId.m_extension = custom;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We also handle the only language variant known at the time of writing:
|
||||||
|
// valencia (ca-ES-valencia resp ca_ES@valencia).
|
||||||
|
CheckLanguageVariant(locId);
|
||||||
|
|
||||||
return locId;
|
return locId;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxLocaleIdent& wxLocaleIdent::Language(const wxString& language)
|
wxLocaleIdent& wxLocaleIdent::Language(const wxString& language)
|
||||||
{
|
{
|
||||||
m_language = language;
|
if (language.IsSameAs("C", false) || language.IsSameAs("POSIX", false))
|
||||||
|
{
|
||||||
|
m_language = language.Upper();
|
||||||
|
}
|
||||||
|
else if ((language.length() == 2 || language.length() == 3) &&
|
||||||
|
language.find_first_not_of(validCharsAlpha) == wxString::npos)
|
||||||
|
{
|
||||||
|
m_language = language.Lower();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_language.clear();
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxLocaleIdent& wxLocaleIdent::Region(const wxString& region)
|
wxLocaleIdent& wxLocaleIdent::Region(const wxString& region)
|
||||||
{
|
{
|
||||||
m_region = region;
|
if ((region.length() == 2 || region.length() == 3) &&
|
||||||
|
region.find_first_not_of(validCharsAlnum) == wxString::npos)
|
||||||
|
{
|
||||||
|
m_region = region.Upper();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_region.clear();
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxLocaleIdent& wxLocaleIdent::Script(const wxString& script)
|
wxLocaleIdent& wxLocaleIdent::Script(const wxString& script)
|
||||||
{
|
{
|
||||||
m_script = script;
|
if (script.length() == 4 &&
|
||||||
|
script.find_first_not_of(validCharsAlpha) == wxString::npos)
|
||||||
|
{
|
||||||
|
// Capitalize first character
|
||||||
|
m_script = script.Left(1).Upper() + script.Mid(2).Lower();
|
||||||
|
}
|
||||||
|
else if (!script.empty())
|
||||||
|
{
|
||||||
|
m_script = wxUILocale::GetScriptNameFromAlias(script.Lower());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_script.clear();
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxLocaleIdent& wxLocaleIdent::Charset(const wxString& charset)
|
wxLocaleIdent& wxLocaleIdent::Charset(const wxString& charset)
|
||||||
{
|
{
|
||||||
|
if (charset.find_first_not_of(validCharsModExt) == wxString::npos)
|
||||||
|
{
|
||||||
m_charset = charset;
|
m_charset = charset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_charset.clear();
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxLocaleIdent& wxLocaleIdent::Modifier(const wxString& modifier)
|
wxLocaleIdent& wxLocaleIdent::Modifier(const wxString& modifier)
|
||||||
{
|
{
|
||||||
|
if (modifier.find_first_not_of(validCharsModExt) == wxString::npos)
|
||||||
|
{
|
||||||
m_modifier = modifier;
|
m_modifier = modifier;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_modifier.clear();
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString wxLocaleIdent::GetTag() const
|
wxLocaleIdent& wxLocaleIdent::Extension(const wxString& extension)
|
||||||
{
|
{
|
||||||
if ( !m_tag.empty() )
|
// Windows extensions follow the BCP 47 syntax
|
||||||
|
if (extension.find_first_not_of(validCharsModExt) == wxString::npos)
|
||||||
|
{
|
||||||
|
m_extension = extension;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxLocaleIdent& wxLocaleIdent::SortOrder(const wxString& sortorder)
|
||||||
|
{
|
||||||
|
// Windows sortorder identifiers all seem to have a length of 6 characters.
|
||||||
|
// To distinguish sortorder from script and region identifiers require length > 4.
|
||||||
|
if (sortorder.length() > 4 &&
|
||||||
|
sortorder.find_first_not_of(validCharsAlpha) == wxString::npos)
|
||||||
|
{
|
||||||
|
m_sortorder = sortorder;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString wxLocaleIdent::GetTag(wxLocaleTagType tagType) const
|
||||||
|
{
|
||||||
|
if (tagType == wxLOCALE_TAGTYPE_DEFAULT && !m_tag.empty() )
|
||||||
return m_tag;
|
return m_tag;
|
||||||
|
|
||||||
wxString tag = m_language;
|
wxString tag = m_language;
|
||||||
|
switch (tagType)
|
||||||
if ( !m_script.empty() )
|
{
|
||||||
|
case wxLOCALE_TAGTYPE_BCP47:
|
||||||
|
if (!m_script.empty())
|
||||||
tag << '-' << m_script;
|
tag << '-' << m_script;
|
||||||
|
if (!m_region.empty())
|
||||||
if ( !m_region.empty() )
|
|
||||||
tag << '-' << m_region;
|
tag << '-' << m_region;
|
||||||
|
if (!m_extension.empty())
|
||||||
|
tag << '-' << m_extension;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case wxLOCALE_TAGTYPE_MACOS:
|
||||||
|
if (!m_script.empty())
|
||||||
|
tag << '-' << m_script;
|
||||||
|
if (!m_region.empty())
|
||||||
|
tag << '_' << m_region;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case wxLOCALE_TAGTYPE_POSIX:
|
||||||
|
if (!m_region.empty())
|
||||||
|
tag << '_' << m_region;
|
||||||
|
if (!m_charset.empty())
|
||||||
|
tag << '.' << m_charset;
|
||||||
|
if (!m_script.empty())
|
||||||
|
tag << '@' << wxUILocale::GetScriptAliasFromName(m_script);
|
||||||
|
else if (!m_modifier.empty())
|
||||||
|
tag << '@' << m_modifier;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case wxLOCALE_TAGTYPE_WINDOWS:
|
||||||
|
if (!m_script.empty())
|
||||||
|
tag << '-' << m_script;
|
||||||
|
if (!m_region.empty())
|
||||||
|
tag << '-' << m_region;
|
||||||
|
if (!m_extension.empty())
|
||||||
|
tag << '-' << m_extension;
|
||||||
|
if (!m_sortorder.empty())
|
||||||
|
tag << '-' << m_sortorder;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case wxLOCALE_TAGTYPE_SYSTEM:
|
||||||
|
default:
|
||||||
|
tag = GetName();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
@@ -240,10 +467,31 @@ bool wxUILocale::UseDefault()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
bool wxUILocale::UseLanguage(const wxLanguageInfo& info)
|
bool wxUILocale::UseLocaleName(const wxString& localeName)
|
||||||
{
|
{
|
||||||
wxUILocaleImpl* const impl = wxUILocaleImpl::CreateForLanguage(info);
|
wxUILocaleImpl* impl = NULL;
|
||||||
if ( !impl )
|
if (localeName.IsSameAs("C", false) || localeName.IsSameAs("POSIX", false))
|
||||||
|
{
|
||||||
|
impl = wxUILocaleImpl::CreateStdC();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxLocaleIdent localeId = wxLocaleIdent::FromTag(localeName);
|
||||||
|
impl = wxUILocaleImpl::CreateForLocale(localeId);
|
||||||
|
if (!impl)
|
||||||
|
{
|
||||||
|
// Creating the locale may have failed due to lacking support for wxUILocaleImplName
|
||||||
|
// Try to locate the locale in our language database
|
||||||
|
const wxLanguageInfo* const info = wxUILocale::FindLanguageInfo(localeId);
|
||||||
|
if (info)
|
||||||
|
{
|
||||||
|
// Language found in language database
|
||||||
|
// Try to create a locale based on the language
|
||||||
|
impl = wxUILocaleImpl::CreateForLanguage(*info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!impl)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
impl->Use();
|
impl->Use();
|
||||||
@@ -308,6 +556,14 @@ wxString wxUILocale::GetName() const
|
|||||||
return m_impl->GetName();
|
return m_impl->GetName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxLocaleIdent wxUILocale::GetLocaleId() const
|
||||||
|
{
|
||||||
|
if (!m_impl)
|
||||||
|
return wxLocaleIdent();
|
||||||
|
|
||||||
|
return m_impl->GetLocaleId();
|
||||||
|
}
|
||||||
|
|
||||||
wxString wxUILocale::GetInfo(wxLocaleInfo index, wxLocaleCategory cat) const
|
wxString wxUILocale::GetInfo(wxLocaleInfo index, wxLocaleCategory cat) const
|
||||||
{
|
{
|
||||||
if ( !m_impl )
|
if ( !m_impl )
|
||||||
@@ -316,6 +572,35 @@ wxString wxUILocale::GetInfo(wxLocaleInfo index, wxLocaleCategory cat) const
|
|||||||
return m_impl->GetInfo(index, cat);
|
return m_impl->GetInfo(index, cat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxString wxUILocale::GetLocalizedName(wxLocaleName name, wxLocaleForm form) const
|
||||||
|
{
|
||||||
|
if (!m_impl)
|
||||||
|
return wxString();
|
||||||
|
|
||||||
|
return m_impl->GetLocalizedName(name, form);
|
||||||
|
}
|
||||||
|
|
||||||
|
wxLayoutDirection wxUILocale::GetLayoutDirection() const
|
||||||
|
{
|
||||||
|
if (!m_impl)
|
||||||
|
return wxLayout_Default;
|
||||||
|
|
||||||
|
wxLayoutDirection dir = m_impl->GetLayoutDirection();
|
||||||
|
if (dir == wxLayout_Default)
|
||||||
|
{
|
||||||
|
wxLocaleIdent localeId = m_impl->GetLocaleId();
|
||||||
|
if (!localeId.IsEmpty())
|
||||||
|
{
|
||||||
|
const wxLanguageInfo* const info = wxUILocale::FindLanguageInfo(localeId);
|
||||||
|
if (info)
|
||||||
|
{
|
||||||
|
dir = info->LayoutDirection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
wxUILocale::CompareStrings(const wxString& lhs,
|
wxUILocale::CompareStrings(const wxString& lhs,
|
||||||
const wxString& rhs,
|
const wxString& rhs,
|
||||||
@@ -341,4 +626,180 @@ wxUILocale::~wxUILocale()
|
|||||||
m_impl->DecRef();
|
m_impl->DecRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/
|
||||||
|
int wxUILocale::GetSystemLanguage()
|
||||||
|
{
|
||||||
|
const wxLanguageInfos& languagesDB = wxGetLanguageInfos();
|
||||||
|
size_t count = languagesDB.size();
|
||||||
|
wxVector<wxString> preferred = wxUILocaleImpl::GetPreferredUILanguages();
|
||||||
|
|
||||||
|
for (wxVector<wxString>::const_iterator j = preferred.begin();
|
||||||
|
j != preferred.end();
|
||||||
|
++j)
|
||||||
|
{
|
||||||
|
wxLocaleIdent localeId = wxLocaleIdent::FromTag(*j);
|
||||||
|
wxString lang = localeId.GetTag(wxLOCALE_TAGTYPE_BCP47);
|
||||||
|
size_t pos = lang.find('-');
|
||||||
|
wxString langShort = (pos != wxString::npos) ? lang.substr(0, pos) : wxString();
|
||||||
|
size_t ixShort = count;
|
||||||
|
|
||||||
|
for (size_t ixLanguage = 0; ixLanguage < count; ++ixLanguage)
|
||||||
|
{
|
||||||
|
if (languagesDB[ixLanguage].LocaleTag == lang)
|
||||||
|
{
|
||||||
|
return languagesDB[ixLanguage].Language;
|
||||||
|
}
|
||||||
|
if (pos != wxString::npos)
|
||||||
|
{
|
||||||
|
if (languagesDB[ixLanguage].LocaleTag == lang)
|
||||||
|
{
|
||||||
|
ixShort = ixLanguage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ixShort < count)
|
||||||
|
{
|
||||||
|
return languagesDB[ixShort].Language;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// no info about this language in the database
|
||||||
|
return wxLANGUAGE_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
wxVector<wxString> wxUILocale::GetPreferredUILanguages()
|
||||||
|
{
|
||||||
|
return wxUILocaleImpl::GetPreferredUILanguages();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
const wxLanguageInfo* wxUILocale::GetLanguageInfo(int lang)
|
||||||
|
{
|
||||||
|
CreateLanguagesDB();
|
||||||
|
|
||||||
|
// calling GetLanguageInfo(wxLANGUAGE_DEFAULT) is a natural thing to do, so
|
||||||
|
// make it work
|
||||||
|
if (lang == wxLANGUAGE_DEFAULT)
|
||||||
|
lang = GetSystemLanguage();
|
||||||
|
|
||||||
|
if (lang == wxLANGUAGE_UNKNOWN)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
const wxLanguageInfos& languagesDB = wxGetLanguageInfos();
|
||||||
|
const size_t count = languagesDB.size();
|
||||||
|
for (size_t i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
if (languagesDB[i].Language == lang)
|
||||||
|
return &languagesDB[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
wxString wxUILocale::GetLanguageName(int lang)
|
||||||
|
{
|
||||||
|
wxString string;
|
||||||
|
|
||||||
|
if (lang == wxLANGUAGE_DEFAULT || lang == wxLANGUAGE_UNKNOWN)
|
||||||
|
return string;
|
||||||
|
|
||||||
|
const wxLanguageInfo* info = GetLanguageInfo(lang);
|
||||||
|
if (info)
|
||||||
|
string = info->Description;
|
||||||
|
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
wxString wxUILocale::GetLanguageCanonicalName(int lang)
|
||||||
|
{
|
||||||
|
wxString string;
|
||||||
|
|
||||||
|
if (lang == wxLANGUAGE_DEFAULT || lang == wxLANGUAGE_UNKNOWN)
|
||||||
|
return string;
|
||||||
|
|
||||||
|
const wxLanguageInfo* info = GetLanguageInfo(lang);
|
||||||
|
if (info)
|
||||||
|
string = info->CanonicalName;
|
||||||
|
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
const wxLanguageInfo* wxUILocale::FindLanguageInfo(const wxString& locale)
|
||||||
|
{
|
||||||
|
CreateLanguagesDB();
|
||||||
|
|
||||||
|
const wxLanguageInfo* infoRet = NULL;
|
||||||
|
|
||||||
|
const wxLanguageInfos& languagesDB = wxGetLanguageInfos();
|
||||||
|
const size_t count = languagesDB.size();
|
||||||
|
for (size_t i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
const wxLanguageInfo* info = &languagesDB[i];
|
||||||
|
|
||||||
|
if (wxStricmp(locale, info->CanonicalName) == 0 ||
|
||||||
|
wxStricmp(locale, info->Description) == 0)
|
||||||
|
{
|
||||||
|
// exact match, stop searching
|
||||||
|
infoRet = info;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wxStricmp(locale, info->CanonicalName.BeforeFirst(wxS('_'))) == 0)
|
||||||
|
{
|
||||||
|
// a match -- but maybe we'll find an exact one later, so continue
|
||||||
|
// looking
|
||||||
|
//
|
||||||
|
// OTOH, maybe we had already found a language match and in this
|
||||||
|
// case don't overwrite it because the entry for the default
|
||||||
|
// country always appears first in gs_languagesDB
|
||||||
|
if (!infoRet)
|
||||||
|
infoRet = info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return infoRet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
const wxLanguageInfo* wxUILocale::FindLanguageInfo(const wxLocaleIdent& locId)
|
||||||
|
{
|
||||||
|
CreateLanguagesDB();
|
||||||
|
|
||||||
|
const wxLanguageInfo* infoRet = NULL;
|
||||||
|
wxString localeTag = locId.GetTag(wxLOCALE_TAGTYPE_BCP47);
|
||||||
|
|
||||||
|
const wxLanguageInfos& languagesDB = wxGetLanguageInfos();
|
||||||
|
const size_t count = languagesDB.size();
|
||||||
|
for (size_t i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
const wxLanguageInfo* info = &languagesDB[i];
|
||||||
|
|
||||||
|
if (wxStricmp(localeTag, info->LocaleTag) == 0)
|
||||||
|
{
|
||||||
|
// exact match, stop searching
|
||||||
|
infoRet = info;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wxStricmp(localeTag, info->LocaleTag.BeforeFirst(wxS('-'))) == 0)
|
||||||
|
{
|
||||||
|
// a match -- but maybe we'll find an exact one later, so continue
|
||||||
|
// looking
|
||||||
|
//
|
||||||
|
// OTOH, maybe we had already found a language match and in this
|
||||||
|
// case don't overwrite it because the entry for the default
|
||||||
|
// country always appears first in gs_languagesDB
|
||||||
|
if (!infoRet)
|
||||||
|
infoRet = info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return infoRet;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // wxUSE_INTL
|
#endif // wxUSE_INTL
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "wx/msw/private/uilocale.h"
|
#include "wx/msw/private/uilocale.h"
|
||||||
|
|
||||||
|
#include "wx/scopedarray.h"
|
||||||
#include "wx/dynlib.h"
|
#include "wx/dynlib.h"
|
||||||
|
|
||||||
#ifndef LOCALE_NAME_USER_DEFAULT
|
#ifndef LOCALE_NAME_USER_DEFAULT
|
||||||
@@ -35,6 +36,42 @@
|
|||||||
#define MUI_LANGUAGE_NAME 8
|
#define MUI_LANGUAGE_NAME 8
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef LOCALE_ICONSTRUCTEDLOCALE
|
||||||
|
#define LOCALE_ICONSTRUCTEDLOCALE 0x0000007d
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LOCALE_RETURN_NUMBER
|
||||||
|
#define LOCALE_RETURN_NUMBER 0x20000000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LOCALE_SENGLISHDISPLAYNAME
|
||||||
|
#define LOCALE_SENGLISHDISPLAYNAME 0x00000072
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LOCALE_SNATIVEDISPLAYNAME
|
||||||
|
#define LOCALE_SNATIVEDISPLAYNAME 0x00000073
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LOCALE_SENGLISHLANGUAGENAME
|
||||||
|
#define LOCALE_SENGLISHLANGUAGENAME 0x00001001
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LOCALE_SNATIVELANGUAGENAME
|
||||||
|
#define LOCALE_SNATIVELANGUAGENAME 0x00000004
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LOCALE_SENGLISHCOUNTRYNAME
|
||||||
|
#define LOCALE_SENGLISHCOUNTRYNAME 0x00001002
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LOCALE_SNATIVECOUNTRYNAME
|
||||||
|
#define LOCALE_SNATIVECOUNTRYNAME 0x00000008
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LOCALE_IREADINGLAYOUT
|
||||||
|
#define LOCALE_IREADINGLAYOUT 0x00000070
|
||||||
|
#endif
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// implementation
|
// implementation
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -96,11 +133,105 @@ wxString wxLocaleIdent::GetName() const
|
|||||||
{
|
{
|
||||||
name << "-" << m_region;
|
name << "-" << m_region;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!m_extension.empty())
|
||||||
|
{
|
||||||
|
name << "-" << m_extension;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_sortorder.empty())
|
||||||
|
{
|
||||||
|
name << "_" << m_sortorder;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Standard C wxUILocale implementation for MSW
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class wxUILocaleImplStdC : public wxUILocaleImpl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Create object corresponding to the given locale, return NULL if not
|
||||||
|
// supported.
|
||||||
|
static wxUILocaleImplStdC* Create()
|
||||||
|
{
|
||||||
|
return new wxUILocaleImplStdC();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
~wxUILocaleImplStdC() wxOVERRIDE
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Use() wxOVERRIDE
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString GetName() const wxOVERRIDE
|
||||||
|
{
|
||||||
|
return wxString("C");
|
||||||
|
}
|
||||||
|
|
||||||
|
wxLocaleIdent GetLocaleId() const wxOVERRIDE
|
||||||
|
{
|
||||||
|
return wxLocaleIdent().Language("C");
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString GetInfo(wxLocaleInfo index, wxLocaleCategory cat) const wxOVERRIDE
|
||||||
|
{
|
||||||
|
return wxGetStdCLocaleInfo(index, cat);
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString GetLocalizedName(wxLocaleName name, wxLocaleForm WXUNUSED(form)) const wxOVERRIDE
|
||||||
|
{
|
||||||
|
wxString str;
|
||||||
|
switch (name)
|
||||||
|
{
|
||||||
|
case wxLOCALE_NAME_LOCALE:
|
||||||
|
case wxLOCALE_NAME_LANGUAGE:
|
||||||
|
str = wxString("English");
|
||||||
|
break;
|
||||||
|
case wxLOCALE_NAME_COUNTRY:
|
||||||
|
str = wxString();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
wxFAIL_MSG("unknown wxLocaleInfo");
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxLayoutDirection GetLayoutDirection() const wxOVERRIDE
|
||||||
|
{
|
||||||
|
return wxLayout_Default;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CompareStrings(const wxString& lhs, const wxString& rhs,
|
||||||
|
int flags) const wxOVERRIDE
|
||||||
|
{
|
||||||
|
const int rc = flags & wxCompare_CaseInsensitive ? lhs.CmpNoCase(rhs)
|
||||||
|
: lhs.Cmp(rhs);
|
||||||
|
if (rc < 0)
|
||||||
|
return -1;
|
||||||
|
if (rc > 0)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Ctor is private, use Create() instead.
|
||||||
|
explicit wxUILocaleImplStdC()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDECLARE_NO_COPY_CLASS(wxUILocaleImplStdC);
|
||||||
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// LCID-based wxUILocale implementation for MSW
|
// LCID-based wxUILocale implementation for MSW
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -121,23 +252,27 @@ public:
|
|||||||
|
|
||||||
wxString GetName() const wxOVERRIDE
|
wxString GetName() const wxOVERRIDE
|
||||||
{
|
{
|
||||||
wxChar buf[256];
|
wxString str;
|
||||||
buf[0] = wxT('\0');
|
|
||||||
|
|
||||||
// Try using newer constant available since Vista which produces names
|
// Try using newer constant available since Vista which produces names
|
||||||
// more similar to the other platforms.
|
// more similar to the other platforms.
|
||||||
if ( wxGetWinVersion() >= wxWinVersion_Vista )
|
if ( wxGetWinVersion() >= wxWinVersion_Vista )
|
||||||
{
|
{
|
||||||
::GetLocaleInfo(m_lcid, LOCALE_SNAME, buf, WXSIZEOF(buf));
|
str = DoGetInfo(LOCALE_SNAME);
|
||||||
}
|
}
|
||||||
else // TODO-XP: Drop this branch.
|
else // TODO-XP: Drop this branch.
|
||||||
{
|
{
|
||||||
// This name constant is available under all systems, including
|
// This name constant is available under all systems, including
|
||||||
// pre-Vista ones.
|
// pre-Vista ones.
|
||||||
::GetLocaleInfo(m_lcid, LOCALE_SENGLANGUAGE, buf, WXSIZEOF(buf));
|
str = DoGetInfo(LOCALE_SENGLANGUAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return buf;
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxLocaleIdent GetLocaleId() const wxOVERRIDE
|
||||||
|
{
|
||||||
|
return wxLocaleIdent::FromTag(GetName());
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString GetInfo(wxLocaleInfo index, wxLocaleCategory cat) const wxOVERRIDE
|
wxString GetInfo(wxLocaleInfo index, wxLocaleCategory cat) const wxOVERRIDE
|
||||||
@@ -145,6 +280,68 @@ public:
|
|||||||
return wxGetInfoFromLCID(m_lcid, index, cat);
|
return wxGetInfoFromLCID(m_lcid, index, cat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxString GetLocalizedName(wxLocaleName name, wxLocaleForm form) const wxOVERRIDE
|
||||||
|
{
|
||||||
|
wxString str;
|
||||||
|
switch (name)
|
||||||
|
{
|
||||||
|
case wxLOCALE_NAME_LOCALE:
|
||||||
|
switch (form)
|
||||||
|
{
|
||||||
|
case wxLOCALE_FORM_NATIVE:
|
||||||
|
{
|
||||||
|
wxString strLang = DoGetInfo(LOCALE_SNATIVELANGNAME);
|
||||||
|
wxString strCtry = DoGetInfo(LOCALE_SNATIVECTRYNAME);
|
||||||
|
str << strLang << " (" << strCtry << ")";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case wxLOCALE_FORM_ENGLISH:
|
||||||
|
{
|
||||||
|
wxString strLang = DoGetInfo(LOCALE_SENGLANGUAGE);
|
||||||
|
wxString strCtry = DoGetInfo(LOCALE_SENGCOUNTRY);
|
||||||
|
str << strLang << " (" << strCtry << ")";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
wxFAIL_MSG("unknown wxLocaleForm");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case wxLOCALE_NAME_LANGUAGE:
|
||||||
|
switch (form)
|
||||||
|
{
|
||||||
|
case wxLOCALE_FORM_NATIVE:
|
||||||
|
str = DoGetInfo(LOCALE_SNATIVELANGNAME);
|
||||||
|
break;
|
||||||
|
case wxLOCALE_FORM_ENGLISH:
|
||||||
|
str = DoGetInfo(LOCALE_SENGLANGUAGE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
wxFAIL_MSG("unknown wxLocaleForm");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case wxLOCALE_NAME_COUNTRY:
|
||||||
|
switch (form)
|
||||||
|
{
|
||||||
|
case wxLOCALE_FORM_NATIVE:
|
||||||
|
str = DoGetInfo(LOCALE_SNATIVECTRYNAME);
|
||||||
|
break;
|
||||||
|
case wxLOCALE_FORM_ENGLISH:
|
||||||
|
str = DoGetInfo(LOCALE_SENGCOUNTRY);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
wxFAIL_MSG("unknown wxLocaleForm");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxLayoutDirection GetLayoutDirection() const wxOVERRIDE
|
||||||
|
{
|
||||||
|
return wxLayout_Default;
|
||||||
|
}
|
||||||
|
|
||||||
int CompareStrings(const wxString& lhs, const wxString& rhs,
|
int CompareStrings(const wxString& lhs, const wxString& rhs,
|
||||||
int flags) const wxOVERRIDE
|
int flags) const wxOVERRIDE
|
||||||
{
|
{
|
||||||
@@ -158,6 +355,18 @@ public:
|
|||||||
private:
|
private:
|
||||||
const LCID m_lcid;
|
const LCID m_lcid;
|
||||||
|
|
||||||
|
wxString DoGetInfo(LCTYPE lctype) const
|
||||||
|
{
|
||||||
|
wchar_t buf[256];
|
||||||
|
if (!::GetLocaleInfo(m_lcid, lctype, buf, WXSIZEOF(buf)))
|
||||||
|
{
|
||||||
|
wxLogLastError(wxT("GetLocaleInfo"));
|
||||||
|
return wxString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
wxDECLARE_NO_COPY_CLASS(wxUILocaleImplLCID);
|
wxDECLARE_NO_COPY_CLASS(wxUILocaleImplLCID);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -186,6 +395,9 @@ public:
|
|||||||
wxDL_INIT_FUNC(ms_, SetThreadPreferredUILanguages, dllKernel32);
|
wxDL_INIT_FUNC(ms_, SetThreadPreferredUILanguages, dllKernel32);
|
||||||
if ( !ms_SetThreadPreferredUILanguages )
|
if ( !ms_SetThreadPreferredUILanguages )
|
||||||
return false;
|
return false;
|
||||||
|
wxDL_INIT_FUNC(ms_, GetUserPreferredUILanguages, dllKernel32);
|
||||||
|
if (!ms_GetUserPreferredUILanguages)
|
||||||
|
return false;
|
||||||
|
|
||||||
wxDL_INIT_FUNC(ms_, CompareStringEx, dllKernel32);
|
wxDL_INIT_FUNC(ms_, CompareStringEx, dllKernel32);
|
||||||
if ( !ms_CompareStringEx )
|
if ( !ms_CompareStringEx )
|
||||||
@@ -197,6 +409,66 @@ public:
|
|||||||
return s_canUse == 1;
|
return s_canUse == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static wxVector<wxString> GetPreferredUILanguages()
|
||||||
|
{
|
||||||
|
wxVector<wxString> preferred;
|
||||||
|
|
||||||
|
if (CanUse())
|
||||||
|
{
|
||||||
|
ULONG numberOfLanguages = 0;
|
||||||
|
ULONG bufferSize = 0;
|
||||||
|
if (ms_GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &numberOfLanguages, NULL, &bufferSize))
|
||||||
|
{
|
||||||
|
wxScopedArray<WCHAR> languages(bufferSize);
|
||||||
|
if (ms_GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &numberOfLanguages, languages.get(), &bufferSize))
|
||||||
|
{
|
||||||
|
WCHAR* buf = languages.get();
|
||||||
|
for (unsigned k = 0; k < numberOfLanguages; ++k)
|
||||||
|
{
|
||||||
|
const wxString language(buf);
|
||||||
|
preferred.push_back(language);
|
||||||
|
buf += language.length() + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxLogLastError(wxT("GetUserPreferredUILanguages"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxLogLastError(wxT("GetUserPreferredUILanguages"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const wxLanguageInfos& languagesDB = wxGetLanguageInfos();
|
||||||
|
size_t count = languagesDB.size();
|
||||||
|
const LANGID langid = ::GetUserDefaultUILanguage();
|
||||||
|
if (langid != LOCALE_CUSTOM_UI_DEFAULT)
|
||||||
|
{
|
||||||
|
size_t ixLanguage = 0;
|
||||||
|
wxUint32 lang = PRIMARYLANGID(langid);
|
||||||
|
wxUint32 sublang = SUBLANGID(langid);
|
||||||
|
|
||||||
|
for (ixLanguage = 0; ixLanguage < count; ++ixLanguage)
|
||||||
|
{
|
||||||
|
if (languagesDB[ixLanguage].WinLang == lang &&
|
||||||
|
languagesDB[ixLanguage].WinSublang == sublang)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ixLanguage < count)
|
||||||
|
{
|
||||||
|
preferred.push_back(languagesDB[ixLanguage].CanonicalName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return preferred;
|
||||||
|
}
|
||||||
|
|
||||||
// Create object corresponding to the default user locale.
|
// Create object corresponding to the default user locale.
|
||||||
static wxUILocaleImplName* CreateDefault()
|
static wxUILocaleImplName* CreateDefault()
|
||||||
{
|
{
|
||||||
@@ -212,6 +484,37 @@ public:
|
|||||||
if ( !ms_GetLocaleInfoEx(name, LOCALE_SNAME, NULL, 0) )
|
if ( !ms_GetLocaleInfoEx(name, LOCALE_SNAME, NULL, 0) )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
// Unfortunately under Windows 10 the call above only fails if the given
|
||||||
|
// locale name is not a valid BCP 47 identifier. For example,
|
||||||
|
// valid language codes can have 2 or 3 letters:
|
||||||
|
// - using name "w" fails
|
||||||
|
// - using name "wx" succeeds
|
||||||
|
// - using name "wxy" succeeds
|
||||||
|
// - using name "wxyz" fails
|
||||||
|
// and so we need another check on these systems (but note that this
|
||||||
|
// check must not be done under Windows 7 because there plenty of
|
||||||
|
// actually supported locales are "constructed") by checking
|
||||||
|
// whether the locale is "constructed" or not: "not constructed"
|
||||||
|
// means the locale is a predefined locale, "constructed"
|
||||||
|
// means the locale is not predefined, but has to be constructed.
|
||||||
|
// For example, "de-US" would be a constructed locale.
|
||||||
|
if ( wxGetWinVersion() >= wxWinVersion_10 )
|
||||||
|
{
|
||||||
|
// Using LOCALE_ICONSTRUCTEDLOCALE to query the locale status is
|
||||||
|
// discouraged by Microsoft (the constant is not even defined in a
|
||||||
|
// Windows header file). However, for now constructed locales will
|
||||||
|
// be rejected here.
|
||||||
|
int isConstructed = 0;
|
||||||
|
if (!ms_GetLocaleInfoEx
|
||||||
|
(
|
||||||
|
name,
|
||||||
|
LOCALE_ICONSTRUCTEDLOCALE | LOCALE_RETURN_NUMBER,
|
||||||
|
(LPWSTR)&isConstructed,
|
||||||
|
sizeof(int)
|
||||||
|
) || isConstructed != 0)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return new wxUILocaleImplName(name);
|
return new wxUILocaleImplName(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,6 +545,11 @@ public:
|
|||||||
return DoGetInfo(LOCALE_SNAME);
|
return DoGetInfo(LOCALE_SNAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxLocaleIdent GetLocaleId() const wxOVERRIDE
|
||||||
|
{
|
||||||
|
return wxLocaleIdent::FromTag(GetName());
|
||||||
|
}
|
||||||
|
|
||||||
wxString GetInfo(wxLocaleInfo index, wxLocaleCategory cat) const wxOVERRIDE
|
wxString GetInfo(wxLocaleInfo index, wxLocaleCategory cat) const wxOVERRIDE
|
||||||
{
|
{
|
||||||
// TODO-XP: This duplicates code from in wxGetInfoFromLCID(), but
|
// TODO-XP: This duplicates code from in wxGetInfoFromLCID(), but
|
||||||
@@ -286,6 +594,93 @@ public:
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxString GetLocalizedName(wxLocaleName name, wxLocaleForm form) const wxOVERRIDE
|
||||||
|
{
|
||||||
|
// TODO-XP: This duplicates code from in wxGetInfoFromLCID(), but
|
||||||
|
// it's only temporary because we will drop all code using LCID soon.
|
||||||
|
// LOCALE_SINTLSYMBOL (Currency 3-letter ISO 4217)
|
||||||
|
static wxWinVersion ver = wxGetWinVersion();
|
||||||
|
wxString str;
|
||||||
|
switch (name)
|
||||||
|
{
|
||||||
|
case wxLOCALE_NAME_LOCALE:
|
||||||
|
switch (form)
|
||||||
|
{
|
||||||
|
case wxLOCALE_FORM_NATIVE:
|
||||||
|
if (ver >= wxWinVersion_7)
|
||||||
|
{
|
||||||
|
str = DoGetInfo(LOCALE_SNATIVEDISPLAYNAME);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxString strLang = DoGetInfo(LOCALE_SNATIVELANGNAME);
|
||||||
|
wxString strCtry = DoGetInfo(LOCALE_SNATIVECTRYNAME);
|
||||||
|
str << strLang << " (" << strCtry << ")";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case wxLOCALE_FORM_ENGLISH:
|
||||||
|
if (ver >= wxWinVersion_7)
|
||||||
|
{
|
||||||
|
str = DoGetInfo(LOCALE_SENGLISHDISPLAYNAME);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxString strLang = DoGetInfo(LOCALE_SENGLANGUAGE);
|
||||||
|
wxString strCtry = DoGetInfo(LOCALE_SENGCOUNTRY);
|
||||||
|
str << strLang << " (" << strCtry << ")";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
wxFAIL_MSG("unknown wxLocaleForm");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case wxLOCALE_NAME_LANGUAGE:
|
||||||
|
switch (form)
|
||||||
|
{
|
||||||
|
case wxLOCALE_FORM_NATIVE:
|
||||||
|
str = DoGetInfo((ver >= wxWinVersion_7) ? LOCALE_SNATIVELANGUAGENAME : LOCALE_SNATIVELANGNAME);
|
||||||
|
break;
|
||||||
|
case wxLOCALE_FORM_ENGLISH:
|
||||||
|
str = DoGetInfo((ver >= wxWinVersion_7) ? LOCALE_SENGLISHLANGUAGENAME : LOCALE_SENGLANGUAGE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
wxFAIL_MSG("unknown wxLocaleForm");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case wxLOCALE_NAME_COUNTRY:
|
||||||
|
switch (form)
|
||||||
|
{
|
||||||
|
case wxLOCALE_FORM_NATIVE:
|
||||||
|
str = DoGetInfo((ver >= wxWinVersion_7) ? LOCALE_SNATIVECOUNTRYNAME : LOCALE_SNATIVECTRYNAME);
|
||||||
|
break;
|
||||||
|
case wxLOCALE_FORM_ENGLISH:
|
||||||
|
str = DoGetInfo((ver >= wxWinVersion_7) ? LOCALE_SENGLISHCOUNTRYNAME : LOCALE_SENGCOUNTRY);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
wxFAIL_MSG("unknown wxLocaleForm");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxLayoutDirection GetLayoutDirection() const wxOVERRIDE
|
||||||
|
{
|
||||||
|
if (wxGetWinVersion() >= wxWinVersion_7)
|
||||||
|
{
|
||||||
|
wxString str = DoGetInfo(LOCALE_IREADINGLAYOUT);
|
||||||
|
// str contains a number between 0 and 3:
|
||||||
|
// 0 = LTR, 1 = RTL, 2 = TTB+RTL, 3 = TTB + LTR
|
||||||
|
// If str equals 1 return RTL, otherwise LTR
|
||||||
|
return (str.IsSameAs("1") ? wxLayout_RightToLeft : wxLayout_LeftToRight);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return wxLayout_Default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int CompareStrings(const wxString& lhs, const wxString& rhs,
|
int CompareStrings(const wxString& lhs, const wxString& rhs,
|
||||||
int flags) const wxOVERRIDE
|
int flags) const wxOVERRIDE
|
||||||
{
|
{
|
||||||
@@ -326,6 +721,9 @@ private:
|
|||||||
typedef BOOL (WINAPI *SetThreadPreferredUILanguages_t)(DWORD, CONST WCHAR*, ULONG*);
|
typedef BOOL (WINAPI *SetThreadPreferredUILanguages_t)(DWORD, CONST WCHAR*, ULONG*);
|
||||||
static SetThreadPreferredUILanguages_t ms_SetThreadPreferredUILanguages;
|
static SetThreadPreferredUILanguages_t ms_SetThreadPreferredUILanguages;
|
||||||
|
|
||||||
|
typedef BOOL (WINAPI *GetUserPreferredUILanguages_t)(DWORD, ULONG*, WCHAR*, ULONG*);
|
||||||
|
static GetUserPreferredUILanguages_t ms_GetUserPreferredUILanguages;
|
||||||
|
|
||||||
// Note: we currently don't use NLSVERSIONINFO output parameter and so we
|
// Note: we currently don't use NLSVERSIONINFO output parameter and so we
|
||||||
// don't bother dealing with the different sizes of this struct under
|
// don't bother dealing with the different sizes of this struct under
|
||||||
// different OS versions and define the function type as using "void*" to
|
// different OS versions and define the function type as using "void*" to
|
||||||
@@ -367,6 +765,7 @@ private:
|
|||||||
|
|
||||||
wxUILocaleImplName::GetLocaleInfoEx_t wxUILocaleImplName::ms_GetLocaleInfoEx;
|
wxUILocaleImplName::GetLocaleInfoEx_t wxUILocaleImplName::ms_GetLocaleInfoEx;
|
||||||
wxUILocaleImplName::SetThreadPreferredUILanguages_t wxUILocaleImplName::ms_SetThreadPreferredUILanguages;
|
wxUILocaleImplName::SetThreadPreferredUILanguages_t wxUILocaleImplName::ms_SetThreadPreferredUILanguages;
|
||||||
|
wxUILocaleImplName::GetUserPreferredUILanguages_t wxUILocaleImplName::ms_GetUserPreferredUILanguages;
|
||||||
wxUILocaleImplName::CompareStringEx_t wxUILocaleImplName::ms_CompareStringEx;
|
wxUILocaleImplName::CompareStringEx_t wxUILocaleImplName::ms_CompareStringEx;
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -376,14 +775,7 @@ wxUILocaleImplName::CompareStringEx_t wxUILocaleImplName::ms_CompareStringEx;
|
|||||||
/* static */
|
/* static */
|
||||||
wxUILocaleImpl* wxUILocaleImpl::CreateStdC()
|
wxUILocaleImpl* wxUILocaleImpl::CreateStdC()
|
||||||
{
|
{
|
||||||
if ( !wxUILocaleImplName::CanUse() )
|
return wxUILocaleImplStdC::Create();
|
||||||
{
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
return wxUILocaleImplName::Create(L"en-US");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
@@ -398,14 +790,19 @@ wxUILocaleImpl* wxUILocaleImpl::CreateUserDefault()
|
|||||||
/* static */
|
/* static */
|
||||||
wxUILocaleImpl* wxUILocaleImpl::CreateForLanguage(const wxLanguageInfo& info)
|
wxUILocaleImpl* wxUILocaleImpl::CreateForLanguage(const wxLanguageInfo& info)
|
||||||
{
|
{
|
||||||
if ( info.WinLang == 0 )
|
if (!wxUILocaleImplName::CanUse())
|
||||||
|
{
|
||||||
|
if (info.WinLang == 0)
|
||||||
{
|
{
|
||||||
wxLogWarning(wxS("Locale '%s' not supported by OS."), info.Description);
|
wxLogWarning(wxS("Locale '%s' not supported by OS."), info.Description);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new wxUILocaleImplLCID(info.GetLCID());
|
return new wxUILocaleImplLCID(info.GetLCID());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return wxUILocaleImplName::Create(info.LocaleTag.wc_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
@@ -420,7 +817,13 @@ wxUILocaleImpl* wxUILocaleImpl::CreateForLocale(const wxLocaleIdent& locId)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wxUILocaleImplName::Create(locId.GetTag().wc_str());
|
return wxUILocaleImplName::Create(locId.GetTag(wxLOCALE_TAGTYPE_WINDOWS).wc_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
wxVector<wxString> wxUILocaleImpl::GetPreferredUILanguages()
|
||||||
|
{
|
||||||
|
return wxUILocaleImplName::GetPreferredUILanguages();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // wxUSE_INTL
|
#endif // wxUSE_INTL
|
||||||
|
|||||||
@@ -101,7 +101,10 @@ public:
|
|||||||
|
|
||||||
void Use() wxOVERRIDE;
|
void Use() wxOVERRIDE;
|
||||||
wxString GetName() const wxOVERRIDE;
|
wxString GetName() const wxOVERRIDE;
|
||||||
|
wxLocaleIdent GetLocaleId() const wxOVERRIDE;
|
||||||
wxString GetInfo(wxLocaleInfo index, wxLocaleCategory cat) const wxOVERRIDE;
|
wxString GetInfo(wxLocaleInfo index, wxLocaleCategory cat) const wxOVERRIDE;
|
||||||
|
wxString GetLocalizedName(wxLocaleName name, wxLocaleForm form) const wxOVERRIDE;
|
||||||
|
wxLayoutDirection GetLayoutDirection() const wxOVERRIDE;
|
||||||
int CompareStrings(const wxString& lhs, const wxString& rhs,
|
int CompareStrings(const wxString& lhs, const wxString& rhs,
|
||||||
int flags) const wxOVERRIDE;
|
int flags) const wxOVERRIDE;
|
||||||
|
|
||||||
@@ -130,12 +133,78 @@ wxUILocaleImplCF::GetName() const
|
|||||||
return wxCFStringRef::AsString([m_nsloc localeIdentifier]);
|
return wxCFStringRef::AsString([m_nsloc localeIdentifier]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxLocaleIdent
|
||||||
|
wxUILocaleImplCF::GetLocaleId() const
|
||||||
|
{
|
||||||
|
return wxLocaleIdent::FromTag(GetName());
|
||||||
|
}
|
||||||
|
|
||||||
wxString
|
wxString
|
||||||
wxUILocaleImplCF::GetInfo(wxLocaleInfo index, wxLocaleCategory cat) const
|
wxUILocaleImplCF::GetInfo(wxLocaleInfo index, wxLocaleCategory cat) const
|
||||||
{
|
{
|
||||||
return wxGetInfoFromCFLocale((CFLocaleRef)m_nsloc, index, cat);
|
return wxGetInfoFromCFLocale((CFLocaleRef)m_nsloc, index, cat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxString
|
||||||
|
wxUILocaleImplCF::GetLocalizedName(wxLocaleName name, wxLocaleForm form) const
|
||||||
|
{
|
||||||
|
NSString* str = NULL;
|
||||||
|
switch (name)
|
||||||
|
{
|
||||||
|
case wxLOCALE_NAME_LOCALE:
|
||||||
|
switch (form)
|
||||||
|
{
|
||||||
|
case wxLOCALE_FORM_NATIVE:
|
||||||
|
str = [m_nsloc localizedStringForLocaleIdentifier:[m_nsloc localeIdentifier]];
|
||||||
|
break;
|
||||||
|
case wxLOCALE_FORM_ENGLISH:
|
||||||
|
str = [m_nsloc displayNameForKey:NSLocaleIdentifier value:[m_nsloc localeIdentifier]];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
wxFAIL_MSG("unknown wxLocaleForm");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case wxLOCALE_NAME_LANGUAGE:
|
||||||
|
switch (form)
|
||||||
|
{
|
||||||
|
case wxLOCALE_FORM_NATIVE:
|
||||||
|
str = [m_nsloc localizedStringForLanguageCode:[m_nsloc languageCode]];
|
||||||
|
break;
|
||||||
|
case wxLOCALE_FORM_ENGLISH:
|
||||||
|
str = [m_nsloc displayNameForKey:NSLocaleIdentifier value:[m_nsloc localeIdentifier]];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
wxFAIL_MSG("unknown wxLocaleForm");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case wxLOCALE_NAME_COUNTRY:
|
||||||
|
switch (form)
|
||||||
|
{
|
||||||
|
case wxLOCALE_FORM_NATIVE:
|
||||||
|
str = [m_nsloc localizedStringForCountryCode:[m_nsloc countryCode]];
|
||||||
|
break;
|
||||||
|
case wxLOCALE_FORM_ENGLISH:
|
||||||
|
str = [m_nsloc displayNameForKey:NSLocaleIdentifier value:[m_nsloc localeIdentifier]];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
wxFAIL_MSG("unknown wxLocaleForm");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return wxCFStringRef::AsString(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
wxLayoutDirection
|
||||||
|
wxUILocaleImplCF::GetLayoutDirection() const
|
||||||
|
{
|
||||||
|
NSLocaleLanguageDirection layoutDirection = [NSLocale characterDirectionForLanguage:[m_nsloc languageCode]];
|
||||||
|
if (layoutDirection == NSLocaleLanguageDirectionLeftToRight)
|
||||||
|
return wxLayout_LeftToRight;
|
||||||
|
else if (layoutDirection == NSLocaleLanguageDirectionRightToLeft)
|
||||||
|
return wxLayout_RightToLeft;
|
||||||
|
return wxLayout_Default;
|
||||||
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
wxUILocaleImpl* wxUILocaleImpl::CreateStdC()
|
wxUILocaleImpl* wxUILocaleImpl::CreateStdC()
|
||||||
{
|
{
|
||||||
@@ -154,6 +223,19 @@ wxUILocaleImpl* wxUILocaleImpl::CreateForLocale(const wxLocaleIdent& locId)
|
|||||||
return wxUILocaleImplCF::Create(locId);
|
return wxUILocaleImplCF::Create(locId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
wxVector<wxString> wxUILocaleImpl::GetPreferredUILanguages()
|
||||||
|
{
|
||||||
|
wxVector<wxString> preferred;
|
||||||
|
NSArray* preferredLangs = [NSLocale preferredLanguages];
|
||||||
|
NSUInteger count = preferredLangs.count;
|
||||||
|
|
||||||
|
for (NSUInteger j = 0; j < count; ++j)
|
||||||
|
preferred.push_back(wxCFStringRef::AsString(preferredLangs[j]));
|
||||||
|
|
||||||
|
return preferred;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
wxUILocaleImplCF::CompareStrings(const wxString& lhs, const wxString& rhs,
|
wxUILocaleImplCF::CompareStrings(const wxString& lhs, const wxString& rhs,
|
||||||
int flags) const
|
int flags) const
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include "wx/unix/private/uilocale.h"
|
#include "wx/unix/private/uilocale.h"
|
||||||
|
|
||||||
#include "wx/intl.h"
|
#include "wx/intl.h"
|
||||||
|
#include "wx/utils.h"
|
||||||
|
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#ifdef HAVE_LANGINFO_H
|
#ifdef HAVE_LANGINFO_H
|
||||||
@@ -35,6 +36,13 @@
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// Small helper function: get the value of the given environment variable and
|
||||||
|
// return true only if the variable was found and has non-empty value.
|
||||||
|
inline bool wxGetNonEmptyEnvVar(const wxString& name, wxString* value)
|
||||||
|
{
|
||||||
|
return wxGetEnv(name, value) && !value->empty();
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxUILocale implementation using standard Unix/C functions
|
// wxUILocale implementation using standard Unix/C functions
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -53,7 +61,11 @@ public:
|
|||||||
void Use() wxOVERRIDE;
|
void Use() wxOVERRIDE;
|
||||||
|
|
||||||
wxString GetName() const wxOVERRIDE;
|
wxString GetName() const wxOVERRIDE;
|
||||||
|
wxLocaleIdent GetLocaleId() const wxOVERRIDE;
|
||||||
wxString GetInfo(wxLocaleInfo index, wxLocaleCategory cat) const wxOVERRIDE;
|
wxString GetInfo(wxLocaleInfo index, wxLocaleCategory cat) const wxOVERRIDE;
|
||||||
|
wxString GetLocalizedName(wxLocaleName name, wxLocaleForm form) const wxOVERRIDE;
|
||||||
|
wxLayoutDirection GetLayoutDirection() const wxOVERRIDE;
|
||||||
|
|
||||||
int CompareStrings(const wxString& lhs, const wxString& rhs,
|
int CompareStrings(const wxString& lhs, const wxString& rhs,
|
||||||
int flags) const wxOVERRIDE;
|
int flags) const wxOVERRIDE;
|
||||||
|
|
||||||
@@ -64,6 +76,7 @@ private:
|
|||||||
#endif // HAVE_LANGINFO_H
|
#endif // HAVE_LANGINFO_H
|
||||||
|
|
||||||
wxLocaleIdent m_locId;
|
wxLocaleIdent m_locId;
|
||||||
|
wxString m_codeset;
|
||||||
|
|
||||||
#ifdef HAVE_LOCALE_T
|
#ifdef HAVE_LOCALE_T
|
||||||
// Only null for the default locale.
|
// Only null for the default locale.
|
||||||
@@ -85,15 +98,39 @@ inline locale_t TryCreateLocale(const wxLocaleIdent& locId)
|
|||||||
// modifying its wxLocaleIdent argument if it succeeds).
|
// modifying its wxLocaleIdent argument if it succeeds).
|
||||||
locale_t TryCreateLocaleWithUTF8(wxLocaleIdent& locId)
|
locale_t TryCreateLocaleWithUTF8(wxLocaleIdent& locId)
|
||||||
{
|
{
|
||||||
locale_t loc = TryCreateLocale(locId);
|
locale_t loc = NULL;
|
||||||
if ( !loc && locId.GetCharset().empty() )
|
|
||||||
|
#if wxUSE_UNICODE
|
||||||
|
if ( locId.GetCharset().empty() )
|
||||||
{
|
{
|
||||||
wxLocaleIdent locIdUTF8 = wxLocaleIdent(locId).Charset("UTF-8");
|
wxLocaleIdent locIdUTF8(locId);
|
||||||
|
locIdUTF8.Charset(wxS("UTF-8"));
|
||||||
|
|
||||||
loc = TryCreateLocale(locIdUTF8);
|
loc = TryCreateLocale(locIdUTF8);
|
||||||
|
if ( !loc )
|
||||||
|
{
|
||||||
|
locIdUTF8.Charset(wxS("utf-8"));
|
||||||
|
loc = TryCreateLocale(locIdUTF8);
|
||||||
|
}
|
||||||
|
if ( !loc )
|
||||||
|
{
|
||||||
|
locIdUTF8.Charset(wxS("UTF8"));
|
||||||
|
loc = TryCreateLocale(locIdUTF8);
|
||||||
|
}
|
||||||
|
if ( !loc )
|
||||||
|
{
|
||||||
|
locIdUTF8.Charset(wxS("utf8"));
|
||||||
|
loc = TryCreateLocale(locIdUTF8);
|
||||||
|
}
|
||||||
if ( loc )
|
if ( loc )
|
||||||
locId = locIdUTF8;
|
locId = locIdUTF8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if we can't set UTF-8 locale, try non-UTF-8 one:
|
||||||
|
if ( !loc )
|
||||||
|
#endif // wxUSE_UNICODE
|
||||||
|
loc = TryCreateLocale(locId);
|
||||||
|
|
||||||
return loc;
|
return loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,8 +144,6 @@ locale_t TryCreateMatchingLocale(wxLocaleIdent& locId)
|
|||||||
// Try to find a variant of this locale available on this system: first
|
// Try to find a variant of this locale available on this system: first
|
||||||
// of all, using just the language, without the territory, typically
|
// of all, using just the language, without the territory, typically
|
||||||
// does _not_ work under Linux, so try adding one if we don't have it.
|
// does _not_ work under Linux, so try adding one if we don't have it.
|
||||||
if ( locId.GetRegion().empty() )
|
|
||||||
{
|
|
||||||
const wxString lang = locId.GetLanguage();
|
const wxString lang = locId.GetLanguage();
|
||||||
|
|
||||||
const wxLanguageInfos& infos = wxGetLanguageInfos();
|
const wxLanguageInfos& infos = wxGetLanguageInfos();
|
||||||
@@ -116,7 +151,7 @@ locale_t TryCreateMatchingLocale(wxLocaleIdent& locId)
|
|||||||
it != infos.end();
|
it != infos.end();
|
||||||
++it )
|
++it )
|
||||||
{
|
{
|
||||||
const wxString& fullname = it->CanonicalName;
|
const wxString& fullname = it->CanonicalRef.empty() ? it->CanonicalName : it->CanonicalRef;
|
||||||
if ( fullname.BeforeFirst('_') == lang )
|
if ( fullname.BeforeFirst('_') == lang )
|
||||||
{
|
{
|
||||||
// We never have encoding in our canonical names, but we
|
// We never have encoding in our canonical names, but we
|
||||||
@@ -141,7 +176,6 @@ locale_t TryCreateMatchingLocale(wxLocaleIdent& locId)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return loc;
|
return loc;
|
||||||
}
|
}
|
||||||
@@ -170,7 +204,9 @@ wxString wxLocaleIdent::GetName() const
|
|||||||
if ( !m_charset.empty() )
|
if ( !m_charset.empty() )
|
||||||
name << "." << m_charset;
|
name << "." << m_charset;
|
||||||
|
|
||||||
if ( !m_modifier.empty() )
|
if ( !m_script.empty() )
|
||||||
|
name << "@" << wxUILocale::GetScriptAliasFromName(m_script);
|
||||||
|
else if ( !m_modifier.empty() )
|
||||||
name << "@" << m_modifier;
|
name << "@" << m_modifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,22 +225,22 @@ static const char *wxSetlocaleTryUTF8(int c, const wxLocaleIdent& locId)
|
|||||||
if ( locId.GetCharset().empty() )
|
if ( locId.GetCharset().empty() )
|
||||||
{
|
{
|
||||||
wxLocaleIdent locIdUTF8(locId);
|
wxLocaleIdent locIdUTF8(locId);
|
||||||
locIdUTF8.Charset(wxS(".UTF-8"));
|
locIdUTF8.Charset(wxS("UTF-8"));
|
||||||
|
|
||||||
l = wxSetlocale(c, locIdUTF8.GetName());
|
l = wxSetlocale(c, locIdUTF8.GetName());
|
||||||
if ( !l )
|
if ( !l )
|
||||||
{
|
{
|
||||||
locIdUTF8.Charset(wxS(".utf-8"));
|
locIdUTF8.Charset(wxS("utf-8"));
|
||||||
l = wxSetlocale(c, locIdUTF8.GetName());
|
l = wxSetlocale(c, locIdUTF8.GetName());
|
||||||
}
|
}
|
||||||
if ( !l )
|
if ( !l )
|
||||||
{
|
{
|
||||||
locIdUTF8.Charset(wxS(".UTF8"));
|
locIdUTF8.Charset(wxS("UTF8"));
|
||||||
l = wxSetlocale(c, locIdUTF8.GetName());
|
l = wxSetlocale(c, locIdUTF8.GetName());
|
||||||
}
|
}
|
||||||
if ( !l )
|
if ( !l )
|
||||||
{
|
{
|
||||||
locIdUTF8.Charset(wxS(".utf8"));
|
locIdUTF8.Charset(wxS("utf8"));
|
||||||
l = wxSetlocale(c, locIdUTF8.GetName());
|
l = wxSetlocale(c, locIdUTF8.GetName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -245,6 +281,11 @@ wxUILocaleImplUnix::wxUILocaleImplUnix(wxLocaleIdent locId
|
|||||||
, m_locale(loc)
|
, m_locale(loc)
|
||||||
#endif // HAVE_LOCALE_T
|
#endif // HAVE_LOCALE_T
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_LANGINFO_H
|
||||||
|
m_codeset = GetLangInfo(CODESET);
|
||||||
|
#else
|
||||||
|
m_codeset = "";
|
||||||
|
#endif // HAVE_LANGINFO_H
|
||||||
}
|
}
|
||||||
|
|
||||||
wxUILocaleImplUnix::~wxUILocaleImplUnix()
|
wxUILocaleImplUnix::~wxUILocaleImplUnix()
|
||||||
@@ -292,7 +333,20 @@ wxUILocaleImplUnix::Use()
|
|||||||
wxString
|
wxString
|
||||||
wxUILocaleImplUnix::GetName() const
|
wxUILocaleImplUnix::GetName() const
|
||||||
{
|
{
|
||||||
return m_locId.GetName();
|
wxString name = m_locId.GetName();
|
||||||
|
if (name.empty())
|
||||||
|
{
|
||||||
|
char* rv = setlocale(LC_ALL, NULL);
|
||||||
|
if (rv)
|
||||||
|
name = wxString::FromUTF8(rv);
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxLocaleIdent
|
||||||
|
wxUILocaleImplUnix::GetLocaleId() const
|
||||||
|
{
|
||||||
|
return m_locId;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_LANGINFO_H
|
#ifdef HAVE_LANGINFO_H
|
||||||
@@ -360,6 +414,86 @@ wxUILocaleImplUnix::GetInfo(wxLocaleInfo index, wxLocaleCategory cat) const
|
|||||||
#endif // HAVE_LANGINFO_H/!HAVE_LANGINFO_H
|
#endif // HAVE_LANGINFO_H/!HAVE_LANGINFO_H
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxString
|
||||||
|
wxUILocaleImplUnix::GetLocalizedName(wxLocaleName name, wxLocaleForm form) const
|
||||||
|
{
|
||||||
|
#ifdef HAVE_LANGINFO_H
|
||||||
|
wxString str;
|
||||||
|
switch (name)
|
||||||
|
{
|
||||||
|
case wxLOCALE_NAME_LOCALE:
|
||||||
|
switch (form)
|
||||||
|
{
|
||||||
|
case wxLOCALE_FORM_NATIVE:
|
||||||
|
{
|
||||||
|
str = wxString(GetLangInfo(_NL_ADDRESS_LANG_NAME), wxCSConv(m_codeset));
|
||||||
|
wxString strCtry = wxString(GetLangInfo(_NL_ADDRESS_COUNTRY_NAME), wxCSConv(m_codeset));
|
||||||
|
if (!strCtry.empty())
|
||||||
|
{
|
||||||
|
str << " (" << strCtry << ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case wxLOCALE_FORM_ENGLISH:
|
||||||
|
{
|
||||||
|
str = wxString(GetLangInfo(_NL_IDENTIFICATION_LANGUAGE), wxCSConv(m_codeset));
|
||||||
|
wxString strCtry = wxString(GetLangInfo(_NL_IDENTIFICATION_TERRITORY), wxCSConv(m_codeset));
|
||||||
|
if (!strCtry.empty())
|
||||||
|
{
|
||||||
|
str << " (" << strCtry << ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
wxFAIL_MSG("unknown wxLocaleForm");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case wxLOCALE_NAME_LANGUAGE:
|
||||||
|
switch (form)
|
||||||
|
{
|
||||||
|
case wxLOCALE_FORM_NATIVE:
|
||||||
|
str = wxString(GetLangInfo(_NL_ADDRESS_LANG_NAME), wxCSConv(m_codeset));
|
||||||
|
break;
|
||||||
|
case wxLOCALE_FORM_ENGLISH:
|
||||||
|
str = wxString(GetLangInfo(_NL_IDENTIFICATION_LANGUAGE), wxCSConv(m_codeset));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
wxFAIL_MSG("unknown wxLocaleForm");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case wxLOCALE_NAME_COUNTRY:
|
||||||
|
switch (form)
|
||||||
|
{
|
||||||
|
case wxLOCALE_FORM_NATIVE:
|
||||||
|
str = wxString(GetLangInfo(_NL_ADDRESS_COUNTRY_NAME), wxCSConv(m_codeset));
|
||||||
|
break;
|
||||||
|
case wxLOCALE_FORM_ENGLISH:
|
||||||
|
str = wxString(GetLangInfo(_NL_IDENTIFICATION_TERRITORY), wxCSConv(m_codeset));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
wxFAIL_MSG("unknown wxLocaleForm");
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
wxFAIL_MSG("unknown wxLocaleName");
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
#else // !HAVE_LANGINFO_H
|
||||||
|
// If HAVE_LANGINFO_H is not available, we could use our own language database
|
||||||
|
// to retrieve the requested information.
|
||||||
|
// For now, just return an empty string.
|
||||||
|
return wxString();
|
||||||
|
#endif // HAVE_LANGINFO_H/!HAVE_LANGINFO_H
|
||||||
|
}
|
||||||
|
|
||||||
|
wxLayoutDirection
|
||||||
|
wxUILocaleImplUnix::GetLayoutDirection() const
|
||||||
|
{
|
||||||
|
// Under Linux/Unix the locale data do not contain information
|
||||||
|
// about layout direction. For now, return wxLayout_Default.
|
||||||
|
// wxUILocale will try to use the language database as a fallback.
|
||||||
|
return wxLayout_Default;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
wxUILocaleImplUnix::CompareStrings(const wxString& lhs, const wxString& rhs,
|
wxUILocaleImplUnix::CompareStrings(const wxString& lhs, const wxString& rhs,
|
||||||
int WXUNUSED(flags)) const
|
int WXUNUSED(flags)) const
|
||||||
@@ -413,4 +547,127 @@ wxUILocaleImpl* wxUILocaleImpl::CreateForLocale(const wxLocaleIdent& locIdOrig)
|
|||||||
#endif // HAVE_LOCALE_T/!HAVE_LOCALE_T
|
#endif // HAVE_LOCALE_T/!HAVE_LOCALE_T
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
wxVector<wxString> wxUILocaleImpl::GetPreferredUILanguages()
|
||||||
|
{
|
||||||
|
wxVector<wxString> preferred;
|
||||||
|
|
||||||
|
// 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))
|
||||||
|
{
|
||||||
|
// no language specified, treat it as English
|
||||||
|
preferred.push_back("en-US");
|
||||||
|
return preferred;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the language string has the following form
|
||||||
|
//
|
||||||
|
// lang[_LANG][.encoding][@modifier]
|
||||||
|
//
|
||||||
|
// (see environ(5) in the Open Unix specification)
|
||||||
|
//
|
||||||
|
// where lang is the primary language, LANG is a sublang/territory,
|
||||||
|
// encoding is the charset to use and modifier "allows the user to select
|
||||||
|
// a specific instance of localization data within a single category"
|
||||||
|
//
|
||||||
|
// for example, the following strings are valid:
|
||||||
|
// fr
|
||||||
|
// fr_FR
|
||||||
|
// de_DE.iso88591
|
||||||
|
// de_DE@euro
|
||||||
|
// de_DE.iso88591@euro
|
||||||
|
|
||||||
|
// for now we don't use the encoding, although we probably should (doing
|
||||||
|
// translations of the msg catalogs on the fly as required) (TODO)
|
||||||
|
//
|
||||||
|
// we need the modifier for languages like Valencian: ca_ES@valencia
|
||||||
|
// though, remember it
|
||||||
|
wxString modifier;
|
||||||
|
size_t posModifier = langFull.find_first_of(wxS("@"));
|
||||||
|
if (posModifier != wxString::npos)
|
||||||
|
modifier = langFull.Mid(posModifier);
|
||||||
|
|
||||||
|
size_t posEndLang = langFull.find_first_of(wxS("@."));
|
||||||
|
if (posEndLang != wxString::npos)
|
||||||
|
{
|
||||||
|
langFull.Truncate(posEndLang);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (langFull == wxS("C") || langFull == wxS("POSIX"))
|
||||||
|
{
|
||||||
|
// default C locale is English too
|
||||||
|
preferred.push_back("en_US");
|
||||||
|
return preferred;
|
||||||
|
}
|
||||||
|
|
||||||
|
// do we have just the language (or sublang too)?
|
||||||
|
const bool justLang = langFull.find('_') == wxString::npos;
|
||||||
|
|
||||||
|
if (justLang && langFull.length() > 2)
|
||||||
|
{
|
||||||
|
const wxLanguageInfos& languagesDB = wxGetLanguageInfos();
|
||||||
|
size_t count = languagesDB.size();
|
||||||
|
|
||||||
|
// In addition to the format above, we also can have full language
|
||||||
|
// names in LANG env var - for example, SuSE is known to use
|
||||||
|
// LANG="german" - so check for use of non-standard format and try to
|
||||||
|
// find the name in verbose description.
|
||||||
|
for (size_t i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
if (languagesDB[i].Description.CmpNoCase(langFull) == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i < count)
|
||||||
|
langFull = languagesDB[i].CanonicalName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 0. Make sure the lang is according to latest ISO 639
|
||||||
|
// (this is necessary because glibc uses iw and in instead
|
||||||
|
// of he and id respectively).
|
||||||
|
|
||||||
|
// the language itself (second part is the region)
|
||||||
|
wxString langOrig = ExtractLang(langFull);
|
||||||
|
wxString region = ExtractNotLang(langFull);
|
||||||
|
|
||||||
|
wxString lang;
|
||||||
|
if (langOrig == wxS("iw"))
|
||||||
|
lang = wxS("he");
|
||||||
|
else if (langOrig == wxS("in"))
|
||||||
|
lang = wxS("id");
|
||||||
|
else if (langOrig == wxS("ji"))
|
||||||
|
lang = wxS("yi");
|
||||||
|
else if (langOrig == wxS("no") && region == wxS("_NO"))
|
||||||
|
lang = wxS("nb");
|
||||||
|
else if (langOrig == wxS("no") && region == wxS("_NY"))
|
||||||
|
{
|
||||||
|
lang = wxS("nn");
|
||||||
|
region = wxS("_NO");
|
||||||
|
}
|
||||||
|
else if (langOrig == wxS("no"))
|
||||||
|
lang = wxS("nb");
|
||||||
|
else
|
||||||
|
lang = langOrig;
|
||||||
|
|
||||||
|
// did we change it?
|
||||||
|
if (lang != langOrig)
|
||||||
|
{
|
||||||
|
langFull = lang + region;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!modifier.empty())
|
||||||
|
{
|
||||||
|
// Locale name with modifier
|
||||||
|
preferred.push_back(langFull + modifier);
|
||||||
|
}
|
||||||
|
// Locale name without modifier
|
||||||
|
preferred.push_back(langFull);
|
||||||
|
|
||||||
|
return preferred;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // wxUSE_INTL
|
#endif // wxUSE_INTL
|
||||||
|
|||||||
@@ -262,7 +262,8 @@ TEST_CASE("wxUILocale::IsSupported", "[uilocale]")
|
|||||||
{
|
{
|
||||||
CheckSupported(wxUILocale::FromTag("en"), "English");
|
CheckSupported(wxUILocale::FromTag("en"), "English");
|
||||||
CheckSupported(wxUILocale(wxLocaleIdent().Language("fr").Region("FR")), "French");
|
CheckSupported(wxUILocale(wxLocaleIdent().Language("fr").Region("FR")), "French");
|
||||||
CHECK( !wxUILocale::FromTag("bloordyblop").IsSupported() );
|
CHECK_FALSE( wxUILocale::FromTag("bloordyblop").IsSupported() );
|
||||||
|
CHECK_FALSE( wxUILocale::FromTag("xyz").IsSupported() );
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("wxUILocale::GetInfo", "[uilocale]")
|
TEST_CASE("wxUILocale::GetInfo", "[uilocale]")
|
||||||
|
|||||||
Reference in New Issue
Block a user