Using boost locale with French

I have modified an example program provided on the www.boost.org website, to use the "fr_FR" locale (French), to test if floating-point numbers are displayed as expected (with a comma instead of the decimal point). However, a decimal point still echoes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//

#include <boost/locale.hpp>
#include <iostream>
#include <ctime>

int main()
{
using namespace boost::locale;
using namespace std;
generator gen;
locale loc=gen("fr_FR"); 
// Create system default locale
locale::global(loc); 
// Make it system global
cout.imbue(loc);
// Set as default locale for output
cout <<format("Today {1,date} at {1,time} we had run our first localization example") % time(0) 
<<endl;
cout<<"This is how we show numbers in this locale "<<as::number << 103.34 <<endl; 
cout<<"This is how we show currency in this locale "<<as::currency << 103.34 <<endl; 
cout<<"This is typical date in the locale "<<as::date << std::time(0) <<endl;
cout<<"This is typical time in the locale "<<as::time << std::time(0) <<endl;
cout<<"This is upper case "<<to_upper("Hello World!")<<endl;
cout<<"This is lower case "<<to_lower("Hello World!")<<endl;
cout<<"This is title case "<<to_title("Hello World!")<<endl;
cout<<"This is fold case "<<fold_case("Hello World!")<<endl;
}


https://wandbox.org/permlink/HuNd5od3q55bWAev

Why doesn't the locale display numbers with a comma, as in French? How do I get it to?

Thanks.
I get this output on my workstation:

Today 04/12/2017 at 11:54:58 we had run our first localization example
This is how we show numbers in this locale 103,34
This is how we show currency in this locale 103.34 EUR
This is typical date in the locale 04/12/2017
This is typical time in the locale 11:54:58
This is upper case HELLO WORLD!
This is lower case hello world!
This is title case Hello World!
This is fold case hello world!


looks like wandbox's C library does not have the locales configured. In fact, it's easy enough to test: https://wandbox.org/permlink/5nAP9sOYbb7zf9qA

looks like wandbox's C library does not have the locales configured.


You seem to be saying that, even with boost installed, a system would use the C library for locales. Ie, boost would use the locales from the underlying system.

I thought that boost/locale would be providing the locales. What is the purpose of boost/locale then?

In this case, how can I install the locales on a system, if boost doesn't do that?

Thanks.
> I thought that boost/locale would be providing the locales.

Boost.Locale requires a back-end library; it works best with an ICU back-end.
http://www.boost.org/doc/libs/1_65_1/libs/locale/doc/html/using_localization_backends.html

On Windows (and MinGW and CygWin), the WinAPI backend gives good localization support.

On platforms where the standard C++ library has reasonable localization support (GNU on Linux and MSVC on Windows), the standard C++ library back-end too would work quite well.


> how can I install the locales on a system, if boost doesn't do that?

See: http://www.boost.org/doc/libs/1_65_1/libs/locale/doc/html/building_boost_locale.html#building_boost_locale_bb

With Visual Studio, it may be more convenient to use VcPkg:
https://blogs.msdn.microsoft.com/vcblog/2016/09/19/vcpkg-a-tool-to-acquire-and-build-c-open-source-libraries-on-windows/

Boost.Locale requires a back-end library; it works best with an ICU back-end.


By default, boost.locale already uses the ICU back-end l10n library. We don't have to do anything special to get that. But still, it doesn't work.

This is all the more strange, because the boost.locale website specifically states boost is provided to overcome some of the "common critical problems of the standard library":


Many standard libraries provide only the C and POSIX locales, thus GCC supports localization only under Linux. On all other platforms, attempting to create locales other than "C" or "POSIX" would fail.


Therefore, boost/locale can't be based on the OS or standard library's features for locales.

Further, I have also tried using boost/locale with 2 separate l10n backends: std and WINAPI, both of which result in exactly the same disappointing results.

std l10n backend: https://wandbox.org/permlink/ROzOIZUTeKMffdRg
WINAPI l10n backend: https://wandbox.org/permlink/ZH9rl1HovjKbtrZF
> By default, boost.locale already uses the ICU back-end l10n library.

It will use it only if the ICU library is available (ICU is not part of the standard boost distribution.)

We can check this by printing out the list of all available back-ends.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include <boost/locale.hpp>
#include <iomanip>

int main()
{
    auto mgr = boost::locale::localization_backend_manager::global() ;
    
    // list all back-ends
    std::cout << "available back-ends are: " ;
    for( const std::string& name : mgr.get_all_backends() ) std::cout << std::quoted(name) << ' ' ;
    std::cout << "\n\n" ;
    
    // with the default locale associated with std::cout
    std::cout << std::fixed << boost::locale::as::number << 1234567.89 << '\n' 
              << std::showbase <<  boost::locale::as::currency << 1234567.89 << "\n\n" ;

    // set the standard C++ library back-end as the default global back-end
    mgr.select("std") ; // GNU library on Linux; so this is fine
    boost::locale::localization_backend_manager::global(mgr) ;
    
    // create a locale: POSIX and std back-ends use their own OS specific naming conventions for locales
    // so pick a locale name from the list of locales listed earlier with locale -a
    const auto loc = boost::locale::generator{}.generate( "de_DE.utf8" ) ;
    
    std::cout.imbue(loc) ; // assciate this locale with std::cout
    std::cout << std::fixed << boost::locale::as::number << 1234567.89 << '\n' 
              << std::showbase <<  boost::locale::as::currency << 1234567.89 << '\n' ;
}

http://coliru.stacked-crooked.com/a/2a263ee68ae16b8e
This is quite exciting - something related to locales works - Finally!

And it wasn't thanks to boost.locale; it was thanks to std::locale.

Fortunately, you had issued an OS command to display the locale names. From that, I was able to ascertain the availability of the "de_DE.utf8" on coliru.

I have been trying (for some time now) to test the automatic translation of floating-point formats from English to French (which uses a comma in place of the decimal point). Evidently coliru doesn't support a standard-library locale for French; but it does support one for German ("de_DE.utf8" ).

German is similar to French in its numeric format - it displays a comma in place of the decimal point.

So, I was able to test this successfully on coliru using standard-library locales.

http://coliru.stacked-crooked.com/a/e79e3772a68b6b34

Thanks.
You have used the following OS command to display the locale names hosted by the platform:

 
echo 'locale names' && locale -a && echo && echo


This requires the "locale" executable to be present on the platform.

This doesn't work on msys, which, of course, doesn't have the "locale" executable.

Also, for online environments, this command can be issued only if that environment allows the command to be entered. coliru allows this, but not ideone.com or wandbox.org.

Is it possible to similarly ascertain the locale names hosted by a platform, for online environments such as ideone.com / wandbox.org and also for g++ / clang?

Thanks.
Windows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#define _WIN32_WINNT 0x6000
#include <windows.h>
#include <vector>
#include <string>
#include <cstdlib>
#include <iostream>
#include <iomanip>

static std::string to_string( const wchar_t* wcstr )
{
    char buffer[LOCALE_NAME_MAX_LENGTH] {} ;
    return std::wcstombs( buffer, wcstr, LOCALE_NAME_MAX_LENGTH ) != std::size_t(-1) ? buffer : "" ;
}

static BOOL CALLBACK enum_locale_call_back( LPWSTR loc_name, DWORD, LPARAM vec )
{
    reinterpret_cast< std::vector<std::string>* >(vec)->push_back( to_string(loc_name) ) ;
    return TRUE ;
}

std::vector<std::string> all_locale_names()
{
    std::vector<std::string> names ;
    ::EnumSystemLocalesEx( enum_locale_call_back, 0, LPARAM( std::addressof(names) ), nullptr ) ;
    return names ;
}

int main()
{
    for( const std::string& loc_name : all_locale_names() )
        std::cout << std::quoted(loc_name) << '\n' ;
}

http://rextester.com/WSUM58602

POSIX:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <vector>
#include <string>
#include <cstdlib>
#include <fstream>
#include <iterator>
#include <iostream>
#include <iomanip>

std::vector<std::string> all_locale_names()
{
    std::system( "locale -a > locale_names.txt" ) ;
    
    std::ifstream file( "locale_names.txt" ) ;
    return { std::istream_iterator<std::string>(file), std::istream_iterator<std::string>() } ;    
}

int main()
{
    for( const std::string& loc_name : all_locale_names() ) 
        std::cout << std::quoted(loc_name) << '\n' ;
}

http://coliru.stacked-crooked.com/a/969ef317ae45526d
Topic archived. No new replies allowed.