Index: src/libictranslate/ResourceManager.cpp
===================================================================
diff -u -rd0d46e0ace97519c52eefcd66e1cab5b586dcac1 -ra347fac4097d0504825a93fec5233adade6345a3
--- src/libictranslate/ResourceManager.cpp	(.../ResourceManager.cpp)	(revision d0d46e0ace97519c52eefcd66e1cab5b586dcac1)
+++ src/libictranslate/ResourceManager.cpp	(.../ResourceManager.cpp)	(revision a347fac4097d0504825a93fec5233adade6345a3)
@@ -80,6 +80,7 @@
 		delete [] (*it).second;
 	}
 	m_mStrings.clear();
+	m_mChecksums.clear();
 }
 
 CLangData::CLangData(const CLangData& ld) :
@@ -103,6 +104,25 @@
 	SetVersion(ld.GetVersion());
 }
 
+CLangData& CLangData::operator=(const CLangData& rSrc)
+{
+	if(this != &rSrc)
+	{
+		SetFilename(rSrc.GetFilename(true));
+		SetLangName(rSrc.GetLangName());
+		SetLangCode(rSrc.GetLangCode());
+		SetFontFace(rSrc.GetFontFace());
+		SetCharset(rSrc.GetCharset());
+		SetPointSize(rSrc.GetPointSize());
+		SetDirection(rSrc.GetDirection());
+		SetHelpName(rSrc.GetHelpName());
+		SetAuthor(rSrc.GetAuthor());
+		SetVersion(rSrc.GetVersion());
+	}
+
+	return *this;
+}
+
 bool CLangData::ReadInfo(PCTSTR pszFile)
 {
 	try
@@ -192,22 +212,59 @@
 	}
 	else
 	{
-		uint_t uiVal = _ttoi(pszName);
+		// parse the pszName to get both the string id and checksum
+		const tchar_t* pszChecksum = _tcschr(pszName, _T('['));
+		if(pszChecksum == NULL)
+		{
+			TRACE(_T("Warning! Old-style translation string %s; skipping.\n"), pszName);
+			return;			// old-style translation; assume incompatibility
+		}
+
+		UINT uiID = 0;
+		UINT uiChecksum = 0;
+		int iCount = _stscanf(pszName, UIFMT _T("[0x%lx]"), &uiID, &uiChecksum);
+		if(iCount != 2)
+		{
+			TRACE(_T("Warning! Problem retrieving checksum from string '%s'\n"), pszName);
+			return;
+		}
+
+		uint_t uiKey = pLangData->m_uiSectionID << 16 | uiID;
 		if(pLangData->m_bUpdating)
 		{
+			// check if the checksum exists and matches
+			checksum_map::const_iterator itChecksum = pLangData->m_mChecksums.find(uiKey);
+			if(itChecksum == pLangData->m_mChecksums.end())
+			{
+				TRACE(_T("Warning! Superfluous entry %lu in processed language file\n"), uiKey);
+				return;		// entry not found - probably superfluous entry in the language file
+			}
+
+			if((*itChecksum).second != uiChecksum)
+			{
+				TRACE(_T("Warning! Invalid checksum for string ID %lu in processed language file\n"), uiKey);
+				return;		// entry has invalid checksum (older version of translation)
+			}
+
 			// check if the entry already exists
-			strings_map::iterator it = pLangData->m_mStrings.find(pLangData->m_uiSectionID << 16 | uiVal);
+			strings_map::iterator it = pLangData->m_mStrings.find(uiKey);
 			if(it != pLangData->m_mStrings.end())
-				return;
+			{
+				delete [] (*it).second;
+				pLangData->m_mStrings.erase(it);
+			}
 		}
+
 		size_t stLen = _tcslen(pszValue);
 		tchar_t* pszStr = new tchar_t[stLen + 1];
 		_tcscpy(pszStr, pszValue);
 
 		// convert escape strings into escape sequences
 		CLangData::UnescapeString(pszStr);
 
-		pLangData->m_mStrings.insert(strings_map::value_type(pLangData->m_uiSectionID << 16 | uiVal, pszStr));
+		pLangData->m_mStrings.insert(strings_map::value_type(uiKey, pszStr));
+		if(!pLangData->m_bUpdating)
+			pLangData->m_mChecksums.insert(checksum_map::value_type(uiKey, uiChecksum));
 	}
 }
 
@@ -241,12 +298,24 @@
 
 }
 
-bool CLangData::ReadTranslation(PCTSTR pszFile, bool bUpdate)
+bool CLangData::ReadTranslation(PCTSTR pszFile, bool bReadBase)
 {
 	try
 	{
-		if(!bUpdate)
+		// first read the standard language - hard-code english one
+		const tchar_t* pszBaseName = _t("english.lng");
+		if(!bReadBase && _tcsstr(pszFile, pszBaseName) == NULL)
+		{
 			Clear();
+			TCHAR szData[512];
+			const TCHAR* pszName=_tcsrchr(pszFile, _T('\\'));
+			if(pszName)
+			{
+				_tcsncpy(szData, pszFile, pszName-pszFile+1);
+				_tcscpy(szData+(pszName-pszFile+1), pszBaseName);
+				ReadTranslation(szData, true);
+			}
+		}
 
 		// load data from file
 		icpf::config cfg(icpf::config::eIni);
@@ -262,56 +331,52 @@
 		const uint_t uiVersion = cfg.register_string(_T("Info/Version"), _T(""));
 		cfg.read(pszFile);
 
-		TCHAR szData[512];
-		if(!bUpdate)
-		{
-			const tchar_t* psz = cfg.get_string(uiLangName);
-			if(!psz || psz[0] == _t('\0'))
-				return false;
-			SetLangName(psz);
+		const tchar_t* psz = cfg.get_string(uiLangName);
+		if(!psz || psz[0] == _t('\0'))
+			return false;
+		SetLangName(psz);
 
-			ll_t ll = cfg.get_signed_num(uiLangCode);
-			if(ll == 0)
-				return false;
-			SetLangCode((WORD)ll);
+		ll_t ll = cfg.get_signed_num(uiLangCode);
+		if(ll == 0)
+			return false;
+		SetLangCode((WORD)ll);
 
-			psz = cfg.get_string(uiBaseLanguage);
-			SetBaseFile(psz);
+		psz = cfg.get_string(uiBaseLanguage);
+		SetBaseFile(psz);
 
-			psz = cfg.get_string(uiFontFace);
-			if(!psz || psz[0] == _t('\0'))
-				return false;
-			SetFontFace(psz);
+		psz = cfg.get_string(uiFontFace);
+		if(!psz || psz[0] == _t('\0'))
+			return false;
+		SetFontFace(psz);
 
-			ll = cfg.get_signed_num(uiCharset);
-			if(ll == 0)
-				return false;
-			SetCharset((BYTE)ll);
+		ll = cfg.get_signed_num(uiCharset);
+		if(ll == 0)
+			return false;
+		SetCharset((BYTE)ll);
 
-			ll = cfg.get_signed_num(uiSize);
-			if(ll == 0)
-				return false;
-			SetPointSize((WORD)ll);
+		ll = cfg.get_signed_num(uiSize);
+		if(ll == 0)
+			return false;
+		SetPointSize((WORD)ll);
 
-			SetDirection(cfg.get_bool(uiRTL));
+		SetDirection(cfg.get_bool(uiRTL));
 
-			psz = cfg.get_string(uiHelpName);
-			if(!psz || psz[0] == _t('\0'))
-				return false;
-			SetHelpName(psz);
+		psz = cfg.get_string(uiHelpName);
+		if(!psz || psz[0] == _t('\0'))
+			return false;
+		SetHelpName(psz);
 
-			psz = cfg.get_string(uiAuthor);
-			if(!psz || psz[0] == _t('\0'))
-				return false;
-			SetAuthor(psz);
+		psz = cfg.get_string(uiAuthor);
+		if(!psz || psz[0] == _t('\0'))
+			return false;
+		SetAuthor(psz);
 
-			psz = cfg.get_string(uiVersion);
-			if(!psz || psz[0] == _t('\0'))
-				return false;
-			SetVersion(psz);
-		}
+		psz = cfg.get_string(uiVersion);
+		if(!psz || psz[0] == _t('\0'))
+			return false;
+		SetVersion(psz);
 		
-		m_bUpdating = bUpdate;
+		m_bUpdating = !bReadBase;
 		m_uiSectionID = 0;
 		if(!cfg.enum_properties(_t("*"), EnumAttributesCallback, this))
 		{
@@ -320,25 +385,9 @@
 		}
 		m_bUpdating = false;
 
-		if(!bUpdate)
-		{
-			// remember the filename
+		if(!m_bUpdating)
 			SetFilename(pszFile);
 
-			// establish path to the base file
-			if (_tcslen(GetBaseFile()) != 0)
-			{
-				const TCHAR* pszName=_tcsrchr(pszFile, _T('\\'));
-				if (pszName)
-				{
-					_tcsncpy(szData, pszFile, pszName-pszFile+1);
-					_tcscpy(szData+(pszName-pszFile+1), GetBaseFile());
-					TRACE(_t("Base (update) path=%s\n"), szData);
-					ReadTranslation(szData, true);
-				}
-			}
-		}
-		
 		return true;
 	}
 	catch(...)
@@ -380,6 +429,48 @@
 	}
 }
 
+void CLangData::SetLangName(PCTSTR psz)
+{
+	if (m_pszLngName)
+		delete [] m_pszLngName;
+	m_pszLngName=new TCHAR[_tcslen(psz)+1];
+	_tcscpy(m_pszLngName, psz);
+}
+
+void CLangData::SetBaseFile(PCTSTR psz)
+{
+	SetFnameData(&m_pszBaseFile, psz);
+}
+
+void CLangData::SetFontFace(PCTSTR psz)
+{
+	if (m_pszFontFace)
+		delete [] m_pszFontFace;
+	m_pszFontFace=new TCHAR[_tcslen(psz)+1];
+	_tcscpy(m_pszFontFace, psz);
+}
+
+void CLangData::SetHelpName(PCTSTR psz)
+{
+	SetFnameData(&m_pszHelpName, psz);
+}
+
+void CLangData::SetAuthor(PCTSTR psz)
+{
+	if (m_pszAuthor)
+		delete [] m_pszAuthor;
+	m_pszAuthor=new TCHAR[_tcslen(psz)+1];
+	_tcscpy(m_pszAuthor, psz);
+}
+
+void CLangData::SetVersion(PCTSTR psz)
+{
+	if (m_pszVersion)
+		delete [] m_pszVersion;
+	m_pszVersion=new TCHAR[_tcslen(psz)+1];
+	_tcscpy(m_pszVersion, psz);
+}
+
 void CLangData::SetFnameData(PTSTR *ppszDst, PCTSTR pszSrc)
 {
 	if (*ppszDst)
Index: src/libictranslate/ResourceManager.h
===================================================================
diff -u -rd0d46e0ace97519c52eefcd66e1cab5b586dcac1 -ra347fac4097d0504825a93fec5233adade6345a3
--- src/libictranslate/ResourceManager.h	(.../ResourceManager.h)	(revision d0d46e0ace97519c52eefcd66e1cab5b586dcac1)
+++ src/libictranslate/ResourceManager.h	(.../ResourceManager.h)	(revision a347fac4097d0504825a93fec5233adade6345a3)
@@ -41,7 +41,8 @@
 
 ///////////////////////////////////////////////////////////
 // language description structure
-typedef map<DWORD, tchar_t*> strings_map;
+typedef std::map<uint_t, tchar_t*> strings_map;
+typedef std::map<uint_t, uint_t> checksum_map;
 
 class LIBICTRANSLATE_API CLangData
 {
@@ -51,27 +52,29 @@
 	~CLangData();
 	CLangData(const CLangData& ld);
 
+	CLangData& operator=(const CLangData& rSrc);
+
 	void Clear();
 // operations
 	bool ReadInfo(PCTSTR pszFile);
-	bool ReadTranslation(PCTSTR pszFile, bool bUpdate=false);
+	bool ReadTranslation(PCTSTR pszFile, bool bReadBase = false);
 
 	PCTSTR GetString(WORD wHiID, WORD wLoID);
 
 // attributes
 	void SetFilename(PCTSTR psz);
 	PCTSTR GetFilename(bool bFullPath) const;
 
-	void SetLangName(PCTSTR psz) { if (m_pszLngName) delete [] m_pszLngName; m_pszLngName=new TCHAR[_tcslen(psz)+1]; _tcscpy(m_pszLngName, psz); };
+	void SetLangName(PCTSTR psz);
 	PCTSTR GetLangName() const { return m_pszLngName; };
 
-	void SetBaseFile(PCTSTR psz) { SetFnameData(&m_pszBaseFile, psz); };
+	void SetBaseFile(PCTSTR psz);
 	PCTSTR GetBaseFile() const { return m_pszBaseFile; };
 
 	void SetLangCode(WORD wLang) { m_wLangCode=wLang; };
 	WORD GetLangCode() const { return m_wLangCode; };
 
-	void SetFontFace(PCTSTR psz) { if (m_pszFontFace) delete [] m_pszFontFace; m_pszFontFace=new TCHAR[_tcslen(psz)+1]; _tcscpy(m_pszFontFace, psz); };
+	void SetFontFace(PCTSTR psz);
 	PCTSTR GetFontFace() const { return m_pszFontFace; };
 
 	void SetCharset(BYTE byChar) { m_byCharset=byChar; };
@@ -83,17 +86,15 @@
 	void SetDirection(bool brtl) { m_bRTL=brtl; };
 	bool GetDirection() const { return m_bRTL; };
 
-	void SetHelpName(PCTSTR psz) { SetFnameData(&m_pszHelpName, psz); };
+	void SetHelpName(PCTSTR psz);
 	PCTSTR GetHelpName() const { return m_pszHelpName; };
 
-	void SetAuthor(PCTSTR psz) { if (m_pszAuthor) delete [] m_pszAuthor; m_pszAuthor=new TCHAR[_tcslen(psz)+1]; _tcscpy(m_pszAuthor, psz); };
+	void SetAuthor(PCTSTR psz);
 	PCTSTR GetAuthor() const { return m_pszAuthor; };
 
-	void SetVersion(PCTSTR psz) { if (m_pszVersion) delete [] m_pszVersion; m_pszVersion=new TCHAR[_tcslen(psz)+1]; _tcscpy(m_pszVersion, psz); };
+	void SetVersion(PCTSTR psz);
 	PCTSTR GetVersion() const { return m_pszVersion; };
 
-//	void SetStringData(PCTSTR psz, size_t tCnt) { tCount=tCnt; if (pszStrings) delete [] pszStrings; if (tCount > 0) { pszStrings=new TCHAR[tCnt]; memcpy(pszStrings, psz, tCnt*sizeof(TCHAR)); } };
-
 protected:
 	void SetFnameData(PTSTR *ppszDst, PCTSTR pszSrc);
 	static void EnumAttributesCallback(bool bGroup, const tchar_t* pszName, const tchar_t* pszValue, ptr_t pData);
@@ -113,7 +114,8 @@
 	bool m_bRTL;				// does the language require right-to-left reading order ?
 
 	// strings (for controls in dialog boxes the ID contains hi:dlg ID, lo:ctrl ID, for strings hi part is 0)
-	strings_map m_mStrings;	// maps string ID to the offset in pszStrings
+	strings_map m_mStrings;		// maps string ID to the offset in pszStrings
+	checksum_map m_mChecksums;	// checksums of strings
 
 private:
 	uint_t m_uiSectionID;			///< ID of the currently processed section