vanilla-wow-addons – Blame information for rev 1

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