Localize trophy notifications with embedded JSON catalogs

This commit is contained in:
Pipe530
2026-10-16 16:19:43 +02:00
committed by nmzik
parent 584c2e8ca6
commit 4c6be6cd1d
38 changed files with 446 additions and 12 deletions
+14
View File
@@ -12,9 +12,23 @@ endif()
add_library(common STATIC ${common_src} ${common_headers})
set(localization_dir "${PROJECT_SOURCE_DIR}/assets/localization")
file(GLOB localization_catalogs CONFIGURE_DEPENDS "${localization_dir}/*.json")
set(localization_data "${CMAKE_CURRENT_BINARY_DIR}/localizationData.h")
add_custom_command(
OUTPUT "${localization_data}"
COMMAND ${CMAKE_COMMAND} "-DINPUTS=${localization_catalogs}" "-DOUTPUT=${localization_data}"
-P "${KYTY_SOURCE_DIR}/embed_localization.cmake"
DEPENDS ${localization_catalogs} "${KYTY_SOURCE_DIR}/embed_localization.cmake"
COMMENT "Embed notification localization catalogs"
VERBATIM
)
target_sources(common PRIVATE "${localization_data}")
target_include_directories(common
PUBLIC ${KYTY_SOURCE_DIR}
PRIVATE
${CMAKE_CURRENT_BINARY_DIR}
${KYTY_THIRD_PARTY_DIR}/cpuinfo/include
)
+53
View File
@@ -0,0 +1,53 @@
#include "common/localization.h"
#include <array>
#include <cstddef>
#include <nlohmann/json.hpp>
#include <string>
#include "localizationData.h"
namespace Common::Localization {
namespace {
constexpr std::array<std::string_view, 30> Locales = {
"ja-JP", "en-US", "fr-FR", "es-ES", "de-DE", "it-IT", "nl-NL", "pt-PT",
"ru-RU", "ko-KR", "zh-Hant", "zh-Hans", "fi-FI", "sv-SE", "da-DK", "no-NO",
"pl-PL", "pt-BR", "en-GB", "tr-TR", "es-419", "ar-AE", "fr-CA", "cs-CZ",
"hu-HU", "el-GR", "ro-RO", "th-TH", "vi-VN", "id-ID"};
size_t LanguageIndex(int console_language) {
return console_language >= 0 && console_language < static_cast<int>(Locales.size())
? static_cast<size_t>(console_language)
: 1;
}
} // namespace
std::string_view LocaleName(int console_language) {
return Locales[LanguageIndex(console_language)];
}
std::string_view Get(int console_language, std::string_view key) {
static const auto catalogs = [] {
std::array<nlohmann::json, Locales.size()> result;
for (size_t i = 0; i < Locales.size(); ++i) {
const auto bytes = EmbeddedCatalog(Locales[i]);
result[i] = nlohmann::json::parse(bytes.begin(), bytes.end(), nullptr, false);
}
return result;
}();
for (const auto index: std::array {LanguageIndex(console_language), size_t {1}}) {
const auto& catalog = catalogs[index];
const auto found = catalog.find(key);
if (found != catalog.end() && found->is_string()) {
const auto& text = found->get_ref<const std::string&>();
if (!text.empty()) {
return text;
}
}
}
return key;
}
} // namespace Common::Localization
+13
View File
@@ -0,0 +1,13 @@
#pragma once
#include <string_view>
namespace Common::Localization {
// Console language indices follow the system configuration; invalid indices use English.
[[nodiscard]] std::string_view LocaleName(int console_language);
// Translations have static lifetime. Missing translations use English, then the supplied key.
[[nodiscard]] std::string_view Get(int console_language, std::string_view key);
} // namespace Common::Localization
+2 -8
View File
@@ -1,9 +1,9 @@
#include "common/trophies.h"
#include "common/file.h"
#include "common/localization.h"
#include <algorithm>
#include <array>
#include <charconv>
#include <fmt/format.h>
#include <nlohmann/json.hpp>
@@ -105,13 +105,7 @@ Package ParsePackage(std::span<const std::byte> data, int console_language) {
!conf["defaultLanguage"].is_string()) {
return {};
}
static constexpr std::array<std::string_view, 30> locales = {
"ja-JP", "en-US", "fr-FR", "es-ES", "de-DE", "it-IT", "nl-NL", "pt-PT",
"ru-RU", "ko-KR", "zh-Hant", "zh-Hans", "fi-FI", "sv-SE", "da-DK", "no-NO",
"pl-PL", "pt-BR", "en-GB", "tr-TR", "es-419", "ar-AE", "fr-CA", "cs-CZ",
"hu-HU", "el-GR", "ro-RO", "th-TH", "vi-VN", "id-ID"};
const auto locale =
locales[console_language >= 0 && console_language < locales.size() ? console_language : 1];
const auto locale = Localization::LocaleName(console_language);
auto meta = ReadJson(files, fmt::format("tropmeta_{}.json", locale));
if (meta.is_null()) {
meta = ReadJson(files, fmt::format("tropmeta_{}.json",