Can not `setlocale(3)' more than once in Linux

S

Steven Woody

Hi,

I am in Linux writing a program using setlocale(3). But I found, only
the first invocation of setlocale(3) can be success, any subsequent
calling of this function will fail $B!J(B return NULL ) and the locale is
not changed. Is there any tip here?

Thanks.


#define _(String) gettext (String)

static void init_lc( const char* lc )
{
setlocale( LC_ALL, "" );
bindtextdomain( "hello", "/usr/local/share/locale" );
textdomain( "hello" );
}

int main( void )
{
init_lc( "" );

printf( _("Current locale is %s\n"), setlocale( LC_ALL, NULL ) );
printf( _("press 'e' to select English, 'c' to select Simplified
Chinese: ") );

int c;
while ( true ) {
c = getch();
if ( c == 'e' )
setlocale( "en_US" );
else if ( c == 'c' )
setlocale( "zh_CN" );
printf( _("press 'e' to select English, 'c' to select
Simplified Chinese: ") );
printf( _("Hello, world!\n") );
}

return 0;
}
 
B

Ben Bacarisse

Steven Woody said:
I am in Linux writing a program using setlocale(3). But I found, only
the first invocation of setlocale(3) can be success, any subsequent
calling of this function will fail ( return NULL ) and the locale is
not changed. Is there any tip here?

All I can say is that is not the case on my system. I can call
setlocale as often as I like. The program you posted should not have
compiled and certainly would not have been able to set the locale
since all but on of the calls was badly formed so it is not clear to me
how you even know there is a problem.

Although the function is standard, the standard says very little about
what locale strings mean, so you will need to post in, say,
comp.unix.programmer to get more help. Before you do, prepare a small
example that illustrates the problem you are having. The solution may
be simple.
 
A

Antoninus Twink

I am in Linux writing a program using setlocale(3). But I found, only
the first invocation of setlocale(3) can be success, any subsequent
calling of this function will fail ( return NULL ) and the locale is
not changed. Is there any tip here? [snip]
if ( c == 'e' )
setlocale( "en_US" );
else if ( c == 'c' )
setlocale( "zh_CN" );

The prototype for setlocale is
char *setlocale(int category, const char *locale);

You're missing an argument.
 
S

Steven Woody

I am in Linux writing a program usingsetlocale(3). But I found, only
the first invocation ofsetlocale(3) can be success, any subsequent
calling of this function will fail ( return NULL ) and the locale is
not changed. Is there any tip here? [snip]
if ( c == 'e' )
setlocale( "en_US" );
else if ( c == 'c' )
setlocale( "zh_CN" );

The prototype forsetlocaleis
char *setlocale(int category, const char *locale);

You're missing an argument.

Sorry, when I modified the original code to make it simple to show
you, I made some errors. But the original code is right and I did
supplied correct arguments. Well, below is a correct version of the
code and I made it more simple to illustrate the problem:

#include <libintl.h>
#include <locale.h>
#include <stdio.h>

int main( void )
{
printf( "Current locale is %s\n", setlocale( LC_ALL, NULL ) );

bindtextdomain( "hellonls", "/usr/local/share/locale" );
textdomain( "hellonls" );

const char* msg = gettext( "Hello, world!" );

if ( ! setlocale( LC_ALL, "en_US" ) )
fprintf( stderr, "setlocale( en_US ) error\n" );
printf( "%s\n", msg );

if ( ! setlocale( LC_ALL, "zh_CN" ) )
fprintf( stderr, "setlocale( zh_CN ) error\n" );
printf( "%s\n", msg );

if ( ! setlocale( LC_ALL, "" ) )
fprintf( stderr, "setlocale( \"\" ) error\n" );
printf( "%s\n", msg );

return 0;
}

I found only the 3rd invocation of setlocale( ... ) can be success,
that is, I can only set locale to the system default. The calling
lines with "en_US" and "zh_CN" failed and returned NULL. So if my
system has LC_ALL=en_US, the code will print three same lines of
"Hello, world!" in english on the stdout, and If I set the LC_ALL to
zh_CN before run the code, I will got three same lines of "Hello,
world!" in Chinese.

Could you please try the code and tell me what's wrong here? You may
need to change "zh_CN" to a suitable locale to you. Thanks.

-
woody
 
A

Antoninus Twink

I found only the 3rd invocation of setlocale( ... ) can be success,
that is, I can only set locale to the system default. The calling
lines with "en_US" and "zh_CN" failed and returned NULL.

The first thing you could try is is perror(NULL) when setlocale() fails,
and see if there's any useful error message.

Then, try
strace ./yourprog 2>&1 | grep locale
and see if that provides any information.
 
F

Flash Gordon

Steven Woody wrote, On 27/04/08 16:42:
Sorry, when I modified the original code to make it simple to show
you, I made some errors. But the original code is right and I did
supplied correct arguments.

This, of course, is why you should always copy and paste actual tested code.
Well, below is a correct version of the
code and I made it more simple to illustrate the problem:

#include <libintl.h>

The above header is not defined by the C standard, so it would have been
better if you provided an example which did not use it.
#include <locale.h>
#include <stdio.h>

int main( void )
{
printf( "Current locale is %s\n", setlocale( LC_ALL, NULL ) );

bindtextdomain( "hellonls", "/usr/local/share/locale" );
textdomain( "hellonls" );

const char* msg = gettext( "Hello, world!" );

The above three functions are not part of the C standard. It is possible
they are doing something to affect the results, so try again without
using them. If they are the problem then I suggest asking in a Linux
group or if that is your platform or possibly comp.unix.programmer.
if ( ! setlocale( LC_ALL, "en_US" ) )
fprintf( stderr, "setlocale( en_US ) error\n" );

I don't believe that errno is required to be set by setlocale, but it
might be worth replacing the above (and the other error printouts) with
calls to perror for testing just in case your implementation is helpful.
I.e.
perror( "setlocale( en_US ) error\n" );
printf( "%s\n", msg );

if ( ! setlocale( LC_ALL, "zh_CN" ) )
fprintf( stderr, "setlocale( zh_CN ) error\n" );
printf( "%s\n", msg );

if ( ! setlocale( LC_ALL, "" ) )
fprintf( stderr, "setlocale( \"\" ) error\n" );
printf( "%s\n", msg );

return 0;
}

I found only the 3rd invocation of setlocale( ... ) can be success,
that is, I can only set locale to the system default. The calling
lines with "en_US" and "zh_CN" failed and returned NULL. So if my
system has LC_ALL=en_US, the code will print three same lines of
"Hello, world!" in english on the stdout, and If I set the LC_ALL to
zh_CN before run the code, I will got three same lines of "Hello,
world!" in Chinese.

Could you please try the code and tell me what's wrong here? You may
need to change "zh_CN" to a suitable locale to you. Thanks.

Having removed the non-standard code and changed to supported locales it
works, so I suspect either one of the non-standard function calls is
breaking setlocale or you are selecting locales not supported on your
system. If you ask on a group dedicated to your implementation they may
be able to tell you how to check what locales are supported (you could
try the command "locale -a") and as I say if removing the non-standard
functions helps a group dedicated to your implementation may be able to
tell you why.
 
B

Ben Bacarisse

Steven Woody said:
Sorry, when I modified the original code to make it simple to show
you, I made some errors. But the original code is right and I did
supplied correct arguments. Well, below is a correct version of the
code and I made it more simple to illustrate the problem:

<snip code>

The problem is not (now) the call to setlocale but the way your system
interprets the string it is passed. If you are using a POSIX system
(most Unix-like OSes) then post in comp.unix.programmer and you will
get access to lots of experts.

Here, the topic is standard C, and your problem is no longer with that
standard function but with what your system does with the string. The
only help you are likely to get here is from Antoninus Twink who is
single-handedly attempting to broaden the topicality here to include
other languages as well as Linux locale commands. Over in c.u.p you
will find lot of people who can help.
 
S

Steven Woody

<snip code>

The problem is not (now) the call to setlocale but the way your system
interprets the string it is passed. If you are using a POSIX system
(most Unix-like OSes) then post in comp.unix.programmer and you will
get access to lots of experts.

Here, the topic is standard C, and your problem is no longer with that
standard function but with what your system does with the string. The
only help you are likely to get here is from Antoninus Twink who is
single-handedly attempting to broaden the topicality here to include
other languages as well as Linux locale commands. Over in c.u.p you
will find lot of people who can help.

Yes, I think I am in wrong group. I will go to comp.unix.programmer.
Thanks.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top