From b6563f6667473328186c2da1032e296b8a423ebd Mon Sep 17 00:00:00 2001 From: Logon Date: Wed, 25 Sep 2024 22:18:32 +0200 Subject: [PATCH] feat: initial generate translation trie and HTML files This change introduces a new feature to generate a translation trie and HTML files for the localized strings in the project. The key changes include: - Added a new script `generate_translation_trie.lua` that creates a trie data structure from the translation strings and writes the translations to HTML files with segmentation support. - Updated the `main.lua` script to call the new `Compile_translations_to_html` function from `generate_translation_trie.lua`. - Added a `run.sh` script to execute the main script and a `Dockerfile` to build a Docker container for the project. - Updated the `CLI_Helpers.lua` script to handle file paths with backslashes correctly when loading script files. - Refactored the `l10n.lua` script to improve the handling of localization data. These changes improve the localization capabilities of the project by providing a more efficient way to manage and display the translated strings. --- .generate_database_lua/Dockerfile | 13 ++ .generate_database_lua/createStatic.lua | 170 ++++++++++++++ .generate_database_lua/docker-compose.yml | 9 + .../generate_translation_trie.lua | 183 +++++++++++++++ .generate_database_lua/helpers.lua | 219 ++++++++++++++++++ .generate_database_lua/main.lua | 100 ++++++++ .generate_database_lua/run.sh | 19 ++ Database/l10n/l10n.lua | 20 +- cli/CLI_Helpers.lua | 6 +- 9 files changed, 730 insertions(+), 9 deletions(-) create mode 100644 .generate_database_lua/Dockerfile create mode 100644 .generate_database_lua/createStatic.lua create mode 100644 .generate_database_lua/docker-compose.yml create mode 100644 .generate_database_lua/generate_translation_trie.lua create mode 100644 .generate_database_lua/helpers.lua create mode 100644 .generate_database_lua/main.lua create mode 100644 .generate_database_lua/run.sh diff --git a/.generate_database_lua/Dockerfile b/.generate_database_lua/Dockerfile new file mode 100644 index 00000000..a20ef736 --- /dev/null +++ b/.generate_database_lua/Dockerfile @@ -0,0 +1,13 @@ +FROM nickblah/lua:5.1-luarocks + +RUN apt-get update && apt-get install -y git gcc +# Install OpenSSL for LuaSec +RUN apt-get install -y libssl-dev + +RUN luarocks install bit32 +RUN luarocks install argparse +RUN luarocks install luafilesystem +RUN luarocks install luasocket +RUN luarocks install luasec + +RUN apt-get update && apt-get install -y wget \ No newline at end of file diff --git a/.generate_database_lua/createStatic.lua b/.generate_database_lua/createStatic.lua new file mode 100644 index 00000000..fc905bc4 --- /dev/null +++ b/.generate_database_lua/createStatic.lua @@ -0,0 +1,170 @@ +-- Allow accessing private fields +---@diagnostic disable: invisible +require("cli.dump") +local argparse = require("argparse") +local helpers = require(".helpers") + +require("cli.Addon_Meta") +require("cli.CLI_Helpers") + +assert(Is_CLI, "This function should only be called from the CLI environment") + +local f = string.format + +Is_Create_Static = true + +function DumpDatabase(version) + local lowerVersion = version:lower() + local capitalizedVersion = lowerVersion:gsub("^%l", string.upper) + print(f("\n\27[36mCompiling %s database...\27[0m", capitalizedVersion)) + + -- Reset data objects, load the files and set wow version + LibQuestieDBTable = AddonInitializeVersion(capitalizedVersion) + + -- Drain all the timers + C_Timer.drainTimerList() + + local itemOverride = {} + local npcOverride = {} + local objectOverride = {} + local questOverride = {} + + local Corrections = LibQuestieDBTable.Corrections + + Corrections.DumpFunctions.testDumpFunctions() + + do + CLI_Helpers.loadFile(f(".generate_database/_data/%sItemDB.lua", lowerVersion)) + itemOverride = loadstring(QuestieDB.itemData)() + LibQuestieDBTable.Item.LoadOverrideData(false, true) + local itemMeta = Corrections.ItemMeta + for itemId, corrections in pairs(LibQuestieDBTable.Item.override) do + if not itemOverride[itemId] then + itemOverride[itemId] = {} + end + for key, correction in pairs(corrections) do + local correctionIndex = itemMeta.itemKeys[key] + itemOverride[itemId][correctionIndex] = correction + end + end + end + + do + CLI_Helpers.loadFile(f(".generate_database/_data/%sNpcDB.lua", lowerVersion)) + npcOverride = loadstring(QuestieDB.npcData)() + LibQuestieDBTable.Npc.LoadOverrideData(false, true) + local npcMeta = Corrections.NpcMeta + for npcId, corrections in pairs(LibQuestieDBTable.Npc.override) do + if not npcOverride[npcId] then + npcOverride[npcId] = {} + end + for key, correction in pairs(corrections) do + local correctionIndex = npcMeta.npcKeys[key] + npcOverride[npcId][correctionIndex] = correction + end + end + end + + do + CLI_Helpers.loadFile(f(".generate_database/_data/%sObjectDB.lua", lowerVersion)) + objectOverride = loadstring(QuestieDB.objectData)() + LibQuestieDBTable.Object.LoadOverrideData(false, true) + local objectMeta = Corrections.ObjectMeta + for objectId, corrections in pairs(LibQuestieDBTable.Object.override) do + if not objectOverride[objectId] then + objectOverride[objectId] = {} + end + for key, correction in pairs(corrections) do + local correctionIndex = objectMeta.objectKeys[key] + objectOverride[objectId][correctionIndex] = correction + end + end + end + + do + CLI_Helpers.loadFile(f(".generate_database/_data/%sQuestDB.lua", lowerVersion)) + questOverride = loadstring(QuestieDB.questData)() + LibQuestieDBTable.Quest.LoadOverrideData(false, true) + local questMeta = Corrections.QuestMeta + for questId, corrections in pairs(LibQuestieDBTable.Quest.override) do + if not questOverride[questId] then + questOverride[questId] = {} + end + for key, correction in pairs(corrections) do + local correctionIndex = questMeta.questKeys[key] + questOverride[questId][correctionIndex] = correction + end + end + end + + -- Write all the overrides to disk + ---@diagnostic disable-next-line: param-type-mismatch + -- local file = io.open(f(".generate_database/_data/output/Item/%s/ItemData.lua-table", capitalizedVersion), "w") + print("Dumping item overrides") + -- assert(file, "Failed to open file for writing") + local itemData = helpers.dumpData(itemOverride, Corrections.ItemMeta.itemKeys, Corrections.ItemMeta.dumpFuncs, Corrections.ItemMeta.combine) + ---@diagnostic disable-next-line: undefined-field + -- file:write(itemData) + ---@diagnostic disable-next-line: undefined-field + -- file:close() + + -- ---@diagnostic disable-next-line: param-type-mismatch + -- file = io.open(f(".generate_database/_data/output/Quest/%s/QuestData.lua-table", capitalizedVersion), "w") + -- print("Dumping quest overrides") + -- assert(file, "Failed to open file for writing") + -- local questData = helpers.dumpData(questOverride, Corrections.QuestMeta.questKeys, Corrections.QuestMeta.dumpFuncs) + -- ---@diagnostic disable-next-line: undefined-field + -- file:write(questData) + -- ---@diagnostic disable-next-line: undefined-field + -- file:close() + + -- ---@diagnostic disable-next-line: param-type-mismatch + -- file = io.open(f(".generate_database/_data/output/Npc/%s/NpcData.lua-table", capitalizedVersion), "w") + -- print("Dumping npc overrides") + -- assert(file, "Failed to open file for writing") + -- local npcData = helpers.dumpData(npcOverride, Corrections.NpcMeta.npcKeys, Corrections.NpcMeta.dumpFuncs, Corrections.NpcMeta.combine) + -- ---@diagnostic disable-next-line: undefined-field + -- file:write(npcData) + -- ---@diagnostic disable-next-line: undefined-field + -- file:close() + + -- ---@diagnostic disable-next-line: param-type-mismatch + -- file = io.open(f(".generate_database/_data/output/Object/%s/ObjectData.lua-table", capitalizedVersion), "w") + -- print("Dumping object overrides") + -- assert(file, "Failed to open file for writing") + -- local objectData = helpers.dumpData(objectOverride, Corrections.ObjectMeta.objectKeys, Corrections.ObjectMeta.dumpFuncs) + -- ---@diagnostic disable-next-line: undefined-field + -- file:write(objectData) + -- ---@diagnostic disable-next-line: undefined-field + -- file:close() + + print(f("\n\27[32m%s corrections dumped successfully\27[0m", capitalizedVersion)) +end + +-- local validVersions = { +-- ["era"] = true, +-- ["tbc"] = true, +-- ["wotlk"] = true, +-- } +-- local versionString = "" +-- for version in pairs(validVersions) do +-- local v = string.gsub(version, "^%l", string.upper) +-- versionString = versionString .. v .. "/" +-- end +-- -- Add all +-- versionString = versionString .. "All" + +-- local parser = argparse("createStatic", "createStatic.lua Era") +-- parser:argument("version", f("Game version, %s.", versionString)) + +-- local args = parser:parse() + +-- if args.version and validVersions[args.version:lower()] then +-- DumpDatabase(args.version) +-- elseif args.version and args.version:lower() == "all" then +-- for version in pairs(validVersions) do +-- DumpDatabase(version) +-- end +-- else +-- print("No version specified") +-- end diff --git a/.generate_database_lua/docker-compose.yml b/.generate_database_lua/docker-compose.yml new file mode 100644 index 00000000..e3bb49d5 --- /dev/null +++ b/.generate_database_lua/docker-compose.yml @@ -0,0 +1,9 @@ +version: '3' + +services: + lua_2: + #image: nickblah/lua:5.1-luarocks + build: . + command: sh /QuestieDB/.generate_database_lua/run.sh + volumes: + - '../:/QuestieDB' diff --git a/.generate_database_lua/generate_translation_trie.lua b/.generate_database_lua/generate_translation_trie.lua new file mode 100644 index 00000000..a852747b --- /dev/null +++ b/.generate_database_lua/generate_translation_trie.lua @@ -0,0 +1,183 @@ +require("cli.dump") + +-- Define the maximum number of translations per file +local MAX_TRANSLATIONS_PER_FILE = 35 +local SEGMENT_SIZE = 4000 +local REDUCE_SEGMENT_SIZE = math.max(math.min(SEGMENT_SIZE * 0.05, 100), 10) +print("Max translations per file: " .. MAX_TRANSLATIONS_PER_FILE) +print("Segment size: " .. SEGMENT_SIZE, "Reduced segment size: " .. SEGMENT_SIZE - REDUCE_SEGMENT_SIZE) + +-- Function to sanitize translation strings by replacing special characters with HTML entities +local function sanitize_translation(str) + str = string.gsub(str, "&", "&") + str = string.gsub(str, "<", "<") + str = string.gsub(str, ">", ">") + return str +end + +-- Function to create directories recursively using os.execute +local function mkdir(path) + os.execute("mkdir -p " .. path) +end + +-- Function to split a string into segments based on maximum characters per segment +local function split_into_segments(str, max_chars) + local segments = {} + local total_segments = math.ceil(#str / max_chars) + + -- Loop through the string and create segments + for i = 1, total_segments do + local start_pos = (i - 1) * max_chars + 1 + local end_pos = math.min(i * max_chars, #str) + local segment = string.sub(str, start_pos, end_pos) + -- Add segment number prefix for all segments except the first one + if i > 1 then + segment = tostring(i) .. segment + end + table.insert(segments, segment) + end + + -- Add total segments count to the first segment + segments[1] = total_segments .. segments[1] + + return segments +end + +-- Function to write translations to an HTML file with segmentation +local function write_html_file(key_path, translations) + -- Define the file path + local filename = key_path .. ".html" + + -- Open the file for writing + local file, err = io.open(filename, "w") + if not file then + print("Error opening file " .. filename .. ": " .. err) + return + end + + -- Write the HTML structure + file:write("\n") + for _, translation in ipairs(translations) do + -- Check if the translation needs to be segmented + if #translation > SEGMENT_SIZE - REDUCE_SEGMENT_SIZE then + print("Splitting translation into segments", translation) + -- Split the translation into segments + local segments = split_into_segments(translation, SEGMENT_SIZE - REDUCE_SEGMENT_SIZE) + -- Write each segment as a separate paragraph + for _, segment in ipairs(segments) do + file:write("

" .. sanitize_translation(segment) .. "

\n") + end + else + -- Write the translation as a single paragraph + file:write("

" .. sanitize_translation(translation) .. "

\n") + end + end + file:write("\n") + file:close() +end + +-- Function to create a branch in the trie structure +local function create_branch(strings, stringIndex) + local branch = {} + -- Process each string in the input array + for i = 1, #strings do + local string = strings[i] + local cleanedString = string.gsub(string, "%s", "") + -- Remove all numbers from the string + -- cleanedString = string.gsub(cleanedString, "%d+", "") + cleanedString = string.gsub(cleanedString, "%p", "") + cleanedString = string.gsub(cleanedString, "%c", "") + + -- Get the character at the current index + -- local char = string.sub(string.lower(cleanedString), stringIndex, stringIndex) + local char = string.sub(cleanedString, stringIndex, stringIndex) + + if char == "" then + error(string.format("%s: %d out of range, increase MAX_TRANSLATIONS_PER_FILE", string, stringIndex)) + end + + -- Create a new branch for the character if it doesn't exist + if not branch[char] then + branch[char] = {} + end + table.insert(branch[char], string) + end + + -- Recursively create branches for child nodes if needed + for char, child in pairs(branch) do + if #child > MAX_TRANSLATIONS_PER_FILE then + branch[char] = create_branch(child, stringIndex + 1) + end + end + + return branch +end + +-- Function to create trie folders and write translations to HTML files +local function create_trie_folders(trie, current_path) + print("Current path: " .. current_path) + for key, value in pairs(trie) do + local new_path = current_path .. "/" .. key + if type(value) == "table" then + -- If the number of translations is greater than the maximum or there are no translations + if #value > MAX_TRANSLATIONS_PER_FILE or #value == 0 then + mkdir(new_path) + -- print("Continuing recursion for: " .. new_path) + create_trie_folders(value, new_path) + else + print("Writing HTML file for: " .. new_path) + write_html_file(new_path, value) + end + end + end +end + +-- Main function to compile translations to HTML +function Compile_translations_to_html(strings) + -- Initialize the trie + local success, trie + repeat + success, trie = pcall(create_branch, strings, 1) + if not success then + MAX_TRANSLATIONS_PER_FILE = MAX_TRANSLATIONS_PER_FILE + 1 + print(trie) + print("Shortest word does not fit! - increasing MAX_TRANSLATIONS_PER_FILE to: " .. MAX_TRANSLATIONS_PER_FILE) + end + until success + + -- Create the root folder + local root_folder = "translations" + mkdir(root_folder) + + -- Create trie folders and write translations + create_trie_folders(trie, root_folder) + + -- DevTools_Dump(trie) + -- Dump the trie to a lua file + -- local lines = {} + local function dump_trie(trie, indent) + local lines = {} + local indent_str = string.rep(" ", indent) + if type(trie) == "table" then + for char, value in pairs(trie) do + if type(value) == "table" then + table.insert(lines, indent_str .. "['" .. char .. "'] = {") + table.insert(lines, dump_trie(value, indent + 1)) + table.insert(lines, indent_str .. "},") + else + table.insert(lines, indent_str .. "\"" .. value .. "\",") + end + end + else + table.insert(lines, indent_str .. "[\"" .. trie .. "\"]") + end + return table.concat(lines, "\n") + end + + local lua_file = io.open(root_folder .. "/trie.lua", "w") + if lua_file ~= nil then + local dump_str = dump_trie(trie, 1) + lua_file:write("local trie = {\n" .. dump_str .. "\n}") + lua_file:close() + end +end diff --git a/.generate_database_lua/helpers.lua b/.generate_database_lua/helpers.lua new file mode 100644 index 00000000..7b47659e --- /dev/null +++ b/.generate_database_lua/helpers.lua @@ -0,0 +1,219 @@ +-- helpers.lua +local lfs = require("lfs") + +-- Require the necessary LuaSocket modules +local http = require("socket.http") +local https = require("ssl.https") +local ltn12 = require("ltn12") + +--- Get the script directory. +---@return string The directory containing the script. +local function get_script_dir() + local script_path = debug.getinfo(1, "S").source:sub(2) + return script_path:match("(.*/)") +end + +--- Get the project directory path. +---@return string The project directory path. +local function get_project_dir_path() + return get_script_dir() .. ".." +end + +--- Get the data directory path for a given entity type and expansion. +---@param entity_type string The type of entity (e.g., "Quest", "Item"). +---@param expansion string The expansion name (e.g., "Era", "Tbc", "Wotlk"). +---@return string The data directory path. +local function get_data_dir_path(entity_type, expansion) + local path = get_project_dir_path() .. "/Database/" .. entity_type .. "/" .. expansion + -- Does path not exist, l10n has this issue... + if not lfs.attributes(path, "mode") then + print("Path " .. path .. " does not exist, trying lowercase") + path = get_project_dir_path() .. "/Database/" .. entity_type:lower() .. "/" .. expansion + end + return path +end + +--- Find the addon name. +---@return string The addon name. +local function find_addon_name() + local current_dir = lfs.currentdir() + local previous_dir = nil + local addon_dir = nil + local max_level = 20 + local level = 0 + + while level < max_level do + local dir_name = current_dir:match("([^/]+)$") + local parent_dir = current_dir:match("^(.*)/[^/]+$") + if type(dir_name) == "nil" then + addon_dir = previous_dir + break + elseif dir_name:lower() == "addons" and parent_dir:match("([^/]+)$"):lower() == "interface" then + addon_dir = previous_dir + break + else + previous_dir = current_dir + current_dir = parent_dir + level = level + 1 + end + end + + if not addon_dir then + print("Could not find the Addons folder, defaulting to 'QuestieDB'.") + return "QuestieDB" + else + print("Found Addons folder: " .. addon_dir) + end + + return addon_dir +end + +--- Read expansion data from a Lua file. +---@param expansion string The expansion name (e.g., "Era", "Tbc", "Wotlk"). +---@param entity_type string The type of entity (e.g., "Quest", "Item"). +---@return string|nil The content of the Lua file, or nil if not found. +local function read_expansion_data(expansion, entity_type) + local path = get_data_dir_path(entity_type, expansion) + print("Reading " .. expansion .. " lua " .. entity_type:lower() .. " data from " .. path) + local file_path = path .. "/" .. entity_type:sub(1, 1):upper() .. entity_type:sub(2):lower() .. "Data.lua-table" + + if not lfs.attributes(file_path, "mode") then + file_path = path .. "/" .. entity_type:lower() .. "Data.lua-table" + if not lfs.attributes(file_path, "mode") then + print("File not found: " .. file_path) + return nil + end + end + + local file, err = io.open(file_path, "r") + if not file then + print("File not found: " .. path) + return nil + end + + local data = file:read("*all") + file:close() + + -- Perform any necessary replacements on the data string + data = data:gsub("&", "and"):gsub("<", "|"):gsub(">", "|") + return data +end + +--- Download a raw text file from a URL and return its contents as a string. +-- @param url string The URL of the text file to download. +-- @return string|nil The contents of the text file, or nil if the download fails. +local function download_text_file(url) + local response_body = {} + local res, code, response_headers = https.request { + url = url, + sink = ltn12.sink.table(response_body), + } + + if res == 1 and code == 200 then + -- Concatenate the table into a single string + return table.concat(response_body) + else + print("Failed to download file: HTTP response code " .. tostring(code)) + return nil + end +end + +---Dumps the data for Item, Quest, Npc, Object into a string +---@param tbl table> @ Table that will be dumped, Item, Quest, Npc, Object +---@param dataKeys ItemDBKeys|QuestDBKeys|NpcDBKeys|ObjectDBKeys @ Contains name of data as keys and their index as value +---@param dumpFunctions table @ Contains the functions that will be used to dump the data +---@param combineFunc function? @ Function that will be used to combine the data, if nil the data will not be combined +---@return string,table[] @ Returns the dumped data as a string and a table of the dumped data +local function dumpData(tbl, dataKeys, dumpFunctions, combineFunc) + -- sort tbl by key + local sortedKeys = {} + for key in pairs(tbl) do + sortedKeys[#sortedKeys + 1] = key + end + table.sort(sortedKeys) + + local nrDataKeys = 0 + local reversedKeys = {} + for key, id in pairs(dataKeys) do + reversedKeys[id] = key + nrDataKeys = nrDataKeys + 1 + end + + local allResultsTbl = {} + local allResults = { "{\n", } + for sortKeyIndex = 1, #sortedKeys do + local sortKey = sortedKeys[sortKeyIndex] + + -- print(sortKey) + local value = tbl[sortKey] + + local resulttable = {} + for i = 1, nrDataKeys do + resulttable[i] = "nil" + end + + for key = 1, nrDataKeys do + -- The name of the key e.g. "objectDrops" + local dataName = dataKeys[key] == nil and reversedKeys[key] or key + -- The id of the key e.g. "3"-(objectDrops) + local dataKey = type(key) == "number" and key or dataKeys[key] + + -- print(key, dataName, dataKey) + + -- Get the data from the table + local data = value[key] + + -- Because we build it with nil we have to check for nil here, if the value is nil we just print nil + if data ~= "nil" and data ~= nil then + local dumpFunction = dumpFunctions[dataName] + if dumpFunction then + local dumpedData = dumpFunction(data) + resulttable[dataKey] = dumpedData + else + error("No dump function for key: " .. "dataName" .. " (" .. tostring(dataName) .. ")" .. " dataKey: " .. tostring(dataKey)) + end + else + resulttable[dataKey] = "nil" + end + end + -- DevTools_Dump({resulttable}) + + -- If a combine funnction exist we run it here + assert(#resulttable == nrDataKeys, "resulttable length is not equal to dataKeys length, combine will fail") + if combineFunc then + combineFunc(resulttable) + end + -- DevTools_Dump({resulttable}) + + -- Concat the data into a string + local data = table.concat(resulttable, ",") + + allResultsTbl[sortKey] = data + + -- Remove trailing nil + repeat + local count = 0 + data, count = string.gsub(data, ",nil$", "") + until count == 0 + + -- Add the data to the result + allResults[#allResults + 1] = " [" .. sortKey .. "] = {" + allResults[#allResults + 1] = data + allResults[#allResults + 1] = ",},\n" + end + allResults[#allResults + 1] = "}" + -- return result .. "}" + return table.concat(allResults), allResultsTbl +end + +---@class helpers +local return_table = { + get_project_dir_path = get_project_dir_path, + get_data_dir_path = get_data_dir_path, + find_addon_name = find_addon_name, + read_expansion_data = read_expansion_data, + dumpData = dumpData, + download_text_file = download_text_file, +} +-- Expose functions +return return_table diff --git a/.generate_database_lua/main.lua b/.generate_database_lua/main.lua new file mode 100644 index 00000000..5c807711 --- /dev/null +++ b/.generate_database_lua/main.lua @@ -0,0 +1,100 @@ +-- main.lua +-- Prepend your script's directory to the package.path +local script_path = debug.getinfo(1, "S").source:sub(2) +local script_dir = script_path:match("(.*/)") +package.path = script_dir .. "?.lua;" .. package.path + +local helpers = require("helpers") +require("cli.CLI_Helpers") + +-- Main function to demonstrate the usage of helper functions +local function main() + -- Get the project directory path + local project_dir = helpers.get_project_dir_path() + print("Project Directory Path: " .. project_dir) + + -- Get the data directory path for a specific entity type and expansion + local entity_type = "Quest" + local expansion = "Wotlk" + local data_dir = helpers.get_data_dir_path(entity_type, expansion) + print("Data Directory Path for " .. entity_type .. " in " .. expansion .. ": " .. data_dir) + + -- Find the addon name + local addon_name = helpers.find_addon_name() + print("Addon Name: " .. addon_name) + + -- Read expansion data + local expansion_data = helpers.read_expansion_data(expansion, entity_type) + if expansion_data then + local lines = 4 + local count = 0 + for line in expansion_data:gmatch(" [^\n]+") do + print(line) + count = count + 1 + if count >= lines then + break + end + end + else + print("No data found for " .. entity_type .. " in " .. expansion) + end + + -- Download a file from a URL + local url = "https://raw.githubusercontent.com/Questie/Questie/master/Database/Classic/classicItemDB.lua" + local data = helpers.download_text_file(url) + if data then + print("Downloaded data from URL: ") + local lines = 4 + local count = 0 + for line in data:gmatch(" [^\n]+") do + print(line) + count = count + 1 + if count >= lines then + break + end + end + else + print("Failed to download data from URL: " .. url) + end + + -- Write data to a file + -- Write data to a file + local output_dir = ".generate_database/_data" + local output_file = output_dir .. "/eraItemDB.lua" + + -- Write the data to the file + local file, err = io.open(output_file, "w") + if not file then + print("Error opening file for writing: " .. err) + else + file:write(data) + file:close() + print("Data written to file: " .. output_file) + end +end + + +require("cli.Addon_Meta") +local translations = {} +QuestieLoader = { + ImportModule = function() + return { translations = translations, } + end, +} + +CLI_Helpers.loadTOC(".generate_database_lua/translations.toc") + + +local single_translation = {} +for key, value in pairs(translations) do + local translation = string.gsub(key, "\n", "
") + translation = string.gsub(translation, '"', '\\"') + table.insert(single_translation, translation) +end + +require("generate_translation_trie") + +Compile_translations_to_html(single_translation) + +-- Run the main function +-- main() diff --git a/.generate_database_lua/run.sh b/.generate_database_lua/run.sh new file mode 100644 index 00000000..743969e3 --- /dev/null +++ b/.generate_database_lua/run.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +echo "Current directory: $(pwd)" +echo "$(which $1) is the lua executable" + +# First argument points to lua executable set "lua" if not set +if [ -z "$1" ]; then + LUA=lua +else + LUA=$1 +fi + +# Needed for the docker container but not action but it doesn't hurt the run if it fails +cd /QuestieDB + + + +$LUA ./.generate_database_lua/main.lua +# $LUA ./.generate_database_lua/generate_translation_trie.lua \ No newline at end of file diff --git a/Database/l10n/l10n.lua b/Database/l10n/l10n.lua index d50ee3dc..badcb5ae 100644 --- a/Database/l10n/l10n.lua +++ b/Database/l10n/l10n.lua @@ -9,9 +9,7 @@ local l10n = LibQuestieDB.CreateDatabaseInTable(LibQuestieDB.l10n, "l10n", {}) l10n.currentLocale = GetLocale() -- Set this to nil to use the locale of the client -- Override locale -l10n.currentLocale = "ptBR" - -GLOBl10n = l10n +-- l10n.currentLocale = "ptBR" -- Order Item, Npc, Object, Quest -- "enUS": "", # English (US) # Yes EN is empty @@ -45,20 +43,28 @@ local indexToLocale = { local localeToIndex = {} local localeToPattern = {} do + -- Populate the localeToIndex table with locale as key and its index as value + -- This helps in quickly finding the index of a given locale for k, v in pairs(indexToLocale) do localeToIndex[v] = k end + -- Function to create a pattern string for a given locale + -- This pattern is used to extract the localized string from a concatenated string of all locales local function createPatternForLocale(locale) - local patternString = "^" - local repeatPattern = ".-" - local capturePattern = "(.-)" + local patternString = "^" -- Start of the string + local repeatPattern = ".-" -- Non-greedy match for any character sequence + local capturePattern = "(.-)" -- Non-greedy match for any character sequence, to be captured for i = 1, localeToIndex[locale] do - patternString = patternString .. (i == localeToIndex[locale] and capturePattern or repeatPattern) .. (i == #indexToLocale and "$" or specialChar) + -- Append the appropriate pattern based on the current index + patternString = patternString .. (i == localeToIndex[locale] and capturePattern or repeatPattern) + patternString = patternString .. (i == #indexToLocale and "$" or specialChar) end return patternString end + -- Populate the localeToPattern table with locale as key and its pattern as value + -- This pattern is used to extract the localized string for the given locale for i = 1, #indexToLocale do localeToPattern[indexToLocale[i]] = createPatternForLocale(indexToLocale[i]) end diff --git a/cli/CLI_Helpers.lua b/cli/CLI_Helpers.lua index 874fb5d9..567fc247 100644 --- a/cli/CLI_Helpers.lua +++ b/cli/CLI_Helpers.lua @@ -68,8 +68,10 @@ function CLI_Helpers.loadTOC(file) local xmlFilePath = line:match("^(.*)/.-%.xml$") .. "/" -- print(xmlFilePath) for xmlFile in string.gmatch(filetext, "