Add internationalization (WIP); add trading house icons; add grocery store icons

katkat42 [09-29-14 - 04:05]
Add internationalization (WIP); add trading house icons; add grocery store icons
Filename
Common.lua
Provisioning.lua
SousChef.lua
SousChef.txt
SousChef.xml
Strings.lua
TradingHouse.lua
Utility.lua
bindings.xml
diff --git a/Common.lua b/Common.lua
index f2fff04..433aeb2 100644
--- a/Common.lua
+++ b/Common.lua
@@ -1,6 +1,7 @@
 local SousChef = SousChef
 local u = SousChef.Utility
 local m = SousChef.Media
+local str = SousChef.Strings[SousChef.lang]

 local BACKPACK = ZO_PlayerInventoryBackpack
 local BANK = ZO_PlayerBankBackpack
@@ -36,10 +37,11 @@ m.COOKINGB = { COOKING_RANK_1B, COOKING_RANK_2B, COOKING_RANK_3B, COOKING_RANK_4
 m.CANLEARN = [[/esoui/art/loot/loot_finesseitem.dds]]

 local INVENTORIES = {
-						[PLAYER_INVENTORY.inventories[1].listView] = {GetItemLink, "bagId", "slotIndex"}, -- Backpack
-						[PLAYER_INVENTORY.inventories[3].listView] = {GetItemLink, "bagId", "slotIndex"}, -- Bank
-						[PLAYER_INVENTORY.inventories[4].listView] = {GetItemLink, "bagId", "slotIndex"}, -- GuildBank
-						[LOOT_WINDOW.list]   					   = {GetLootItemLink, "lootId", nil}	  -- LootWindow
+						[PLAYER_INVENTORY.inventories[1].listView]	= {GetItemLink, "bagId", "slotIndex"}, -- Backpack
+						[PLAYER_INVENTORY.inventories[3].listView]	= {GetItemLink, "bagId", "slotIndex"}, -- Bank
+						[PLAYER_INVENTORY.inventories[4].listView]	= {GetItemLink, "bagId", "slotIndex"}, -- GuildBank
+						[LOOT_WINDOW.list]							= {GetLootItemLink, "lootId", nil},	  -- LootWindow
+						[STORE_WINDOW.list]							= {GetStoreItemLink, "slotIndex", nil},	-- Store
 }
 local rowClicked = {}

@@ -105,12 +107,16 @@ function SousChef.AddDetails(row)
 	local rowInfo = row.dataEntry.data
 	local bagId = rowInfo.bagId or rowInfo.lootId
 	local slotIndex = rowInfo.slotIndex
+	if bagId == nil then
+		bagId = slotIndex
+		slotIndex = nil
+	end

 	if u.MatchesRecipe(rowInfo.name and rowInfo.name or "") then
         local gmatch = u.MatchInGlobalCookbook(rowInfo.name)
         if gmatch then
             ZO_Tooltip_AddDivider(ItemTooltip)
-            ItemTooltip:AddLine("Known by ", "ZoFontWinH5", 1,1,1, BOTTOM, MODIFY_TEXT_TYPE_UPPERCASE)
+            ItemTooltip:AddLine(str.TOOLTIP_KNOWN_BY, "ZoFontWinH5", 1,1,1, BOTTOM, MODIFY_TEXT_TYPE_UPPERCASE)
             ItemTooltip:AddLine(u.TableKeyConcat(gmatch))
             return false
         end
@@ -118,12 +124,12 @@ function SousChef.AddDetails(row)

     if SousChef.settings.onlyShowShopping and SousChef.slotLines[row:GetName()] and SousChef.slotLines[row:GetName()]:IsHidden() then return end

-	local itemId = u.GetItemID(slotIndex and GetItemLink(bagId, slotIndex) or GetLootItemLink(bagId)) -- Get itemId of inventory or loot slot
+	local itemId = u.GetItemID((slotIndex and GetItemLink(bagId, slotIndex)) or (rowInfo.lootId and GetLootItemLink(bagId)) or (GetStoreItemLink(bagId))) -- Get itemId of inventory or loot or store slot
 	local usableIngredient = SousChef.ReverseCookbook[itemId]
 	if SousChef.settings.showAltIngredientKnowledge then usableIngredient = SousChef.settings.ReverseCookbook[itemId] end
 	if usableIngredient then
 		ZO_Tooltip_AddDivider(ItemTooltip)
-		ItemTooltip:AddLine("Used in:", "ZoFontWinH5", 1,1,1, BOTTOM, MODIFY_TEXT_TYPE_UPPERCASE)
+		ItemTooltip:AddLine(str.TOOLTIP_USED_IN, "ZoFontWinH5", 1,1,1, BOTTOM, MODIFY_TEXT_TYPE_UPPERCASE)
 	    for i,v in ipairs(usableIngredient) do
 	    	local line = v
 	    	if type(SousChef.settings.shoppingList[v]) == "table" and next(SousChef.settings.shoppingList[v]) then
@@ -147,19 +153,19 @@ end
 function SousChef.AddRecipeToIgnoreList(link)
 	if GetItemLinkInfo(link) ~= "" then link = string.match(link, "([%w\128-\244 ]+)%]") end
 	SousChef.settings.ignoredRecipes[link] = true
-	d("Adding " .. link .. " to ignored recipes")
+	d(str.SC_ADDING1 .. link .. str.SC_ADDING2)

 end

 function SousChef.RemoveRecipeFromIgnoreList(link)
 	if GetItemLinkInfo(link) ~= "" then link = string.match(link, "([%w\128-\244 ]+)%]") end
-	if not SousChef.settings.ignoredRecipes[link] then d(link .. " not found in ignore list") return end
+	if not SousChef.settings.ignoredRecipes[link] then d(link .. str.SC_NOT_FOUND) return end
 	SousChef.settings.ignoredRecipes[link] = nil
-	d("Removed " .. link .. " from ignored recipes")
+	d(str.SC_REMOVING1 .. link .. str.SC_REMOVING2)
 end

 function SousChef.ListIgnoredRecipes()
-	d("Ignoring:")
+	d(str.SC_IGNORED)
 	 for recipe in pairs(SousChef.settings.ignoredRecipes) do
         d(recipe)
     end
diff --git a/Provisioning.lua b/Provisioning.lua
index afe8acf..67e0840 100644
--- a/Provisioning.lua
+++ b/Provisioning.lua
@@ -1,6 +1,7 @@
 local SousChef = SousChef
 local u = SousChef.Utility
 local m = SousChef.Media
+local str = SousChef.Strings[SousChef.lang]

 -- SousChef:UpdateProvisioningTable() adds the Quality checkbox to the provisioner window and overrides the filtering function to incorporate it
 function SousChef:UpdateProvisioningTable()
@@ -11,7 +12,7 @@ function SousChef:UpdateProvisioningTable()
 	-- set up the quality checkbox
     self.qualityCheckBox = SousChef_ControllerOnlyQuality
     self.qualityCheckBox:SetParent(ZO_ProvisionerTopLevel)
-    ZO_CheckButton_SetLabelText(self.qualityCheckBox, "Quality")
+    ZO_CheckButton_SetLabelText(self.qualityCheckBox, str.PROVISIONING_QUALITY)
     ZO_CheckButton_SetToggleFunction(self.qualityCheckBox, OnFilterChanged)
     ZO_CraftingUtils_ConnectCheckBoxToCraftingProcess(self.qualityCheckBox)
     ZO_CheckButton_SetCheckState(self.qualityCheckBox, self.settings.qualityChecked)
@@ -22,17 +23,16 @@ function SousChef:UpdateProvisioningTable()

 	-- incorporate new checkbox into the filter
     SousChef.filter = PROVISIONER.DoesRecipePassFilter
-    PROVISIONER.DoesRecipePassFilter =
-        function(control, specialIngredientType, numCreatable, provisionerLevelReq, qualityReq)
-            if ZO_CheckButton_IsChecked(self.qualityCheckBox) and qualityReq < 2 then return false end
-            return SousChef.filter(control, specialIngredientType, numCreatable, provisionerLevelReq, qualityReq)
-        end
+    PROVISIONER.DoesRecipePassFilter = function(control, specialIngredientType, numCreatable, provisionerLevelReq, qualityReq)
+		if ZO_CheckButton_IsChecked(self.qualityCheckBox) and qualityReq < 2 then return false end
+		return SousChef.filter(control, specialIngredientType, numCreatable, provisionerLevelReq, qualityReq)
+	end
 end

 -- this is our "Mark Recipe" button definition
 SousChef.ProvisioningButton=
 {{
-    name = "Mark Recipe", -- or function that returns a name
+    name = str.KEY_MARK,
     keybind = "SC_MARK_RECIPE",
     control = self,
     callback = function(descriptor) SousChef:MarkRecipe() end,
@@ -80,19 +80,19 @@ function SousChef:getMarkedIcon(row, marked)
         rankIcon:SetAnchor(RIGHT, row, LEFT, -10)
         rankIcon:SetMouseEnabled(true)
         rankIcon:SetHandler("OnMouseExit", function()
-                                                ClearTooltip(InformationTooltip)
-                                            end)
+			ClearTooltip(InformationTooltip)
+		end)
     end
 	-- then, if the recipe is marked by someone, show who, and set the checkmark's alpha accordingly
     if marked then
         rankIcon:SetHandler("OnMouseEnter", function()
-                                        InitializeTooltip(InformationTooltip, rankIcon, RIGHT, -15, 0)
-                                        InformationTooltip:AddLine("Marked by: " .. marked)
-                                    end)
+			InitializeTooltip(InformationTooltip, rankIcon, RIGHT, -15, 0)
+			InformationTooltip:AddLine(str.PROVISIONING_MARKED .. marked)
+		end)
         if not marked:find(GetUnitName("player"), 1, true) then
-            rankIcon:SetColor(1,1,1,0.2)
+			rankIcon:SetColor(1,1,1,0.2)
         else
-            rankIcon:SetColor(1,1,1,1)
+			rankIcon:SetColor(1,1,1,1)
         end
     end
     return rankIcon
@@ -125,7 +125,7 @@ function SousChef:MarkRecipe()
     else
         SousChef.settings.shoppingList[link][GetUnitName("player")] = nil -- we're now unmarked
 		-- if that was the last mark we just got rid of, then nil out the entire recipe entry
-		if u.TableLength(SousChef.settings.shoppingList[link]) == 0 then
+		if NonContiguousCount(SousChef.settings.shoppingList[link]) == 0 then
 			SousChef.settings.shoppingList[link] = nil
 		end
     end
@@ -146,19 +146,16 @@ function SousChef:UnhookRecipeTree()
 end

 function SousChef:HookGetRecipeInfo()
-
     if SousChef.settings.sortProvisioningTable then
         SousChef.OldRefreshRecipeTree = ZO_Provisioner.RefreshRecipeTree
-        ZO_Provisioner.RefreshRecipeTree =
-            function()
-                return SousChef.RefreshRecipeTree(PROVISIONER)
-            end
+        ZO_Provisioner.RefreshRecipeTree = function()
+			return SousChef.RefreshRecipeTree(PROVISIONER)
+		end
     end
     SousChef.OldZO_ProvisionerRow_GetTextColor = ZO_ProvisionerRow_GetTextColor
-    ZO_ProvisionerRow_GetTextColor =
-        function(self)
-            return SousChef.ZO_ProvisionerRow_GetTextColor(self)
-        end
+    ZO_ProvisionerRow_GetTextColor = function(self)
+		return SousChef.ZO_ProvisionerRow_GetTextColor(self)
+	end
 end

 local function SortRecipe(a, b)
diff --git a/SousChef.lua b/SousChef.lua
index c930537..fcba617 100644
--- a/SousChef.lua
+++ b/SousChef.lua
@@ -27,6 +27,8 @@ SousChef.settings = nil
 SousChef.slotLines = {}
 SousChef.hookedFunctions = {}
 SousChef.hookedDataFunction = nil
+SousChef.lang = GetCVar("Language.2")
+if SousChef.lang ~= "en" and SousChef.lang ~= "de" and SousChef.lang ~= "fr" then SousChef.lang = "en" end

 local rowHandler = {}

@@ -110,7 +112,8 @@ function SousChef:ParseRecipes()
 end

 -- SousChefCreateSettings() creates the configuration menu for the add-on
-local function SousChefCreateSettings()
+local function SousChefCreateSettings()
+	local str = SousChef.Strings[SousChef.lang]
 	local panelData = {
 		type = "panel",
 		name = "Sous Chef",
@@ -118,6 +121,7 @@ local function SousChefCreateSettings()
 		author = "Wobin & KatKat42 & CrazyDutchGuy",
 		version = "1.18",
 		registerForRefresh = true,
+		slashCommand = "/souschef",
 	}

 	LAM:RegisterAddonPanel("SousChefSettings", panelData)
@@ -125,174 +129,202 @@ local function SousChefCreateSettings()
 	local optionsMenu = {
 		[1] = {
 			type = "header",
-			name = "Recipe Options",
+			name = str.MENU_RECIPE_HEADER,
 			width = "full",
 		},

 		[2] = {
 			type = "checkbox",
-			name = "Have Sous Chef check for recipes",
-			tooltip = "Non English clients may want to untick this if the experimental matching isn't sufficient",
+			name = str.MENU_PROCESS_RECIPES,
+			tooltip = str.MENU_PROCESS_RECIPES_TOOLTIP,
 			getFunc = function() return SousChef.settings.processRecipes end,
-			setFunc = function(value)
-								SousChef.settings.processRecipes = not SousChef.settings.processRecipes
-							end,
+			setFunc = function(value) SousChef.settings.processRecipes = value end,
 			width = "full",
 		},

 		[3] = {
 			type = "dropdown",
-			name = "Mark if recipes are ",
-			tooltip = "How do you want Sous Chef to indicate your knowledge of a recipe?",
-			choices = {"known", "unknown"},
-			getFunc = function() return SousChef.settings.checkKnown end,
-			setFunc = function(valueString) SousChef.settings.checkKnown = valueString end,
+			name = str.MENU_MARK_IF_KNOWN,
+			tooltip = str.MENU_MARK_IF_KNOWN_TOOLTIP,
+			choices = {str.MENU_KNOWN, str.MENU_UNKNOWN},
+			getFunc = function()
+				if SousChef.settings.checkKnown == "known" then
+					return str.MENU_KNOWN
+				elseif SousChef.settings.checkKnown == "unknown" then
+					return str.MENU_UNKNOWN
+				else
+					-- can't happen
+					d("Yikes! MENU_MARK_IF_KNOWN getter")
+					return str.MENU_UNKNOWN
+				end
+			end,
+			setFunc = function(valueString)
+				if valueString == str.MENU_KNOWN then
+					SousChef.settings.checkKnown = "known"
+				elseif valueString == str.MENU_UNKNOWN then
+					SousChef.settings.checkKnown = "unknown"
+				else
+					-- can't happen
+					d("Oops! MENU_MARK_IF_KNOWN setter")
+					SousChef.settings.checkKnown = "unknown"
+				end
+			end,
 			disabled = function() return not SousChef.settings.processRecipes end,
 		},

 		[4] = {
 			type = "checkbox",
-			name = "Alternate Character Check",
-			tooltip = "Indicate if an alt knows the recipe on unknown recipes. Will only work if the above setting is set to 'unknown'",
+			name = str.MENU_MARK_IF_ALT_KNOWS,
+			tooltip = str.MENU_MARK_IF_ALT_KNOWS_TOOLTIP,
 			getFunc = function() return SousChef.settings.markAlt end,
-			setFunc = function(value) SousChef.settings.markAlt = not SousChef.settings.markAlt SousChef:RefreshViews() end,
-			disabled = function() return not SousChef.settings.processRecipes end,
+			setFunc = function(value) SousChef.settings.markAlt = value SousChef:RefreshViews() end,
+			disabled = function() return (not SousChef.settings.processRecipes) or (SousChef.settings.checkKnown == "known") end,
 		},

 		[5] = {
 			type = "checkbox",
-			name = "Alternate Character Recipe Knowledge",
-			tooltip = "Show in tooltips which characters know a recipe",
+			name = str.MENU_TOOLTIP_IF_ALT_KNOWS,
+			tooltip = str.MENU_TOOLTIP_IF_ALT_KNOWS_TOOLTIP,
 			getFunc = function() return SousChef.settings.showAltKnowledge end,
-			setFunc = function(value) SousChef.settings.showAltKnowledge = not SousChef.settings.showAltKnowledge SousChef:RefreshViews() end,
+			setFunc = function(value) SousChef.settings.showAltKnowledge = value SousChef:RefreshViews() end,
 			disabled = function() return not SousChef.settings.processRecipes end,
 		},

 		[6] = {
 			type = "checkbox",
-			name = "Use the Experimental Recipe Matcher",
-			tooltip = "Currently Sous Chef cannot match reliably in other languages. This will attempt to match as best it can by stripping out common prepositions so that the recipe and result match better. (NOTE: please file a typo bug report with Zenimax if you find recipe names that don't match their results exactly)",
+			name = str.MENU_MATCHER,
+			tooltip = str.MENU_MATCHER_TOOLTIP,
 			getFunc = function() return SousChef.settings.experimentalMatch end,
-			setFunc = function(value) SousChef.settings.experimentalMatch = not SousChef.settings.experimentalMatch end,
+			setFunc = function(value) SousChef.settings.experimentalMatch = value end,
 			disabled = function() return not SousChef.settings.processRecipes end,
 		},

 		[7] = {
 			type = "checkbox",
-			name = "Sort the Provisioning Table",
-			tooltip = "Will sort the provisioning table by Rank, Quality, then Name (but not by required level)",
+			name = str.MENU_SORT_PROVISIONING,
+			tooltip = str.MENU_SORT_PROVISIONING_TOOLTIP,
 			getFunc = function() return SousChef.settings.sortProvisioningTable end,
-			setFunc = function(value) SousChef.settings.sortProvisioningTable = not SousChef.settings.sortProvisioningTable end,
+			setFunc = function(value) SousChef.settings.sortProvisioningTable = value end,
 		},

 		[8] = {
 			type = "header",
-			name = "Tooltip Options",
+			name = str.MENU_TOOLTIP_HEADER,
 			width = "full",
 		},

 		[9] = {
 			type = "checkbox",
-			name = "Show Sous Chef in Ingredient tooltips after Mouse Click",
-			tooltip = "Only show Sous Chef information in ingredient tooltips after a mouse click, to save space",
-			warning = "Requires UI Reload",
+			name = str.MENU_TOOLTIP_CLICK,
+			tooltip = str.MENU_TOOLTIP_CLICK_TOOLTIP,
+			warning = str.MENU_RELOAD,
 			getFunc = function() return SousChef.settings.showOnClick end,
-			setFunc = function(value) SousChef.settings.showOnClick = not SousChef.settings.showOnClick end,
+			setFunc = function(value) SousChef.settings.showOnClick = value end,
 		},

 		[10] = {
 			type = "checkbox",
-			name = "Show Recipe Result Counts",
-			tooltip = "Show how many of each recipe can be made in the Ingredient tooltip",
+			name = str.MENU_RESULT_COUNTS,
+			tooltip = str.MENU_RESULT_COUNTS_TOOLTIP,
 			getFunc = function() return SousChef.settings.showCounts end,
-			setFunc = function(value) SousChef.settings.showCounts = not SousChef.settings.showCounts end,
+			setFunc = function(value) SousChef.settings.showCounts = value end,
 		},

 		[11] = {
 			type = "checkbox",
-			name = "Alternate Character Ingredient Knowledge",
-			tooltip = "Indicte if an alt uses the ingredients",
+			name = str.MENU_ALT_USE,
+			tooltip = str.MENU_ALT_USE_TOOLTIP,
 			getFunc = function() return SousChef.settings.showAltIngredientKnowledge end,
-			setFunc = function(value) SousChef.settings.showAltIngredientKnowledge = not SousChef.settings.showAltIngredientKnowledge SousChef:RefreshViews() end,
+			setFunc = function(value) SousChef.settings.showAltIngredientKnowledge = value SousChef:RefreshViews() end,
 		},

 		[12] = {
 			type = "header",
-			name = "Indicator Options",
+			name = str.MENU_INDICATOR_HEADER,
 			width = "full",
 		},

 		[13] = {
 			type = "checkbox",
-			name = "Use bolder icons",
-			tooltip = "Swap out rank icons to a more flat display",
+			name = str.MENU_ICON_SET,
+			tooltip = str.MENU_ICON_SET_TOOLTIP,
 			getFunc = function() return SousChef.settings.boldIcon end,
-			setFunc = function(value) SousChef.settings.boldIcon = not SousChef.settings.boldIcon SousChef:RefreshViews() end,
+			setFunc = function(value) SousChef.settings.boldIcon = value SousChef:RefreshViews() end,
 		},

 		[14] = {
 			type = "checkbox",
-			name = "Show Special Ingredients",
-			tooltip = "If an ingredient is considered a Spice/Flavour, indicate that rather than the tier of the highest tier recipe that uses it",
+			name = str.MENU_SPECIAL_ICONS,
+			tooltip = str.MENU_SPECIAL_ICONS_TOOLTIP,
 			getFunc = function() return SousChef.settings.showSpecialIngredients end,
 			setFunc = function(value)
-							SousChef.settings.showSpecialIngredients = not SousChef.settings.showSpecialIngredients
-							SousChef.ParseRecipes()
-						end,
+				SousChef.settings.showSpecialIngredients = value
+				SousChef.ParseRecipes()
+			end,
 		},

 		[15] = {
 			type = "checkbox",
-			name = "Show Special Ingredient Types",
-			tooltip = "Use the icon for the type of food it's a special ingredient for, eg Grilled",
+			name = str.MENU_SPECIAL_TYPES,
+			tooltip = str.MENU_SPECIAL_TYPES_TOOLTIP,
 			getFunc = function() return SousChef.settings.typeIcon end,
-			setFunc = function(value) SousChef.settings.typeIcon = not SousChef.settings.typeIcon SousChef.ParseRecipes() SousChef:RefreshViews() end,
+			setFunc = function(value) SousChef.settings.typeIcon = value SousChef.ParseRecipes() SousChef:RefreshViews() end,
 			disabled = function() return not SousChef.settings.showSpecialIngredients end,
 		},

 		[16] = {
 			type = "colorpicker",
-			name = "Indicator Colour",
-			tooltip = "Allows you to set the colour of the recipe indicator",
+			name = str.MENU_INDICATOR_COLOR,
+			tooltip = str.MENU_INDICATOR_COLOR_TOOLTIP,
 			getFunc = function() return SousChef.settings.colour[1], SousChef.settings.colour[2], SousChef.settings.colour[3] end,
-			setFunc = function(r,g,b) SousChef.settings.colour[1] = r; SousChef.settings.colour[2] = g; SousChef.settings.colour[3] = b; SousChef:RefreshViews() end,
+			setFunc = function(r,g,b)
+				SousChef.settings.colour[1] = r
+				SousChef.settings.colour[2] = g
+				SousChef.settings.colour[3] = b
+				SousChef:RefreshViews()
+			end,
 		},

 		[17] = {
 			type = "colorpicker",
-			name = "Shopping List Indicator Colour",
-			tooltip = "Allows you to set the colour of hte indicator for ingredients in your Shopping List",
+			name = str.MENU_SHOPPING_COLOR,
+			tooltip = str.MENU_SHOPPING_COLOR_TOOLTIP,
 			getFunc = function() return SousChef.settings.shoppingColour[1], SousChef.settings.shoppingColour[2], SousChef.settings.shoppingColour[3] end,
-			setFunc = function(r,g,b) SousChef.settings.shoppingColour[1] = r; SousChef.settings.shoppingColour[2] = g; SousChef.settings.shoppingColour[3] = b; SousChef:RefreshViews() end,
+			setFunc = function(r,g,b)
+				SousChef.settings.shoppingColour[1] = r
+				SousChef.settings.shoppingColour[2] = g
+				SousChef.settings.shoppingColour[3] = b
+				SousChef:RefreshViews()
+			end,
 		},

 		[18] = {
 			type = "checkbox",
-			name = "Only Mark Shopping List Ingredients",
-			tooltip = "Only mark ingredients on your Shopping List",
+			name = str.MENU_ONLY_MARK_SHOPPING,
+			tooltip = str.MENU_ONLY_MARK_SHOPPING_TOOLTIP,
 			getFunc = function() return SousChef.settings.onlyShowShopping end,
-			setFunc = function(value) SousChef.settings.onlyShowShopping = not SousChef.settings.onlyShowShopping SousChef:RefreshViews() end,
+			setFunc = function(value) SousChef.settings.onlyShowShopping = value SousChef:RefreshViews() end,
 		},

 		[19] = {
 			type = "checkbox",
-			name = "Sort Ingredients in Inventory",
-			tooltip = "Will sort known ingredients by rank",
+			name = str.MENU_SORT_INGREDIENTS,
+			tooltip = str.MENU_SORT_INGREDIENTS_TOOLTIP,
 			getFunc = function() return SousChef.settings.sortKnownIngredients end,
 			setFunc = function(value)
-								SousChef.settings.sortKnownIngredients = not SousChef.settings.sortKnownIngredients
-								if not SousChef.settings.sortKnownIngredients then
-									SousChef.UnregisterSort()
-								else
-									SousChef.SetupSort()
-								end
-							end,
+				SousChef.settings.sortKnownIngredients = not SousChef.settings.sortKnownIngredients
+				if not SousChef.settings.sortKnownIngredients then
+					SousChef.UnregisterSort()
+				else
+					SousChef.SetupSort()
+				end
+			end,
 		},
 	}

 	LAM:RegisterOptionControls("SousChefSettings", optionsMenu)

-	ZO_CreateStringId("SI_BINDING_NAME_SC_MARK_RECIPE", "Mark Recipe")
+	ZO_CreateStringId("SI_BINDING_NAME_SC_MARK_RECIPE", str.KEY_MARK)
 end

 -- SousChef_Loaded(eventCode, addOnName) runs when the EVENT_ADD_ON_LOADED event fires.
@@ -301,7 +333,7 @@ local function SousChef_Loaded(eventCode, addOnName)

 	-- default config settings
 	local defaults = {
-		watching = true,
+		--watching = true,
 		checkKnown = "unknown",
 		markAlt = false,
 		colour = {1, 1, 1},
@@ -326,19 +358,22 @@ local function SousChef_Loaded(eventCode, addOnName)
         sortKnownIngredients = false
 	}

+	local localized = SousChef.Strings[SousChef.lang]
+
 	-- Fetch the saved variables
-    SousChef.settings = ZO_SavedVars:NewAccountWide("SousChef_Settings", 9, GetCVar("Language.2"), defaults)
+    SousChef.settings = ZO_SavedVars:NewAccountWide("SousChef_Settings", 9, SousChef.lang, defaults)

-	local function tablelength(T)
-		local count = 0
-		for _ in pairs(T) do count = count + 1 end
-		return count
-	end
+	-- replaced with ZO's NonContiguousCount()
+	-- local function tablelength(T)
+		-- local count = 0
+		-- for _ in pairs(T) do count = count + 1 end
+		-- return count
+	-- end

 	-- define some slash commands
 	SLASH_COMMANDS['/scstats'] = function()
-		d("Number of recipes known: ".. tablelength(SousChef.settings.Cookbook))
-		d("Number of ingredients tracked: "..tablelength(SousChef.settings.Pantry))
+		d(localized.SC_NUM_RECIPES_KNOWN.. NonContiguousCount(SousChef.settings.Cookbook))
+		d(localized.SC_NUM_INGREDIENTS_TRACKED..NonContiguousCount(SousChef.settings.Pantry))
 	end
 	SLASH_COMMANDS['/sciadd'] = SousChef.AddRecipeToIgnoreList
 	SLASH_COMMANDS['/sciremove'] = SousChef.RemoveRecipeFromIgnoreList
diff --git a/SousChef.txt b/SousChef.txt
index 048b160..f816c08 100644
--- a/SousChef.txt
+++ b/SousChef.txt
@@ -1,4 +1,4 @@
-## Title: |cFFFFB0Sous Chef|r by |c00C000Wobin & CrazyDutchGuy & KatKat42|r
+## Title: Sous Chef by Wobin, CrazyDutchGuy & KatKat42
 ## Author: Wobin & CrazyDutchGuy & KatKat42
 ## Version: @project-version@
 ## APIVersion: 100009
@@ -25,6 +25,7 @@ libs\LibSort-1.0\LibSort-1.0.lua

 SousChef.lua
 Utility.lua
+Strings.lua
 Common.lua
 Inventory.lua
 TradingHouse.lua
diff --git a/SousChef.xml b/SousChef.xml
index 68275d2..6f6b1b6 100644
--- a/SousChef.xml
+++ b/SousChef.xml
@@ -2,10 +2,10 @@
     <Controls>
         <TopLevelControl name="SousChef_Controller">
         	<Controls>
-        	<Button name="$(parent)OnlyQuality" inherits="ZO_CheckButton">
-                    <Anchor point="LEFT" relativeTo="ZO_ProvisionerTopLevelHaveSkills" relativePoint="RIGHT" offsetX="150" />
-            </Button>
-        </Controls>
+				<Button name="$(parent)OnlyQuality" inherits="ZO_CheckButton">
+					<Anchor point="LEFT" relativeTo="ZO_ProvisionerTopLevelHaveSkills" relativePoint="RIGHT" offsetX="150" />
+				</Button>
+			</Controls>
         </TopLevelControl>
     </Controls>
 </GuiXml>
\ No newline at end of file
diff --git a/Strings.lua b/Strings.lua
new file mode 100644
index 0000000..e40c423
--- /dev/null
+++ b/Strings.lua
@@ -0,0 +1,188 @@
+SousChef.Strings = {
+	en = {
+		-- for slash commands
+		SC_NUM_RECIPES_KNOWN = "Number of recipes known: ",
+		SC_NUM_INGREDIENTS_TRACKED = "Number of ingredients tracked: ",
+		SC_NOT_FOUND = " not found in ignore list",
+		SC_ADDING1 = "Adding ",
+		SC_ADDING2 = " to ignored recipes",
+		SC_REMOVING1 = "Removed ",
+		SC_REMOVING2 = " from ignored recipes",
+		SC_IGNORED = "Ignoring:",
+
+		-- Menu items
+		MENU_RECIPE_HEADER = "Recipe Options",
+		MENU_PROCESS_RECIPES = "Have Sous Chef display info for recipes",
+		MENU_PROCESS_RECIPES_TOOLTIP = "Non English clients may want to untick this if the experimental matching isn't sufficient",
+		MENU_MARK_IF_KNOWN = "Mark recipe if it is ",
+		MENU_KNOWN = "known",
+		MENU_UNKNOWN = "unknown",
+		MENU_MARK_IF_KNOWN_TOOLTIP = "When do you want Sous Chef to display an indicator by a recipe?",
+		MENU_MARK_IF_ALT_KNOWS = "Alternate Character Indicator",
+		MENU_MARK_IF_ALT_KNOWS_TOOLTIP = "Fade the indicator for unknown recipes if an alt knows the recipe.",
+		MENU_TOOLTIP_IF_ALT_KNOWS = "List Character Recipe Knowledge in Tooltips",
+		MENU_TOOLTIP_IF_ALT_KNOWS_TOOLTIP = "Show in tooltips which characters know a recipe",
+		MENU_MATCHER = "Use the Experimental Recipe Matcher",
+		MENU_MATCHER_TOOLTIP = "Currently Sous Chef cannot match reliably in other languages. This will attempt to match as best it can by stripping out common prepositions so that the recipe and result match better. (NOTE: please file a typo bug report with Zenimax if you find recipe names that don't match their results exactly)",
+		MENU_SORT_PROVISIONING = "Sort the Provisioning Table",
+		MENU_SORT_PROVISIONING_TOOLTIP = "Will sort the provisioning table by Level, Quality, then Name",
+		MENU_TOOLTIP_HEADER = "Ingredient Tooltip Options",
+		MENU_TOOLTIP_CLICK = "Require Mouse Click to Show Sous Chef Data",
+		MENU_TOOLTIP_CLICK_TOOLTIP = "Only show Sous Chef information in ingredient tooltips after a mouse click, to save space",
+		MENU_RESULT_COUNTS = "Show Recipe Result Counts",
+		MENU_RESULT_COUNTS_TOOLTIP = "Show how many of each recipe can be made in the Ingredient tooltip",
+		MENU_ALT_USE = "Alternate Character Ingredient Usage",
+		MENU_ALT_USE_TOOLTIP = "Indicte if an alt uses an ingredient",
+		MENU_INDICATOR_HEADER = "Indicator Options",
+		MENU_ICON_SET = "Use bolder icons",
+		MENU_ICON_SET_TOOLTIP = "Swap out rank icons to a more flat display",
+		MENU_SPECIAL_ICONS = "Special Icons for Special Ingredients",
+		MENU_SPECIAL_ICONS_TOOLTIP = "If an ingredient is considered a Spice/Flavour, indicate that rather than the tier of the highest tier recipe that uses it",
+		MENU_SPECIAL_TYPES = "Show Special Ingredient Types",
+		MENU_SPECIAL_TYPES_TOOLTIP = "Use the icon for the type of food it's a special ingredient for, eg Grilled",
+		MENU_INDICATOR_COLOR = "Indicator Colour",
+		MENU_INDICATOR_COLOR_TOOLTIP = "Allows you to set the colour of the recipe indicator",
+		MENU_SHOPPING_COLOR = "Shopping List Indicator Colour",
+		MENU_SHOPPING_COLOR_TOOLTIP = "Allows you to set the colour of the indicator for ingredients in your Shopping List",
+		MENU_ONLY_MARK_SHOPPING = "Only Mark Shopping List Ingredients",
+		MENU_ONLY_MARK_SHOPPING_TOOLTIP = "Only mark ingredients on your Shopping List",
+		MENU_SORT_INGREDIENTS = "Sort Ingredients in Inventory",
+		MENU_SORT_INGREDIENTS_TOOLTIP = "Will sort known ingredients by rank",
+		MENU_RELOAD = "Requires UI Reload",
+
+		-- keybinding label
+		KEY_MARK = "Mark Recipe",
+
+		-- provisioning window
+		PROVISIONING_QUALITY = "Hide Green Recipes",
+		PROVISIONING_MARKED = "Marked by: ",
+
+		-- tooltip
+		TOOLTIP_KNOWN_BY = "Known by ",
+		TOOLTIP_USED_IN = "Used in:",
+	},
+	de = {
+		-- for slash commands
+		SC_NUM_RECIPES_KNOWN = "Wieviele Rezepte bekannt: ",
+		SC_NUM_INGREDIENTS_TRACKED = "Wieviele Zutaten nachspuert: ",
+		SC_NOT_FOUND = ": nicht in Ausklammersliste gefunden",
+		SC_ADDING1 = "",
+		SC_ADDING2 = " zu Ausklammersliste",
+		SC_REMOVING1 = "",
+		SC_REMOVING2 = "wurde aus Ausklammersliste entfernt",
+		SC_IGNORED = "Ausgeklammert:",
+
+		-- Menu items
+		MENU_RECIPE_HEADER = "Rezeptswaehle",
+		MENU_PROCESS_RECIPES = "Rezeptsinfos zeigen",
+		MENU_PROCESS_RECIPES_TOOLTIP = "Wenn experimentell Rezeptspasser nicht genug ist, dieses Quadrat unwaehlen",
+		MENU_MARK_IF_KNOWN = "Rezept markieren wenn?",
+		MENU_KNOWN = "bekannt",
+		MENU_UNKNOWN = "unbekannt",
+		MENU_MARK_IF_KNOWN_TOOLTIP = "Wenn soll Sous Chef ein Ikon beim Rezept anzeigen?",
+		MENU_MARK_IF_ALT_KNOWS = "Alternate Character Indicator",
+		MENU_MARK_IF_ALT_KNOWS_TOOLTIP = "Fade the indicator for unknown recipes if an alt knows the recipe.",
+		MENU_TOOLTIP_IF_ALT_KNOWS = "List Character Recipe Knowledge in Tooltips",
+		MENU_TOOLTIP_IF_ALT_KNOWS_TOOLTIP = "Show in tooltips which characters know a recipe",
+		MENU_MATCHER = "Experimentell Rezeptspasser benuetzen",
+		MENU_MATCHER_TOOLTIP = "Currently Sous Chef cannot match reliably in other languages. This will attempt to match as best it can by stripping out common prepositions so that the recipe and result match better. (NOTE: please file a typo bug report with Zenimax if you find recipe names that don't match their results exactly)",
+		MENU_SORT_PROVISIONING = "Provisioning Table sortieren",
+		MENU_SORT_PROVISIONING_TOOLTIP = "Will sort the provisioning table by Level, Quality, then Name",
+		MENU_TOOLTIP_HEADER = "Zutats-tooltip Waehle",
+		MENU_TOOLTIP_CLICK = "Require Mouse Click to Show Sous Chef Data",
+		MENU_TOOLTIP_CLICK_TOOLTIP = "Only show Sous Chef information in ingredient tooltips after a mouse click, to save space",
+		MENU_RESULT_COUNTS = "Show Recipe Result Counts",
+		MENU_RESULT_COUNTS_TOOLTIP = "Show how many of each recipe can be made in the Ingredient tooltip",
+		MENU_ALT_USE = "Alternate Character Ingredient Usage",
+		MENU_ALT_USE_TOOLTIP = "Indicte if an alt uses an ingredient",
+		MENU_INDICATOR_HEADER = "Indicator Options",
+		MENU_ICON_SET = "Staerker Ikons benuetzen",
+		MENU_ICON_SET_TOOLTIP = "Swap out rank icons to a more flat display",
+		MENU_SPECIAL_ICONS = "Spezielicons fuer Spezielzutaten",
+		MENU_SPECIAL_ICONS_TOOLTIP = "If an ingredient is considered a Spice/Flavour, indicate that rather than the tier of the highest tier recipe that uses it",
+		MENU_SPECIAL_TYPES = "Spezielzutaten Typen zeigen",
+		MENU_SPECIAL_TYPES_TOOLTIP = "Use the icon for the type of food it's a special ingredient for, eg Grilled",
+		MENU_INDICATOR_COLOR = "Ikonsfarbe",
+		MENU_INDICATOR_COLOR_TOOLTIP = "Allows you to set the colour of the recipe indicator",
+		MENU_SHOPPING_COLOR = "Einkaufzettel Ikonsfarbe",
+		MENU_SHOPPING_COLOR_TOOLTIP = "Allows you to set the colour of hte indicator for ingredients in your Shopping List",
+		MENU_ONLY_MARK_SHOPPING = "Nur Zutaten auf dem Einkaufzettel markieren",
+		MENU_ONLY_MARK_SHOPPING_TOOLTIP = "Only mark ingredients on your Shopping List",
+		MENU_SORT_INGREDIENTS = "Zutaten in Inventory sortieren",
+		MENU_SORT_INGREDIENTS_TOOLTIP = "Will sort known ingredients by rank",
+		MENU_RELOAD = "Requires UI Reload",
+
+		-- keybinding label
+		KEY_MARK = "Rezept markieren",
+
+		-- provisioning window
+		PROVISIONING_QUALITY = "Gruene Rezepte verstecken",
+		PROVISIONING_MARKED = "Markiert von: ",
+
+		-- tooltip
+		TOOLTIP_KNOWN_BY = "Bekannt von ",
+		TOOLTIP_USED_IN = "Benuezt beim:",
+	},
+	fr = {
+		-- for slash commands
+		SC_NUM_RECIPES_KNOWN = "Number of recipes known: ",
+		SC_NUM_INGREDIENTS_TRACKED = "Number of ingredients tracked: ",
+		SC_NOT_FOUND = " not found in ignore list",
+		SC_ADDING1 = "Adding ",
+		SC_ADDING2 = " to ignored recipes",
+		SC_REMOVING1 = "Removed ",
+		SC_REMOVING2 = " from ignored recipes",
+		SC_IGNORED = "Ignoring:",
+
+		-- Menu items
+		MENU_RECIPE_HEADER = "Recipe Options",
+		MENU_PROCESS_RECIPES = "Have Sous Chef display info for recipes",
+		MENU_PROCESS_RECIPES_TOOLTIP = "Non English clients may want to untick this if the experimental matching isn't sufficient",
+		MENU_MARK_IF_KNOWN = "Mark recipe if it is ",
+		MENU_KNOWN = "known",
+		MENU_UNKNOWN = "unknown",
+		MENU_MARK_IF_KNOWN_TOOLTIP = "When do you want Sous Chef to display an indicator by a recipe?",
+		MENU_MARK_IF_ALT_KNOWS = "Alternate Character Indicator",
+		MENU_MARK_IF_ALT_KNOWS_TOOLTIP = "Fade the indicator for unknown recipes if an alt knows the recipe.",
+		MENU_TOOLTIP_IF_ALT_KNOWS = "List Character Recipe Knowledge in Tooltips",
+		MENU_TOOLTIP_IF_ALT_KNOWS_TOOLTIP = "Show in tooltips which characters know a recipe",
+		MENU_MATCHER = "Use the Experimental Recipe Matcher",
+		MENU_MATCHER_TOOLTIP = "Currently Sous Chef cannot match reliably in other languages. This will attempt to match as best it can by stripping out common prepositions so that the recipe and result match better. (NOTE: please file a typo bug report with Zenimax if you find recipe names that don't match their results exactly)",
+		MENU_SORT_PROVISIONING = "Sort the Provisioning Table",
+		MENU_SORT_PROVISIONING_TOOLTIP = "Will sort the provisioning table by Level, Quality, then Name",
+		MENU_TOOLTIP_HEADER = "Ingredient Tooltip Options",
+		MENU_TOOLTIP_CLICK = "Require Mouse Click to Show Sous Chef Data",
+		MENU_TOOLTIP_CLICK_TOOLTIP = "Only show Sous Chef information in ingredient tooltips after a mouse click, to save space",
+		MENU_RESULT_COUNTS = "Show Recipe Result Counts",
+		MENU_RESULT_COUNTS_TOOLTIP = "Show how many of each recipe can be made in the Ingredient tooltip",
+		MENU_ALT_USE = "Alternate Character Ingredient Usage",
+		MENU_ALT_USE_TOOLTIP = "Indicte if an alt uses an ingredient",
+		MENU_INDICATOR_HEADER = "Indicator Options",
+		MENU_ICON_SET = "Use bolder icons",
+		MENU_ICON_SET_TOOLTIP = "Swap out rank icons to a more flat display",
+		MENU_SPECIAL_ICONS = "Special Icons for Special Ingredients",
+		MENU_SPECIAL_ICONS_TOOLTIP = "If an ingredient is considered a Spice/Flavour, indicate that rather than the tier of the highest tier recipe that uses it",
+		MENU_SPECIAL_TYPES = "Show Special Ingredient Types",
+		MENU_SPECIAL_TYPES_TOOLTIP = "Use the icon for the type of food it's a special ingredient for, eg Grilled",
+		MENU_INDICATOR_COLOR = "Indicator Colour",
+		MENU_INDICATOR_COLOR_TOOLTIP = "Allows you to set the colour of the recipe indicator",
+		MENU_SHOPPING_COLOR = "Shopping List Indicator Colour",
+		MENU_SHOPPING_COLOR_TOOLTIP = "Allows you to set the colour of hte indicator for ingredients in your Shopping List",
+		MENU_ONLY_MARK_SHOPPING = "Only Mark Shopping List Ingredients",
+		MENU_ONLY_MARK_SHOPPING_TOOLTIP = "Only mark ingredients on your Shopping List",
+		MENU_SORT_INGREDIENTS = "Sort Ingredients in Inventory",
+		MENU_SORT_INGREDIENTS_TOOLTIP = "Will sort known ingredients by rank",
+		MENU_RELOAD = "Requires UI Reload",
+
+		-- keybinding label
+		KEY_MARK = "Mark Recipe",
+
+		-- provisioning window
+		PROVISIONING_QUALITY = "Hide Green Recipes",
+		PROVISIONING_MARKED = "Marked by: ",
+
+		-- tooltip
+		TOOLTIP_KNOWN_BY = "Known by ",
+		TOOLTIP_USED_IN = "Used in:",
+	},
+}
\ No newline at end of file
diff --git a/TradingHouse.lua b/TradingHouse.lua
index cdd45d1..a9f66d9 100644
--- a/TradingHouse.lua
+++ b/TradingHouse.lua
@@ -2,32 +2,30 @@ local SousChef = SousChef
 local u = SousChef.Utility
 local m = SousChef.Media

-function SousChef.AddTradingSlot(row, result)
-	local rankIcon = SousChef.getIcon(row)
+-- function SousChef.AddTradingSlot(row, result)
+	-- local rankIcon = SousChef.getIcon(row)

-	rankIcon:SetHidden(true)
-    if SousChef.settings.processRecipes then
-        if u.MatchInIgnoreList(result.name) then return end
-        if u.MatchesRecipe(result.name) then
-            local match = u.MatchInCookbook(result.name)
-            local gmatch = u.MatchInGlobalCookbook(result.name)
-            if (match and SousChef.settings.checkKnown == "known") or
-               (not match and SousChef.settings.checkKnown == "unknown")then
-                rankIcon:SetDimensions(30, 30)
-                rankIcon:SetAnchor(CENTER, row, CENTER, 230)
-                rankIcon:SetTexture(m.CANLEARN)
-                rankIcon:SetHidden(false)
-                if not match and gmatch and SousChef.settings.checkKnown == "unknown" and SousChef.settings.markAlt then
-                    rankIcon:SetColor(1,1,1,0.2)
-                else
-                    rankIcon:SetColor(1,1,1,1)
-                end
-            end
-        end
-    end
-end
-
-
+	-- rankIcon:SetHidden(true)
+    -- if SousChef.settings.processRecipes then
+        -- if u.MatchInIgnoreList(result.name) then return end
+        -- if u.MatchesRecipe(result.name) then
+            -- local match = u.MatchInCookbook(result.name)
+            -- local gmatch = u.MatchInGlobalCookbook(result.name)
+            -- if (match and SousChef.settings.checkKnown == "known") or
+               -- (not match and SousChef.settings.checkKnown == "unknown")then
+                -- rankIcon:SetDimensions(30, 30)
+                -- rankIcon:SetAnchor(CENTER, row, CENTER, 230)
+                -- rankIcon:SetTexture(m.CANLEARN)
+                -- rankIcon:SetHidden(false)
+                -- if not match and gmatch and SousChef.settings.checkKnown == "unknown" and SousChef.settings.markAlt then
+                    -- rankIcon:SetColor(1,1,1,0.2)
+                -- else
+                    -- rankIcon:SetColor(1,1,1,1)
+                -- end
+            -- end
+        -- end
+    -- end
+-- end

 function SousChef.HookTrading(...)
     if SousChef.hookedDataFunction then return end
@@ -36,7 +34,7 @@ function SousChef.HookTrading(...)
         TRADING_HOUSE.m_searchResultsList.dataTypes[1].setupCallback = function(...)
             local row, data = ...
             SousChef.hookedDataFunction(...)
-            SousChef.AddTradingSlot(row, data)
+            SousChef.AddRankToSlot(row, {GetTradingHouseSearchResultItemLink, "slotIndex", nil})
         end
     else
         d("SousChef could not hook into the Trading House")
diff --git a/Utility.lua b/Utility.lua
index 7596302..638ef5d 100644
--- a/Utility.lua
+++ b/Utility.lua
@@ -1,5 +1,4 @@
 local SousChef = SousChef
-
 local u =  SousChef.Utility

 function u.GetItemID(link)
@@ -70,8 +69,8 @@ function u.MatchInGlobalCookbook(name)
     name = u.CleanString(name)
     for recipe,known in pairs(SousChef.settings.Cookbook) do
         if u.StartsWith(name,recipe) or u.EndsWith(name, recipe) then
-            local difference =  (#recipe + #u.CleanString(GetString(SI_ITEMTYPE29)) - #name)
-            if  difference < 3 and difference > - 3 then
+            local difference = (#recipe + #u.CleanString(GetString(SI_ITEMTYPE29)) - #name)
+            if difference < 3 and difference > - 3 then
                 return known
             end
         end
@@ -86,12 +85,3 @@ function u.MatchInIgnoreList(name)
     end
     return false
 end
-
-function u.TableLength(t)
-	if type(t) ~= "table" then return #t end
-	local n = 0
-	for k, v in pairs(t) do
-		n = n + 1
-	end
-	return n
-end
\ No newline at end of file
diff --git a/bindings.xml b/bindings.xml
index fde0185..2b7e10f 100644
--- a/bindings.xml
+++ b/bindings.xml
@@ -1,9 +1,9 @@
 <Bindings>
-  <Layer name="General">
-    <Category name="Sous Chef">
-      <Action name="SC_MARK_RECIPE">
-        <Down>SousChef:MarkRecipe()</Down>
-      </Action>
-    </Category>
-  </Layer>
+	<Layer name="SI_KEYBINDINGS_LAYER_GENERAL">
+		<Category name="Sous Chef">
+			<Action name="SC_MARK_RECIPE">
+				<Down>SousChef:MarkRecipe()</Down>
+			</Action>
+		</Category>
+	</Layer>
 </Bindings>
\ No newline at end of file