diff --git a/userspace/libraries/LibC/string.cpp b/userspace/libraries/LibC/string.cpp
index b15b711a..e1a4dce9 100644
--- a/userspace/libraries/LibC/string.cpp
+++ b/userspace/libraries/LibC/string.cpp
@@ -156,7 +156,12 @@ char* strncat(char* __restrict__ dest, const char* __restrict__ src, size_t n)
 
 int strcoll(const char* s1, const char* s2)
 {
-	switch (__getlocale(LC_COLLATE))
+	return strcoll_l(s1, s2, __getlocale(LC_COLLATE));
+}
+
+int strcoll_l(const char *s1, const char *s2, locale_t locale)
+{
+	switch (locale)
 	{
 		case LOCALE_INVALID:
 			ASSERT_NOT_REACHED();
@@ -362,6 +367,53 @@ char* strtok_r(char* __restrict str, const char* __restrict sep, char** __restri
 	return str;
 }
 
+size_t strxfrm(char* __restrict s1, const char* __restrict s2, size_t n)
+{
+	return strxfrm_l(s1, s2, n, __getlocale(LC_COLLATE));
+}
+
+size_t strxfrm_l(char* __restrict s1, const char* __restrict s2, size_t n, locale_t locale)
+{
+	(void)s1;
+	(void)s2;
+	(void)n;
+	ASSERT_NOT_REACHED();
+
+
+	switch (locale)
+	{
+		case LOCALE_INVALID:
+			ASSERT_NOT_REACHED();
+		case LOCALE_POSIX:
+			return strcmp(s1, s2);
+		case LOCALE_UTF8:
+		{
+			const unsigned char* u1 = (unsigned char*)s1;
+			const unsigned char* u2 = (unsigned char*)s2;
+			if (!*u1 || !*u2)
+				return *u1 - *u2;
+
+			wchar_t wc1, wc2;
+			while (*u1 && *u2)
+			{
+				wc1 = BAN::UTF8::to_codepoint(u1);
+				wc2 = BAN::UTF8::to_codepoint(u2);
+				if (wc1 == (wchar_t)BAN::UTF8::invalid || wc2 == (wchar_t)BAN::UTF8::invalid)
+				{
+					errno = EINVAL;
+					return -1;
+				}
+				if (wc1 != wc2)
+					break;
+				u1 += BAN::UTF8::byte_length(*u1);
+				u2 += BAN::UTF8::byte_length(*u2);
+			}
+			return wc1 - wc2;
+		}
+	}
+	ASSERT_NOT_REACHED();
+}
+
 char* strsignal(int signum)
 {
 	static char buffer[128];