1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-10-05 19:31:04 +00:00

Implement language code parsing

This commit is contained in:
y5nw 2025-02-23 23:34:05 +01:00 committed by y5nw
parent 56bc7814de
commit 2c91ba2513
6 changed files with 85 additions and 3 deletions

View file

@ -19,6 +19,7 @@ set (UNITTEST_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/test_irrptr.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test_irr_matrix4.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test_irr_rotation.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test_langcode.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test_logging.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test_lbmmanager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test_lua.cpp

View file

@ -0,0 +1,16 @@
// Luanti
// SPDX-License-Identifier: LGPL-2.1-or-later
#include "util/langcode.h"
#include "catch.h"
TEST_CASE("test langcode")
{
SECTION("test language list")
{
CHECK(expand_language_list(L"de_DE@euro.UTF-8:fr") == L"de_DE@euro:de_DE:de:fr");
CHECK(expand_language_list(L"zh_HK:yue_HK:zh_TW") == L"zh_HK:yue_HK:yue:zh_TW:zh");
CHECK(expand_language_list(L"de_DE:fr:de_CH:en:de:de_AT") == L"de_DE:fr:de_CH:en:de:de_AT");
CHECK(expand_language_list(L".UTF-8:de:.ISO-8859-1:fr:.GB2312") == L"de:fr");
}
}

View file

@ -11,6 +11,7 @@ set(util_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/guid.cpp
${CMAKE_CURRENT_SOURCE_DIR}/hashing.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ieee_float.cpp
${CMAKE_CURRENT_SOURCE_DIR}/langcode.cpp
${CMAKE_CURRENT_SOURCE_DIR}/metricsbackend.cpp
${CMAKE_CURRENT_SOURCE_DIR}/numeric.cpp
${CMAKE_CURRENT_SOURCE_DIR}/pointedthing.cpp

47
src/util/langcode.cpp Normal file
View file

@ -0,0 +1,47 @@
// Luanti
// SPDX-License-Identifier: LGPL-2.1-or-later
#include <unordered_map>
#include "util/string.h"
std::vector<std::wstring> parse_language_list(const std::wstring &lang)
{
std::unordered_map<std::wstring, std::wstring> added_by;
std::vector<std::vector<std::wstring>> expanded;
for (const auto &name: str_split(lang, L':')) {
auto pos = name.find(L'.'); // strip encoding information
const auto realname = pos == name.npos ? name : name.substr(0, pos);
if (realname.empty())
continue;
std::vector<std::wstring> basenames = {};
auto base = realname;
do {
if (added_by[base] == base)
break;
added_by[base] = realname;
basenames.push_back(base);
pos = base.find_last_of(L"_@");
base = base.substr(0, pos);
} while (pos != base.npos);
if (!basenames.empty())
expanded.push_back(std::move(basenames));
}
std::vector<std::wstring> langlist;
for (auto &basenames: expanded)
{
auto first = basenames.front();
for (auto &&name: basenames)
if (added_by[name] == first)
langlist.push_back(std::move(name));
}
return langlist;
}
std::wstring expand_language_list(const std::wstring &lang)
{
return str_join(parse_language_list(lang), L":");
}

9
src/util/langcode.h Normal file
View file

@ -0,0 +1,9 @@
// Luanti
// SPDX-License-Identifier: LGPL-2.1-or-later
#pragma once
#include <vector>
#include <string>
std::vector<std::wstring> parse_language_list(const std::wstring &lang);
std::wstring expand_language_list(const std::wstring &lang);

View file

@ -746,11 +746,12 @@ inline const std::string duration_to_string(int sec)
*
* @return A std::string
*/
template<typename T>
[[nodiscard]]
inline std::string str_join(const std::vector<std::string> &list,
std::string_view delimiter)
inline std::basic_string<T> str_join(const std::vector<std::basic_string<T>> &list,
std::basic_string_view<T> delimiter)
{
std::ostringstream oss;
std::basic_ostringstream<T> oss;
bool first = true;
for (const auto &part : list) {
if (!first)
@ -761,6 +762,13 @@ inline std::string str_join(const std::vector<std::string> &list,
return oss.str();
}
template<typename T>
inline std::basic_string<T> str_join(const std::vector<std::basic_string<T>> &list,
const T *delimiter)
{
return str_join(list, std::basic_string_view<T>(delimiter));
}
#if IS_CLIENT_BUILD
/**
* Create a UTF8 std::string from an core::stringw.