if(NOT DEFINED INPUTS OR NOT DEFINED OUTPUT) message(FATAL_ERROR "embed_localization.cmake requires INPUTS and OUTPUT") endif() set(contents "// Generated from assets/localization; do not edit.\n#pragma once\n#include \n#include \n\nnamespace {\n") set(lookup "std::span EmbeddedCatalog(std::string_view locale) {\n") set(continuation "[89ab][0-9a-f]") string(CONCAT utf8_character "[0-7][0-9a-f]|(c[2-9a-f]|d[0-9a-f])${continuation}" "|e0[ab][0-9a-f]${continuation}|e[1-9abcef]${continuation}${continuation}" "|ed[89][0-9a-f]${continuation}|f0[9ab][0-9a-f]${continuation}${continuation}" "|f[123]${continuation}${continuation}${continuation}|f48[0-9a-f]${continuation}${continuation}") foreach(catalog IN LISTS INPUTS) file(READ "${catalog}" bytes HEX) # Validate UTF-8, excluding overlong sequences, surrogates, and values above U+10FFFF. if(NOT bytes MATCHES "^(${utf8_character})*$") message(FATAL_ERROR "Localization must be UTF-8: ${catalog}") endif() file(READ "${catalog}" json) string(JSON type ERROR_VARIABLE error TYPE "${json}") if(error OR NOT type STREQUAL "OBJECT") message(FATAL_ERROR "Invalid localization object in ${catalog}: ${error}") endif() string(JSON count LENGTH "${json}") if(count GREATER 0) math(EXPR last "${count} - 1") foreach(index RANGE ${last}) string(JSON key MEMBER "${json}" ${index}) string(JSON type TYPE "${json}" "${key}") if(NOT type STREQUAL "STRING") message(FATAL_ERROR "Localization value '${key}' must be a string: ${catalog}") endif() string(JSON text GET "${json}" "${key}") if(key STREQUAL "" OR text STREQUAL "") message(FATAL_ERROR "Localization keys and values must not be empty: ${catalog}") endif() endforeach() endif() get_filename_component(locale "${catalog}" NAME_WE) if(locale STREQUAL "en-US") string(JSON earned ERROR_VARIABLE error GET "${json}" "trophy.toast.earned") if(error OR earned STREQUAL "") message(FATAL_ERROR "English localization requires trophy.toast.earned: ${catalog}") endif() set(english_found TRUE) endif() string(MAKE_C_IDENTIFIER "${locale}" symbol) string(REGEX REPLACE "(..)" "0x\\1," bytes "${bytes}") string(APPEND contents "constexpr unsigned char catalog_${symbol}[] = {${bytes}};\n") string(APPEND lookup "\tif (locale == \"${locale}\") return catalog_${symbol};\n") endforeach() if(NOT english_found) message(FATAL_ERROR "Localization requires an en-US.json fallback") endif() string(APPEND contents "\n${lookup}\treturn {};\n}\n} // namespace\n") get_filename_component(output_dir "${OUTPUT}" DIRECTORY) file(MAKE_DIRECTORY "${output_dir}") file(WRITE "${OUTPUT}.tmp" "${contents}") execute_process(COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${OUTPUT}.tmp" "${OUTPUT}" COMMAND_ERROR_IS_FATAL ANY) file(REMOVE "${OUTPUT}.tmp")