Mercurial > wow > reaction
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 0:4e2ce2894c21 | 1:c11ca1d8ed91 |
|---|---|
| 1 --[[ | |
| 2 Name: AceLocale-2.0 | |
| 3 Revision: $Rev: 18753 $ | |
| 4 Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team) | |
| 5 Inspired By: Ace 1.x by Turan (turan@gryphon.com) | |
| 6 Website: http://www.wowace.com/ | |
| 7 Documentation: http://www.wowace.com/index.php/AceLocale-2.0 | |
| 8 SVN: http://svn.wowace.com/root/trunk/Ace2/AceLocale-2.0 | |
| 9 Description: Localization library for addons to use to handle proper | |
| 10 localization and internationalization. | |
| 11 Dependencies: AceLibrary | |
| 12 ]] | |
| 13 | |
| 14 local MAJOR_VERSION = "AceLocale-2.0" | |
| 15 local MINOR_VERSION = "$Revision: 18753 $" | |
| 16 | |
| 17 if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary.") end | |
| 18 if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end | |
| 19 | |
| 20 local AceLocale = {} | |
| 21 | |
| 22 local DEFAULT_LOCALE = "enUS" | |
| 23 local _G = getfenv(0) | |
| 24 | |
| 25 local __baseTranslations__, __debugging__, __translations__, __baseLocale__, __translationTables__, __reverseTranslations__, __strictness__ | |
| 26 | |
| 27 local __call = function(self, key1, key2) | |
| 28 if key2 then | |
| 29 return self[key1][key2] | |
| 30 else | |
| 31 return self[key1] | |
| 32 end | |
| 33 end | |
| 34 | |
| 35 local rawget = rawget | |
| 36 local rawset = rawset | |
| 37 local type = type | |
| 38 | |
| 39 local lastSelf | |
| 40 | |
| 41 local __index = function(self, key) | |
| 42 lastSelf = self | |
| 43 local value = (rawget(self, __translations__) or AceLocale.prototype)[key] | |
| 44 rawset(self, key, value) | |
| 45 return value | |
| 46 end | |
| 47 | |
| 48 local __newindex = function(self, k, v) | |
| 49 if type(v) ~= "function" and type(k) ~= "table" then | |
| 50 AceLocale.error(self, "Cannot change the values of an AceLocale instance.") | |
| 51 end | |
| 52 rawset(self, k, v) | |
| 53 end | |
| 54 | |
| 55 local __tostring = function(self) | |
| 56 if type(rawget(self, 'GetLibraryVersion')) == "function" then | |
| 57 return self:GetLibraryVersion() | |
| 58 else | |
| 59 return "AceLocale(" .. self[__name__] .. ")" | |
| 60 end | |
| 61 end | |
| 62 | |
| 63 local refixInstance = function(instance) | |
| 64 if getmetatable(instance) then | |
| 65 setmetatable(instance, nil) | |
| 66 end | |
| 67 local translations = instance[__translations__] | |
| 68 if translations then | |
| 69 if getmetatable(translations) then | |
| 70 setmetatable(translations, nil) | |
| 71 end | |
| 72 local baseTranslations = instance[__baseTranslations__] | |
| 73 if getmetatable(baseTranslations) then | |
| 74 setmetatable(baseTranslations, nil) | |
| 75 end | |
| 76 if translations == baseTranslations or instance[__strictness__] then | |
| 77 setmetatable(instance, { | |
| 78 __index = __index, | |
| 79 __newindex = __newindex, | |
| 80 __call = __call, | |
| 81 __tostring = __tostring | |
| 82 }) | |
| 83 | |
| 84 setmetatable(translations, { | |
| 85 __index = AceLocale.prototype | |
| 86 }) | |
| 87 else | |
| 88 setmetatable(instance, { | |
| 89 __index = __index, | |
| 90 __newindex = __newindex, | |
| 91 __call = __call, | |
| 92 __tostring = __tostring | |
| 93 }) | |
| 94 | |
| 95 setmetatable(translations, { | |
| 96 __index = baseTranslations, | |
| 97 }) | |
| 98 | |
| 99 setmetatable(baseTranslations, { | |
| 100 __index = AceLocale.prototype, | |
| 101 }) | |
| 102 end | |
| 103 else | |
| 104 setmetatable(instance, { | |
| 105 __index = __index, | |
| 106 __newindex = __newindex, | |
| 107 __call = __call, | |
| 108 __tostring = __tostring, | |
| 109 }) | |
| 110 end | |
| 111 end | |
| 112 | |
| 113 function AceLocale:new(name) | |
| 114 error(MAJOR_VERSION .. " is not supported in WoW 2.0", 2) | |
| 115 self:argCheck(name, 2, "string") | |
| 116 | |
| 117 if self.registry[name] and type(rawget(self.registry[name], 'GetLibraryVersion')) ~= "function" then | |
| 118 return self.registry[name] | |
| 119 end | |
| 120 | |
| 121 local self = { | |
| 122 [__strictness__] = false, | |
| 123 [__name__] = name, | |
| 124 } | |
| 125 refixInstance(self) | |
| 126 | |
| 127 AceLocale.registry[name] = self | |
| 128 return self | |
| 129 end | |
| 130 | |
| 131 setmetatable(AceLocale, { __call = AceLocale.new }) | |
| 132 | |
| 133 AceLocale.prototype = {} | |
| 134 AceLocale.prototype.class = AceLocale | |
| 135 | |
| 136 function AceLocale.prototype:EnableDebugging() | |
| 137 if rawget(self, __baseTranslations__) then | |
| 138 AceLocale:error("Cannot enable debugging after a translation has been registered.") | |
| 139 end | |
| 140 rawset(self, __debugging__, true) | |
| 141 end | |
| 142 | |
| 143 function AceLocale.prototype:RegisterTranslations(locale, func) | |
| 144 AceLocale.argCheck(self, locale, 2, "string") | |
| 145 AceLocale.argCheck(self, func, 3, "function") | |
| 146 | |
| 147 if locale == rawget(self, __baseLocale__) then | |
| 148 AceLocale.error(self, "Cannot provide the same locale more than once. %q provided twice.", locale) | |
| 149 end | |
| 150 | |
| 151 if rawget(self, __baseTranslations__) and GetLocale() ~= locale then | |
| 152 if rawget(self, __debugging__) then | |
| 153 local t = func() | |
| 154 func = nil | |
| 155 if type(t) ~= "table" then | |
| 156 AceLocale.error(self, "Bad argument #3 to `RegisterTranslations'. function did not return a table. (expected table, got %s)", type(t)) | |
| 157 end | |
| 158 self[__translationTables__][locale] = t | |
| 159 t = nil | |
| 160 end | |
| 161 func = nil | |
| 162 return | |
| 163 end | |
| 164 local t = func() | |
| 165 func = nil | |
| 166 if type(t) ~= "table" then | |
| 167 AceLocale.error(self, "Bad argument #3 to `RegisterTranslations'. function did not return a table. (expected table, got %s)", type(t)) | |
| 168 end | |
| 169 | |
| 170 rawset(self, __translations__, t) | |
| 171 if not rawget(self, __baseTranslations__) then | |
| 172 rawset(self, __baseTranslations__, t) | |
| 173 rawset(self, __baseLocale__, locale) | |
| 174 for key,value in pairs(t) do | |
| 175 if value == true then | |
| 176 t[key] = key | |
| 177 end | |
| 178 end | |
| 179 else | |
| 180 for key, value in pairs(self[__translations__]) do | |
| 181 if not rawget(self[__baseTranslations__], key) then | |
| 182 AceLocale.error(self, "Improper translation exists. %q is likely misspelled for locale %s.", key, locale) | |
| 183 end | |
| 184 if value == true then | |
| 185 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) | |
| 186 end | |
| 187 end | |
| 188 end | |
| 189 refixInstance(self) | |
| 190 if rawget(self, __debugging__) then | |
| 191 if not rawget(self, __translationTables__) then | |
| 192 rawset(self, __translationTables__, {}) | |
| 193 end | |
| 194 self[__translationTables__][locale] = t | |
| 195 end | |
| 196 t = nil | |
| 197 end | |
| 198 | |
| 199 function AceLocale.prototype:SetStrictness(strict) | |
| 200 AceLocale.argCheck(self, strict, 2, "boolean") | |
| 201 local mt = getmetatable(self) | |
| 202 if not mt then | |
| 203 AceLocale.error(self, "Cannot call `SetStrictness' without a metatable.") | |
| 204 end | |
| 205 if not rawget(self, __translations__) then | |
| 206 AceLocale.error(self, "No translations registered.") | |
| 207 end | |
| 208 rawset(self, __strictness__, strict) | |
| 209 refixInstance(self) | |
| 210 end | |
| 211 | |
| 212 function AceLocale.prototype:GetTranslationStrict(text, sublevel) | |
| 213 AceLocale.argCheck(self, text, 1, "string") | |
| 214 local translations = rawget(self, __translations__) | |
| 215 if not translations then | |
| 216 AceLocale.error(self, "No translations registered") | |
| 217 end | |
| 218 if sublevel then | |
| 219 local t = rawget(translations, text) | |
| 220 if type(t) ~= "table" then | |
| 221 AceLocale.error(self, "Strict translation %q::%q does not exist", text, sublevel) | |
| 222 end | |
| 223 local value = t[sublevel] | |
| 224 if not value then | |
| 225 AceLocale.error(self, "Strict translation %q::%q does not exist", text, sublevel) | |
| 226 end | |
| 227 return value | |
| 228 else | |
| 229 local value = rawget(translations, text) | |
| 230 if not value then | |
| 231 AceLocale.error(self, "Strict translation %q does not exist", text) | |
| 232 end | |
| 233 return value | |
| 234 end | |
| 235 end | |
| 236 | |
| 237 function AceLocale.prototype:GetTranslation(text, sublevel) | |
| 238 AceLocale.argCheck(self, text, 1, "string") | |
| 239 local translations = rawget(self, __translations__) | |
| 240 if not translations then | |
| 241 AceLocale.error(self, "No translations registered") | |
| 242 end | |
| 243 if sublevel then | |
| 244 local base = self[__baseTranslations__] | |
| 245 local standard = rawget(translations, text) | |
| 246 local current | |
| 247 local baseStandard | |
| 248 if not standard then | |
| 249 baseStandard = rawget(base, text) | |
| 250 current = baseStandard | |
| 251 end | |
| 252 if not type(current) ~= "table" then | |
| 253 AceLocale.error(self, "Loose translation %q::%q does not exist", text, sublevel) | |
| 254 end | |
| 255 local value = current[sublevel] | |
| 256 if not value then | |
| 257 if current == baseStandard or type(baseStandard) ~= "table" then | |
| 258 AceLocale.error(self, "Loose translation %q::%q does not exist", text, sublevel) | |
| 259 end | |
| 260 value = baseStandard[sublevel] | |
| 261 if not value then | |
| 262 AceLocale.error(self, "Loose translation %q::%q does not exist", text, sublevel) | |
| 263 end | |
| 264 end | |
| 265 return value | |
| 266 else | |
| 267 local value = rawget(translations, text) | |
| 268 if not value then | |
| 269 AceLocale.error(self, "Loose translation %q does not exist", text) | |
| 270 end | |
| 271 return value | |
| 272 end | |
| 273 end | |
| 274 | |
| 275 local function initReverse(self) | |
| 276 rawset(self, __reverseTranslations__, {}) | |
| 277 local alpha = self[__translations__] | |
| 278 local bravo = self[__reverseTranslations__] | |
| 279 for base, localized in pairs(alpha) do | |
| 280 bravo[localized] = base | |
| 281 end | |
| 282 end | |
| 283 | |
| 284 function AceLocale.prototype:GetReverseTranslation(text) | |
| 285 local x = rawget(self, __reverseTranslations__) | |
| 286 if not x then | |
| 287 if not rawget(self, __translations__) then | |
| 288 AceLocale.error(self, "No translations registered") | |
| 289 end | |
| 290 initReverse(self) | |
| 291 x = self[__reverseTranslations__] | |
| 292 end | |
| 293 local translation = x[text] | |
| 294 if not translation then | |
| 295 AceLocale.error(self, "Reverse translation for %q does not exist", text) | |
| 296 end | |
| 297 return translation | |
| 298 end | |
| 299 | |
| 300 function AceLocale.prototype:GetIterator() | |
| 301 local x = rawget(self, __translations__) | |
| 302 if not x then | |
| 303 AceLocale.error(self, "No translations registered") | |
| 304 end | |
| 305 return next, x, nil | |
| 306 end | |
| 307 | |
| 308 function AceLocale.prototype:GetReverseIterator() | |
| 309 local x = rawget(self, __reverseTranslations__) | |
| 310 if not x then | |
| 311 if not rawget(self, __translations__) then | |
| 312 AceLocale.error(self, "No translations registered") | |
| 313 end | |
| 314 initReverse(self) | |
| 315 x = self[__reverseTranslations__] | |
| 316 end | |
| 317 return next, x, nil | |
| 318 end | |
| 319 | |
| 320 function AceLocale.prototype:HasTranslation(text, sublevel) | |
| 321 AceLocale.argCheck(self, text, 1, "string") | |
| 322 local x = rawget(self, __translations__) | |
| 323 if not x then | |
| 324 AceLocale.error(self, "No translations registered") | |
| 325 end | |
| 326 if sublevel then | |
| 327 AceLocale.argCheck(self, sublevel, 2, "string", "nil") | |
| 328 return type(rawget(x, text)) == "table" and x[text][sublevel] and true | |
| 329 end | |
| 330 return rawget(x, text) and true | |
| 331 end | |
| 332 | |
| 333 function AceLocale.prototype:HasReverseTranslation(text) | |
| 334 local x = rawget(self, __reverseTranslations__) | |
| 335 if not x then | |
| 336 if not rawget(self, __translations__) then | |
| 337 AceLocale.error(self, "No translations registered") | |
| 338 end | |
| 339 initReverse(self) | |
| 340 x = self[__reverseTranslations__] | |
| 341 end | |
| 342 return x[text] and true | |
| 343 end | |
| 344 | |
| 345 AceLocale.prototype.GetTableStrict = AceLocale.prototype.GetTranslationStrict | |
| 346 AceLocale.prototype.GetTable = AceLocale.prototype.GetTranslation | |
| 347 | |
| 348 function AceLocale.prototype:Debug() | |
| 349 if not rawget(self, __debugging__) then | |
| 350 return | |
| 351 end | |
| 352 local words = {} | |
| 353 local locales = {"enUS", "deDE", "frFR", "koKR", "zhCN", "zhTW"} | |
| 354 local localizations = {} | |
| 355 DEFAULT_CHAT_FRAME:AddMessage("--- AceLocale Debug ---") | |
| 356 for _,locale in ipairs(locales) do | |
| 357 if not self[__translationTables__][locale] then | |
| 358 DEFAULT_CHAT_FRAME:AddMessage(string.format("Locale %q not found", locale)) | |
| 359 else | |
| 360 localizations[locale] = self[__translationTables__][locale] | |
| 361 end | |
| 362 end | |
| 363 local localeDebug = {} | |
| 364 for locale, localization in pairs(localizations) do | |
| 365 localeDebug[locale] = {} | |
| 366 for word in pairs(localization) do | |
| 367 if type(localization[word]) == "table" then | |
| 368 if type(words[word]) ~= "table" then | |
| 369 words[word] = {} | |
| 370 end | |
| 371 for bit in pairs(localization[word]) do | |
| 372 if type(localization[word][bit]) == "string" then | |
| 373 words[word][bit] = true | |
| 374 end | |
| 375 end | |
| 376 elseif type(localization[word]) == "string" then | |
| 377 words[word] = true | |
| 378 end | |
| 379 end | |
| 380 end | |
| 381 for word in pairs(words) do | |
| 382 if type(words[word]) == "table" then | |
| 383 for bit in pairs(words[word]) do | |
| 384 for locale, localization in pairs(localizations) do | |
| 385 if not rawget(localization, word) or not localization[word][bit] then | |
| 386 localeDebug[locale][word .. "::" .. bit] = true | |
| 387 end | |
| 388 end | |
| 389 end | |
| 390 else | |
| 391 for locale, localization in pairs(localizations) do | |
| 392 if not rawget(localization, word) then | |
| 393 localeDebug[locale][word] = true | |
| 394 end | |
| 395 end | |
| 396 end | |
| 397 end | |
| 398 for locale, t in pairs(localeDebug) do | |
| 399 if not next(t) then | |
| 400 DEFAULT_CHAT_FRAME:AddMessage(string.format("Locale %q complete", locale)) | |
| 401 else | |
| 402 DEFAULT_CHAT_FRAME:AddMessage(string.format("Locale %q missing:", locale)) | |
| 403 for word in pairs(t) do | |
| 404 DEFAULT_CHAT_FRAME:AddMessage(string.format(" %q", word)) | |
| 405 end | |
| 406 end | |
| 407 end | |
| 408 DEFAULT_CHAT_FRAME:AddMessage("--- End AceLocale Debug ---") | |
| 409 end | |
| 410 | |
| 411 setmetatable(AceLocale.prototype, { | |
| 412 __index = function(self, k) | |
| 413 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. | |
| 414 AceLocale.error(lastSelf or self, "Translation %q does not exist.", k) | |
| 415 end | |
| 416 return nil | |
| 417 end | |
| 418 }) | |
| 419 | |
| 420 local function activate(self, oldLib, oldDeactivate) | |
| 421 AceLocale = self | |
| 422 | |
| 423 if oldLib then | |
| 424 self.registry = oldLib.registry | |
| 425 self.__baseTranslations__ = oldLib.__baseTranslations__ | |
| 426 self.__debugging__ = oldLib.__debugging__ | |
| 427 self.__translations__ = oldLib.__translations__ | |
| 428 self.__baseLocale__ = oldLib.__baseLocale__ | |
| 429 self.__translationTables__ = oldLib.__translationTables__ | |
| 430 self.__reverseTranslations__ = oldLib.__reverseTranslations__ | |
| 431 self.__strictness__ = oldLib.__strictness__ | |
| 432 self.__name__ = oldLib.__name__ | |
| 433 end | |
| 434 if not self.__baseTranslations__ then | |
| 435 self.__baseTranslations__ = {} | |
| 436 end | |
| 437 if not self.__debugging__ then | |
| 438 self.__debugging__ = {} | |
| 439 end | |
| 440 if not self.__translations__ then | |
| 441 self.__translations__ = {} | |
| 442 end | |
| 443 if not self.__baseLocale__ then | |
| 444 self.__baseLocale__ = {} | |
| 445 end | |
| 446 if not self.__translationTables__ then | |
| 447 self.__translationTables__ = {} | |
| 448 end | |
| 449 if not self.__reverseTranslations__ then | |
| 450 self.__reverseTranslations__ = {} | |
| 451 end | |
| 452 if not self.__strictness__ then | |
| 453 self.__strictness__ = {} | |
| 454 end | |
| 455 if not self.__name__ then | |
| 456 self.__name__ = {} | |
| 457 end | |
| 458 | |
| 459 __baseTranslations__ = self.__baseTranslations__ | |
| 460 __debugging__ = self.__debugging__ | |
| 461 __translations__ = self.__translations__ | |
| 462 __baseLocale__ = self.__baseLocale__ | |
| 463 __translationTables__ = self.__translationTables__ | |
| 464 __reverseTranslations__ = self.__reverseTranslations__ | |
| 465 __strictness__ = self.__strictness__ | |
| 466 __name__ = self.__name__ | |
| 467 | |
| 468 if not self.registry then | |
| 469 self.registry = {} | |
| 470 else | |
| 471 for name, instance in pairs(self.registry) do | |
| 472 local name = name | |
| 473 local mt = getmetatable(instance) | |
| 474 setmetatable(instance, nil) | |
| 475 instance[__name__] = name | |
| 476 local strict | |
| 477 if instance.translations then | |
| 478 instance[__translations__], instance.translations = instance.translations | |
| 479 instance[__baseLocale__], instance.baseLocale = instance.baseLocale | |
| 480 instance[__baseTranslations__], instance.baseTranslations = instance.baseTranslations | |
| 481 instance[__debugging__], instance.debugging = instance.debugging | |
| 482 instance.reverseTranslations = nil | |
| 483 instance[__translationTables__], instance.translationTables = instance.translationTables | |
| 484 if mt and mt.__call == oldLib.prototype.GetTranslationStrict then | |
| 485 strict = true | |
| 486 end | |
| 487 else | |
| 488 if instance[__strictness__] ~= nil then | |
| 489 strict = instance[__strictness__] | |
| 490 elseif instance[__translations__] ~= instance[__baseTranslations__] then | |
| 491 if getmetatable(instance[__translations__]).__index == oldLib.prototype then | |
| 492 strict = true | |
| 493 end | |
| 494 end | |
| 495 end | |
| 496 instance[__strictness__] = strict and true or false | |
| 497 refixInstance(instance) | |
| 498 end | |
| 499 end | |
| 500 | |
| 501 if oldDeactivate then | |
| 502 oldDeactivate(oldLib) | |
| 503 end | |
| 504 end | |
| 505 | |
| 506 AceLibrary:Register(AceLocale, MAJOR_VERSION, MINOR_VERSION, activate) |
