Quantcast

Working on adding new config screens to all my addons. Also added localization for the future.

Xruptor [10-01-18 - 13:36]
Working on adding new config screens to all my addons.  Also added localization for the future.
Filename
XanChat.lua
XanChat.toc
config.lua
libs/AceLocale-3.0/AceLocale-3.0.lua
libs/AceLocale-3.0/AceLocale-3.0.xml
libs/LibStub/LibStub.lua
libs/LibStub/LibStub.toc
libs/LibStub/tests/test.lua
libs/LibStub/tests/test2.lua
libs/LibStub/tests/test3.lua
libs/LibStub/tests/test4.lua
locale/enUS.lua
diff --git a/XanChat.lua b/XanChat.lua
index 20a982a..0e0cc6b 100644
--- a/XanChat.lua
+++ b/XanChat.lua
@@ -1,7 +1,12 @@
 --Some stupid custom Chat modifications for made for myself.
 --Sharing it with the world in case anybody wants to actually use this.

-local eFrame = CreateFrame("frame","xanChatEvent_Frame",UIParent)
+local ADDON_NAME, addon = ...
+if not _G[ADDON_NAME] then _G[ADDON_NAME] = addon
+
+addon.eventFrame = CreateFrame("frame","xanChatEvent_Frame",UIParent)
+local eFrame = addon.eventFrame
+
 eFrame:SetScript("OnEvent", function(self, event, ...) if self[event] then return self[event](self, event, ...) end end)

 local debugf = tekDebug and tekDebug:GetFrame("xanChat")
@@ -9,6 +14,8 @@ local function Debug(...)
     if debugf then debugf:AddMessage(string.join(", ", tostringall(...))) end
 end

+local L = LibStub("AceLocale-3.0"):GetLocale("xanChat")
+
 --[[------------------------
 	Scrolling and Chat Links
 --------------------------]]
@@ -69,7 +76,7 @@ StaticPopupDialogs["COPYNAME"] = {
 }

 UnitPopupButtons["WHOPLAYER"] = {
-	text = "Who Player?",
+	text = L.WhoPlayer,
 	func = function()
 		local dropdownFrame = UIDROPDOWNMENU_INIT_MENU
 		local name = dropdownFrame.name
@@ -83,7 +90,7 @@ tinsert(UnitPopupMenus["FRIEND"], #UnitPopupMenus["FRIEND"] - 1, "WHOPLAYER")
 customPopups["WHOPLAYER"] = true

 UnitPopupButtons["GUILDINVITE"] = {
-	text = "Guild Invite",
+	text = L.GuildInvite,
 	func = function()
 		local dropdownFrame = UIDROPDOWNMENU_INIT_MENU
 		local name = dropdownFrame.name
@@ -97,7 +104,7 @@ tinsert(UnitPopupMenus["FRIEND"], #UnitPopupMenus["FRIEND"] - 1, "GUILDINVITE")
 customPopups["GUILDINVITE"] = true

 UnitPopupButtons["COPYNAME"] = {
-	text = "Copy Name",
+	text = L.CopyName,
 	func = function()
 		local dropdownFrame = UIDROPDOWNMENU_INIT_MENU
 		local name = dropdownFrame.name
@@ -163,7 +170,7 @@ function urlFilter(self, event, msg, author, ...)
 end

 StaticPopupDialogs["LINKME"] = {
-	text = "URL COPY",
+	text = L.URLCopy,
 	button2 = CANCEL,
 	hasEditBox = true,
     hasWideEditBox = true,
@@ -222,9 +229,9 @@ local msgHooks = {}
 local HistoryDB

 StaticPopupDialogs["XANCHAT_APPLYCHANGES"] = {
-  text = "xanChat: Would you like to apply the changes now?",
-  button1 = "Yes",
-  button2 = "No",
+  text = L.ApplyChanges,
+  button1 = L.Yes,
+  button2 = L.No,
   OnAccept = function()
       ReloadUI()
   end,
@@ -237,12 +244,12 @@ local AddMessage = function(frame, text, ...)
 	if type(text) == "string" then
 		local chatNum = string.match(text,"%d+") or ""
 		if not tonumber(chatNum) then chatNum = "" else chatNum = chatNum..":" end
-		text = gsub(text, "%[%d+%. General.-%]", "["..chatNum.."GN]")
-		text = gsub(text, "%[%d+%. Trade.-%]", "["..chatNum.."TR]")
-		text = gsub(text, "%[%d+%. WorldDefense%]", "["..chatNum.."WD]")
-		text = gsub(text, "%[%d+%. LocalDefense.-%]", "["..chatNum.."LD]")
-		text = gsub(text, "%[%d+%. LookingForGroup%]", "["..chatNum.."LFG]")
-		text = gsub(text, "%[%d+%. GuildRecruitment.-%]", "["..chatNum.."GR]")
+		text = gsub(text, L.ChannelGeneral, "["..chatNum..L.ShortGeneral.."]")
+		text = gsub(text, L.ChannelTrade, "["..chatNum..L.ShortTrade.."]")
+		text = gsub(text, L.ChannelWorldDefense, "["..chatNum..L.ShortWorldDefense.."]")
+		text = gsub(text, L.ChannelLocalDefense, "["..chatNum..L.ShortLocalDefense.."]")
+		text = gsub(text, L.ChannelLookingForGroup, "["..chatNum..L.ShortLookingForGroup.."]")
+		text = gsub(text, L.ChannelGuildRecruitment, "["..chatNum..L.ShortGuildRecruitment.."]")
 	end
 	msgHooks[frame:GetName()].AddMessage(frame, text, ...)
 end
@@ -677,20 +684,20 @@ function eFrame:PLAYER_LOGIN()

 	--enable short channel names for globals
 	if XCHT_DB.shortNames then
-        CHAT_WHISPER_GET 				= "[W] %s: "
-        CHAT_WHISPER_INFORM_GET 		= "[W2] %s: "
-        CHAT_YELL_GET 					= "|Hchannel:Yell|h[Y]|h %s: "
-        CHAT_SAY_GET 					= "|Hchannel:Say|h[S]|h %s: "
-        CHAT_BATTLEGROUND_GET			= "|Hchannel:Battleground|h[BG]|h %s: "
-        CHAT_BATTLEGROUND_LEADER_GET 	= [[|Hchannel:Battleground|h[BG|TInterface\GroupFrame\UI-Group-LeaderIcon:0|t]|h %s: ]]
-        CHAT_GUILD_GET   				= "|Hchannel:Guild|h[G]|h %s: "
-        CHAT_OFFICER_GET 				= "|Hchannel:Officer|h[O]|h %s: "
-        CHAT_PARTY_GET        			= "|Hchannel:Party|h[P]|h %s: "
-        CHAT_PARTY_LEADER_GET 			= [[|Hchannel:Party|h[P|TInterface\GroupFrame\UI-Group-LeaderIcon:0|t]|h %s: ]]
-        CHAT_PARTY_GUIDE_GET  			= CHAT_PARTY_LEADER_GET
-        CHAT_RAID_GET         			= "|Hchannel:Raid|h[R]|h %s: "
-        CHAT_RAID_LEADER_GET  			= [[|Hchannel:Raid|h[R|TInterface\GroupFrame\UI-Group-LeaderIcon:0|t]|h %s: ]]
-        CHAT_RAID_WARNING_GET 			= [[|Hchannel:RaidWarning|h[RW|TInterface\GroupFrame\UI-GROUP-MAINASSISTICON:0|t]|h %s: ]]
+        CHAT_WHISPER_GET 				= L.CHAT_WHISPER_GET
+        CHAT_WHISPER_INFORM_GET 		= L.CHAT_WHISPER_INFORM_GET
+        CHAT_YELL_GET 					= L.CHAT_YELL_GET
+        CHAT_SAY_GET 					= L.CHAT_SAY_GET
+        CHAT_BATTLEGROUND_GET			= L.CHAT_BATTLEGROUND_GET
+        CHAT_BATTLEGROUND_LEADER_GET 	= L.CHAT_BATTLEGROUND_LEADER_GET
+        CHAT_GUILD_GET   				= L.CHAT_GUILD_GET
+        CHAT_OFFICER_GET 				= L.CHAT_OFFICER_GET
+        CHAT_PARTY_GET        			= L.CHAT_PARTY_GET
+        CHAT_PARTY_LEADER_GET 			= L.CHAT_PARTY_LEADER_GET
+        CHAT_PARTY_GUIDE_GET  			= L.CHAT_PARTY_GUIDE_GET
+        CHAT_RAID_GET         			= L.CHAT_RAID_GET
+        CHAT_RAID_LEADER_GET  			= L.CHAT_RAID_LEADER_GET
+        CHAT_RAID_WARNING_GET 			= L.CHAT_RAID_WARNING_GET

         CHAT_MONSTER_PARTY_GET   		= CHAT_PARTY_GET
         CHAT_MONSTER_SAY_GET     		= CHAT_SAY_GET
@@ -727,74 +734,74 @@ function eFrame:PLAYER_LOGIN()
 		local a,b,c=strfind(msg, "(%S+)")

 		if a and XCHT_DB then
-			if c and c:lower() == "social" then
+			if c and c:lower() == L.SlashSocial then
 				if XCHT_DB.hideSocial then
 					XCHT_DB.hideSocial = false
-					DEFAULT_CHAT_FRAME:AddMessage("xanChat: Social buttons are now [|cFF99CC33ON|r]")
+					DEFAULT_CHAT_FRAME:AddMessage(L.SlashSocialOn)
 				else
 					XCHT_DB.hideSocial = true
-					DEFAULT_CHAT_FRAME:AddMessage("XanDebuffTimers: Social buttons are now [|cFF99CC33OFF|r]")
+					DEFAULT_CHAT_FRAME:AddMessage(L.SlashSocialOff)
 				end
 				StaticPopup_Show("XANCHAT_APPLYCHANGES")
 				return true
-			elseif c and c:lower() == "scroll" then
+			elseif c and c:lower() == L.SlashScroll then
 				if XCHT_DB.hideScroll then
 					XCHT_DB.hideScroll = false
-					DEFAULT_CHAT_FRAME:AddMessage("xanChat: Scroll buttons are now [|cFF99CC33ON|r]")
+					DEFAULT_CHAT_FRAME:AddMessage(L.SlashScrollOn)
 				else
 					XCHT_DB.hideScroll = true
-					DEFAULT_CHAT_FRAME:AddMessage("xanChat: Scroll buttons are now [|cFF99CC33OFF|r]")
+					DEFAULT_CHAT_FRAME:AddMessage(L.SlashScrollOff)
 				end
 				StaticPopup_Show("XANCHAT_APPLYCHANGES")
 				return true
-			elseif c and c:lower() == "shortnames" then
+			elseif c and c:lower() == L.SlashShortNames then
 				if XCHT_DB.shortNames then
 					XCHT_DB.shortNames = false
-					DEFAULT_CHAT_FRAME:AddMessage("xanChat: Short channel names are now [|cFF99CC33OFF|r]")
+					DEFAULT_CHAT_FRAME:AddMessage(L.SlashShortNamesOff)
 				else
 					XCHT_DB.shortNames = true
-					DEFAULT_CHAT_FRAME:AddMessage("xanChat: Short channel names are now [|cFF99CC33ON|r]")
+					DEFAULT_CHAT_FRAME:AddMessage(L.SlashShortNamesOn)
 				end
 				StaticPopup_Show("XANCHAT_APPLYCHANGES")
 				return true
-			elseif c and c:lower() == "editbox" then
+			elseif c and c:lower() == L.SlashEditBox then
 				if XCHT_DB.editBoxTop then
 					XCHT_DB.editBoxTop = false
 					setEditBox()
-					DEFAULT_CHAT_FRAME:AddMessage("xanChat: The edit box is now at the [|cFF99CC33BOTTOM|r]")
+					DEFAULT_CHAT_FRAME:AddMessage(L.SlashEditBoxBottom)
 				else
 					XCHT_DB.editBoxTop = true
 					setEditBox(true)
-					DEFAULT_CHAT_FRAME:AddMessage("xanChat: The edit box is now at the [|cFF99CC33TOP|r]")
+					DEFAULT_CHAT_FRAME:AddMessage(L.SlashEditBoxTop)
 				end
 				return true
-			elseif c and c:lower() == "tabs" then
+			elseif c and c:lower() == L.SlashTabs then
 				if XCHT_DB.hideTabs then
 					XCHT_DB.hideTabs = false
-					DEFAULT_CHAT_FRAME:AddMessage("xanChat: The chat tabs are now [|cFF99CC33ON|r]")
+					DEFAULT_CHAT_FRAME:AddMessage(L.SlashTabsOn)
 				else
 					XCHT_DB.hideTabs = true
-					DEFAULT_CHAT_FRAME:AddMessage("xanChat: The chat tabs are now [|cFF99CC33OFF|r]")
+					DEFAULT_CHAT_FRAME:AddMessage(L.SlashTabsOff)
 				end
 				StaticPopup_Show("XANCHAT_APPLYCHANGES")
 				return true
-			elseif c and c:lower() == "shadow" then
+			elseif c and c:lower() == L.SlashShadow then
 				if XCHT_DB.addFontShadow then
 					XCHT_DB.addFontShadow = false
-					DEFAULT_CHAT_FRAME:AddMessage("xanChat: Chat font shadows are now [|cFF99CC33OFF|r]")
+					DEFAULT_CHAT_FRAME:AddMessage(L.SlashShadowOff)
 				else
 					XCHT_DB.addFontShadow = true
-					DEFAULT_CHAT_FRAME:AddMessage("xanChat: Chat font shadows are now [|cFF99CC33ON|r]")
+					DEFAULT_CHAT_FRAME:AddMessage(L.SlashShadowOn)
 				end
 				StaticPopup_Show("XANCHAT_APPLYCHANGES")
 				return true
-			elseif c and c:lower() == "voice" then
+			elseif c and c:lower() == L.SlashVoice then
 				if XCHT_DB.hideVoice then
 					XCHT_DB.hideVoice = false
-					DEFAULT_CHAT_FRAME:AddMessage("xanChat: Voice chat buttons are now [|cFF99CC33ON|r]")
+					DEFAULT_CHAT_FRAME:AddMessage(L.SlashVoiceOn)
 				else
 					XCHT_DB.hideVoice = true
-					DEFAULT_CHAT_FRAME:AddMessage("xanChat: Voice chat buttons are now [|cFF99CC33OFF|r]")
+					DEFAULT_CHAT_FRAME:AddMessage(L.SlashVoiceOff)
 					ChatFrameToggleVoiceDeafenButton:Hide()
 					ChatFrameToggleVoiceMuteButton:Hide()
 					ChatFrameChannelButton:Hide()
@@ -805,13 +812,13 @@ function eFrame:PLAYER_LOGIN()
 		end

 		DEFAULT_CHAT_FRAME:AddMessage("xanChat")
-		DEFAULT_CHAT_FRAME:AddMessage("/xanchat social - toggles the chat social buttons")
-		DEFAULT_CHAT_FRAME:AddMessage("/xanchat scroll - toggles the chat scroll bars")
-		DEFAULT_CHAT_FRAME:AddMessage("/xanchat shortnames - toggles short channels names")
-		DEFAULT_CHAT_FRAME:AddMessage("/xanchat editbox - toggles editbox to show at the top or the bottom")
-		DEFAULT_CHAT_FRAME:AddMessage("/xanchat tabs - toggles the chat tabs on or off")
-		DEFAULT_CHAT_FRAME:AddMessage("/xanchat shadow - toggles text shadows for chat fonts on or off")
-		DEFAULT_CHAT_FRAME:AddMessage("/xanchat voice - toggles voice chat buttons on or off")
+		DEFAULT_CHAT_FRAME:AddMessage(L.SlashSocialInfo)
+		DEFAULT_CHAT_FRAME:AddMessage(L.SlashScrollInfo)
+		DEFAULT_CHAT_FRAME:AddMessage(L.SlashShortNamesInfo)
+		DEFAULT_CHAT_FRAME:AddMessage(L.SlashEditBoxInfo)
+		DEFAULT_CHAT_FRAME:AddMessage(L.SlashTabsInfo)
+		DEFAULT_CHAT_FRAME:AddMessage(L.SlashShadowInfo)
+		DEFAULT_CHAT_FRAME:AddMessage(L.SlashVoiceInfo)
 	end

 	local ver = GetAddOnMetadata("xanChat","Version") or '1.0'
diff --git a/XanChat.toc b/XanChat.toc
index 68c9bf2..0c8b9a7 100644
--- a/XanChat.toc
+++ b/XanChat.toc
@@ -6,4 +6,10 @@
 ## OptionalDeps: tekDebug
 ## SavedVariables: XCHT_DB, XCHT_HISTORY

+libs\LibStub\LibStub.lua
+libs\AceLocale-3.0\AceLocale-3.0.xml
+
+locale\enUS.lua
+
 xanChat.lua
+config.lua
diff --git a/config.lua b/config.lua
new file mode 100644
index 0000000..7f4c246
--- /dev/null
+++ b/config.lua
@@ -0,0 +1,66 @@
+local ADDON_NAME, addon = ...
+if not _G[ADDON_NAME] then _G[ADDON_NAME] = addon
+
+local chkBoxIndex = 1
+
+function createCheckbutton(parentFrame, xPos, yPos, displayText)
+	chkBoxIndex = chkBoxIndex + 1
+
+	local checkbutton = CreateFrame("CheckButton", ADDON_NAME.."_config_chkbtn_" .. chkBoxIndex, parentFrame, "ChatConfigCheckButtonTemplate")
+	checkbutton:SetPoint("TOPLEFT", xPos, yPos)
+	getglobal(checkbutton:GetName() .. 'Text'):SetText(displayText)
+
+	return checkbutton
+end
+
+local function LoadAboutFrame()
+
+	--Code inspired from tekKonfigAboutPanel
+	local about = CreateFrame("Frame", ADDON_NAME.."AboutPanel", InterfaceOptionsFramePanelContainer)
+	about.name = ADDON_NAME
+	about:Hide()
+
+    local fields = {"Version", "Author"}
+	local notes = GetAddOnMetadata(ADDON_NAME, "Notes")
+
+    local title = about:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge")
+
+	title:SetPoint("TOPLEFT", 16, -16)
+	title:SetText(ADDON_NAME)
+
+	local subtitle = about:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
+	subtitle:SetHeight(32)
+	subtitle:SetPoint("TOPLEFT", title, "BOTTOMLEFT", 0, -8)
+	subtitle:SetPoint("RIGHT", about, -32, 0)
+	subtitle:SetNonSpaceWrap(true)
+	subtitle:SetJustifyH("LEFT")
+	subtitle:SetJustifyV("TOP")
+	subtitle:SetText(notes)
+
+	local anchor
+	for _,field in pairs(fields) do
+		local val = GetAddOnMetadata(ADDON_NAME, field)
+		if val then
+			local title = about:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
+			title:SetWidth(75)
+			if not anchor then title:SetPoint("TOPLEFT", subtitle, "BOTTOMLEFT", -2, -8)
+			else title:SetPoint("TOPLEFT", anchor, "BOTTOMLEFT", 0, -6) end
+			title:SetJustifyH("RIGHT")
+			title:SetText(field:gsub("X%-", ""))
+
+			local detail = about:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
+			detail:SetPoint("LEFT", title, "RIGHT", 4, 0)
+			detail:SetPoint("RIGHT", -16, 0)
+			detail:SetJustifyH("LEFT")
+			detail:SetText(val)
+
+			anchor = title
+		end
+	end
+
+	InterfaceOptions_AddCategory(about)
+
+	return about
+end
+
+addon.aboutPanel = LoadAboutFrame()
\ No newline at end of file
diff --git a/libs/AceLocale-3.0/AceLocale-3.0.lua b/libs/AceLocale-3.0/AceLocale-3.0.lua
new file mode 100644
index 0000000..e133781
--- /dev/null
+++ b/libs/AceLocale-3.0/AceLocale-3.0.lua
@@ -0,0 +1,137 @@
+--- **AceLocale-3.0** manages localization in addons, allowing for multiple locale to be registered with fallback to the base locale for untranslated strings.
+-- @class file
+-- @name AceLocale-3.0
+-- @release $Id: AceLocale-3.0.lua 1035 2011-07-09 03:20:13Z kaelten $
+local MAJOR,MINOR = "AceLocale-3.0", 6
+
+local AceLocale, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not AceLocale then return end -- no upgrade needed
+
+-- Lua APIs
+local assert, tostring, error = assert, tostring, error
+local getmetatable, setmetatable, rawset, rawget = getmetatable, setmetatable, rawset, rawget
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: GAME_LOCALE, geterrorhandler
+
+local gameLocale = GetLocale()
+if gameLocale == "enGB" then
+	gameLocale = "enUS"
+end
+
+AceLocale.apps = AceLocale.apps or {}          -- array of ["AppName"]=localetableref
+AceLocale.appnames = AceLocale.appnames or {}  -- array of [localetableref]="AppName"
+
+-- This metatable is used on all tables returned from GetLocale
+local readmeta = {
+	__index = function(self, key) -- requesting totally unknown entries: fire off a nonbreaking error and return key
+		rawset(self, key, key)      -- only need to see the warning once, really
+		geterrorhandler()(MAJOR..": "..tostring(AceLocale.appnames[self])..": Missing entry for '"..tostring(key).."'")
+		return key
+	end
+}
+
+-- 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
+local readmetasilent = {
+	__index = function(self, key) -- requesting totally unknown entries: return key
+		rawset(self, key, key)      -- only need to invoke this function once
+		return key
+	end
+}
+
+-- Remember the locale table being registered right now (it gets set by :NewLocale())
+-- NOTE: Do never try to register 2 locale tables at once and mix their definition.
+local registering
+
+-- local assert false function
+local assertfalse = function() assert(false) end
+
+-- This metatable proxy is used when registering nondefault locales
+local writeproxy = setmetatable({}, {
+	__newindex = function(self, key, value)
+		rawset(registering, key, value == true and key or value) -- assigning values: replace 'true' with key string
+	end,
+	__index = assertfalse
+})
+
+-- This metatable proxy is used when registering the default locale.
+-- It refuses to overwrite existing values
+-- Reason 1: Allows loading locales in any order
+-- Reason 2: If 2 modules have the same string, but only the first one to be
+--           loaded has a translation for the current locale, the translation
+--           doesn't get overwritten.
+--
+local writedefaultproxy = setmetatable({}, {
+	__newindex = function(self, key, value)
+		if not rawget(registering, key) then
+			rawset(registering, key, value == true and key or value)
+		end
+	end,
+	__index = assertfalse
+})
+
+--- Register a new locale (or extend an existing one) for the specified application.
+-- :NewLocale will return a table you can fill your locale into, or nil if the locale isn't needed for the players
+-- game locale.
+-- @paramsig application, locale[, isDefault[, silent]]
+-- @param application Unique name of addon / module
+-- @param locale Name of the locale to register, e.g. "enUS", "deDE", etc.
+-- @param isDefault If this is the default locale being registered (your addon is written in this language, generally enUS)
+-- @param silent If true, the locale will not issue warnings for missing keys. Must be set on the first locale registered. If set to "raw", nils will be returned for unknown keys (no metatable used).
+-- @usage
+-- -- enUS.lua
+-- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "enUS", true)
+-- L["string1"] = true
+--
+-- -- deDE.lua
+-- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "deDE")
+-- if not L then return end
+-- L["string1"] = "Zeichenkette1"
+-- @return Locale Table to add localizations to, or nil if the current locale is not required.
+function AceLocale:NewLocale(application, locale, isDefault, silent)
+
+	-- GAME_LOCALE allows translators to test translations of addons without having that wow client installed
+	local gameLocale = GAME_LOCALE or gameLocale
+
+	local app = AceLocale.apps[application]
+
+	if silent and app and getmetatable(app) ~= readmetasilent then
+		geterrorhandler()("Usage: NewLocale(application, locale[, isDefault[, silent]]): 'silent' must be specified for the first locale registered")
+	end
+
+	if not app then
+		if silent=="raw" then
+			app = {}
+		else
+			app = setmetatable({}, silent and readmetasilent or readmeta)
+		end
+		AceLocale.apps[application] = app
+		AceLocale.appnames[app] = application
+	end
+
+	if locale ~= gameLocale and not isDefault then
+		return -- nop, we don't need these translations
+	end
+
+	registering = app -- remember globally for writeproxy and writedefaultproxy
+
+	if isDefault then
+		return writedefaultproxy
+	end
+
+	return writeproxy
+end
+
+--- Returns localizations for the current locale (or default locale if translations are missing).
+-- Errors if nothing is registered (spank developer, not just a missing translation)
+-- @param application Unique name of addon / module
+-- @param silent If true, the locale is optional, silently return nil if it's not found (defaults to false, optional)
+-- @return The locale table for the current language.
+function AceLocale:GetLocale(application, silent)
+	if not silent and not AceLocale.apps[application] then
+		error("Usage: GetLocale(application[, silent]): 'application' - No locales registered for '"..tostring(application).."'", 2)
+	end
+	return AceLocale.apps[application]
+end
diff --git a/libs/AceLocale-3.0/AceLocale-3.0.xml b/libs/AceLocale-3.0/AceLocale-3.0.xml
new file mode 100644
index 0000000..bf023f0
--- /dev/null
+++ b/libs/AceLocale-3.0/AceLocale-3.0.xml
@@ -0,0 +1,4 @@
+<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
+..\FrameXML\UI.xsd">
+	<Script file="AceLocale-3.0.lua"/>
+</Ui>
diff --git a/libs/LibStub/LibStub.lua b/libs/LibStub/LibStub.lua
new file mode 100644
index 0000000..0a41ac0
--- /dev/null
+++ b/libs/LibStub/LibStub.lua
@@ -0,0 +1,30 @@
+-- LibStub is a simple versioning stub meant for use in Libraries.  http://www.wowace.com/wiki/LibStub for more info
+-- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
+local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2  -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
+local LibStub = _G[LIBSTUB_MAJOR]
+
+if not LibStub or LibStub.minor < LIBSTUB_MINOR then
+	LibStub = LibStub or {libs = {}, minors = {} }
+	_G[LIBSTUB_MAJOR] = LibStub
+	LibStub.minor = LIBSTUB_MINOR
+
+	function LibStub:NewLibrary(major, minor)
+		assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
+		minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
+
+		local oldminor = self.minors[major]
+		if oldminor and oldminor >= minor then return nil end
+		self.minors[major], self.libs[major] = minor, self.libs[major] or {}
+		return self.libs[major], oldminor
+	end
+
+	function LibStub:GetLibrary(major, silent)
+		if not self.libs[major] and not silent then
+			error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
+		end
+		return self.libs[major], self.minors[major]
+	end
+
+	function LibStub:IterateLibraries() return pairs(self.libs) end
+	setmetatable(LibStub, { __call = LibStub.GetLibrary })
+end
diff --git a/libs/LibStub/LibStub.toc b/libs/LibStub/LibStub.toc
new file mode 100644
index 0000000..0277222
--- /dev/null
+++ b/libs/LibStub/LibStub.toc
@@ -0,0 +1,13 @@
+## Interface: 80000
+## Title: Lib: LibStub
+## Notes: Universal Library Stub
+## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel
+## X-Website: http://www.wowace.com/addons/libstub/
+## X-Category: Library
+## X-License: Public Domain
+## X-Curse-Packaged-Version: 1.0.2.60000
+## X-Curse-Project-Name: LibStub
+## X-Curse-Project-ID: libstub
+## X-Curse-Repository-ID: wow/libstub/mainline
+
+LibStub.lua
diff --git a/libs/LibStub/tests/test.lua b/libs/LibStub/tests/test.lua
new file mode 100644
index 0000000..276ddab
--- /dev/null
+++ b/libs/LibStub/tests/test.lua
@@ -0,0 +1,41 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+local lib, oldMinor = LibStub:NewLibrary("Pants", 1) -- make a new thingy
+assert(lib) -- should return the library table
+assert(not oldMinor) -- should not return the old minor, since it didn't exist
+
+-- the following is to create data and then be able to check if the same data exists after the fact
+function lib:MyMethod()
+end
+local MyMethod = lib.MyMethod
+lib.MyTable = {}
+local MyTable = lib.MyTable
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 1) -- try to register a library with the same version, should silently fail
+assert(not newLib) -- should not return since out of date
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 0) -- try to register a library with a previous, should silently fail
+assert(not newLib) -- should not return since out of date
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 2) -- register a new version
+assert(newLib) -- library table
+assert(rawequal(newLib, lib)) -- should be the same reference as the previous
+assert(newOldMinor == 1) -- should return the minor version of the previous version
+
+assert(rawequal(lib.MyMethod, MyMethod)) -- verify that values were saved
+assert(rawequal(lib.MyTable, MyTable)) -- verify that values were saved
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 3 Blah") -- register a new version with a string minor version (instead of a number)
+assert(newLib) -- library table
+assert(newOldMinor == 2) -- previous version was 2
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 4 and please ignore 15 Blah") -- register a new version with a string minor version (instead of a number)
+assert(newLib)
+assert(newOldMinor == 3) -- previous version was 3 (even though it gave a string)
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 5) -- register a new library, using a normal number instead of a string
+assert(newLib)
+assert(newOldMinor == 4) -- previous version was 4 (even though it gave a string)
\ No newline at end of file
diff --git a/libs/LibStub/tests/test2.lua b/libs/LibStub/tests/test2.lua
new file mode 100644
index 0000000..eae7172
--- /dev/null
+++ b/libs/LibStub/tests/test2.lua
@@ -0,0 +1,27 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+for major, library in LibStub:IterateLibraries() do
+	-- check that MyLib doesn't exist yet, by iterating through all the libraries
+	assert(major ~= "MyLib")
+end
+
+assert(not LibStub:GetLibrary("MyLib", true)) -- check that MyLib doesn't exist yet by direct checking
+assert(not pcall(LibStub.GetLibrary, LibStub, "MyLib")) -- don't silently fail, thus it should raise an error.
+local lib = LibStub:NewLibrary("MyLib", 1) -- create the lib
+assert(lib) -- check it exists
+assert(rawequal(LibStub:GetLibrary("MyLib"), lib)) -- verify that :GetLibrary("MyLib") properly equals the lib reference
+
+assert(LibStub:NewLibrary("MyLib", 2))	-- create a new version
+
+local count=0
+for major, library in LibStub:IterateLibraries() do
+	-- check that MyLib exists somewhere in the libraries, by iterating through all the libraries
+	if major == "MyLib" then -- we found it!
+		count = count +1
+		assert(rawequal(library, lib)) -- verify that the references are equal
+	end
+end
+assert(count == 1) -- verify that we actually found it, and only once
diff --git a/libs/LibStub/tests/test3.lua b/libs/LibStub/tests/test3.lua
new file mode 100644
index 0000000..30f7b94
--- /dev/null
+++ b/libs/LibStub/tests/test3.lua
@@ -0,0 +1,14 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+local proxy = newproxy() -- non-string
+
+assert(not pcall(LibStub.NewLibrary, LibStub, proxy, 1)) -- should error, proxy is not a string, it's userdata
+local success, ret = pcall(LibStub.GetLibrary, proxy, true)
+assert(not success or not ret) -- either error because proxy is not a string or because it's not actually registered.
+
+assert(not pcall(LibStub.NewLibrary, LibStub, "Something", "No number in here")) -- should error, minor has no string in it.
+
+assert(not LibStub:GetLibrary("Something", true)) -- shouldn't've created it from the above statement
\ No newline at end of file
diff --git a/libs/LibStub/tests/test4.lua b/libs/LibStub/tests/test4.lua
new file mode 100644
index 0000000..43eb338
--- /dev/null
+++ b/libs/LibStub/tests/test4.lua
@@ -0,0 +1,41 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+
+-- Pretend like loaded libstub is old and doesn't have :IterateLibraries
+assert(LibStub.minor)
+LibStub.minor = LibStub.minor - 0.0001
+LibStub.IterateLibraries = nil
+
+loadfile("../LibStub.lua")()
+
+assert(type(LibStub.IterateLibraries)=="function")
+
+
+-- Now pretend that we're the same version -- :IterateLibraries should NOT be re-created
+LibStub.IterateLibraries = 123
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+-- Now pretend that a newer version is loaded -- :IterateLibraries should NOT be re-created
+LibStub.minor = LibStub.minor + 0.0001
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+-- Again with a huge number
+LibStub.minor = LibStub.minor + 1234567890
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+print("OK")
\ No newline at end of file
diff --git a/locale/enUS.lua b/locale/enUS.lua
new file mode 100644
index 0000000..2b95594
--- /dev/null
+++ b/locale/enUS.lua
@@ -0,0 +1,93 @@
+
+local L = LibStub("AceLocale-3.0"):NewLocale("xanChat", "enUS", true)
+if not L then return end
+
+--for non-english fonts
+--https://github.com/tomrus88/BlizzardInterfaceCode/blob/master/Interface/FrameXML/Fonts.xml
+
+--Get the best possible font for the localization langugage.
+--Some fonts are better than others to display special character sets.
+L.GetFontType = "Fonts\\FRIZQT__.TTF"
+
+L.WhoPlayer = "Who Player?"
+L.GuildInvite = "Guild Invite"
+L.CopyName = "Copy Name"
+L.URLCopy = "URL COPY"
+L.ApplyChanges = "xanChat: Would you like to apply the changes now?"
+L.Yes = "Yes"
+L.No = "No"
+
+--Channel Config (Only change the actual english word, leave the characters.  It's case sensitive!)
+L.ChannelGeneral = "%[%d+%. General.-%]"
+L.ChannelTrade = "%[%d+%. General.-%]"
+L.ChannelWorldDefense = "%[%d+%. General.-%]"
+L.ChannelLocalDefense = "%[%d+%. General.-%]"
+L.ChannelLookingForGroup = "%[%d+%. General.-%]"
+L.ChannelGuildRecruitment = "%[%d+%. General.-%]"
+
+L.ShortGeneral = "GN"
+L.ShortTrade = "TR"
+L.ShortWorldDefense = "WD"
+L.ShortLocalDefense = "LD"
+L.ShortLookingForGroup = "LFG"
+L.ShortGuildRecruitment = "GR"
+
+--short channel globals
+--Example: "|Hchannel:  Channel Type   |h  [short channel name]   |h %s: "
+--Example Yell: "|Hchannel:  Yell  |h  [Y]  |h %s: "   Channel Type = Yell, short name = Y
+L.CHAT_WHISPER_GET 				= "[W] %s: "
+L.CHAT_WHISPER_INFORM_GET 		= "[W2] %s: "
+L.CHAT_YELL_GET 				= "|Hchannel:Yell|h[Y]|h %s: "
+L.CHAT_SAY_GET 					= "|Hchannel:Say|h[S]|h %s: "
+L.CHAT_BATTLEGROUND_GET			= "|Hchannel:Battleground|h[BG]|h %s: "
+L.CHAT_BATTLEGROUND_LEADER_GET 	= [[|Hchannel:Battleground|h[BG|TInterface\GroupFrame\UI-Group-LeaderIcon:0|t]|h %s: ]]
+L.CHAT_GUILD_GET   				= "|Hchannel:Guild|h[G]|h %s: "
+L.CHAT_OFFICER_GET 				= "|Hchannel:Officer|h[O]|h %s: "
+L.CHAT_PARTY_GET        			= "|Hchannel:Party|h[P]|h %s: "
+L.CHAT_PARTY_LEADER_GET 			= [[|Hchannel:Party|h[P|TInterface\GroupFrame\UI-Group-LeaderIcon:0|t]|h %s: ]]
+L.CHAT_PARTY_GUIDE_GET  			= [[|Hchannel:Party|h[PG|TInterface\GroupFrame\UI-Group-LeaderIcon:0|t]|h %s: ]]
+L.CHAT_RAID_GET         			= "|Hchannel:Raid|h[R]|h %s: "
+L.CHAT_RAID_LEADER_GET  			= [[|Hchannel:Raid|h[R|TInterface\GroupFrame\UI-Group-LeaderIcon:0|t]|h %s: ]]
+L.CHAT_RAID_WARNING_GET 			= [[|Hchannel:RaidWarning|h[RW|TInterface\GroupFrame\UI-GROUP-MAINASSISTICON:0|t]|h %s: ]]
+
+L.SlashSocial = "social"
+L.SlashSocialOn = "xanChat: Social buttons are now [|cFF99CC33ON|r]"
+L.SlashSocialOff = "xanChat: Social buttons are now [|cFF99CC33OFF|r]"
+L.SlashSocialInfoShort = "Toggles the chat social buttons"
+L.SlashSocialInfo = "/xanchat "..L.SlashSocial.." - "..L.SlashSocialInfoShort
+
+L.SlashScroll = "scroll"
+L.SlashScrollOn = "xanChat: Scroll buttons are now [|cFF99CC33ON|r]"
+L.SlashScrollOff = "xanChat: Scroll buttons are now [|cFF99CC33OFF|r]"
+L.SlashScrollInfoShort = "Toggles the chat scroll bars"
+L.SlashScrollInfo = "/xanchat "..L.SlashScroll.." - "..L.SlashScrollInfoShort
+
+L.SlashShortNames = "shortnames"
+L.SlashShortNamesOn = "xanChat: Short channel names are now [|cFF99CC33ON|r]"
+L.SlashShortNamesOff = "xanChat: Short channel names are now [|cFF99CC33OFF|r]"
+L.SlashShortNamesInfoShort = "Toggles short channels names"
+L.SlashShortNamesInfo = "/xanchat "..L.SlashShortNames.." - "..L.SlashShortNamesInfoShort
+
+L.SlashEditBox = "editbox"
+L.SlashEditBoxBottom = "xanChat: The edit box is now at the [|cFF99CC33BOTTOM|r]"
+L.SlashEditBoxTop = "xanChat: The edit box is now at the [|cFF99CC33TOP|r]"
+L.SlashEditBoxInfoShort = "Toggles editbox to show at the top or the bottom"
+L.SlashEditBoxInfo = "/xanchat "..L.SlashEditBox.." - "..L.SlashEditBoxInfoShort
+
+L.SlashTabs = "tabs"
+L.SlashTabsOn = "xanChat: The chat tabs are now [|cFF99CC33ON|r]"
+L.SlashTabsOff = "xanChat: The chat tabs are now [|cFF99CC33OFF|r]"
+L.SlashTabsInfoShort = "Toggles the chat tabs on or off"
+L.SlashTabsInfo = "/xanchat "..L.SlashTabs.." - "..L.SlashTabsInfoShort
+
+L.SlashShadow = "shadow"
+L.SlashShadowOn = "xanChat: Chat font shadows are now [|cFF99CC33ON|r]"
+L.SlashShadowOff = "xanChat: Chat font shadows are now [|cFF99CC33OFF|r]"
+L.SlashShadowInfoShort = "Toggles text shadows for chat fonts on or off"
+L.SlashShadowInfo = "/xanchat "..L.SlashShadow.." - "..L.SlashShadowInfoShort
+
+L.SlashVoice = "voice"
+L.SlashVoiceOn = "xanChat: Voice chat buttons are now [|cFF99CC33ON|r]"
+L.SlashVoiceOff = "xanChat: Voice chat buttons are now [|cFF99CC33OFF|r]"
+L.SlashVoiceInfoShort = "Toggles voice chat buttons on or off"
+L.SlashVoiceInfo = "/xanchat "..L.SlashVoice.." - "..L.SlashVoiceInfoShort