build(i18n): embed language JSON only on Windows, add lookup fallbacks
CMake turned every res/lang/*.json into an xxd header that i18n.cpp compiled in as a fallback, on every platform. Only the Windows single-file exe needs it: the Linux zip and AppImage and the macOS .app always ship res/lang, and loadLanguage() reads the loose file first. On Linux the embedded copy added about 1.5 MB to the binary, and every translation edit recompiled i18n.cpp. A new option, DRAGONX_EMBED_LANG, defaults to ON for WIN32 and OFF elsewhere: - ON without xxd is now a configure error (it used to warn, then fail to compile i18n.cpp on the missing headers); - i18n.cpp compiles the embedded includes and the fallback only when ON; - outside Windows, loadLanguage() also tries <exe>/../share/<app>/res/lang (the cmake --install layout and the full-node AppImage) and <exe>/../Resources/res/lang (the macOS .app binary run directly), so those layouts find the loose files whatever the working directory; before, only the embedded copy covered that. Measured: - full-node Linux binary: .data 1,699,696 -> 168,592 bytes; stripped 19,983,136 -> 18,456,128 bytes (-1.53 MB); - with the ImGui demo stubs, the Linux zips and AppImages are 0.50-0.55 MB smaller, with identical file lists including all 8 language files; - a Lite build started from an unrelated working directory loads the ja.json next to the binary (2422 strings), and the packaged Lite zip and AppImage load ja.json with no new not-found or failed lines; - Windows keeps the embedded copy: the 8 language headers are generated and the ja.json bytes are in the exe. A new test loads "de" from the loose files and checks a translated string; with bin/res/lang moved away exactly its two assertions fail. Behaviour changes on Linux and macOS: a missing or corrupt res/lang now falls back to English instead of the embedded copy, and a translation edit needs only the copy_langs step instead of a recompile. Not verifiable here: the macOS .app in a non-English language, and the Windows single-file exe at runtime. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+17
-5
@@ -9,9 +9,14 @@
|
||||
#include <fstream>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
// Embedded language files
|
||||
#ifndef DRAGONX_EMBED_LANG
|
||||
#define DRAGONX_EMBED_LANG 1 // legacy build paths keep the old behaviour
|
||||
#endif
|
||||
#if DRAGONX_EMBED_LANG
|
||||
// Embedded language files (Windows single-file exe has no res/lang)
|
||||
#include "embedded/lang_es.h"
|
||||
#include "embedded/lang_zh.h"
|
||||
#include "embedded/lang_ru.h"
|
||||
@@ -20,6 +25,7 @@
|
||||
#include "embedded/lang_pt.h"
|
||||
#include "embedded/lang_ja.h"
|
||||
#include "embedded/lang_ko.h"
|
||||
#endif
|
||||
#include "../util/logger.h"
|
||||
|
||||
namespace dragonx {
|
||||
@@ -109,10 +115,14 @@ bool I18n::loadLanguage(const std::string& locale)
|
||||
{
|
||||
// Try to load from file: CWD-relative first, then exe-relative
|
||||
std::string rel_path = "res/lang/" + locale + ".json";
|
||||
std::string exe_path = Platform::getExecutableDirectory() + "/" + rel_path;
|
||||
|
||||
// Try both paths; prefer whichever opens successfully
|
||||
for (const auto& lang_file : { rel_path, exe_path }) {
|
||||
const std::string exe_dir = Platform::getExecutableDirectory();
|
||||
std::vector<std::string> candidates = { rel_path, exe_dir + "/" + rel_path };
|
||||
#ifndef _WIN32
|
||||
// Layouts where res/ is not beside the binary, independent of the launcher's cd:
|
||||
candidates.push_back(exe_dir + "/../share/" DRAGONX_APP_NAME "/" + rel_path); // cmake --install; full AppImage
|
||||
candidates.push_back(exe_dir + "/../Resources/" + rel_path); // macOS .app (.bin run directly)
|
||||
#endif
|
||||
for (const auto& lang_file : candidates) {
|
||||
std::ifstream file(lang_file);
|
||||
if (!file.is_open()) continue;
|
||||
|
||||
@@ -137,6 +147,7 @@ bool I18n::loadLanguage(const std::string& locale)
|
||||
}
|
||||
}
|
||||
|
||||
#if DRAGONX_EMBED_LANG
|
||||
// Try embedded language data
|
||||
const unsigned char* embedded_data = nullptr;
|
||||
unsigned int embedded_size = 0;
|
||||
@@ -188,6 +199,7 @@ bool I18n::loadLanguage(const std::string& locale)
|
||||
DEBUG_LOGF("Error parsing embedded language %s: %s\n", locale.c_str(), e.what());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// If English, use built-in strings
|
||||
if (locale == "en") {
|
||||
|
||||
Reference in New Issue
Block a user