flickerstreak@1
|
1 --[[
|
flickerstreak@1
|
2 Name: AceLocale-2.2
|
flickerstreak@22
|
3 Revision: $Rev: 40629 $
|
flickerstreak@1
|
4 Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team)
|
flickerstreak@1
|
5 Inspired By: Ace 1.x by Turan (turan@gryphon.com)
|
flickerstreak@1
|
6 Website: http://www.wowace.com/
|
flickerstreak@1
|
7 Documentation: http://www.wowace.com/index.php/AceLocale-2.2
|
flickerstreak@1
|
8 SVN: http://svn.wowace.com/root/trunk/Ace2/AceLocale-2.2
|
flickerstreak@1
|
9 Description: Localization library for addons to use to handle proper
|
flickerstreak@1
|
10 localization and internationalization.
|
flickerstreak@1
|
11 Dependencies: AceLibrary
|
flickerstreak@7
|
12 License: LGPL v2.1
|
flickerstreak@1
|
13 ]]
|
flickerstreak@1
|
14
|
flickerstreak@1
|
15 local MAJOR_VERSION = "AceLocale-2.2"
|
flickerstreak@22
|
16 local MINOR_VERSION = "$Revision: 40629 $"
|
flickerstreak@1
|
17
|
flickerstreak@1
|
18 if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary.") end
|
flickerstreak@1
|
19 if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
|
flickerstreak@1
|
20
|
flickerstreak@1
|
21 local AceLocale = {}
|
flickerstreak@22
|
22 AceLocale.prototype = { class = AceLocale }
|
flickerstreak@1
|
23
|
flickerstreak@1
|
24 local BASE_TRANSLATIONS, DEBUGGING, TRANSLATIONS, BASE_LOCALE, TRANSLATION_TABLES, REVERSE_TRANSLATIONS, STRICTNESS, DYNAMIC_LOCALES, CURRENT_LOCALE, NAME
|
flickerstreak@1
|
25
|
flickerstreak@22
|
26 local _G = _G
|
flickerstreak@1
|
27 local rawget = rawget
|
flickerstreak@1
|
28 local rawset = rawset
|
flickerstreak@1
|
29 local type = type
|
flickerstreak@22
|
30 local pairs = pairs
|
flickerstreak@22
|
31 local next = next
|
flickerstreak@22
|
32 local getmetatable = getmetatable
|
flickerstreak@22
|
33 local setmetatable = setmetatable
|
flickerstreak@22
|
34 local GetTime = GetTime
|
flickerstreak@22
|
35 local geterrorhandler = geterrorhandler
|
flickerstreak@22
|
36 local pcall = pcall
|
flickerstreak@22
|
37 local ipairs = ipairs
|
flickerstreak@22
|
38 local GetLocale = GetLocale
|
flickerstreak@1
|
39
|
flickerstreak@1
|
40 local newRegistries = {}
|
flickerstreak@1
|
41 local scheduleClear
|
flickerstreak@1
|
42
|
flickerstreak@1
|
43 local lastSelf
|
flickerstreak@22
|
44 local strict__index = function(self, key)
|
flickerstreak@1
|
45 lastSelf = self
|
flickerstreak@1
|
46 local value = (rawget(self, TRANSLATIONS) or AceLocale.prototype)[key]
|
flickerstreak@1
|
47 rawset(self, key, value)
|
flickerstreak@1
|
48 return value
|
flickerstreak@1
|
49 end
|
flickerstreak@22
|
50 local nonstrict__index = function(self, key)
|
flickerstreak@22
|
51 lastSelf = self
|
flickerstreak@22
|
52 local t = rawget(self, TRANSLATIONS)
|
flickerstreak@22
|
53 if t then
|
flickerstreak@22
|
54 local value = rawget(t, key)
|
flickerstreak@22
|
55 if value then
|
flickerstreak@22
|
56 rawset(self, key, value)
|
flickerstreak@22
|
57 return value
|
flickerstreak@22
|
58 end
|
flickerstreak@22
|
59 end
|
flickerstreak@22
|
60 local value = (rawget(self, BASE_TRANSLATIONS) or AceLocale.prototype)[key]
|
flickerstreak@22
|
61 rawset(self, key, value)
|
flickerstreak@22
|
62 return value
|
flickerstreak@22
|
63 end
|
flickerstreak@1
|
64
|
flickerstreak@1
|
65 local __newindex = function(self, k, v)
|
flickerstreak@1
|
66 if type(v) ~= "function" and type(k) ~= "table" then
|
flickerstreak@1
|
67 AceLocale.error(self, "Cannot change the values of an AceLocale instance.")
|
flickerstreak@1
|
68 end
|
flickerstreak@1
|
69 rawset(self, k, v)
|
flickerstreak@1
|
70 end
|
flickerstreak@1
|
71
|
flickerstreak@1
|
72 local __tostring = function(self)
|
flickerstreak@1
|
73 if type(rawget(self, 'GetLibraryVersion')) == "function" then
|
flickerstreak@1
|
74 return self:GetLibraryVersion()
|
flickerstreak@1
|
75 else
|
flickerstreak@1
|
76 return "AceLocale(" .. self[NAME] .. ")"
|
flickerstreak@1
|
77 end
|
flickerstreak@1
|
78 end
|
flickerstreak@1
|
79
|
flickerstreak@1
|
80 local function clearCache(self)
|
flickerstreak@22
|
81 for k, v in pairs(AceLocale.prototype) do
|
flickerstreak@22
|
82 if type(v) == "function" and type(rawget(self, k)) == "function" then
|
flickerstreak@22
|
83 self[k] = nil
|
flickerstreak@22
|
84 end
|
flickerstreak@22
|
85 end
|
flickerstreak@1
|
86 if not rawget(self, BASE_TRANSLATIONS) then
|
flickerstreak@1
|
87 return
|
flickerstreak@1
|
88 end
|
flickerstreak@1
|
89
|
flickerstreak@1
|
90 local cache = self[BASE_TRANSLATIONS]
|
flickerstreak@1
|
91 rawset(self, REVERSE_TRANSLATIONS, nil)
|
flickerstreak@1
|
92
|
flickerstreak@1
|
93 for k in pairs(self) do
|
flickerstreak@1
|
94 if rawget(cache, k) ~= nil then
|
flickerstreak@1
|
95 self[k] = nil
|
flickerstreak@1
|
96 end
|
flickerstreak@1
|
97 end
|
flickerstreak@1
|
98 rawset(self, 'tmp', true)
|
flickerstreak@1
|
99 self.tmp = nil
|
flickerstreak@1
|
100 end
|
flickerstreak@1
|
101
|
flickerstreak@22
|
102 local strict_instance_mt, nonstrict_instance_mt
|
flickerstreak@22
|
103 local baseTranslations_mt
|
flickerstreak@22
|
104
|
flickerstreak@1
|
105 local function refixInstance(instance)
|
flickerstreak@1
|
106 if getmetatable(instance) then
|
flickerstreak@1
|
107 setmetatable(instance, nil)
|
flickerstreak@1
|
108 end
|
flickerstreak@1
|
109 local translations = instance[TRANSLATIONS]
|
flickerstreak@1
|
110 if translations then
|
flickerstreak@1
|
111 if getmetatable(translations) then
|
flickerstreak@1
|
112 setmetatable(translations, nil)
|
flickerstreak@1
|
113 end
|
flickerstreak@1
|
114 local baseTranslations = instance[BASE_TRANSLATIONS]
|
flickerstreak@1
|
115 if getmetatable(baseTranslations) then
|
flickerstreak@1
|
116 setmetatable(baseTranslations, nil)
|
flickerstreak@1
|
117 end
|
flickerstreak@1
|
118 if translations == baseTranslations or instance[STRICTNESS] then
|
flickerstreak@22
|
119 setmetatable(instance, strict_instance_mt)
|
flickerstreak@1
|
120
|
flickerstreak@22
|
121 setmetatable(translations, baseTranslations_mt)
|
flickerstreak@1
|
122 else
|
flickerstreak@22
|
123 setmetatable(instance, nonstrict_instance_mt)
|
flickerstreak@1
|
124
|
flickerstreak@22
|
125 setmetatable(baseTranslations, baseTranslations_mt)
|
flickerstreak@1
|
126 end
|
flickerstreak@1
|
127 else
|
flickerstreak@22
|
128 setmetatable(instance, strict_instance_mt)
|
flickerstreak@1
|
129 end
|
flickerstreak@1
|
130 clearCache(instance)
|
flickerstreak@1
|
131 newRegistries[instance] = true
|
flickerstreak@1
|
132 scheduleClear()
|
flickerstreak@1
|
133 return instance
|
flickerstreak@1
|
134 end
|
flickerstreak@1
|
135
|
flickerstreak@1
|
136 function AceLocale:new(name)
|
flickerstreak@1
|
137 self:argCheck(name, 2, "string")
|
flickerstreak@1
|
138
|
flickerstreak@1
|
139 if self.registry[name] and type(rawget(self.registry[name], 'GetLibraryVersion')) ~= "function" then
|
flickerstreak@1
|
140 return self.registry[name]
|
flickerstreak@1
|
141 end
|
flickerstreak@1
|
142
|
flickerstreak@1
|
143 AceLocale.registry[name] = refixInstance({
|
flickerstreak@1
|
144 [STRICTNESS] = false,
|
flickerstreak@1
|
145 [NAME] = name,
|
flickerstreak@1
|
146 })
|
flickerstreak@1
|
147 newRegistries[AceLocale.registry[name]] = true
|
flickerstreak@1
|
148 return AceLocale.registry[name]
|
flickerstreak@1
|
149 end
|
flickerstreak@1
|
150
|
flickerstreak@1
|
151 function AceLocale.prototype:EnableDebugging()
|
flickerstreak@1
|
152 if rawget(self, BASE_TRANSLATIONS) then
|
flickerstreak@1
|
153 AceLocale.error(self, "Cannot enable debugging after a translation has been registered.")
|
flickerstreak@1
|
154 end
|
flickerstreak@1
|
155 rawset(self, DEBUGGING, true)
|
flickerstreak@1
|
156 end
|
flickerstreak@1
|
157
|
flickerstreak@1
|
158 function AceLocale.prototype:EnableDynamicLocales(override)
|
flickerstreak@1
|
159 AceLocale.argCheck(self, override, 2, "boolean", "nil")
|
flickerstreak@1
|
160 if not override and rawget(self, BASE_TRANSLATIONS) then
|
flickerstreak@1
|
161 AceLocale.error(self, "Cannot enable dynamic locales after a translation has been registered.")
|
flickerstreak@1
|
162 end
|
flickerstreak@1
|
163 if not rawget(self, DYNAMIC_LOCALES) then
|
flickerstreak@1
|
164 rawset(self, DYNAMIC_LOCALES, true)
|
flickerstreak@1
|
165 if rawget(self, BASE_LOCALE) then
|
flickerstreak@1
|
166 if not rawget(self, TRANSLATION_TABLES) then
|
flickerstreak@1
|
167 rawset(self, TRANSLATION_TABLES, {})
|
flickerstreak@1
|
168 end
|
flickerstreak@1
|
169 self[TRANSLATION_TABLES][self[BASE_LOCALE]] = self[BASE_TRANSLATIONS]
|
flickerstreak@1
|
170 self[TRANSLATION_TABLES][self[CURRENT_LOCALE]] = self[TRANSLATIONS]
|
flickerstreak@1
|
171 end
|
flickerstreak@1
|
172 end
|
flickerstreak@1
|
173 end
|
flickerstreak@1
|
174
|
flickerstreak@1
|
175 function AceLocale.prototype:RegisterTranslations(locale, func)
|
flickerstreak@1
|
176 AceLocale.argCheck(self, locale, 2, "string")
|
flickerstreak@1
|
177 AceLocale.argCheck(self, func, 3, "function")
|
flickerstreak@1
|
178
|
flickerstreak@1
|
179 if locale == rawget(self, BASE_LOCALE) then
|
flickerstreak@1
|
180 AceLocale.error(self, "Cannot provide the same locale more than once. %q provided twice.", locale)
|
flickerstreak@1
|
181 end
|
flickerstreak@1
|
182
|
flickerstreak@1
|
183 if rawget(self, BASE_TRANSLATIONS) and GetLocale() ~= locale then
|
flickerstreak@1
|
184 if rawget(self, DEBUGGING) or rawget(self, DYNAMIC_LOCALES) then
|
flickerstreak@1
|
185 if not rawget(self, TRANSLATION_TABLES) then
|
flickerstreak@1
|
186 rawset(self, TRANSLATION_TABLES, {})
|
flickerstreak@1
|
187 end
|
flickerstreak@1
|
188 if self[TRANSLATION_TABLES][locale] then
|
flickerstreak@1
|
189 AceLocale.error(self, "Cannot provide the same locale more than once. %q provided twice.", locale)
|
flickerstreak@1
|
190 end
|
flickerstreak@1
|
191 local t = func()
|
flickerstreak@1
|
192 func = nil
|
flickerstreak@1
|
193 if type(t) ~= "table" then
|
flickerstreak@1
|
194 AceLocale.error(self, "Bad argument #3 to `RegisterTranslations'. function did not return a table. (expected table, got %s)", type(t))
|
flickerstreak@1
|
195 end
|
flickerstreak@1
|
196 self[TRANSLATION_TABLES][locale] = t
|
flickerstreak@1
|
197 t = nil
|
flickerstreak@1
|
198 end
|
flickerstreak@1
|
199 func = nil
|
flickerstreak@1
|
200 return
|
flickerstreak@1
|
201 end
|
flickerstreak@1
|
202 local t = func()
|
flickerstreak@1
|
203 func = nil
|
flickerstreak@1
|
204 if type(t) ~= "table" then
|
flickerstreak@1
|
205 AceLocale.error(self, "Bad argument #3 to `RegisterTranslations'. function did not return a table. (expected table, got %s)", type(t))
|
flickerstreak@1
|
206 end
|
flickerstreak@1
|
207
|
flickerstreak@1
|
208 rawset(self, TRANSLATIONS, t)
|
flickerstreak@1
|
209 if not rawget(self, BASE_TRANSLATIONS) then
|
flickerstreak@1
|
210 rawset(self, BASE_TRANSLATIONS, t)
|
flickerstreak@1
|
211 rawset(self, BASE_LOCALE, locale)
|
flickerstreak@1
|
212 for key,value in pairs(t) do
|
flickerstreak@1
|
213 if value == true then
|
flickerstreak@1
|
214 t[key] = key
|
flickerstreak@1
|
215 end
|
flickerstreak@1
|
216 end
|
flickerstreak@1
|
217 else
|
flickerstreak@1
|
218 for key, value in pairs(self[TRANSLATIONS]) do
|
flickerstreak@1
|
219 if not rawget(self[BASE_TRANSLATIONS], key) then
|
flickerstreak@1
|
220 AceLocale.error(self, "Improper translation exists. %q is likely misspelled for locale %s.", key, locale)
|
flickerstreak@1
|
221 end
|
flickerstreak@1
|
222 if value == true then
|
flickerstreak@1
|
223 AceLocale.error(self, "Can only accept true as a value on the base locale. %q is the base locale, %q is not.", rawget(self, BASE_LOCALE), locale)
|
flickerstreak@1
|
224 end
|
flickerstreak@1
|
225 end
|
flickerstreak@1
|
226 end
|
flickerstreak@1
|
227 rawset(self, CURRENT_LOCALE, locale)
|
flickerstreak@7
|
228 if not rawget(self, 'reverse') then
|
flickerstreak@7
|
229 rawset(self, 'reverse', setmetatable({}, { __index = function(self2, key)
|
flickerstreak@7
|
230 local self = AceLocale.reverseToBase[self2]
|
flickerstreak@7
|
231 if not rawget(self, REVERSE_TRANSLATIONS) then
|
flickerstreak@7
|
232 self:GetReverseTranslation(key)
|
flickerstreak@7
|
233 end
|
flickerstreak@7
|
234 self.reverse = self[REVERSE_TRANSLATIONS]
|
flickerstreak@7
|
235 return self.reverse[key]
|
flickerstreak@7
|
236 end }))
|
flickerstreak@7
|
237 AceLocale.reverseToBase[self.reverse] = self
|
flickerstreak@7
|
238 end
|
flickerstreak@1
|
239 refixInstance(self)
|
flickerstreak@1
|
240 if rawget(self, DEBUGGING) or rawget(self, DYNAMIC_LOCALES) then
|
flickerstreak@1
|
241 if not rawget(self, TRANSLATION_TABLES) then
|
flickerstreak@1
|
242 rawset(self, TRANSLATION_TABLES, {})
|
flickerstreak@1
|
243 end
|
flickerstreak@1
|
244 self[TRANSLATION_TABLES][locale] = t
|
flickerstreak@1
|
245 end
|
flickerstreak@1
|
246 t = nil
|
flickerstreak@1
|
247 end
|
flickerstreak@1
|
248
|
flickerstreak@1
|
249 function AceLocale.prototype:SetLocale(locale)
|
flickerstreak@1
|
250 AceLocale.argCheck(self, locale, 2, "string", "boolean")
|
flickerstreak@1
|
251 if not rawget(self, DYNAMIC_LOCALES) then
|
flickerstreak@1
|
252 AceLocale.error(self, "Cannot call `SetLocale' without first calling `EnableDynamicLocales'.")
|
flickerstreak@1
|
253 end
|
flickerstreak@1
|
254 if not rawget(self, TRANSLATION_TABLES) then
|
flickerstreak@1
|
255 AceLocale.error(self, "Cannot call `SetLocale' without first calling `RegisterTranslations'.")
|
flickerstreak@1
|
256 end
|
flickerstreak@1
|
257 if locale == true then
|
flickerstreak@1
|
258 locale = GetLocale()
|
flickerstreak@1
|
259 if not self[TRANSLATION_TABLES][locale] then
|
flickerstreak@1
|
260 locale = self[BASE_LOCALE]
|
flickerstreak@1
|
261 end
|
flickerstreak@1
|
262 end
|
flickerstreak@1
|
263
|
flickerstreak@1
|
264 if self[CURRENT_LOCALE] == locale then
|
flickerstreak@1
|
265 return
|
flickerstreak@1
|
266 end
|
flickerstreak@1
|
267
|
flickerstreak@1
|
268 if not self[TRANSLATION_TABLES][locale] then
|
flickerstreak@1
|
269 AceLocale.error(self, "Locale %q not registered.", locale)
|
flickerstreak@1
|
270 end
|
flickerstreak@1
|
271
|
flickerstreak@1
|
272 self[TRANSLATIONS] = self[TRANSLATION_TABLES][locale]
|
flickerstreak@1
|
273 self[CURRENT_LOCALE] = locale
|
flickerstreak@1
|
274 refixInstance(self)
|
flickerstreak@1
|
275 end
|
flickerstreak@1
|
276
|
flickerstreak@1
|
277 function AceLocale.prototype:GetLocale()
|
flickerstreak@1
|
278 if not rawget(self, TRANSLATION_TABLES) then
|
flickerstreak@1
|
279 AceLocale.error(self, "Cannot call `GetLocale' without first calling `RegisterTranslations'.")
|
flickerstreak@1
|
280 end
|
flickerstreak@1
|
281 return self[CURRENT_LOCALE]
|
flickerstreak@1
|
282 end
|
flickerstreak@1
|
283
|
flickerstreak@1
|
284 local function iter(t, position)
|
flickerstreak@1
|
285 return (next(t, position))
|
flickerstreak@1
|
286 end
|
flickerstreak@1
|
287
|
flickerstreak@1
|
288 function AceLocale.prototype:IterateAvailableLocales()
|
flickerstreak@1
|
289 if not rawget(self, DYNAMIC_LOCALES) then
|
flickerstreak@1
|
290 AceLocale.error(self, "Cannot call `IterateAvailableLocales' without first calling `EnableDynamicLocales'.")
|
flickerstreak@1
|
291 end
|
flickerstreak@1
|
292 if not rawget(self, TRANSLATION_TABLES) then
|
flickerstreak@1
|
293 AceLocale.error(self, "Cannot call `IterateAvailableLocales' without first calling `RegisterTranslations'.")
|
flickerstreak@1
|
294 end
|
flickerstreak@1
|
295 return iter, self[TRANSLATION_TABLES], nil
|
flickerstreak@1
|
296 end
|
flickerstreak@1
|
297
|
flickerstreak@1
|
298 function AceLocale.prototype:HasLocale(locale)
|
flickerstreak@1
|
299 if not rawget(self, DYNAMIC_LOCALES) then
|
flickerstreak@1
|
300 AceLocale.error(self, "Cannot call `HasLocale' without first calling `EnableDynamicLocales'.")
|
flickerstreak@1
|
301 end
|
flickerstreak@1
|
302 AceLocale.argCheck(self, locale, 2, "string")
|
flickerstreak@1
|
303 return rawget(self, TRANSLATION_TABLES) and self[TRANSLATION_TABLES][locale] ~= nil
|
flickerstreak@1
|
304 end
|
flickerstreak@1
|
305
|
flickerstreak@1
|
306 function AceLocale.prototype:SetStrictness(strict)
|
flickerstreak@1
|
307 AceLocale.argCheck(self, strict, 2, "boolean")
|
flickerstreak@1
|
308 local mt = getmetatable(self)
|
flickerstreak@1
|
309 if not mt then
|
flickerstreak@1
|
310 AceLocale.error(self, "Cannot call `SetStrictness' without a metatable.")
|
flickerstreak@1
|
311 end
|
flickerstreak@1
|
312 if not rawget(self, TRANSLATIONS) then
|
flickerstreak@1
|
313 AceLocale.error(self, "No translations registered.")
|
flickerstreak@1
|
314 end
|
flickerstreak@1
|
315 rawset(self, STRICTNESS, strict)
|
flickerstreak@1
|
316 refixInstance(self)
|
flickerstreak@1
|
317 end
|
flickerstreak@1
|
318
|
flickerstreak@1
|
319 local function initReverse(self)
|
flickerstreak@7
|
320 rawset(self, REVERSE_TRANSLATIONS, setmetatable({}, { __index = function(_, key)
|
flickerstreak@7
|
321 AceLocale.error(self, "Reverse translation for %q does not exist", key)
|
flickerstreak@7
|
322 end }))
|
flickerstreak@1
|
323 local alpha = self[TRANSLATIONS]
|
flickerstreak@1
|
324 local bravo = self[REVERSE_TRANSLATIONS]
|
flickerstreak@1
|
325 for base, localized in pairs(alpha) do
|
flickerstreak@1
|
326 bravo[localized] = base
|
flickerstreak@1
|
327 end
|
flickerstreak@1
|
328 end
|
flickerstreak@1
|
329
|
flickerstreak@1
|
330 function AceLocale.prototype:GetTranslation(text)
|
flickerstreak@1
|
331 AceLocale.argCheck(self, text, 1, "string", "number")
|
flickerstreak@1
|
332 if not rawget(self, TRANSLATIONS) then
|
flickerstreak@1
|
333 AceLocale.error(self, "No translations registered")
|
flickerstreak@1
|
334 end
|
flickerstreak@1
|
335 return self[text]
|
flickerstreak@1
|
336 end
|
flickerstreak@1
|
337
|
flickerstreak@1
|
338 function AceLocale.prototype:GetStrictTranslation(text)
|
flickerstreak@1
|
339 AceLocale.argCheck(self, text, 1, "string", "number")
|
flickerstreak@1
|
340 local x = rawget(self, TRANSLATIONS)
|
flickerstreak@1
|
341 if not x then
|
flickerstreak@1
|
342 AceLocale.error(self, "No translations registered")
|
flickerstreak@1
|
343 end
|
flickerstreak@1
|
344 local value = rawget(x, text)
|
flickerstreak@1
|
345 if value == nil then
|
flickerstreak@22
|
346 local _, ret = pcall(AceLocale.error, self, "Translation %q does not exist for locale %s", text, self[CURRENT_LOCALE])
|
flickerstreak@22
|
347 geterrorhandler()(ret)
|
flickerstreak@22
|
348 return text
|
flickerstreak@1
|
349 end
|
flickerstreak@1
|
350 return value
|
flickerstreak@1
|
351 end
|
flickerstreak@1
|
352
|
flickerstreak@1
|
353 function AceLocale.prototype:GetReverseTranslation(text)
|
flickerstreak@1
|
354 local x = rawget(self, REVERSE_TRANSLATIONS)
|
flickerstreak@1
|
355 if not x then
|
flickerstreak@1
|
356 if not rawget(self, TRANSLATIONS) then
|
flickerstreak@1
|
357 AceLocale.error(self, "No translations registered")
|
flickerstreak@1
|
358 end
|
flickerstreak@1
|
359 initReverse(self)
|
flickerstreak@1
|
360 x = self[REVERSE_TRANSLATIONS]
|
flickerstreak@1
|
361 end
|
flickerstreak@1
|
362 local translation = x[text]
|
flickerstreak@1
|
363 if not translation then
|
flickerstreak@22
|
364 local _, ret = pcall(AceLocale.error, self, "Reverse translation for %q does not exist", text)
|
flickerstreak@22
|
365 geterrorhandler()(ret)
|
flickerstreak@22
|
366 return text
|
flickerstreak@1
|
367 end
|
flickerstreak@1
|
368 return translation
|
flickerstreak@1
|
369 end
|
flickerstreak@1
|
370
|
flickerstreak@1
|
371 function AceLocale.prototype:GetIterator()
|
flickerstreak@1
|
372 local x = rawget(self, TRANSLATIONS)
|
flickerstreak@1
|
373 if not x then
|
flickerstreak@1
|
374 AceLocale.error(self, "No translations registered")
|
flickerstreak@1
|
375 end
|
flickerstreak@1
|
376 return next, x, nil
|
flickerstreak@1
|
377 end
|
flickerstreak@1
|
378
|
flickerstreak@1
|
379 function AceLocale.prototype:GetReverseIterator()
|
flickerstreak@1
|
380 local x = rawget(self, REVERSE_TRANSLATIONS)
|
flickerstreak@1
|
381 if not x then
|
flickerstreak@1
|
382 if not rawget(self, TRANSLATIONS) then
|
flickerstreak@1
|
383 AceLocale.error(self, "No translations registered")
|
flickerstreak@1
|
384 end
|
flickerstreak@1
|
385 initReverse(self)
|
flickerstreak@1
|
386 x = self[REVERSE_TRANSLATIONS]
|
flickerstreak@1
|
387 end
|
flickerstreak@1
|
388 return next, x, nil
|
flickerstreak@1
|
389 end
|
flickerstreak@1
|
390
|
flickerstreak@1
|
391 function AceLocale.prototype:HasTranslation(text)
|
flickerstreak@1
|
392 AceLocale.argCheck(self, text, 1, "string", "number")
|
flickerstreak@1
|
393 local x = rawget(self, TRANSLATIONS)
|
flickerstreak@1
|
394 if not x then
|
flickerstreak@1
|
395 AceLocale.error(self, "No translations registered")
|
flickerstreak@1
|
396 end
|
flickerstreak@1
|
397 return rawget(x, text) and true
|
flickerstreak@1
|
398 end
|
flickerstreak@1
|
399
|
flickerstreak@22
|
400 function AceLocale.prototype:HasBaseTranslation(text)
|
flickerstreak@22
|
401 AceLocale.argCheck(self, text, 1, "string", "number")
|
flickerstreak@22
|
402 local x = rawget(self, BASE_TRANSLATIONS)
|
flickerstreak@22
|
403 if not x then
|
flickerstreak@22
|
404 AceLocale.error(self, "No translations registered")
|
flickerstreak@22
|
405 end
|
flickerstreak@22
|
406 return rawget(x, text) and true
|
flickerstreak@22
|
407 end
|
flickerstreak@22
|
408
|
flickerstreak@1
|
409 function AceLocale.prototype:HasReverseTranslation(text)
|
flickerstreak@1
|
410 local x = rawget(self, REVERSE_TRANSLATIONS)
|
flickerstreak@1
|
411 if not x then
|
flickerstreak@1
|
412 if not rawget(self, TRANSLATIONS) then
|
flickerstreak@1
|
413 AceLocale.error(self, "No translations registered")
|
flickerstreak@1
|
414 end
|
flickerstreak@1
|
415 initReverse(self)
|
flickerstreak@1
|
416 x = self[REVERSE_TRANSLATIONS]
|
flickerstreak@1
|
417 end
|
flickerstreak@7
|
418 return rawget(x, text) and true
|
flickerstreak@1
|
419 end
|
flickerstreak@1
|
420
|
flickerstreak@1
|
421 function AceLocale.prototype:Debug()
|
flickerstreak@1
|
422 if not rawget(self, DEBUGGING) then
|
flickerstreak@1
|
423 return
|
flickerstreak@1
|
424 end
|
flickerstreak@1
|
425 local words = {}
|
flickerstreak@1
|
426 local locales = {"enUS", "deDE", "frFR", "koKR", "zhCN", "zhTW", "esES"}
|
flickerstreak@1
|
427 local localizations = {}
|
flickerstreak@1
|
428 DEFAULT_CHAT_FRAME:AddMessage("--- AceLocale Debug ---")
|
flickerstreak@1
|
429 for _,locale in ipairs(locales) do
|
flickerstreak@1
|
430 if not self[TRANSLATION_TABLES][locale] then
|
flickerstreak@7
|
431 DEFAULT_CHAT_FRAME:AddMessage(("Locale %q not found"):format(locale))
|
flickerstreak@1
|
432 else
|
flickerstreak@1
|
433 localizations[locale] = self[TRANSLATION_TABLES][locale]
|
flickerstreak@1
|
434 end
|
flickerstreak@1
|
435 end
|
flickerstreak@1
|
436 local localeDebug = {}
|
flickerstreak@1
|
437 for locale, localization in pairs(localizations) do
|
flickerstreak@1
|
438 localeDebug[locale] = {}
|
flickerstreak@1
|
439 for word in pairs(localization) do
|
flickerstreak@1
|
440 if type(localization[word]) == "table" then
|
flickerstreak@1
|
441 if type(words[word]) ~= "table" then
|
flickerstreak@1
|
442 words[word] = {}
|
flickerstreak@1
|
443 end
|
flickerstreak@1
|
444 for bit in pairs(localization[word]) do
|
flickerstreak@1
|
445 if type(localization[word][bit]) == "string" then
|
flickerstreak@1
|
446 words[word][bit] = true
|
flickerstreak@1
|
447 end
|
flickerstreak@1
|
448 end
|
flickerstreak@1
|
449 elseif type(localization[word]) == "string" then
|
flickerstreak@1
|
450 words[word] = true
|
flickerstreak@1
|
451 end
|
flickerstreak@1
|
452 end
|
flickerstreak@1
|
453 end
|
flickerstreak@1
|
454 for word in pairs(words) do
|
flickerstreak@1
|
455 if type(words[word]) == "table" then
|
flickerstreak@1
|
456 for bit in pairs(words[word]) do
|
flickerstreak@1
|
457 for locale, localization in pairs(localizations) do
|
flickerstreak@1
|
458 if not rawget(localization, word) or not localization[word][bit] then
|
flickerstreak@1
|
459 localeDebug[locale][word .. "::" .. bit] = true
|
flickerstreak@1
|
460 end
|
flickerstreak@1
|
461 end
|
flickerstreak@1
|
462 end
|
flickerstreak@1
|
463 else
|
flickerstreak@1
|
464 for locale, localization in pairs(localizations) do
|
flickerstreak@1
|
465 if not rawget(localization, word) then
|
flickerstreak@1
|
466 localeDebug[locale][word] = true
|
flickerstreak@1
|
467 end
|
flickerstreak@1
|
468 end
|
flickerstreak@1
|
469 end
|
flickerstreak@1
|
470 end
|
flickerstreak@1
|
471 for locale, t in pairs(localeDebug) do
|
flickerstreak@1
|
472 if not next(t) then
|
flickerstreak@7
|
473 DEFAULT_CHAT_FRAME:AddMessage(("Locale %q complete"):format(locale))
|
flickerstreak@1
|
474 else
|
flickerstreak@7
|
475 DEFAULT_CHAT_FRAME:AddMessage(("Locale %q missing:"):format(locale))
|
flickerstreak@1
|
476 for word in pairs(t) do
|
flickerstreak@7
|
477 DEFAULT_CHAT_FRAME:AddMessage((" %q"):format(word))
|
flickerstreak@1
|
478 end
|
flickerstreak@1
|
479 end
|
flickerstreak@1
|
480 end
|
flickerstreak@1
|
481 DEFAULT_CHAT_FRAME:AddMessage("--- End AceLocale Debug ---")
|
flickerstreak@1
|
482 end
|
flickerstreak@1
|
483
|
flickerstreak@1
|
484 setmetatable(AceLocale.prototype, {
|
flickerstreak@1
|
485 __index = function(self, k)
|
flickerstreak@1
|
486 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.
|
flickerstreak@22
|
487 local _, ret = pcall(AceLocale.error, lastSelf or self, "Translation %q does not exist.", k)
|
flickerstreak@22
|
488 geterrorhandler()(ret)
|
flickerstreak@22
|
489 return k
|
flickerstreak@1
|
490 end
|
flickerstreak@1
|
491 return nil
|
flickerstreak@1
|
492 end
|
flickerstreak@1
|
493 })
|
flickerstreak@1
|
494
|
flickerstreak@1
|
495 local function activate(self, oldLib, oldDeactivate)
|
flickerstreak@1
|
496 AceLocale = self
|
flickerstreak@1
|
497
|
flickerstreak@1
|
498 self.frame = oldLib and oldLib.frame or CreateFrame("Frame")
|
flickerstreak@1
|
499 self.registry = oldLib and oldLib.registry or {}
|
flickerstreak@1
|
500 self.BASE_TRANSLATIONS = oldLib and oldLib.BASE_TRANSLATIONS or {}
|
flickerstreak@1
|
501 self.DEBUGGING = oldLib and oldLib.DEBUGGING or {}
|
flickerstreak@1
|
502 self.TRANSLATIONS = oldLib and oldLib.TRANSLATIONS or {}
|
flickerstreak@1
|
503 self.BASE_LOCALE = oldLib and oldLib.BASE_LOCALE or {}
|
flickerstreak@1
|
504 self.TRANSLATION_TABLES = oldLib and oldLib.TRANSLATION_TABLES or {}
|
flickerstreak@1
|
505 self.REVERSE_TRANSLATIONS = oldLib and oldLib.REVERSE_TRANSLATIONS or {}
|
flickerstreak@1
|
506 self.STRICTNESS = oldLib and oldLib.STRICTNESS or {}
|
flickerstreak@1
|
507 self.NAME = oldLib and oldLib.NAME or {}
|
flickerstreak@1
|
508 self.DYNAMIC_LOCALES = oldLib and oldLib.DYNAMIC_LOCALES or {}
|
flickerstreak@1
|
509 self.CURRENT_LOCALE = oldLib and oldLib.CURRENT_LOCALE or {}
|
flickerstreak@7
|
510 self.reverseToBase = oldLib and oldLib.reverseToBase or {}
|
flickerstreak@1
|
511
|
flickerstreak@1
|
512 BASE_TRANSLATIONS = self.BASE_TRANSLATIONS
|
flickerstreak@1
|
513 DEBUGGING = self.DEBUGGING
|
flickerstreak@1
|
514 TRANSLATIONS = self.TRANSLATIONS
|
flickerstreak@1
|
515 BASE_LOCALE = self.BASE_LOCALE
|
flickerstreak@1
|
516 TRANSLATION_TABLES = self.TRANSLATION_TABLES
|
flickerstreak@1
|
517 REVERSE_TRANSLATIONS = self.REVERSE_TRANSLATIONS
|
flickerstreak@1
|
518 STRICTNESS = self.STRICTNESS
|
flickerstreak@1
|
519 NAME = self.NAME
|
flickerstreak@1
|
520 DYNAMIC_LOCALES = self.DYNAMIC_LOCALES
|
flickerstreak@1
|
521 CURRENT_LOCALE = self.CURRENT_LOCALE
|
flickerstreak@1
|
522
|
flickerstreak@22
|
523 strict_instance_mt = {
|
flickerstreak@22
|
524 __index = strict__index,
|
flickerstreak@22
|
525 __newindex = __newindex,
|
flickerstreak@22
|
526 __tostring = __tostring
|
flickerstreak@22
|
527 }
|
flickerstreak@22
|
528
|
flickerstreak@22
|
529 nonstrict_instance_mt = {
|
flickerstreak@22
|
530 __index = nonstrict__index,
|
flickerstreak@22
|
531 __newindex = __newindex,
|
flickerstreak@22
|
532 __tostring = __tostring
|
flickerstreak@22
|
533 }
|
flickerstreak@22
|
534
|
flickerstreak@22
|
535 baseTranslations_mt = {
|
flickerstreak@22
|
536 __index = AceLocale.prototype
|
flickerstreak@22
|
537 }
|
flickerstreak@1
|
538
|
flickerstreak@1
|
539 local GetTime = GetTime
|
flickerstreak@1
|
540 local timeUntilClear = GetTime() + 5
|
flickerstreak@1
|
541 scheduleClear = function()
|
flickerstreak@1
|
542 if next(newRegistries) then
|
flickerstreak@1
|
543 self.frame:Show()
|
flickerstreak@1
|
544 timeUntilClear = GetTime() + 5
|
flickerstreak@1
|
545 end
|
flickerstreak@1
|
546 end
|
flickerstreak@1
|
547
|
flickerstreak@22
|
548 for name, instance in pairs(self.registry) do
|
flickerstreak@22
|
549 local name = name
|
flickerstreak@22
|
550 setmetatable(instance, nil)
|
flickerstreak@22
|
551 instance[NAME] = name
|
flickerstreak@22
|
552 local strict
|
flickerstreak@22
|
553 if instance[STRICTNESS] ~= nil then
|
flickerstreak@22
|
554 strict = instance[STRICTNESS]
|
flickerstreak@22
|
555 elseif instance[TRANSLATIONS] ~= instance[BASE_TRANSLATIONS] then
|
flickerstreak@22
|
556 if getmetatable(instance[TRANSLATIONS]).__index == oldLib.prototype then
|
flickerstreak@22
|
557 strict = true
|
flickerstreak@1
|
558 end
|
flickerstreak@1
|
559 end
|
flickerstreak@22
|
560 instance[STRICTNESS] = strict and true or false
|
flickerstreak@22
|
561 refixInstance(instance)
|
flickerstreak@1
|
562 end
|
flickerstreak@1
|
563
|
flickerstreak@1
|
564 self.frame:SetScript("OnEvent", scheduleClear)
|
flickerstreak@1
|
565 self.frame:SetScript("OnUpdate", function() -- (this, elapsed)
|
flickerstreak@1
|
566 if timeUntilClear - GetTime() <= 0 then
|
flickerstreak@1
|
567 self.frame:Hide()
|
flickerstreak@1
|
568 for k in pairs(newRegistries) do
|
flickerstreak@1
|
569 clearCache(k)
|
flickerstreak@1
|
570 newRegistries[k] = nil
|
flickerstreak@1
|
571 k = nil
|
flickerstreak@1
|
572 end
|
flickerstreak@1
|
573 end
|
flickerstreak@1
|
574 end)
|
flickerstreak@1
|
575 self.frame:UnregisterAllEvents()
|
flickerstreak@1
|
576 self.frame:RegisterEvent("ADDON_LOADED")
|
flickerstreak@1
|
577 self.frame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
flickerstreak@1
|
578 self.frame:Show()
|
flickerstreak@1
|
579
|
flickerstreak@1
|
580 if oldDeactivate then
|
flickerstreak@1
|
581 oldDeactivate(oldLib)
|
flickerstreak@1
|
582 end
|
flickerstreak@1
|
583 end
|
flickerstreak@1
|
584
|
flickerstreak@1
|
585 AceLibrary:Register(AceLocale, MAJOR_VERSION, MINOR_VERSION, activate)
|
flickerstreak@22
|
586 --[[
|
flickerstreak@22
|
587 if true then -- debug
|
flickerstreak@22
|
588 local L = AceLocale:new(MINOR_VERSION ~= 100000 and "AceLocale_DEBUG" or "AceLocale_DEBUG3")
|
flickerstreak@22
|
589 L:RegisterTranslations("enUS", function() return {
|
flickerstreak@22
|
590 Monkey = true,
|
flickerstreak@22
|
591 House = true,
|
flickerstreak@22
|
592 } end)
|
flickerstreak@22
|
593
|
flickerstreak@22
|
594 L:RegisterTranslations("deDE", function() return {
|
flickerstreak@22
|
595 Monkey = "Affe"
|
flickerstreak@22
|
596 } end)
|
flickerstreak@22
|
597
|
flickerstreak@22
|
598 L = AceLocale:new(MINOR_VERSION ~= 100000 and "AceLocale_DEBUG" or "AceLocale_DEBUG3")
|
flickerstreak@22
|
599 assert(L.Monkey == "Monkey")
|
flickerstreak@22
|
600 assert(L.House == "House")
|
flickerstreak@22
|
601 if not L.Debug then
|
flickerstreak@22
|
602 local pants = L.Pants
|
flickerstreak@22
|
603 assert(not pants)
|
flickerstreak@22
|
604 end
|
flickerstreak@22
|
605 assert(L.Debug)
|
flickerstreak@22
|
606 assert(L.Debug == AceLocale.prototype.Debug)
|
flickerstreak@22
|
607
|
flickerstreak@22
|
608 if MINOR_VERSION == 100000 then
|
flickerstreak@22
|
609 L = AceLocale:new("AceLocale_DEBUG")
|
flickerstreak@22
|
610 assert(L.Monkey == "Monkey")
|
flickerstreak@22
|
611 assert(L.House == "House")
|
flickerstreak@22
|
612 assert(L.Debug)
|
flickerstreak@22
|
613 assert(type(L.Debug) == "function")
|
flickerstreak@22
|
614 assert(AceLocale.prototype.Debug)
|
flickerstreak@22
|
615 assert(type(AceLocale.prototype.Debug) == "function")
|
flickerstreak@22
|
616 assert(L.Debug == AceLocale.prototype.Debug)
|
flickerstreak@22
|
617 end
|
flickerstreak@22
|
618
|
flickerstreak@22
|
619 local L = AceLocale:new(MINOR_VERSION ~= 100000 and "AceLocale_DEBUG2" or "AceLocale_DEBUG4")
|
flickerstreak@22
|
620 L:RegisterTranslations("deDE", function() return {
|
flickerstreak@22
|
621 Affe = true,
|
flickerstreak@22
|
622 Haus = true,
|
flickerstreak@22
|
623 } end)
|
flickerstreak@22
|
624
|
flickerstreak@22
|
625 L:RegisterTranslations("enUS", function() return {
|
flickerstreak@22
|
626 Affe = "Monkey"
|
flickerstreak@22
|
627 } end)
|
flickerstreak@22
|
628
|
flickerstreak@22
|
629 L = AceLocale:new(MINOR_VERSION ~= 100000 and "AceLocale_DEBUG2" or "AceLocale_DEBUG4")
|
flickerstreak@22
|
630 assert(L.Affe == "Monkey")
|
flickerstreak@22
|
631 assert(L.Haus == "Haus")
|
flickerstreak@22
|
632 assert(L.Debug)
|
flickerstreak@22
|
633 assert(L.Debug == AceLocale.prototype.Debug)
|
flickerstreak@22
|
634
|
flickerstreak@22
|
635 if MINOR_VERSION == 100000 then
|
flickerstreak@22
|
636 L = AceLocale:new("AceLocale_DEBUG2")
|
flickerstreak@22
|
637 assert(L.Affe == "Monkey")
|
flickerstreak@22
|
638 assert(L.Haus == "Haus")
|
flickerstreak@22
|
639 assert(L.Debug)
|
flickerstreak@22
|
640 assert(L.Debug == AceLocale.prototype.Debug)
|
flickerstreak@22
|
641 end
|
flickerstreak@22
|
642
|
flickerstreak@22
|
643 local L = AceLocale:new(MINOR_VERSION ~= 100000 and "AceLocale_DEBUG5" or "AceLocale_DEBUG6")
|
flickerstreak@22
|
644 L:RegisterTranslations("deDE", function() return {
|
flickerstreak@22
|
645 Affe = true,
|
flickerstreak@22
|
646 Haus = true,
|
flickerstreak@22
|
647 } end)
|
flickerstreak@22
|
648
|
flickerstreak@22
|
649 L:RegisterTranslations("enUS", function() return {
|
flickerstreak@22
|
650 Affe = "Monkey"
|
flickerstreak@22
|
651 } end)
|
flickerstreak@22
|
652
|
flickerstreak@22
|
653 L:SetStrictness(true)
|
flickerstreak@22
|
654
|
flickerstreak@22
|
655 L = AceLocale:new(MINOR_VERSION ~= 100000 and "AceLocale_DEBUG5" or "AceLocale_DEBUG6")
|
flickerstreak@22
|
656 assert(L.Affe == "Monkey")
|
flickerstreak@22
|
657 assert(L.Haus == "Haus")
|
flickerstreak@22
|
658 assert(L.Debug)
|
flickerstreak@22
|
659 assert(L.Debug == AceLocale.prototype.Debug)
|
flickerstreak@22
|
660
|
flickerstreak@22
|
661 if MINOR_VERSION == 100000 then
|
flickerstreak@22
|
662 L = AceLocale:new("AceLocale_DEBUG5")
|
flickerstreak@22
|
663 assert(L.Affe == "Monkey")
|
flickerstreak@22
|
664 assert(L.Haus == "Haus")
|
flickerstreak@22
|
665 assert(L.Debug)
|
flickerstreak@22
|
666 assert(L.Debug == AceLocale.prototype.Debug)
|
flickerstreak@22
|
667 end
|
flickerstreak@22
|
668 end
|
flickerstreak@22
|
669 ]] |