Xiiph@0
|
1 --- **AceLocale-3.0** manages localization in addons, allowing for multiple locale to be registered with fallback to the base locale for untranslated strings.
|
Xiiph@0
|
2 -- @class file
|
Xiiph@0
|
3 -- @name AceLocale-3.0
|
Xiiph@0
|
4 -- @release $Id: AceLocale-3.0.lua 895 2009-12-06 16:28:55Z nevcairiel $
|
Xiiph@0
|
5 local MAJOR,MINOR = "AceLocale-3.0", 2
|
Xiiph@0
|
6
|
Xiiph@0
|
7 local AceLocale, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
|
Xiiph@0
|
8
|
Xiiph@0
|
9 if not AceLocale then return end -- no upgrade needed
|
Xiiph@0
|
10
|
Xiiph@0
|
11 -- Lua APIs
|
Xiiph@0
|
12 local assert, tostring, error = assert, tostring, error
|
Xiiph@0
|
13 local setmetatable, rawset, rawget = setmetatable, rawset, rawget
|
Xiiph@0
|
14
|
Xiiph@0
|
15 -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
|
Xiiph@0
|
16 -- List them here for Mikk's FindGlobals script
|
Xiiph@0
|
17 -- GLOBALS: GAME_LOCALE, geterrorhandler
|
Xiiph@0
|
18
|
Xiiph@0
|
19 local gameLocale = GetLocale()
|
Xiiph@0
|
20 if gameLocale == "enGB" then
|
Xiiph@0
|
21 gameLocale = "enUS"
|
Xiiph@0
|
22 end
|
Xiiph@0
|
23
|
Xiiph@0
|
24 AceLocale.apps = AceLocale.apps or {} -- array of ["AppName"]=localetableref
|
Xiiph@0
|
25 AceLocale.appnames = AceLocale.appnames or {} -- array of [localetableref]="AppName"
|
Xiiph@0
|
26
|
Xiiph@0
|
27 -- This metatable is used on all tables returned from GetLocale
|
Xiiph@0
|
28 local readmeta = {
|
Xiiph@0
|
29 __index = function(self, key) -- requesting totally unknown entries: fire off a nonbreaking error and return key
|
Xiiph@0
|
30 rawset(self, key, key) -- only need to see the warning once, really
|
Xiiph@0
|
31 geterrorhandler()(MAJOR..": "..tostring(AceLocale.appnames[self])..": Missing entry for '"..tostring(key).."'")
|
Xiiph@0
|
32 return key
|
Xiiph@0
|
33 end
|
Xiiph@0
|
34 }
|
Xiiph@0
|
35
|
Xiiph@0
|
36 -- This metatable is used on all tables returned from GetLocale if the silent flag is true, it does not issue a warning on unknown keys
|
Xiiph@0
|
37 local readmetasilent = {
|
Xiiph@0
|
38 __index = function(self, key) -- requesting totally unknown entries: return key
|
Xiiph@0
|
39 rawset(self, key, key) -- only need to invoke this function once
|
Xiiph@0
|
40 return key
|
Xiiph@0
|
41 end
|
Xiiph@0
|
42 }
|
Xiiph@0
|
43
|
Xiiph@0
|
44 -- Remember the locale table being registered right now (it gets set by :NewLocale())
|
Xiiph@0
|
45 -- NOTE: Do never try to register 2 locale tables at once and mix their definition.
|
Xiiph@0
|
46 local registering
|
Xiiph@0
|
47
|
Xiiph@0
|
48 -- local assert false function
|
Xiiph@0
|
49 local assertfalse = function() assert(false) end
|
Xiiph@0
|
50
|
Xiiph@0
|
51 -- This metatable proxy is used when registering nondefault locales
|
Xiiph@0
|
52 local writeproxy = setmetatable({}, {
|
Xiiph@0
|
53 __newindex = function(self, key, value)
|
Xiiph@0
|
54 rawset(registering, key, value == true and key or value) -- assigning values: replace 'true' with key string
|
Xiiph@0
|
55 end,
|
Xiiph@0
|
56 __index = assertfalse
|
Xiiph@0
|
57 })
|
Xiiph@0
|
58
|
Xiiph@0
|
59 -- This metatable proxy is used when registering the default locale.
|
Xiiph@0
|
60 -- It refuses to overwrite existing values
|
Xiiph@0
|
61 -- Reason 1: Allows loading locales in any order
|
Xiiph@0
|
62 -- Reason 2: If 2 modules have the same string, but only the first one to be
|
Xiiph@0
|
63 -- loaded has a translation for the current locale, the translation
|
Xiiph@0
|
64 -- doesn't get overwritten.
|
Xiiph@0
|
65 --
|
Xiiph@0
|
66 local writedefaultproxy = setmetatable({}, {
|
Xiiph@0
|
67 __newindex = function(self, key, value)
|
Xiiph@0
|
68 if not rawget(registering, key) then
|
Xiiph@0
|
69 rawset(registering, key, value == true and key or value)
|
Xiiph@0
|
70 end
|
Xiiph@0
|
71 end,
|
Xiiph@0
|
72 __index = assertfalse
|
Xiiph@0
|
73 })
|
Xiiph@0
|
74
|
Xiiph@0
|
75 --- Register a new locale (or extend an existing one) for the specified application.
|
Xiiph@0
|
76 -- :NewLocale will return a table you can fill your locale into, or nil if the locale isn't needed for the players
|
Xiiph@0
|
77 -- game locale.
|
Xiiph@0
|
78 -- @paramsig application, locale[, isDefault[, silent]]
|
Xiiph@0
|
79 -- @param application Unique name of addon / module
|
Xiiph@0
|
80 -- @param locale Name of the locale to register, e.g. "enUS", "deDE", etc.
|
Xiiph@0
|
81 -- @param isDefault If this is the default locale being registered (your addon is written in this language, generally enUS)
|
Xiiph@0
|
82 -- @param silent If true, the locale will not issue warnings for missing keys. Can only be set on the default locale.
|
Xiiph@0
|
83 -- @usage
|
Xiiph@0
|
84 -- -- enUS.lua
|
Xiiph@0
|
85 -- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "enUS", true)
|
Xiiph@0
|
86 -- L["string1"] = true
|
Xiiph@0
|
87 --
|
Xiiph@0
|
88 -- -- deDE.lua
|
Xiiph@0
|
89 -- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "deDE")
|
Xiiph@0
|
90 -- if not L then return end
|
Xiiph@0
|
91 -- L["string1"] = "Zeichenkette1"
|
Xiiph@0
|
92 -- @return Locale Table to add localizations to, or nil if the current locale is not required.
|
Xiiph@0
|
93 function AceLocale:NewLocale(application, locale, isDefault, silent)
|
Xiiph@0
|
94
|
Xiiph@0
|
95 if silent and not isDefault then
|
Xiiph@0
|
96 error("Usage: NewLocale(application, locale[, isDefault[, silent]]): 'silent' can only be specified for the default locale", 2)
|
Xiiph@0
|
97 end
|
Xiiph@0
|
98
|
Xiiph@0
|
99 -- GAME_LOCALE allows translators to test translations of addons without having that wow client installed
|
Xiiph@0
|
100 -- Ammo: I still think this is a bad idea, for instance an addon that checks for some ingame string will fail, just because some other addon
|
Xiiph@0
|
101 -- gives the user the illusion that they can run in a different locale? Ditch this whole thing or allow a setting per 'application'. I'm of the
|
Xiiph@0
|
102 -- opinion to remove this.
|
Xiiph@0
|
103 local gameLocale = GAME_LOCALE or gameLocale
|
Xiiph@0
|
104
|
Xiiph@0
|
105 if locale ~= gameLocale and not isDefault then
|
Xiiph@0
|
106 return -- nop, we don't need these translations
|
Xiiph@0
|
107 end
|
Xiiph@0
|
108
|
Xiiph@0
|
109 local app = AceLocale.apps[application]
|
Xiiph@0
|
110
|
Xiiph@0
|
111 if not app then
|
Xiiph@0
|
112 app = setmetatable({}, silent and readmetasilent or readmeta)
|
Xiiph@0
|
113 AceLocale.apps[application] = app
|
Xiiph@0
|
114 AceLocale.appnames[app] = application
|
Xiiph@0
|
115 end
|
Xiiph@0
|
116
|
Xiiph@0
|
117 registering = app -- remember globally for writeproxy and writedefaultproxy
|
Xiiph@0
|
118
|
Xiiph@0
|
119 if isDefault then
|
Xiiph@0
|
120 return writedefaultproxy
|
Xiiph@0
|
121 end
|
Xiiph@0
|
122
|
Xiiph@0
|
123 return writeproxy
|
Xiiph@0
|
124 end
|
Xiiph@0
|
125
|
Xiiph@0
|
126 --- Returns localizations for the current locale (or default locale if translations are missing).
|
Xiiph@0
|
127 -- Errors if nothing is registered (spank developer, not just a missing translation)
|
Xiiph@0
|
128 -- @param application Unique name of addon / module
|
Xiiph@0
|
129 -- @param silent If true, the locale is optional, silently return nil if it's not found (defaults to false, optional)
|
Xiiph@0
|
130 -- @return The locale table for the current language.
|
Xiiph@0
|
131 function AceLocale:GetLocale(application, silent)
|
Xiiph@0
|
132 if not silent and not AceLocale.apps[application] then
|
Xiiph@0
|
133 error("Usage: GetLocale(application[, silent]): 'application' - No locales registered for '"..tostring(application).."'", 2)
|
Xiiph@0
|
134 end
|
Xiiph@0
|
135 return AceLocale.apps[application]
|
Xiiph@0
|
136 end
|