Custom localization file support
This commit is contained in:
parent
4fa5dbe930
commit
a487e6fcfa
39
data/localizedstrings/english.json
Normal file
39
data/localizedstrings/english.json
Normal file
@ -0,0 +1,39 @@
|
||||
{
|
||||
"MENU_MODS": "MODS",
|
||||
"MENU_MODS_DESC": "Load installed mods.",
|
||||
"LUA_MENU_MOD_DESC_DEFAULT": "Load &&1.",
|
||||
"LUA_MENU_MOD_DESC": "&&1\nAuthor: &&2\nVersion: &&3",
|
||||
"LUA_MENU_LOADED_MOD": "Loaded mod: ^3&&1",
|
||||
"LUA_MENU_AVAILABLE_MODS": "Available mods",
|
||||
"LUA_MENU_UNLOAD": "Unload",
|
||||
"LUA_MENU_UNLOAD_DESC": "Unload the currently loaded mod.",
|
||||
"LUA_MENU_WORKSHOP": "Workshop",
|
||||
"LUA_MENU_WORKSHOP_DESC": "Download and install mods.",
|
||||
|
||||
"MENU_GENERAL": "H2-MOD",
|
||||
"MENU_GENERAL_DESC": "Set h2-mod's settings.",
|
||||
"LUA_MENU_AUTO_UPDATE": "Automatic updates",
|
||||
"LUA_MENU_AUTO_UPDATE_DESC": "Enable or disable automatic updates on startup.",
|
||||
"LUA_MENU_CHECK_UPDATES": "Check for updates",
|
||||
"LUA_MENU_CHECK_UPDATES_DESC": "Check for updates.",
|
||||
"LUA_MENU_DRAWING": "Hud",
|
||||
"LUA_MENU_UPDATES": "Updates",
|
||||
"LUA_MENU_RENDERING": "Rendering",
|
||||
"LUA_MENU_DRAW_FPS": "Draw FPS",
|
||||
"LUA_MENU_DRAW_FPS_DESC": "Enable or disable drawing fps or viewpos on screen.",
|
||||
"LUA_MENU_FPS_ONLY": "FPS only",
|
||||
"LUA_MENU_FPS_AND_VIEWPOS": "FPS and View Pos",
|
||||
"LUA_MENU_DRAW_SPEED": "Draw speed",
|
||||
"LUA_MENU_DRAW_SPEED_DESC": "Enable or disable drawing the player speed on screen.",
|
||||
"LUA_MENU_DRAW_SPEEDGRAPH": "Draw speed graph",
|
||||
"LUA_MENU_DRAW_SPEEDGRAPH_DESC": "Enable or disable the speed graph.",
|
||||
"LUA_MENU_R_FULLBRIGHT": "Fullbright",
|
||||
"LUA_MENU_R_FULLBRIGHT_DESC": "Change the fullbright mode",
|
||||
"LUA_MENU_MODE2": "No dynamic lighting",
|
||||
"LUA_MENU_MODE3": "Debug shader",
|
||||
|
||||
"MENU_SYSINFO_CUSTOMER_SUPPORT_LINK": "Github Page:",
|
||||
"MENU_SYSINFO_CUSTOMER_SUPPORT_URL": "https://github.com/fedddddd/h2-mod",
|
||||
"MENU_SYSINFO_DONATION_LINK": "Donation link:",
|
||||
"MENU_SYSINFO_DONATION_URL": "https://paypal.me/fedecek"
|
||||
}
|
39
data/localizedstrings/italian.json
Normal file
39
data/localizedstrings/italian.json
Normal file
@ -0,0 +1,39 @@
|
||||
{
|
||||
"MENU_MODS": "MODS",
|
||||
"MENU_MODS_DESC": "Abilita mod installate.",
|
||||
"LUA_MENU_MOD_DESC_DEFAULT": "Abilita &&1.",
|
||||
"LUA_MENU_MOD_DESC": "&&1\nAutore: &&2\nVersione: &&3",
|
||||
"LUA_MENU_LOADED_MOD": "Mod attiva: ^3&&1",
|
||||
"LUA_MENU_AVAILABLE_MODS": "Mod disponibili",
|
||||
"LUA_MENU_UNLOAD": "Disabilita",
|
||||
"LUA_MENU_UNLOAD_DESC": "Disabilita la mod attualmente attiva.",
|
||||
"LUA_MENU_WORKSHOP": "Workshop",
|
||||
"LUA_MENU_WORKSHOP_DESC": "Scarica e installa mod.",
|
||||
|
||||
"MENU_GENERAL": "H2-MOD",
|
||||
"MENU_GENERAL_DESC": "Imposta le opzioni di h2-mod.",
|
||||
"LUA_MENU_AUTO_UPDATE": "Aggiornamenti automatici",
|
||||
"LUA_MENU_AUTO_UPDATE_DESC": "Controlla automaticamente gli aggiornamenti all'avvio.",
|
||||
"LUA_MENU_CHECK_UPDATES": "Controlla gli aggiornamenti",
|
||||
"LUA_MENU_CHECK_UPDATES_DESC": "Controlla gli aggiornamenti.",
|
||||
"LUA_MENU_DRAWING": "Hud",
|
||||
"LUA_MENU_UPDATES": "Aggiornamenti",
|
||||
"LUA_MENU_RENDERING": "Rendering",
|
||||
"LUA_MENU_DRAW_FPS": "Mostra FPS",
|
||||
"LUA_MENU_DRAW_FPS_DESC": "Mostra gli FPS o la posizione sullo schermo.",
|
||||
"LUA_MENU_FPS_ONLY": "Solo FPS",
|
||||
"LUA_MENU_FPS_AND_VIEWPOS": "FPS e Posizione",
|
||||
"LUA_MENU_DRAW_SPEED": "Mostra la velocità",
|
||||
"LUA_MENU_DRAW_SPEED_DESC": "Mostra la velocità sullo schermo.",
|
||||
"LUA_MENU_DRAW_SPEEDGRAPH": "Mostra il grafico della velocità",
|
||||
"LUA_MENU_DRAW_SPEEDGRAPH_DESC": "Attiva o disattiva il grafico della velocità.",
|
||||
"LUA_MENU_R_FULLBRIGHT": "Fullbright",
|
||||
"LUA_MENU_R_FULLBRIGHT_DESC": "Cambia la modalità di fullbright",
|
||||
"LUA_MENU_MODE2": "No illuminazione dinamica",
|
||||
"LUA_MENU_MODE3": "Shader di debug",
|
||||
|
||||
"MENU_SYSINFO_CUSTOMER_SUPPORT_LINK": "Pagina di Github:",
|
||||
"MENU_SYSINFO_CUSTOMER_SUPPORT_URL": "https://github.com/fedddddd/h2-mod",
|
||||
"MENU_SYSINFO_DONATION_LINK": "Link per donazioni:",
|
||||
"MENU_SYSINFO_DONATION_URL": "https://paypal.me/fedecek"
|
||||
}
|
@ -1,14 +1,3 @@
|
||||
game:addlocalizedstring("MENU_MODS", "MODS")
|
||||
game:addlocalizedstring("MENU_MODS_DESC", "Load installed mods.")
|
||||
game:addlocalizedstring("LUA_MENU_MOD_DESC_DEFAULT", "Load &&1.")
|
||||
game:addlocalizedstring("LUA_MENU_MOD_DESC", "&&1\nAuthor: &&2\nVersion: &&3")
|
||||
game:addlocalizedstring("LUA_MENU_LOADED_MOD", "Loaded mod: ^3&&1")
|
||||
game:addlocalizedstring("LUA_MENU_AVAILABLE_MODS", "Available mods")
|
||||
game:addlocalizedstring("LUA_MENU_UNLOAD", "Unload")
|
||||
game:addlocalizedstring("LUA_MENU_UNLOAD_DESC", "Unload the currently loaded mod.")
|
||||
game:addlocalizedstring("LUA_MENU_WORKSHOP", "Workshop")
|
||||
game:addlocalizedstring("LUA_MENU_WORKSHOP_DESC", "Download and install mods.")
|
||||
|
||||
function createdivider(menu, text)
|
||||
local element = LUI.UIElement.new( {
|
||||
leftAnchor = true,
|
||||
@ -52,7 +41,6 @@ LUI.addmenubutton("main_campaign", {
|
||||
function getmodname(path)
|
||||
local name = path
|
||||
game:addlocalizedstring(name, name)
|
||||
game:addlocalizedstring("LUA_MENU_MOD_DESC_DEFAULT", "Load &&1.")
|
||||
local desc = Engine.Localize("LUA_MENU_MOD_DESC_DEFAULT", name)
|
||||
local infofile = path .. "/info.json"
|
||||
|
||||
|
@ -1,30 +1,5 @@
|
||||
require("language")
|
||||
|
||||
game:addlocalizedstring("MENU_GENERAL", "GENERAL")
|
||||
game:addlocalizedstring("MENU_GENERAL_DESC", "Set the client's settings.")
|
||||
game:addlocalizedstring("LUA_MENU_AUTO_UPDATE", "Automatic updates")
|
||||
game:addlocalizedstring("LUA_MENU_CHECK_UPDATES", "Check for updates")
|
||||
game:addlocalizedstring("LUA_MENU_CHECK_UPDATES_DESC", "Check for updates.")
|
||||
game:addlocalizedstring("LUA_MENU_DRAWING", "Drawing")
|
||||
game:addlocalizedstring("LUA_MENU_UPDATES", "Updates")
|
||||
game:addlocalizedstring("LUA_MENU_RENDERING", "Rendering")
|
||||
|
||||
game:addlocalizedstring("LUA_MENU_DRAW_FPS", "Draw FPS")
|
||||
game:addlocalizedstring("LUA_MENU_DRAW_FPS_DESC", "Enable or disable drawing fps or viewpos on screen.")
|
||||
game:addlocalizedstring("LUA_MENU_FPS_ONLY", "FPS only")
|
||||
game:addlocalizedstring("LUA_MENU_FPS_AND_VIEWPOS", "FPS and View Pos")
|
||||
|
||||
game:addlocalizedstring("LUA_MENU_DRAW_SPEED", "Draw speed")
|
||||
game:addlocalizedstring("LUA_MENU_DRAW_SPEED_DESC", "Enable or disable drawing the player speed on screen.")
|
||||
|
||||
game:addlocalizedstring("LUA_MENU_DRAW_SPEEDGRAPH", "Draw speed graph")
|
||||
game:addlocalizedstring("LUA_MENU_DRAW_SPEEDGRAPH_DESC", "Enable or disable the speed graph.")
|
||||
|
||||
game:addlocalizedstring("LUA_MENU_R_FULLBRIGHT", "Fullbright")
|
||||
game:addlocalizedstring("LUA_MENU_R_FULLBRIGHT_DESC", "Change the fullbright mode.")
|
||||
game:addlocalizedstring("LUA_MENU_MODE2", "Mode 2")
|
||||
game:addlocalizedstring("LUA_MENU_MODE3", "Mode 3")
|
||||
|
||||
function createdivider(menu, text)
|
||||
local element = LUI.UIElement.new({
|
||||
leftAnchor = true,
|
||||
@ -67,7 +42,7 @@ LUI.MenuBuilder.m_types_build["settings_menu"] = function(a1)
|
||||
menu,
|
||||
"cg_auto_update",
|
||||
"@LUA_MENU_AUTO_UPDATE",
|
||||
"Enable or disable automatic updates on startup.",
|
||||
"@LUA_MENU_AUTO_UPDATE_DESC",
|
||||
{
|
||||
{
|
||||
text = "@LUA_MENU_ENABLED",
|
||||
@ -113,7 +88,7 @@ LUI.MenuBuilder.m_types_build["settings_menu"] = function(a1)
|
||||
menu,
|
||||
"cg_drawSpeed",
|
||||
"@LUA_MENU_DRAW_SPEED",
|
||||
"Enable or disable drawing the player speed on screen.",
|
||||
"@LUA_MENU_DRAW_SPEED_DESC",
|
||||
{
|
||||
{
|
||||
text = "@LUA_MENU_ENABLED",
|
||||
|
@ -40,10 +40,6 @@ namespace branding
|
||||
scheduler::loop(draw, scheduler::pipeline::renderer);
|
||||
|
||||
localized_strings::override("MENU_SP_CAMPAIGN", "H2-MOD");
|
||||
localized_strings::override("MENU_SYSINFO_CUSTOMER_SUPPORT_LINK", "Github Page:");
|
||||
localized_strings::override("MENU_SYSINFO_CUSTOMER_SUPPORT_URL", "https://github.com/fedddddd/h2-mod");
|
||||
localized_strings::override("MENU_SYSINFO_DONATION_LINK", "Donation Link:");
|
||||
localized_strings::override("MENU_SYSINFO_DONATION_URL", "https://paypal.me/fedecek");
|
||||
|
||||
utils::hook::jump(0x14033D550, get_build_number_stub, true);
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include "filesystem.hpp"
|
||||
#include "console.hpp"
|
||||
#include "localized_strings.hpp"
|
||||
|
||||
#include "game/game.hpp"
|
||||
|
||||
@ -38,6 +39,8 @@ namespace filesystem
|
||||
filesystem::register_path(L"h2-mod");
|
||||
filesystem::register_path(L"data");
|
||||
|
||||
localized_strings::clear();
|
||||
|
||||
utils::hook::invoke<void>(0x14060BF50, name);
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,17 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include "localized_strings.hpp"
|
||||
#include "game_console.hpp"
|
||||
#include "filesystem.hpp"
|
||||
#include "console.hpp"
|
||||
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
#include <utils/string.hpp>
|
||||
#include <utils/concurrency.hpp>
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include "game_console.hpp"
|
||||
#include <utils/io.hpp>
|
||||
|
||||
namespace localized_strings
|
||||
{
|
||||
@ -14,7 +19,13 @@ namespace localized_strings
|
||||
{
|
||||
utils::hook::detour seh_string_ed_get_string_hook;
|
||||
|
||||
using localized_map = std::unordered_map<std::string, std::string>;
|
||||
struct localize_entry
|
||||
{
|
||||
std::string value{};
|
||||
bool volatile_{};
|
||||
};
|
||||
|
||||
using localized_map = std::unordered_map<std::string, localize_entry>;
|
||||
utils::concurrency::container<localized_map> localized_overrides;
|
||||
|
||||
const char* seh_string_ed_get_string(const char* reference)
|
||||
@ -24,7 +35,7 @@ namespace localized_strings
|
||||
const auto entry = map.find(reference);
|
||||
if (entry != map.end())
|
||||
{
|
||||
return utils::string::va("%s", entry->second.data());
|
||||
return utils::string::va("%s", entry->second.value.data());
|
||||
}
|
||||
|
||||
return seh_string_ed_get_string_hook.invoke<const char*>(reference);
|
||||
@ -39,7 +50,7 @@ namespace localized_strings
|
||||
const auto entry = map.find(name);
|
||||
if (entry != map.end())
|
||||
{
|
||||
return utils::string::va("%s", entry->second.data());
|
||||
return utils::string::va("%s", entry->second.value.data());
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
@ -56,16 +67,119 @@ namespace localized_strings
|
||||
|
||||
return static_cast<game::XAssetHeader>(&entry);
|
||||
}
|
||||
|
||||
bool parse_localized_strings_file(const std::string& data)
|
||||
{
|
||||
rapidjson::Document j;
|
||||
j.Parse(data.data());
|
||||
|
||||
if (!j.IsObject())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
localized_overrides.access([&](localized_map& map)
|
||||
{
|
||||
const auto obj = j.GetObj();
|
||||
for (const auto& [key, value] : obj)
|
||||
{
|
||||
if (!key.IsString() || !value.IsString())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto name = key.GetString();
|
||||
const auto str = value.GetString();
|
||||
|
||||
const auto entry = map.find(name);
|
||||
if (entry == map.end() || entry->second.volatile_)
|
||||
{
|
||||
map[name] = {str, true};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool try_load_file(const std::string& path, const std::string& language)
|
||||
{
|
||||
const auto file = utils::string::va("%s/localizedstrings/%s.json", path.data(), language.data());
|
||||
if (!utils::io::file_exists(file))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
console::info("[Localized strings] Parsing %s\n", file);
|
||||
const auto data = utils::io::read_file(file);
|
||||
if (!parse_localized_strings_file(data))
|
||||
{
|
||||
console::error("[Localized strings] Invalid language json file\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void load_localized_strings()
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
const auto search_paths = filesystem::get_search_paths();
|
||||
const auto language = game::SEH_GetCurrentLanguageName();
|
||||
|
||||
for (const auto& path : search_paths)
|
||||
{
|
||||
if (!try_load_file(path, language))
|
||||
{
|
||||
if (try_load_file(path, "english"))
|
||||
{
|
||||
found = true;
|
||||
console::warn("[Localized strings] No valid language file found for '%s' in '%s', falling back to 'english'\n",
|
||||
language, path.data());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
console::warn("[Localized strings] No valid language file found!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void override(const std::string& key, const std::string& value)
|
||||
void override(const std::string& key, const std::string& value, bool volatile_)
|
||||
{
|
||||
localized_overrides.access([&](localized_map& map)
|
||||
{
|
||||
map[key] = value;
|
||||
map[key] = {value, volatile_};
|
||||
});
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
localized_overrides.access([&](localized_map& map)
|
||||
{
|
||||
for (auto i = map.begin(); i != map.end();)
|
||||
{
|
||||
if (i->second.volatile_)
|
||||
{
|
||||
i = map.erase(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
++i;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
load_localized_strings();
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
|
@ -2,5 +2,6 @@
|
||||
|
||||
namespace localized_strings
|
||||
{
|
||||
void override(const std::string& key, const std::string& value);
|
||||
void override(const std::string& key, const std::string& value, bool volatile_ = false);
|
||||
void clear();
|
||||
}
|
@ -11,6 +11,7 @@
|
||||
#include "fonts.hpp"
|
||||
#include "mods.hpp"
|
||||
#include "mapents.hpp"
|
||||
#include "localized_strings.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
#include <utils/io.hpp>
|
||||
@ -34,6 +35,7 @@ namespace mods
|
||||
}
|
||||
|
||||
mapents::clear();
|
||||
localized_strings::clear();
|
||||
|
||||
db_release_xassets_hook.invoke<void>();
|
||||
}
|
||||
|
@ -258,7 +258,7 @@ namespace ui_scripting
|
||||
game_type["addlocalizedstring"] = [](const game&, const std::string& string,
|
||||
const std::string& value)
|
||||
{
|
||||
localized_strings::override(string, value);
|
||||
localized_strings::override(string, value, true);
|
||||
};
|
||||
|
||||
game_type["setlanguage"] = [](const game&, const std::string& language)
|
||||
|
@ -764,7 +764,7 @@ namespace scripting::lua
|
||||
game_type["addlocalizedstring"] = [](const game&, const std::string& string,
|
||||
const std::string& value)
|
||||
{
|
||||
localized_strings::override(string, value);
|
||||
localized_strings::override(string, value, true);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user