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) |