Bill Forster Bill Forster - 1 year ago 47
C++ Question

Detecting whether US English or British English spelling is appropriate with C++

Using C++ is there a simple and reliable way to detect whether US English or British English spelling is a better match to the user's locale? I have a simple desktop C++ program and I want to perform this first minimal internationalization step. My user interface uses the word color/colour a lot and I am hoping to present the correct spelling to the user in 99%+ cases without a lot of rocket science or an explicit user option.

Edit: The accepted answer below is good. Just to provide some additional information and a complete usable solution, here is perhaps the simplest possible way to determine whether to use US or British English in your C++ application. This is a small but useful step towards proper internationalization. It's useful for US developers who wish to be culturally sensitive to English speakers outside the US, and for other English speaking developers who want their products to look a little more at home in the US (I am in the latter camp).

It's not a perfect solution, but clearly the standardisation process has failed to provide a perfect and simple solution. I expect that at the very least using this code will get color versus colour wrong for a smaller proportion of your users than simply arbitrarily choosing one or the other, assuming your product is widely used.

#include <string>
#include <clocale>

struct lconv * lc;
lc = localeconv();
std::string sym(lc->int_curr_symbol);
bool us_english = (sym=="USD" || sym=="PHP");

I am basically assuming US English is the preference in the USA and British English elsewhere, although I've made an exception for one country where I know that not to be the case (the Philippines).

On my Windows system this program immediately reflects a change in the default language as controlled by Windows Settings or the Control Panel. Doing it this way avoids parsing any strings that may vary from OS to OS and I expect it to be portable.

I am not going to use my own solution, since in my particular case I am using wxWidgets, and as it happens wxWidgets provides a portable wrapper tailor made for this issue (I should have thought of checking before).

#include "wx/intl.h"
int lang = wxLocale::GetSystemLanguage();
bool us_english = (lang == wxLANGUAGE_ENGLISH_US);

Answer Source

The limitations of standards

As NeomerArcana correctly pointed out, the standard C++ way to do this is:

Unfortunately, the standard doesn't enforce how this name should look like, and MSVC implementation just returns the name that you gave when you've constructed the object, i.e. an empty string.


Fortunately however, there's a C work-around that produces a better result with MSVC: std::setlocale(LC_ALL, NULL);. This function returns a pointer to a null terminated C-string, which contain the full name of the environment's default locale.

However, the format of this string might depend on the OS and version. So you'll have to parse it in a flexible manner: it can be a proper locale name (e.g. "en-US" for windows vs. "en_US.UTF-8" on POSIX) or a Windows specific format (e.g. "English_United States.1252", based on a language table).

Alternatively, if you target only Windows, you could consider simplifying your life by using GetSystemDefaultLangID(void). This function returns a binary language identifier, that you can then check against language LANG_ENGLISH and regional variations SUBLANG_ENGLISH_UK