From 0a411440529e9ed452bf24f833691f443be3bdbe Mon Sep 17 00:00:00 2001 From: Kakarot <57848836+GhzGarage@users.noreply.github.com> Date: Thu, 6 Jan 2022 20:50:13 -0600 Subject: [PATCH] Create locale.lua --- shared/locale.lua | 140 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 shared/locale.lua diff --git a/shared/locale.lua b/shared/locale.lua new file mode 100644 index 0000000..967b737 --- /dev/null +++ b/shared/locale.lua @@ -0,0 +1,140 @@ +--- @class Locale +Locale = {} +Locale.__index = Locale + +local function translateKey(phrase, subs) + if type(phrase) ~= 'string' then + error('TypeError: translateKey function expects arg #1 to be a string') + end + + -- Substituions + if not subs then + return phrase + end + + -- We should be escaping gsub just in case of any + -- shenanigans with nested template patterns or injection + + -- Create and copy our return string + local result = phrase + + -- Initial Scan over result looking for substituions + for k, v in pairs(subs) do + local templateToFind = '%%{' .. k .. '}' + print('Template to find:', templateToFind) + print('Replace val:', v) + result = result:gsub(templateToFind, v) + end + + return result +end + +--- Constructor function for a new Locale class instance +--- @param opts table - Constructor opts param +--- @return Locale +function Locale:new(opts) + local self = {} + setmetatable(self, Locale) + self.warnOnMissing = opts.warnOnMissing or true + + self.phrases = {} + self:extend(opts.phrases or {}) + + return self +end + +--- Method for extending an instances phrases map. This is also, used +--- internally for initial population of phrases field. +--- @param phrases table - Table of phrase definitions +--- @param prefix string | nil - Optional prefix used for recursive calls +--- @return void +function Locale:extend(phrases, prefix) + for key, phrase in pairs(phrases) do + local prefixKey = prefix and ('%s.%s'):format(prefix, key) or key + -- If this is a nested table, we need to go reeeeeeeeeeeecursive + if type(phrase) == 'table' then + self:extend(phrase, prefixKey) + else + self.phrases[prefixKey] = phrase + end + end +end + + +--- Clear locale instance phrases +--- Might be useful for memory management of large phrase maps. +--- @return void +function Locale:clear() + self.phrases = {} +end + +--- Clears all phrases and replaces it with the passed phrases table +--- @param phrases table +function Locale:replace(phrases) + phrases = phrases or {} + self.clear() + self.extend(phrases) +end + +--- Gets & Sets a locale depending on if an argument is passed +--- @param newLocale string - Optional new locale to set +--- @return string +function Locale:locale(newLocale) + if (newLocale) then + self.currentLocale = newLocale + end + return self.currentLocale +end + +--- Primary translation method for a phrase of given key +--- @param key string - The phrase key to target +--- @param subs table +--- @return string +function Locale:t(key, subs) + local phrase, result + subs = subs or {} + + -- See if the passed key resolves to a valid phrase string + if type(self.phrases[key]) == 'string' then + phrase = self.phrases[key] + -- At this point we know whether the phrase does not exist for this key + else + if self.warnOnMissing then + print(('^3Warning: Missing phrase for key: "%s"'):format(key)) + end + result = key + end + + if type(phrase) == 'string' then + result = translateKey(phrase, subs) + end + + return result +end + +--- Check if a phrase key has already been defined within the Locale instance phrase maps. +--- @return boolean +function Locale:has(key) + return self.phrases[key] ~= nil +end + +--- Will remove phrase keys from a Locale instance, using recursion/ +--- @param phraseTarget string | table +--- @param prefix string +function Locale:delete(phraseTarget, prefix) + -- If the target is a string, we know that this is the end + -- of nested table tree. + if type(phraseTarget) == 'string' then + self.phrases[phraseTarget] = nil + else + for key, phrase in pairs(phraseTarget) do + local prefixKey = prefix and prefix .. '.' .. key or key + + if type(phrase) == 'table' then + self:delete(phrase, prefixKey) + else + self.phrases[prefixKey] = nil + end + end + end +end