diff --git a/source/config/__init__.py b/source/config/__init__.py
index c02396d..46ba88d 100644
--- a/source/config/__init__.py
+++ b/source/config/__init__.py
@@ -478,6 +478,8 @@ class ConfigManager(object):
 		synthDriverHandler.handleConfigProfileSwitch()
 		import braille
 		braille.handler.handleConfigProfileSwitch()
+		import speechDictHandler
+		speechDictHandler.handleConfigProfileSwitch(self.profiles)
 
 	def _initBaseConf(self, factoryDefaults=False):
 		fn = os.path.join(globalVars.appArgs.configPath, "nvda.ini")
@@ -642,6 +644,10 @@ class ConfigManager(object):
 		if not os.path.isfile(fn):
 			raise LookupError("No such profile: %s" % name)
 		os.remove(fn)
+		#delete speechDict for this profile as well
+		import speechDictHandler
+		speechDictHandler.deleteProfileDict(name)
+		
 		try:
 			del self._profileCache[name]
 		except KeyError:
@@ -695,6 +701,9 @@ class ConfigManager(object):
 			raise ValueError("A profile with the same name already exists: %s" % newName)
 
 		os.rename(oldFn, newFn)
+		#rename speechDict for this profile, too
+		import speechDictHandler
+		speechDictHandler.renameProfileDict(oldName, newName)
 		# Update any associated triggers.
 		allTriggers = self.triggersToProfiles
 		saveTrigs = False
diff --git a/source/gui/__init__.py b/source/gui/__init__.py
index 5929f08..45807bf 100644
--- a/source/gui/__init__.py
+++ b/source/gui/__init__.py
@@ -187,6 +187,14 @@ class MainFrame(wx.Frame):
 		# Translators: Title for voice dictionary for the current voice such as current eSpeak variant.
 		self._popupSettingsDialog(DictionaryDialog,_("Voice dictionary (%s)")%speechDictHandler.dictionaries["voice"].fileName,speechDictHandler.dictionaries["voice"])
 
+	def onProfileDictionaryCommand(self,evt):
+		profileDict = speechDictHandler.loadProfileDict(config.conf.profiles[-1], False, True)
+		# Translators: Title for configuration profile dictionary for the current configuration profile.
+		self._popupSettingsDialog(DictionaryDialog,_("Profile dictionary (%s)")%profileDict.fileName,profileDict)
+
+	def onUpdateProfileDictionaryMenuItemCommand(self, evt):
+		evt.Enable(True if len(config.conf.profiles) > 1 else False)
+
 	def onTemporaryDictionaryCommand(self,evt):
 		# Translators: Title for temporary speech dictionary dialog (the voice dictionary that is active as long as NvDA is running).
 		self._popupSettingsDialog(DictionaryDialog,_("Temporary dictionary"),speechDictHandler.dictionaries["temp"])
@@ -359,6 +367,10 @@ class SysTrayIcon(wx.TaskBarIcon):
 			# Translators: The label for the menu item to open Voice specific speech dictionary dialog.
 			item = subMenu_speechDicts.Append(wx.ID_ANY,_("&Voice dictionary..."),_("A dialog where you can set voice-specific dictionary by adding dictionary entries to the list"))
 			self.Bind(wx.EVT_MENU, frame.onVoiceDictionaryCommand, item)
+			# Translators: The label for the menu item to open configuration profile specific speech dictionary dialog.
+			item = subMenu_speechDicts.Append(wx.ID_ANY,_("&Profile dictionary..."),_("A dialog where you can set profile-specific dictionary by adding dictionary entries to the list"))
+			self.Bind(wx.EVT_MENU, frame.onProfileDictionaryCommand, item)
+			self.Bind(wx.EVT_UPDATE_UI, frame.onUpdateProfileDictionaryMenuItemCommand, item)
 		# Translators: The label for the menu item to open Temporary speech dictionary dialog.
 		item = subMenu_speechDicts.Append(wx.ID_ANY,_("&Temporary dictionary..."),_("A dialog where you can set temporary dictionary by adding dictionary entries to the edit box"))
 		self.Bind(wx.EVT_MENU, frame.onTemporaryDictionaryCommand, item)
diff --git a/source/speechDictHandler.py b/source/speechDictHandler.py
index 6f83115..3a4bc1c 100644
--- a/source/speechDictHandler.py
+++ b/source/speechDictHandler.py
@@ -14,7 +14,7 @@ import api
 import config
 
 dictionaries = {}
-dictTypes = ("temp", "voice", "default", "builtin") # ordered by their priority E.G. voice specific speech dictionary is processed before the default
+dictTypes = ("temp", "profile", "voice", "default", "builtin") # ordered by their priority E.G. voice specific speech dictionary is processed before the default
 speechDictsPath=os.path.join(globalVars.appArgs.configPath, "speechDicts")
 
 class SpeechDictEntry:
@@ -36,10 +36,12 @@ class SpeechDictEntry:
 
 class SpeechDict(list):
 
-	def load(self, fileName):
+	def load(self, fileName, stack=False):
 		self.fileName=fileName
 		comment=""
-		del self[:]
+		#allow dictionaries from the same type to stack, perticulary profile dictionaries
+		if not stack:
+			del self[:]
 		log.debug("Loading speech dictionary '%s'..." % fileName)
 		if not os.path.isfile(fileName): 
 			log.debug("file '%s' not found." % fileName)
@@ -57,7 +59,9 @@ class SpeechDict(list):
 			else:
 				temp=line.split("\t")
 				if len(temp) ==4:
-					self.append(SpeechDictEntry(temp[0].replace(r'\#','#'),temp[1].replace(r'\#','#'),comment,bool(int(temp[2])),bool(int(temp[3]))))
+					newEntry = (pattern, replacement, comment, caseSensitive, regexp) = (temp[0].replace(r'\#','#'),temp[1].replace(r'\#','#'),comment,bool(int(temp[2])),bool(int(temp[3])))
+					if not any((spde.pattern, spde.replacement, spde.comment, spde.caseSensitive, spde.regexp) == newEntry for spde in self):
+						self.append(SpeechDictEntry(pattern, replacement, comment, caseSensitive, regexp))
 					comment=""
 				else:
 					log.warning("can't parse line '%s'" % line)
@@ -108,3 +112,52 @@ It handles case when the synthesizer doesn't support voice setting.
 	else:
 		fileName=r"%s\%s.dic"%(speechDictsPath,synth.name)
 	dictionaries["voice"].load(fileName)
+
+def loadProfileDict(profile, stack=True, returnDict=False):
+	"""
+	Loads appropriate dictionary for the given profile.
+"""
+	try:
+		profileName = profile.name
+	except:
+		log.debug("bad argument 1 for speechHandler.loadProfileDict: it does not have an argument 'name'")
+		return
+	if not profileName:
+		return
+	fileName=r"%s\%s.dic"%(speechDictsPath,profileName)
+	if not returnDict:
+		dictionaries["profile"].load(fileName, stack)
+	else:
+		profileDict = SpeechDict()
+		profileDict.load(fileName, stack)
+		return profileDict
+
+def handleConfigProfileSwitch(profiles=None):
+	if not profiles:
+		profiles=config.conf.profiles
+	pfs = list(profiles) if not isinstance(profiles, list) and isinstance(profiles, ConfigObj) else profiles
+	if not isinstance(pfs, list):
+		log.debug("bad argument 1 for speechHandler.handleConfigProfileSwitch: expects list or object of type ConfigObj")
+		return
+	del dictionaries["profile"][:]
+	for profile in pfs:
+		loadProfileDict(profile)
+
+def renameProfileDict(oldName, newName):
+	if not oldName or not newName or oldName == newName:
+		return
+	oldFn=r"%s\%s.dic"%(speechDictsPath,oldName)
+	newFn=r"%s\%s.dic"%(speechDictsPath,newName)
+	try:
+		os.rename(oldFn, newFn)
+	except:
+		log.debug("Could not rename profile dict %s to %s" % (oldFn, newFn))
+
+def deleteProfileDict(name):
+	if not name:
+		return
+	fn=r"%s\%s.dic"%(speechDictsPath,name)
+	try:
+		os.remove(fn)
+	except:
+		log.debug("Could not delete profile dict %s" % fn)
diff --git a/user_docs/en/userGuide.t2t b/user_docs/en/userGuide.t2t
index 6fbdc54..ee6f0d0 100644
--- a/user_docs/en/userGuide.t2t
+++ b/user_docs/en/userGuide.t2t
@@ -1048,10 +1048,11 @@ Enable this option while proof reading documents in applications such as Microso
 
 +++ Speech dictionaries +++
 The speech dictionaries menu (found in the Preferences menu) contains dialogs that allow you to manage the way NVDA pronounces particular words or phrases.
-There are currently three different types of speech dictionaries.
+There are currently four different types of speech dictionaries.
 They are:
 - Default: rules in this dictionary affect all speech in NVDA.
 - Voice: rules in this dictionary affect speech for the synthesizer voice currently being used.
+- Profile: rules in this dictionary affect speech for the configuration profile currently being edited. However, if you have more than one active profile, the rules from both will apply with triggered profile taking precedence.
 - Temporary: rules in this dictionary affect all speech in NVDA, but only for the current session. These rules are temporary and will be lost if NVDA is restarted.
 -
 
