Locale VM plugin always returns the default English on Mac Os
Dear maintainers:
It looks like the locale reported by the VM is not working as it should. No matter what I try, I always get the default: English. This was originally reported in the Cuis mailing list.
How to Reproduce
Change your OS locale to a language other than English.
I tried with Portuguese and Italian; currently I'm on Italian. The output of /usr/bin/locale is:
LANG="it_IT.UTF-8"
LC_COLLATE="it_IT.UTF-8"
LC_CTYPE="it_IT.UTF-8"
LC_MESSAGES="it_IT.UTF-8"
LC_MONETARY="it_IT.UTF-8"
LC_NUMERIC="it_IT.UTF-8"
LC_TIME="it_IT.UTF-8"
LC_ALL=
And here is the configuration as reported by the UI:
In Squeak or Pharo (actually Glamorous Toolkit)
Evaluate
Locale current
In GT it prints as:
a Locale(en-PT)
Portugal is correctly reported, as the current configured country in the OS.
In Squeak it prints as:
a Locale(en-US <English (UNITED STATES)>)
In Cuis
Evaluate
Feature require: 'Locales'.
Locale current
It prints as:
a Locale(en-PT)
Speculation
It seems like it all boils down to Locale >> primLanguage. It always returns the null-terminated 'en�'.
Computer
MacBook Air, Intel, 2017 Mac OS Monterey 12.7.6 (21H1320)
Please let me know if you need me to try more things.
Thank you!
Thanks for the report. It is a blocking issue to deploy, for the first time, DrGeo on thousands of computers in Geneva schools, to teach programming.
I am not using Mac OS but on Solaris I have LANG=nl_BE.UTF-8 at the UNIX level and in Squeak v6.1 alpha under "Preferences" there is #useLocale enabled :
In a Workspace:
Preferences valueOfFlag:#useLocale
evaluates to "true".
Locale current prints aLocale(nl-BE <Dutch;Flemish (BELGIUM)>)
the primLanguage instance method returns nl
Smalltalk listLoadedModules also shows LocalePlugin as loaded
Similar results on Pi - turning the locale preference on makes the Locale current value properly reflect what the OS reports. Not entirely sure why we would have set it off as a default; but timezones are probably involved long with the matter. They always are.
On my GNU/Linux Locale current reports the expected language and country code.
Last time I checked , one year ago, it worked as expected on Windows too.
Changing the value of useLocale to true makes no difference. E.g. in Cuis, Locale current returns a locale that prints as 'en-PT' instead of the expected 'it-PT' and Locale new primLanguage returns 'en�'.
Looking at the most recent image I have to hand(23223 update), I see some confusion in the state of several extant Locale instances (and I don't see why there are several) Locale knownLocales.
- a Dictionary with a single instance having the id isoLanguage = 'en' and isoCountry = nil, and no other ivars set to anything but nil Locale current.
- an instance with id isoLanguage = 'en' and isoCountry = 'US'. Of the other ivars only leadingChar is non nil, = 0 (yes, the SmallInteger, not even a Character) Locale currentPlatform
- an instance with id isoLanguage = 'en' and isoCountry = 'GB'. The only other non-nil ivar is currencySymbol which is codepoint 194 + codepoint 163. Which renders improperly in both Squeak on Pi and in my web browser, and in a text editor looks like 'ã' . Looking at what the primitives return directly Locale new primCurrencySymbol. 'ã' Locale new primDST. true Locale new primDecimalSymbol. '.' Locale new primDigitGrouping. ','
Locale new primLanguage. 'en <<<<< Note how pasting the result messed up the copy/paste/browser rendering. There is a Character null after the second char and likely that should have been chopped off in the prim code.
Locale new primLongDateFormat. '%d/%m/%y' Locale new primMeasurement. true Locale new primShortDateFormat. '%d/%m/%y' Locale new primTimeFormat. '%T' Locale new primTimezone. -420 Locale new primVMOffsetToUTC. 0
This is quite confusing. And there is little usage of any of it in the default image to help us work out the intended ways of using any of it.
In an image with preference set to use locale= true, try Locale current: nil and then explore Locale current. That should have cleaned out and rebuilt your Locale. Maybe.
In an image with preference set to use locale= true, try Locale current: nil and then explore Locale current. That should have cleaned out and rebuilt your Locale. Maybe.
It probably rebuilds the locale, but as before, the language is still wrongly reported as English because Locale>>primLanguage always returns 'en�'.
The other issues you observed might be related to this one.
Tested in a newly downloaded Squeak Image v 6.1 alpha 23242 64 bit. Print output in comments
Preferences valueOfPreference: #useLocale "false"
Locale current "a Locale(en-US <English (UNITED STATES)>)"
Locale allInstances "{a Locale(en-US <English (UNITED STATES)>) . a Locale(en-PT <English (PORTUGAL)>)}"
Preferences setPreference: #useLocale toValue: true "a Preference#useLocale true"
Locale current "a Locale(en-US <English (UNITED STATES)>)"
Locale allInstances "{a Locale(en-US <English (UNITED STATES)>) . a Locale(en-PT <English (PORTUGAL)>)}"
Locale current: nil "Locale"
Locale current "a Locale(en-PT <English (PORTUGAL)>)"
Locale allInstances "{a Locale(en-US <English (UNITED STATES)>) . a Locale(en-PT <English (PORTUGAL)>)}"
Locale new primLanguage "'en�'"
Eziquiel, can you take a look at the source? It’s in platforms/*/plugins/LocalePlugin and src/plugins/LocalePlugin/LocalePlugin.c
Looking at the code in https://github.com/OpenSmalltalk/opensmalltalk-vm/tree/Cog/platforms/unix/plugins/LocalePlugin/sqUnixLocale.c around line 570 and up it seems like the only way you could get the effect of the LANG setting being ignored if by the phrase on lines is returning false and so the language ptr is not getting set. That then leaves it to the DEFAULT_LANGUAGE per line 52.
Did the process "inherit" the environment LANG variable from its parent ?
On SqueakSource, there is a class OSProcess. http://www.squeaksource.com/OSProcess which can be loaded into a Squeak image and then:
OSProcess thisOSProcess environmentAt:#LANG
in a Workspace 'print it' evaluates (for me) to "nl_BE.UTF-8'.
This is to check whether the executable is launched with the LANG variable at the UNIX process level.
Perhaps in your case the executable is not getting the or any of the environment variables, perhaps due to some environment resetting.
Anyway, the LocalePlugin is used in a package like 'DrGeo' (for Cuis) which provides as an application localised messages, but those have to be explicitely installed (with the UNIX/POSIX msgfmt command). I think that OpenSmalltalk in itself does not provide a localised interface by setting the LANG environment variable, which is perhaps why in Preferences useLocale is disabled by default.
https://github.com/Dynamic-Book/drgeo uses the LocalePlugin and provides msgfmt files, but I think that many classes or applications do not provide this.
Is OpenSmalltalk started from the command-line in a Unix shell ?
In a Unix shell echo $LANG should print the environment variable.
To get a list of the environment variables GNU coreutils "env" command would print the environment at the Unix shell command line level. Or "setenv" in csh or "export" in bash.
The OpenSmalltalk executable should then be started command line from the shell as a child process of the shell to inherit the environment from the parent.
Inside Smalltalk : OSProcess thisOSProcess environment
this returns a Dictionary instance with the values of LOGNAME, USER, HOME, MAIL, SHELL, LANG etc. as in the Unix shell
The VM can be started either on the command line or through the GUI on at least macOS and Windows. Under X11 we want it to be launched in either way but X11 delegates such schemes and so AFAIA there’s no standard way to launch through the GUI. But the user’s environment should be made available to the system irrespective of the launch mechanism.
Another possibility is that check the output of : locale -a
List all locale to see whether some alias is used.
LANG=nl_BE.utf8 could give a Flemish/Dutch/Belgian locale in Smalltalk (as expected, using utf8 instead of UTF-8), if it is defined as an alias for LANG=nl_BE.UTF-8 at the OS level.
Such mistakes could happen because the operating system package that defines an alias nl_BE.UTF-8 for nl_BE.utf8 may need to be installed
LANG is not in the env when starting the VM via GUI:
Only when started from a shell does it get the full environment including LANG.
However, it looks like sqMacLocaleCocoa.m does the right thing, I'm just not sure if that is actually used.
A related code issue that may be preferred as a separate report - it looks like the unix locale code is configured to only report the 2 letter language code. However, the generated LocalePlugin code is creating a 3 character String (see src/Plugins/LocalePlugin/LocalePlugin.c). Somewhere in the rather convoluted code chain this might create a problem.
LANG is not in the env when starting the VM via GUI:
Only when started from a shell does it get the full environment including LANG.
However, it looks like sqMacLocaleCocoa.m does the right thing, I'm just not sure if that is actually used.
When I look at the build directory it doesn't:
squeak.cog.spur$ ls build/LocalePlugin/ LocalePlugin.o sqIOSLocale.o squeak.cog.spur$
sqMacLocaleCocoa.m is in SqueakLocale. What's the right thing to do here?
However, it looks like sqMacLocaleCocoa.m does the right thing, I'm just not sure if that is actually used.
When I look at the build directory it doesn't:
squeak.cog.spur$ ls build/LocalePlugin/ LocalePlugin.o sqIOSLocale.o squeak.cog.spur$sqMacLocaleCocoa.m is in SqueakLocale. What's the right thing to do here?
I don't really know – maybe "SqueakLocale" needs to be renamed to "LocalePlugin"? I'm not really familiar with the Mac build process.
Maybe we need to ask @johnmci ?
It will be great if @johnmci could give some insights about the Locale plugin in Mac OS X. In the mean time, when time permit it, I could implement a user preference system from Cuis to select the desired language. Is writing his alias in this comment enough to reach him? Thanks
Only when started from a shell does it get the full environment including LANG.