Mercurial > wow > reaction
diff libs/AceLocale-2.0/AceLocale-2.0.lua @ 1:c11ca1d8ed91
Version 0.1
author | Flick <flickerstreak@gmail.com> |
---|---|
date | Tue, 20 Mar 2007 21:03:57 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libs/AceLocale-2.0/AceLocale-2.0.lua Tue Mar 20 21:03:57 2007 +0000 @@ -0,0 +1,506 @@ +--[[ +Name: AceLocale-2.0 +Revision: $Rev: 18753 $ +Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team) +Inspired By: Ace 1.x by Turan (turan@gryphon.com) +Website: http://www.wowace.com/ +Documentation: http://www.wowace.com/index.php/AceLocale-2.0 +SVN: http://svn.wowace.com/root/trunk/Ace2/AceLocale-2.0 +Description: Localization library for addons to use to handle proper + localization and internationalization. +Dependencies: AceLibrary +]] + +local MAJOR_VERSION = "AceLocale-2.0" +local MINOR_VERSION = "$Revision: 18753 $" + +if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary.") end +if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end + +local AceLocale = {} + +local DEFAULT_LOCALE = "enUS" +local _G = getfenv(0) + +local __baseTranslations__, __debugging__, __translations__, __baseLocale__, __translationTables__, __reverseTranslations__, __strictness__ + +local __call = function(self, key1, key2) + if key2 then + return self[key1][key2] + else + return self[key1] + end +end + +local rawget = rawget +local rawset = rawset +local type = type + +local lastSelf + +local __index = function(self, key) + lastSelf = self + local value = (rawget(self, __translations__) or AceLocale.prototype)[key] + rawset(self, key, value) + return value +end + +local __newindex = function(self, k, v) + if type(v) ~= "function" and type(k) ~= "table" then + AceLocale.error(self, "Cannot change the values of an AceLocale instance.") + end + rawset(self, k, v) +end + +local __tostring = function(self) + if type(rawget(self, 'GetLibraryVersion')) == "function" then + return self:GetLibraryVersion() + else + return "AceLocale(" .. self[__name__] .. ")" + end +end + +local refixInstance = function(instance) + if getmetatable(instance) then + setmetatable(instance, nil) + end + local translations = instance[__translations__] + if translations then + if getmetatable(translations) then + setmetatable(translations, nil) + end + local baseTranslations = instance[__baseTranslations__] + if getmetatable(baseTranslations) then + setmetatable(baseTranslations, nil) + end + if translations == baseTranslations or instance[__strictness__] then + setmetatable(instance, { + __index = __index, + __newindex = __newindex, + __call = __call, + __tostring = __tostring + }) + + setmetatable(translations, { + __index = AceLocale.prototype + }) + else + setmetatable(instance, { + __index = __index, + __newindex = __newindex, + __call = __call, + __tostring = __tostring + }) + + setmetatable(translations, { + __index = baseTranslations, + }) + + setmetatable(baseTranslations, { + __index = AceLocale.prototype, + }) + end + else + setmetatable(instance, { + __index = __index, + __newindex = __newindex, + __call = __call, + __tostring = __tostring, + }) + end +end + +function AceLocale:new(name) + error(MAJOR_VERSION .. " is not supported in WoW 2.0", 2) + self:argCheck(name, 2, "string") + + if self.registry[name] and type(rawget(self.registry[name], 'GetLibraryVersion')) ~= "function" then + return self.registry[name] + end + + local self = { + [__strictness__] = false, + [__name__] = name, + } + refixInstance(self) + + AceLocale.registry[name] = self + return self +end + +setmetatable(AceLocale, { __call = AceLocale.new }) + +AceLocale.prototype = {} +AceLocale.prototype.class = AceLocale + +function AceLocale.prototype:EnableDebugging() + if rawget(self, __baseTranslations__) then + AceLocale:error("Cannot enable debugging after a translation has been registered.") + end + rawset(self, __debugging__, true) +end + +function AceLocale.prototype:RegisterTranslations(locale, func) + AceLocale.argCheck(self, locale, 2, "string") + AceLocale.argCheck(self, func, 3, "function") + + if locale == rawget(self, __baseLocale__) then + AceLocale.error(self, "Cannot provide the same locale more than once. %q provided twice.", locale) + end + + if rawget(self, __baseTranslations__) and GetLocale() ~= locale then + if rawget(self, __debugging__) then + local t = func() + func = nil + if type(t) ~= "table" then + AceLocale.error(self, "Bad argument #3 to `RegisterTranslations'. function did not return a table. (expected table, got %s)", type(t)) + end + self[__translationTables__][locale] = t + t = nil + end + func = nil + return + end + local t = func() + func = nil + if type(t) ~= "table" then + AceLocale.error(self, "Bad argument #3 to `RegisterTranslations'. function did not return a table. (expected table, got %s)", type(t)) + end + + rawset(self, __translations__, t) + if not rawget(self, __baseTranslations__) then + rawset(self, __baseTranslations__, t) + rawset(self, __baseLocale__, locale) + for key,value in pairs(t) do + if value == true then + t[key] = key + end + end + else + for key, value in pairs(self[__translations__]) do + if not rawget(self[__baseTranslations__], key) then + AceLocale.error(self, "Improper translation exists. %q is likely misspelled for locale %s.", key, locale) + end + if value == true then + AceLocale.error(self, "Can only accept true as a value on the base locale. %q is the base locale, %q is not.", rawget(self, __baseLocale__), locale) + end + end + end + refixInstance(self) + if rawget(self, __debugging__) then + if not rawget(self, __translationTables__) then + rawset(self, __translationTables__, {}) + end + self[__translationTables__][locale] = t + end + t = nil +end + +function AceLocale.prototype:SetStrictness(strict) + AceLocale.argCheck(self, strict, 2, "boolean") + local mt = getmetatable(self) + if not mt then + AceLocale.error(self, "Cannot call `SetStrictness' without a metatable.") + end + if not rawget(self, __translations__) then + AceLocale.error(self, "No translations registered.") + end + rawset(self, __strictness__, strict) + refixInstance(self) +end + +function AceLocale.prototype:GetTranslationStrict(text, sublevel) + AceLocale.argCheck(self, text, 1, "string") + local translations = rawget(self, __translations__) + if not translations then + AceLocale.error(self, "No translations registered") + end + if sublevel then + local t = rawget(translations, text) + if type(t) ~= "table" then + AceLocale.error(self, "Strict translation %q::%q does not exist", text, sublevel) + end + local value = t[sublevel] + if not value then + AceLocale.error(self, "Strict translation %q::%q does not exist", text, sublevel) + end + return value + else + local value = rawget(translations, text) + if not value then + AceLocale.error(self, "Strict translation %q does not exist", text) + end + return value + end +end + +function AceLocale.prototype:GetTranslation(text, sublevel) + AceLocale.argCheck(self, text, 1, "string") + local translations = rawget(self, __translations__) + if not translations then + AceLocale.error(self, "No translations registered") + end + if sublevel then + local base = self[__baseTranslations__] + local standard = rawget(translations, text) + local current + local baseStandard + if not standard then + baseStandard = rawget(base, text) + current = baseStandard + end + if not type(current) ~= "table" then + AceLocale.error(self, "Loose translation %q::%q does not exist", text, sublevel) + end + local value = current[sublevel] + if not value then + if current == baseStandard or type(baseStandard) ~= "table" then + AceLocale.error(self, "Loose translation %q::%q does not exist", text, sublevel) + end + value = baseStandard[sublevel] + if not value then + AceLocale.error(self, "Loose translation %q::%q does not exist", text, sublevel) + end + end + return value + else + local value = rawget(translations, text) + if not value then + AceLocale.error(self, "Loose translation %q does not exist", text) + end + return value + end +end + +local function initReverse(self) + rawset(self, __reverseTranslations__, {}) + local alpha = self[__translations__] + local bravo = self[__reverseTranslations__] + for base, localized in pairs(alpha) do + bravo[localized] = base + end +end + +function AceLocale.prototype:GetReverseTranslation(text) + local x = rawget(self, __reverseTranslations__) + if not x then + if not rawget(self, __translations__) then + AceLocale.error(self, "No translations registered") + end + initReverse(self) + x = self[__reverseTranslations__] + end + local translation = x[text] + if not translation then + AceLocale.error(self, "Reverse translation for %q does not exist", text) + end + return translation +end + +function AceLocale.prototype:GetIterator() + local x = rawget(self, __translations__) + if not x then + AceLocale.error(self, "No translations registered") + end + return next, x, nil +end + +function AceLocale.prototype:GetReverseIterator() + local x = rawget(self, __reverseTranslations__) + if not x then + if not rawget(self, __translations__) then + AceLocale.error(self, "No translations registered") + end + initReverse(self) + x = self[__reverseTranslations__] + end + return next, x, nil +end + +function AceLocale.prototype:HasTranslation(text, sublevel) + AceLocale.argCheck(self, text, 1, "string") + local x = rawget(self, __translations__) + if not x then + AceLocale.error(self, "No translations registered") + end + if sublevel then + AceLocale.argCheck(self, sublevel, 2, "string", "nil") + return type(rawget(x, text)) == "table" and x[text][sublevel] and true + end + return rawget(x, text) and true +end + +function AceLocale.prototype:HasReverseTranslation(text) + local x = rawget(self, __reverseTranslations__) + if not x then + if not rawget(self, __translations__) then + AceLocale.error(self, "No translations registered") + end + initReverse(self) + x = self[__reverseTranslations__] + end + return x[text] and true +end + +AceLocale.prototype.GetTableStrict = AceLocale.prototype.GetTranslationStrict +AceLocale.prototype.GetTable = AceLocale.prototype.GetTranslation + +function AceLocale.prototype:Debug() + if not rawget(self, __debugging__) then + return + end + local words = {} + local locales = {"enUS", "deDE", "frFR", "koKR", "zhCN", "zhTW"} + local localizations = {} + DEFAULT_CHAT_FRAME:AddMessage("--- AceLocale Debug ---") + for _,locale in ipairs(locales) do + if not self[__translationTables__][locale] then + DEFAULT_CHAT_FRAME:AddMessage(string.format("Locale %q not found", locale)) + else + localizations[locale] = self[__translationTables__][locale] + end + end + local localeDebug = {} + for locale, localization in pairs(localizations) do + localeDebug[locale] = {} + for word in pairs(localization) do + if type(localization[word]) == "table" then + if type(words[word]) ~= "table" then + words[word] = {} + end + for bit in pairs(localization[word]) do + if type(localization[word][bit]) == "string" then + words[word][bit] = true + end + end + elseif type(localization[word]) == "string" then + words[word] = true + end + end + end + for word in pairs(words) do + if type(words[word]) == "table" then + for bit in pairs(words[word]) do + for locale, localization in pairs(localizations) do + if not rawget(localization, word) or not localization[word][bit] then + localeDebug[locale][word .. "::" .. bit] = true + end + end + end + else + for locale, localization in pairs(localizations) do + if not rawget(localization, word) then + localeDebug[locale][word] = true + end + end + end + end + for locale, t in pairs(localeDebug) do + if not next(t) then + DEFAULT_CHAT_FRAME:AddMessage(string.format("Locale %q complete", locale)) + else + DEFAULT_CHAT_FRAME:AddMessage(string.format("Locale %q missing:", locale)) + for word in pairs(t) do + DEFAULT_CHAT_FRAME:AddMessage(string.format(" %q", word)) + end + end + end + DEFAULT_CHAT_FRAME:AddMessage("--- End AceLocale Debug ---") +end + +setmetatable(AceLocale.prototype, { + __index = function(self, k) + if type(k) ~= "table" and k ~= 0 and k ~= "GetLibraryVersion" and k ~= "error" and k ~= "assert" and k ~= "argCheck" and k ~= "pcall" then -- HACK: remove "GetLibraryVersion" and such later. + AceLocale.error(lastSelf or self, "Translation %q does not exist.", k) + end + return nil + end +}) + +local function activate(self, oldLib, oldDeactivate) + AceLocale = self + + if oldLib then + self.registry = oldLib.registry + self.__baseTranslations__ = oldLib.__baseTranslations__ + self.__debugging__ = oldLib.__debugging__ + self.__translations__ = oldLib.__translations__ + self.__baseLocale__ = oldLib.__baseLocale__ + self.__translationTables__ = oldLib.__translationTables__ + self.__reverseTranslations__ = oldLib.__reverseTranslations__ + self.__strictness__ = oldLib.__strictness__ + self.__name__ = oldLib.__name__ + end + if not self.__baseTranslations__ then + self.__baseTranslations__ = {} + end + if not self.__debugging__ then + self.__debugging__ = {} + end + if not self.__translations__ then + self.__translations__ = {} + end + if not self.__baseLocale__ then + self.__baseLocale__ = {} + end + if not self.__translationTables__ then + self.__translationTables__ = {} + end + if not self.__reverseTranslations__ then + self.__reverseTranslations__ = {} + end + if not self.__strictness__ then + self.__strictness__ = {} + end + if not self.__name__ then + self.__name__ = {} + end + + __baseTranslations__ = self.__baseTranslations__ + __debugging__ = self.__debugging__ + __translations__ = self.__translations__ + __baseLocale__ = self.__baseLocale__ + __translationTables__ = self.__translationTables__ + __reverseTranslations__ = self.__reverseTranslations__ + __strictness__ = self.__strictness__ + __name__ = self.__name__ + + if not self.registry then + self.registry = {} + else + for name, instance in pairs(self.registry) do + local name = name + local mt = getmetatable(instance) + setmetatable(instance, nil) + instance[__name__] = name + local strict + if instance.translations then + instance[__translations__], instance.translations = instance.translations + instance[__baseLocale__], instance.baseLocale = instance.baseLocale + instance[__baseTranslations__], instance.baseTranslations = instance.baseTranslations + instance[__debugging__], instance.debugging = instance.debugging + instance.reverseTranslations = nil + instance[__translationTables__], instance.translationTables = instance.translationTables + if mt and mt.__call == oldLib.prototype.GetTranslationStrict then + strict = true + end + else + if instance[__strictness__] ~= nil then + strict = instance[__strictness__] + elseif instance[__translations__] ~= instance[__baseTranslations__] then + if getmetatable(instance[__translations__]).__index == oldLib.prototype then + strict = true + end + end + end + instance[__strictness__] = strict and true or false + refixInstance(instance) + end + end + + if oldDeactivate then + oldDeactivate(oldLib) + end +end + +AceLibrary:Register(AceLocale, MAJOR_VERSION, MINOR_VERSION, activate)