diff --git a/docs/changelog.rst b/docs/changelog.rst index 6462f1da1..72ce14549 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -22,6 +22,11 @@ To update |kitty|, :doc:`follow the instructions `. event which breaks some applications that grab the mouse but cant handle mouse events (:iss:`3902`) +- macOS: When the language is set to English and the country to one for which + an English locale does not exist, set :envvar:`LANG` to ``en_US.UTF-8`` + (:iss:`3899`) + + 0.22.2 [2021-08-02] ---------------------- diff --git a/docs/glossary.rst b/docs/glossary.rst index 93dc71a3b..ce955bc89 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -66,6 +66,12 @@ Variables that influence kitty behavior Variables that kitty sets when running child programs +.. envvar:: LANG + + This is set only on macOS, and only if the country and language from the + macOS user settings form a valid locale. + + .. envvar:: KITTY_WINDOW_ID An integer that is the id for the kitty :term:`window` the program is running in. diff --git a/kitty/cocoa_window.m b/kitty/cocoa_window.m index b65fd2041..235332890 100644 --- a/kitty/cocoa_window.m +++ b/kitty/cocoa_window.m @@ -574,12 +574,7 @@ cocoa_get_lang(PyObject UNUSED *self) { locale = [[NSLocale currentLocale] localeIdentifier]; } if (!locale) { Py_RETURN_NONE; } - // Make sure the locale value is valid, that is it can be used - // to construct an actual locale const char* locale_utf8 = [locale UTF8String]; - locale_t test_locale = newlocale(LC_ALL_MASK, locale_utf8, NULL); - if (!test_locale) { Py_RETURN_NONE; } - freelocale(test_locale); return Py_BuildValue("s", locale_utf8); } // autoreleasepool diff --git a/kitty/data-types.c b/kitty/data-types.c index cfe831341..c296f1225 100644 --- a/kitty/data-types.c +++ b/kitty/data-types.c @@ -23,6 +23,7 @@ #include #include #include +#include #ifdef WITH_PROFILER #include #endif @@ -156,6 +157,15 @@ wcwidth_wrap(PyObject UNUSED *self, PyObject *chr) { return PyLong_FromLong(wcwidth_std(PyLong_AsLong(chr))); } +static PyObject* +locale_is_valid(PyObject *self UNUSED, PyObject *args) { + char *name; + if (!PyArg_ParseTuple(args, "s", &name)) return NULL; + locale_t test_locale = newlocale(LC_ALL_MASK, name, NULL); + if (!test_locale) { Py_RETURN_FALSE; } + freelocale(test_locale); + Py_RETURN_TRUE; +} static PyMethodDef module_methods[] = { {"wcwidth", (PyCFunction)wcwidth_wrap, METH_O, ""}, @@ -169,6 +179,7 @@ static PyMethodDef module_methods[] = { {"parse_bytes", (PyCFunction)parse_bytes, METH_VARARGS, ""}, {"parse_bytes_dump", (PyCFunction)parse_bytes_dump, METH_VARARGS, ""}, {"redirect_std_streams", (PyCFunction)redirect_std_streams, METH_VARARGS, ""}, + {"locale_is_valid", (PyCFunction)locale_is_valid, METH_VARARGS, ""}, #ifdef __APPLE__ METHODB(user_cache_dir, METH_NOARGS), METHODB(process_group_map, METH_NOARGS), diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index 71fdef7ae..5dcb3016c 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -672,6 +672,10 @@ def cocoa_get_lang() -> Optional[str]: pass +def locale_is_valid(name: str) -> bool: + pass + + def mark_os_window_for_close(os_window_id: int, cr_type: int = 2) -> bool: pass diff --git a/kitty/main.py b/kitty/main.py index 21304461f..2bb4a816e 100644 --- a/kitty/main.py +++ b/kitty/main.py @@ -195,10 +195,15 @@ run_app = AppRunner() def ensure_macos_locale() -> None: # Ensure the LANG env var is set. See # https://github.com/kovidgoyal/kitty/issues/90 - from .fast_data_types import cocoa_get_lang + from .fast_data_types import cocoa_get_lang, locale_is_valid if 'LANG' not in os.environ: lang = cocoa_get_lang() if lang is not None: + if not locale_is_valid(lang): + if lang.startswith('en_'): + lang = 'en_US' + else: + log_error(f'Could not set LANG Cocoa returns language as: {lang}') os.environ['LANG'] = lang + '.UTF-8'