ddnet/src/game/client/localization.cpp

125 lines
3.3 KiB
C++
Raw Normal View History

2010-11-20 10:37:14 +00:00
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
/* If you are missing that file, acquire a complete release at teeworlds.com. */
2009-06-13 16:54:04 +00:00
2010-05-29 07:25:38 +00:00
#include "localization.h"
#include <base/tl/algorithm.h>
2009-06-13 16:54:04 +00:00
2012-12-18 23:30:01 +00:00
#include <engine/external/json-parser/json.h>
#include <engine/console.h>
2010-10-06 21:07:35 +00:00
#include <engine/storage.h>
2009-06-13 17:18:06 +00:00
const char *Localize(const char *pStr, const char *pContext)
2009-06-13 16:54:04 +00:00
{
const char *pNewStr = g_Localization.FindString(str_quickhash(pStr), str_quickhash(pContext));
2010-05-29 07:25:38 +00:00
return pNewStr ? pNewStr : pStr;
2009-06-13 16:54:04 +00:00
}
CLocConstString::CLocConstString(const char *pStr, const char *pContext)
2009-06-13 16:54:04 +00:00
{
2010-05-29 07:25:38 +00:00
m_pDefaultStr = pStr;
m_Hash = str_quickhash(m_pDefaultStr);
2013-06-04 16:54:15 +00:00
m_ContextHash = str_quickhash(pContext);
2010-05-29 07:25:38 +00:00
m_Version = -1;
2009-06-13 16:54:04 +00:00
}
2010-05-29 07:25:38 +00:00
void CLocConstString::Reload()
2009-06-13 16:54:04 +00:00
{
2010-05-29 07:25:38 +00:00
m_Version = g_Localization.Version();
const char *pNewStr = g_Localization.FindString(m_Hash, m_ContextHash);
2010-05-29 07:25:38 +00:00
m_pCurrentStr = pNewStr;
if(!m_pCurrentStr)
m_pCurrentStr = m_pDefaultStr;
2009-06-13 16:54:04 +00:00
}
2010-05-29 07:25:38 +00:00
CLocalizationDatabase::CLocalizationDatabase()
2009-06-13 16:54:04 +00:00
{
m_VersionCounter = 0;
2010-05-29 07:25:38 +00:00
m_CurrentVersion = 0;
2009-06-13 16:54:04 +00:00
}
void CLocalizationDatabase::AddString(const char *pOrgStr, const char *pNewStr, const char *pContext)
2009-06-13 16:54:04 +00:00
{
2010-05-29 07:25:38 +00:00
CString s;
s.m_Hash = str_quickhash(pOrgStr);
2013-06-04 16:54:15 +00:00
s.m_ContextHash = str_quickhash(pContext);
s.m_Replacement = *pNewStr ? pNewStr : pOrgStr;
2010-05-29 07:25:38 +00:00
m_Strings.add(s);
2009-06-13 17:18:06 +00:00
}
2010-10-06 21:07:35 +00:00
bool CLocalizationDatabase::Load(const char *pFilename, IStorage *pStorage, IConsole *pConsole)
2009-06-13 17:18:06 +00:00
{
2009-06-15 08:15:53 +00:00
// empty string means unload
2010-05-29 07:25:38 +00:00
if(pFilename[0] == 0)
2009-06-15 08:15:53 +00:00
{
2010-05-29 07:25:38 +00:00
m_Strings.clear();
m_CurrentVersion = 0;
2009-06-15 08:15:53 +00:00
return true;
}
2012-12-18 23:30:01 +00:00
// read file data into buffer
IOHANDLE File = pStorage->OpenFile(pFilename, IOFLAG_READ, IStorage::TYPE_ALL);
if(!File)
2009-06-13 17:18:06 +00:00
return false;
2012-12-18 23:30:01 +00:00
int FileSize = (int)io_length(File);
char *pFileData = (char *)mem_alloc(FileSize+1, 1);
io_read(File, pFileData, FileSize);
pFileData[FileSize] = 0;
io_close(File);
// init
char aBuf[64];
str_format(aBuf, sizeof(aBuf), "loaded '%s'", pFilename);
pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "localization", aBuf);
2010-05-29 07:25:38 +00:00
m_Strings.clear();
2012-12-18 23:30:01 +00:00
// parse json data
json_settings JsonSettings;
mem_zero(&JsonSettings, sizeof(JsonSettings));
char aError[256];
json_value *pJsonData = json_parse_ex(&JsonSettings, pFileData, aError);
if(pJsonData == 0)
2009-06-13 17:18:06 +00:00
{
2012-12-21 23:34:49 +00:00
pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, pFilename, aError);
mem_free(pFileData);
2012-12-18 23:30:01 +00:00
return false;
}
2009-06-13 17:18:06 +00:00
2012-12-18 23:30:01 +00:00
// extract data
const json_value &rStart = (*pJsonData)["translated strings"];
if(rStart.type == json_array)
{
2012-12-20 15:30:16 +00:00
for(unsigned i = 0; i < rStart.u.array.length; ++i)
AddString((const char *)rStart[i]["or"], (const char *)rStart[i]["tr"], (const char *)rStart[i]["context"]);
2009-06-13 17:18:06 +00:00
}
2012-12-18 23:30:01 +00:00
// clean up
json_value_free(pJsonData);
2012-12-20 15:30:16 +00:00
mem_free(pFileData);
m_CurrentVersion = ++m_VersionCounter;
2009-06-13 17:18:06 +00:00
return true;
2009-06-13 16:54:04 +00:00
}
const char *CLocalizationDatabase::FindString(unsigned Hash, unsigned ContextHash)
2009-06-13 16:54:04 +00:00
{
2010-05-29 07:25:38 +00:00
CString String;
String.m_Hash = Hash;
sorted_array<CString>::range r = ::find_binary(m_Strings.all(), String);
2009-06-13 16:54:04 +00:00
if(r.empty())
return 0;
2013-06-04 16:54:15 +00:00
unsigned DefaultHash = str_quickhash("");
unsigned DefaultIndex = 0;
for(unsigned i = 0; i < r.size() && r.index(i).m_Hash == Hash; ++i)
2013-06-04 16:54:15 +00:00
{
const CString &rStr = r.index(i);
if(rStr.m_ContextHash == ContextHash)
return rStr.m_Replacement;
else if(rStr.m_ContextHash == DefaultHash)
DefaultIndex = i;
}
return r.index(DefaultIndex).m_Replacement;
2009-06-13 16:54:04 +00:00
}
2009-06-15 06:45:44 +00:00
2010-05-29 07:25:38 +00:00
CLocalizationDatabase g_Localization;