mirror of
https://github.com/hyprwm/hyprutils.git
synced 2025-12-20 04:40:08 +01:00
i18n/engine: optimize string generation
This commit is contained in:
parent
e3cae692f6
commit
0c6411851c
1 changed files with 70 additions and 9 deletions
|
|
@ -3,11 +3,11 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <format>
|
#include <format>
|
||||||
#include <locale>
|
#include <locale>
|
||||||
#include <hyprutils/string/String.hpp>
|
#include <hyprutils/utils/ScopeGuard.hpp>
|
||||||
|
|
||||||
using namespace Hyprutils::I18n;
|
using namespace Hyprutils::I18n;
|
||||||
using namespace Hyprutils;
|
using namespace Hyprutils;
|
||||||
using namespace Hyprutils::String;
|
using namespace Hyprutils::Utils;
|
||||||
|
|
||||||
CI18nEngine::CI18nEngine() : m_impl(Memory::makeUnique<SI18nEngineImpl>()) {
|
CI18nEngine::CI18nEngine() : m_impl(Memory::makeUnique<SI18nEngineImpl>()) {
|
||||||
;
|
;
|
||||||
|
|
@ -94,16 +94,68 @@ std::string CI18nEngine::localizeEntry(const std::string& locale, uint64_t key,
|
||||||
if (!entry || !entry->exists)
|
if (!entry || !entry->exists)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
std::string rawStr = entry->entry;
|
std::string_view rawStr = entry->entry;
|
||||||
|
std::string fnStringContainer;
|
||||||
|
|
||||||
if (entry->fn)
|
if (entry->fn) {
|
||||||
rawStr = entry->fn(map);
|
fnStringContainer = entry->fn(map);
|
||||||
|
rawStr = fnStringContainer;
|
||||||
for (const auto& e : map) {
|
|
||||||
replaceInString(rawStr, "{" + e.first + "}", e.second);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rawStr;
|
struct SRange {
|
||||||
|
size_t begin = 0;
|
||||||
|
size_t end = 0;
|
||||||
|
const std::string* val = nullptr;
|
||||||
|
};
|
||||||
|
std::vector<SRange> rangesFound;
|
||||||
|
|
||||||
|
// discover all replacable ranges
|
||||||
|
for (const auto& [k, v] : map) {
|
||||||
|
size_t start = rawStr.find(k, 0);
|
||||||
|
while (start != std::string::npos) {
|
||||||
|
if (start == 0 || start + k.size() >= rawStr.size())
|
||||||
|
break;
|
||||||
|
|
||||||
|
// always move the pointer
|
||||||
|
CScopeGuard x([&start, &rawStr, &k] { start = rawStr.find(k, start + 1); });
|
||||||
|
|
||||||
|
if (rawStr[start - 1] != '{' || rawStr[start + k.size()] != '}')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// add range
|
||||||
|
rangesFound.emplace_back(SRange{.begin = start - 1, .end = start + k.size() + 1, .val = &v});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rangesFound.empty())
|
||||||
|
return std::string{rawStr};
|
||||||
|
|
||||||
|
// build the new string. First, sort our entries
|
||||||
|
std::ranges::sort(rangesFound, [](const auto& a, const auto& b) { return a.begin - b.begin; });
|
||||||
|
|
||||||
|
// calc the size
|
||||||
|
size_t stringLen = 0;
|
||||||
|
size_t lastBegin = 0;
|
||||||
|
for (const auto& r : rangesFound) {
|
||||||
|
stringLen += r.begin - lastBegin + r.val->size();
|
||||||
|
lastBegin = r.end;
|
||||||
|
}
|
||||||
|
stringLen += rawStr.size() - lastBegin;
|
||||||
|
|
||||||
|
lastBegin = 0;
|
||||||
|
const auto ORIGINAL_STR = std::string_view{rawStr};
|
||||||
|
std::string newStr;
|
||||||
|
newStr.reserve(stringLen);
|
||||||
|
|
||||||
|
for (const auto& r : rangesFound) {
|
||||||
|
newStr += ORIGINAL_STR.substr(lastBegin, r.begin);
|
||||||
|
newStr += *r.val;
|
||||||
|
|
||||||
|
lastBegin = r.end;
|
||||||
|
}
|
||||||
|
newStr += ORIGINAL_STR.substr(lastBegin);
|
||||||
|
|
||||||
|
return newStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
CI18nLocale CI18nEngine::getSystemLocale() {
|
CI18nLocale CI18nEngine::getSystemLocale() {
|
||||||
|
|
@ -174,6 +226,15 @@ TEST(I18n, Engine) {
|
||||||
EXPECT_EQ(engine.localizeEntry("pl_PL", TXT_KEY_FALLBACK, {}), "Fallback string!");
|
EXPECT_EQ(engine.localizeEntry("pl_PL", TXT_KEY_FALLBACK, {}), "Fallback string!");
|
||||||
|
|
||||||
EXPECT_EQ(engine.localizeEntry("am_AM", TXT_KEY_FALLBACK, {}), "Amongus!");
|
EXPECT_EQ(engine.localizeEntry("am_AM", TXT_KEY_FALLBACK, {}), "Amongus!");
|
||||||
|
|
||||||
|
// test weird translations
|
||||||
|
engine.registerEntry("ts", TXT_KEY_HELLO, "count}");
|
||||||
|
EXPECT_EQ(engine.localizeEntry("ts", TXT_KEY_HELLO, {{"count", "1"}}), "count}");
|
||||||
|
|
||||||
|
engine.registerEntry("ts", TXT_KEY_HELLO, "{count");
|
||||||
|
EXPECT_EQ(engine.localizeEntry("ts", TXT_KEY_HELLO, {{"count", "1"}}), "{count");
|
||||||
|
|
||||||
|
EXPECT_EQ(engine.localizeEntry("ts", 42069 /* invalid key */, {{"count", "1"}}), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue