fix(mac): use same $LANG fallback mechanism as Vim

In a locale "en_US", "en" is the language and "US" is the region.

Before this change, we were too clever for our own good and tried to handle the
region as well. But if the macOS primary language is set to "English" and the
region to "Norway", we would end up with "en_NO", which is a locale that does
not exist.

Now we only take the language into account. Taking the example from above would
yield "en_US", which is a sensible fallback.

If the region is important to you, set $LANG and the more specific LC_*
variables in your shell config or alternatively use `:help :language`.

References https://github.com/neovim/neovim/issues/18292
This commit is contained in:
Marco Hinz 2022-04-28 20:56:44 +02:00
parent 521e91e1c4
commit e038625b87
No known key found for this signature in database
2 changed files with 17 additions and 47 deletions

View File

@ -16,8 +16,8 @@ if(WIN32)
# tell MinGW compiler to enable wmain
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -municode")
elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework CoreFoundation")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -framework CoreFoundation")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework CoreServices")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -framework CoreServices")
endif()
set(TOUCHES_DIR ${PROJECT_BINARY_DIR}/touches)

View File

@ -3,9 +3,10 @@
#ifdef __APPLE__
# define Boolean CFBoolean // Avoid conflict with API's Boolean
# include <CoreFoundation/CFLocale.h>
# include <CoreFoundation/CFString.h>
# define FileInfo CSFileInfo // Avoid conflict with API's Fileinfo
# include <CoreServices/CoreServices.h>
# undef Boolean
# undef FileInfo
#endif
#include "auto/config.h"
@ -21,55 +22,24 @@ void lang_init(void)
{
#ifdef __APPLE__
if (os_getenv("LANG") == NULL) {
const char *lang_region = NULL;
CFTypeRef cf_lang_region = NULL;
CFLocaleRef cf_locale = CFLocaleCopyCurrent();
if (cf_locale) {
cf_lang_region = CFLocaleGetValue(cf_locale, kCFLocaleIdentifier);
CFRetain(cf_lang_region);
lang_region = CFStringGetCStringPtr(cf_lang_region,
kCFStringEncodingUTF8);
CFRelease(cf_locale);
} else {
// Use the primary language defined in Preferences -> Language & Region
CFArrayRef cf_langs = CFLocaleCopyPreferredLanguages();
if (cf_langs && CFArrayGetCount(cf_langs) > 0) {
cf_lang_region = CFArrayGetValueAtIndex(cf_langs, 0);
CFRetain(cf_lang_region);
CFRelease(cf_langs);
lang_region = CFStringGetCStringPtr(cf_lang_region,
kCFStringEncodingUTF8);
} else {
ELOG("$LANG is empty and your primary language cannot be inferred.");
return;
}
}
char buf[50] = { 0 };
bool set_lang;
if (lang_region) {
set_lang = true;
xstrlcpy(buf, lang_region, sizeof(buf));
} else {
set_lang = CFStringGetCString(cf_lang_region, buf, 40,
kCFStringEncodingUTF8);
}
if (set_lang) {
// $LANG is not set, either because it was unset or Nvim was started
// from the Dock. Query the system locale.
if (LocaleRefGetPartString(NULL,
kLocaleLanguageMask | kLocaleLanguageVariantMask |
kLocaleRegionMask | kLocaleRegionVariantMask,
sizeof(buf) - 10, buf) == noErr && *buf) {
if (strcasestr(buf, "utf-8") == NULL) {
xstrlcat(buf, ".UTF-8", sizeof(buf));
}
os_setenv("LANG", buf, true);
setlocale(LC_ALL, "");
// Make sure strtod() uses a decimal point, not a comma.
setlocale(LC_NUMERIC, "C");
} else {
ELOG("$LANG is empty and the macOS primary language cannot be inferred.");
}
CFRelease(cf_lang_region);
# ifdef HAVE_LOCALE_H
setlocale(LC_ALL, "");
# ifdef LC_NUMERIC
// Make sure strtod() uses a decimal point, not a comma.
setlocale(LC_NUMERIC, "C");
# endif
# endif
}
#endif
}