diff --git a/meson.build b/meson.build
index 2d42843d71..78269d1be3 100644
--- a/meson.build
+++ b/meson.build
@@ -385,6 +385,7 @@ features += {'cocoa': cocoa.found()}
if features['cocoa']
dependencies += cocoa
sources += files('osdep/apple_utils.c',
+ 'osdep/language-apple.c',
'osdep/macosx_application.m',
'osdep/macosx_events.m',
'osdep/macosx_menubar.m',
@@ -407,7 +408,8 @@ if posix
endif
if posix and not features['cocoa']
- sources += files('osdep/main-fn-unix.c')
+ sources += files('osdep/main-fn-unix.c',
+ 'osdep/language-posix.c')
endif
if darwin
@@ -492,6 +494,7 @@ if features['win32-desktop']
subprocess_source = files('osdep/subprocess-win.c')
sources += path_source + subprocess_source + \
files('input/ipc-win.c',
+ 'osdep/language-win.c',
'osdep/main-fn-win.c',
'osdep/terminal-win.c',
'video/out/w32_common.c',
diff --git a/misc/language.h b/misc/language.h
index 08d4659571..250d39137c 100644
--- a/misc/language.h
+++ b/misc/language.h
@@ -26,4 +26,6 @@
// Where applicable, l1 is the user-specified code and l2 is the code being checked against it
int mp_match_lang_single(const char *l1, const char *l2);
+char **mp_get_user_langs(void);
+
#endif /* MP_LANGUAGE_H */
diff --git a/osdep/language-apple.c b/osdep/language-apple.c
new file mode 100644
index 0000000000..dc83fb545a
--- /dev/null
+++ b/osdep/language-apple.c
@@ -0,0 +1,45 @@
+/*
+ * User language lookup for Apple platforms
+ *
+ * This file is part of mpv.
+ *
+ * mpv is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * mpv is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with mpv. If not, see .
+ */
+
+#include "misc/language.h"
+
+#include "apple_utils.h"
+#include "mpv_talloc.h"
+
+char **mp_get_user_langs(void)
+{
+ CFArrayRef arr = CFLocaleCopyPreferredLanguages();
+ if (!arr)
+ return NULL;
+ CFIndex count = CFArrayGetCount(arr);
+ if (!count)
+ return NULL;
+
+ char **ret = talloc_array_ptrtype(NULL, ret, count + 1);
+
+ for (CFIndex i = 0; i < count; i++) {
+ CFStringRef cfstr = CFArrayGetValueAtIndex(arr, i);
+ ret[i] = talloc_steal(ret, cfstr_get_cstr(cfstr));
+ }
+
+ ret[count] = NULL;
+
+ CFRelease(arr);
+ return ret;
+}
diff --git a/osdep/language-posix.c b/osdep/language-posix.c
new file mode 100644
index 0000000000..f5d1a3a72c
--- /dev/null
+++ b/osdep/language-posix.c
@@ -0,0 +1,61 @@
+/*
+ * User language lookup for generic POSIX platforms
+ *
+ * This file is part of mpv.
+ *
+ * mpv is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * mpv is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with mpv. If not, see .
+ */
+
+#include "misc/language.h"
+#include "mpv_talloc.h"
+
+#include
+
+char **mp_get_user_langs(void)
+{
+ static const char *const list[] = {
+ "LC_ALL",
+ "LC_MESSAGES",
+ "LANG",
+ NULL
+ };
+
+ size_t nb = 0;
+ char **ret = NULL;
+
+ // Prefer anything we get from LANGUAGE first
+ for (const char *langList = getenv("LANGUAGE"); langList && *langList;) {
+ size_t len = strcspn(langList, ":");
+ MP_TARRAY_GROW(NULL, ret, nb);
+ ret[nb++] = talloc_strndup(ret, langList, len);
+ langList += len;
+ while (*langList == ':')
+ langList++;
+ }
+
+ // Then, the language components of other relevant locale env vars
+ for (int i = 0; list[i]; i++) {
+ const char *envval = getenv(list[i]);
+ if (envval && *envval) {
+ size_t len = strcspn(envval, ".@");
+ MP_TARRAY_GROW(NULL, ret, nb);
+ ret[nb++] = talloc_strndup(ret, envval, len);
+ }
+ }
+
+ // Null-terminate the list
+ MP_TARRAY_APPEND(NULL, ret, nb, NULL);
+
+ return ret;
+}
diff --git a/osdep/language-win.c b/osdep/language-win.c
new file mode 100644
index 0000000000..7d8e7fe8f7
--- /dev/null
+++ b/osdep/language-win.c
@@ -0,0 +1,65 @@
+/*
+ * User language lookup for win32
+ *
+ * This file is part of mpv.
+ *
+ * mpv is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * mpv is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with mpv. If not, see .
+ */
+
+#include "misc/language.h"
+#include "mpv_talloc.h"
+#include "osdep/io.h"
+
+#include
+
+char **mp_get_user_langs(void)
+{
+ size_t nb = 0;
+ char **ret = NULL;
+ ULONG got_count = 0;
+ ULONG got_size = 0;
+ if (!GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &got_count, NULL, &got_size) ||
+ got_size == 0)
+ return NULL;
+
+ wchar_t *buf = talloc_array(NULL, wchar_t, got_size);
+
+ if (!GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &got_count, buf, &got_size) ||
+ got_size == 0)
+ goto cleanup;
+
+ for (ULONG pos = 0; buf[pos]; pos += wcslen(buf + pos) + 1) {
+ ret = talloc_realloc(NULL, ret, char*, (nb + 2));
+ ret[nb++] = mp_to_utf8(ret, buf + pos);
+ }
+ ret[nb] = NULL;
+
+ if (!GetSystemPreferredUILanguages(MUI_LANGUAGE_NAME, &got_count, NULL, &got_size))
+ goto cleanup;
+
+ buf = talloc_realloc(NULL, buf, wchar_t, got_size);
+
+ if (!GetSystemPreferredUILanguages(MUI_LANGUAGE_NAME, &got_count, buf, &got_size))
+ goto cleanup;
+
+ for (ULONG pos = 0; buf[pos]; pos += wcslen(buf + pos) + 1) {
+ ret = talloc_realloc(NULL, ret, char*, (nb + 2));
+ ret[nb++] = mp_to_utf8(ret, buf + pos);
+ }
+ ret[nb] = NULL;
+
+cleanup:
+ talloc_free(buf);
+ return ret;
+}
diff --git a/wscript_build.py b/wscript_build.py
index bcf6f84791..9650bf94d3 100644
--- a/wscript_build.py
+++ b/wscript_build.py
@@ -249,6 +249,12 @@ def build(ctx):
( "osdep/subprocess-dummy.c" ),
])
+ language_c = ctx.pick_first_matching_dep([
+ ( "osdep/language-apple.c", "cocoa" ),
+ ( "osdep/language-win.c", "win32-desktop" ),
+ ( "osdep/language-posix.c" ),
+ ])
+
sources = [
## Audio
( "audio/aframe.c" ),
@@ -581,6 +587,8 @@ def build(ctx):
( timer_c ),
( "osdep/polldev.c", "posix" ),
+ ( language_c ),
+
( "osdep/android/strnlen.c", "android"),
( "osdep/apple_utils.c", "cocoa" ),
( "osdep/glob-win.c", "glob-win32" ),