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" ),