Canonical Locale

Canonical Locale
Written by Bo Thorsen
2014/11/30

Sometimes you need a fixed locale. One of my latest applications was reading and writing floats in XML, and the string parse and write routines for floats are locale dependent. So the XML file would either have “2,01” (US notation) or “2.01” (Danish notation) in them. And the unit tests were failing. 

I just saw a discussion on the #qt IRC chat where one of the people there got hit by the same problem in his database code.

The solution is to set a known locale while the conversions are done. The proper one to choose is probably the US locale, unless you don’t have to interface with anything else. However, switching locales manually is a bit annoying, so I came up with these two classes:

				
					// Making an object of this kind sets the a specific locale, and returns it to the old
// setting when the object is deleted
class LocaleSaver {
public:
    LocaleSaver(QLocale::Language language, QLocale::Country country) {
        // Make a new locale with the correct settings
        QLocale::setDefault(QLocale(language, country));
    }
    ~LocaleSaver() {
        QLocale::setDefault(restoreLocale);
    }
    const QLocale restoreLocale;
};
// This is a specialized version of the locale saver, that is used whenever we parse
// something from Qt or from a saved file
class CanonicLocale : public LocaleSaver {
public:
    CanonicLocale() : LocaleSaver(QLocale::English, QLocale::UnitedStates) {}
};
				
			

When you need to set the locale for a short while, just instantiate it like this:

				
					// code here in the normal locale
{
    // Set the US locale for a while
    CanonicLocale locale;
    // code here that is with a known locale
}
// code here - back to the normal locale
				
			

Just put the classes in a header file somewhere, and then the locale switching is a one liner.

One thing someone is bound to ask: Initialization of the restoreLocale attribute? When you create a QLocale object, it’s automatically initialized to the current default locale, so this is actually set up correctly.

Multithreaded Applications

This code solves the problem for single threaded code, but in multithreaded code you need a bit more.

You should add a mutex or critical section that prevents any locale changes. I would do that by adding code to the LocaleSaver class. But this would make the class slower and more difficult to understand, which is why it’s not done here. Multithreaded code is also less common in Qt than it is in, say, native Windows coding.

Just remember that you need to worry about this, if you add threading. Just like you need to protect all other shared resources.

Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments