added amb1666 - rehaul over the ml api so extensions can easily use translations
authorDavid Anderson <dvander@alliedmods.net>
Sat May 10 09:23:55 2008 +0000 (2008-05-10)
changeset 20424a2faafca477
parent 2041 1ba9eb0f85c7
child 2043 516b4fbd4305
added amb1666 - rehaul over the ml api so extensions can easily use translations
core/ChatTriggers.cpp
core/ConCmdManager.cpp
core/MenuManager.cpp
core/PhraseCollection.cpp
core/PhraseCollection.h
core/PlayerManager.cpp
core/Translator.cpp
core/Translator.h
core/msvc8/sourcemod_mm.vcproj
core/sm_stringutil.cpp
core/sm_stringutil.h
core/smn_console.cpp
core/smn_core.cpp
core/smn_fakenatives.cpp
core/smn_filesystem.cpp
core/smn_lang.cpp
core/smn_menus.cpp
core/smn_player.cpp
core/systems/PluginSys.cpp
core/systems/PluginSys.h
public/ISourceMod.h
public/ITranslator.h
public/mms_sample_ext/sm_sdk_config.cpp
public/mms_sample_ext/sm_sdk_config.h
public/sample_ext/sdk/smsdk_config.h
public/sample_ext/sdk/smsdk_ext.cpp
public/sample_ext/sdk/smsdk_ext.h
     1.1 --- a/core/ChatTriggers.cpp	Fri May 09 08:22:39 2008 +0000
     1.2 +++ b/core/ChatTriggers.cpp	Sat May 10 09:23:55 2008 +0000
     1.3 @@ -216,15 +216,14 @@
     1.4  	{
     1.5  		char buffer[128];
     1.6  
     1.7 -		/* :TODO: log an error? */
     1.8 -		if (g_Translator.CoreTransEx(g_pFloodPhrases, 
     1.9 -			client, 
    1.10 -			buffer, 
    1.11 +		if (!CoreTranslate(
    1.12 +			buffer,
    1.13  			sizeof(buffer),
    1.14 -			"Flooding the server",
    1.15 +			"%T",
    1.16 +			2,
    1.17  			NULL,
    1.18 -			NULL)
    1.19 -			!= Trans_Okay)
    1.20 +			"Flooding the server",
    1.21 +			&client))
    1.22  		{
    1.23  			UTIL_Format(buffer, sizeof(buffer), "You are flooding the server!");
    1.24  		}
     2.1 --- a/core/ConCmdManager.cpp	Fri May 09 08:22:39 2008 +0000
     2.2 +++ b/core/ConCmdManager.cpp	Sat May 10 09:23:55 2008 +0000
     2.3 @@ -494,8 +494,7 @@
     2.4  	
     2.5  	/* If we got here, the command failed... */
     2.6  	char buffer[128];
     2.7 -	if (g_Translator.CoreTrans(client, buffer, sizeof(buffer), "No Access", NULL, NULL)
     2.8 -		!= Trans_Okay)
     2.9 +	if (!CoreTranslate(buffer, sizeof(buffer), "%T", 1, NULL, "No Access", &client))
    2.10  	{
    2.11  		UTIL_Format(buffer, sizeof(buffer), "You do not have access to this command");
    2.12  	}
     3.1 --- a/core/MenuManager.cpp	Fri May 09 08:22:39 2008 +0000
     3.2 +++ b/core/MenuManager.cpp	Sat May 10 09:23:55 2008 +0000
     3.3 @@ -41,6 +41,7 @@
     3.4  #include "ShareSys.h"
     3.5  #include "HandleSys.h"
     3.6  #include "sourcemm_api.h"
     3.7 +#include "Translator.h"
     3.8  
     3.9  MenuManager g_Menus;
    3.10  VoteMenuHandler s_VoteHandler;
    3.11 @@ -585,14 +586,20 @@
    3.12  				{
    3.13  					if (exitBackButton)
    3.14  					{
    3.15 -						CorePlayerTranslate(client, text, sizeof(text), "Back", NULL);
    3.16 +						if (!CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Back", &client))
    3.17 +						{
    3.18 +							UTIL_Format(text, sizeof(text), "Back");
    3.19 +						}
    3.20  						dr.style = ITEMDRAW_CONTROL;
    3.21  						position = panel->DrawItem(dr);
    3.22  						slots[position].type = ItemSel_ExitBack;
    3.23  					}
    3.24  					else
    3.25  					{
    3.26 -						CorePlayerTranslate(client, text, sizeof(text), "Previous", NULL);
    3.27 +						if (!CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Previous", &client))
    3.28 +						{
    3.29 +							UTIL_Format(text, sizeof(text), "Previous");
    3.30 +						}
    3.31  						dr.style = (displayPrev ? 0 : ITEMDRAW_DISABLED)|ITEMDRAW_CONTROL;
    3.32  						position = panel->DrawItem(dr);
    3.33  						slots[position].type = ItemSel_Back;
    3.34 @@ -610,7 +617,10 @@
    3.35  				/* NEXT */
    3.36  				if (displayNext || canDrawDisabled)
    3.37  				{
    3.38 -					CorePlayerTranslate(client, text, sizeof(text), "Next", NULL);
    3.39 +					if (!CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Next", &client))
    3.40 +					{
    3.41 +						UTIL_Format(text, sizeof(text), "Next");
    3.42 +					}
    3.43  					dr.style = (displayNext ? 0 : ITEMDRAW_DISABLED)|ITEMDRAW_CONTROL;
    3.44  					position = panel->DrawItem(dr);
    3.45  					slots[position].type = ItemSel_Next;
    3.46 @@ -638,7 +648,10 @@
    3.47  		/* EXIT */
    3.48  		if (exitButton)
    3.49  		{
    3.50 -			CorePlayerTranslate(client, text, sizeof(text), "Exit", NULL);
    3.51 +			if (!CoreTranslate(text, sizeof(text), "%T", 2, NULL, "Exit", &client))
    3.52 +			{
    3.53 +				UTIL_Format(text, sizeof(text), "Exit");
    3.54 +			}
    3.55  			dr.style = ITEMDRAW_CONTROL;
    3.56  			position = panel->DrawItem(dr);
    3.57  			slots[position].type = ItemSel_Exit;
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/core/PhraseCollection.cpp	Sat May 10 09:23:55 2008 +0000
     4.3 @@ -0,0 +1,131 @@
     4.4 +/**
     4.5 + * vim: set ts=4 :
     4.6 + * =============================================================================
     4.7 + * SourceMod
     4.8 + * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
     4.9 + * =============================================================================
    4.10 + *
    4.11 + * This program is free software; you can redistribute it and/or modify it under
    4.12 + * the terms of the GNU General Public License, version 3.0, as published by the
    4.13 + * Free Software Foundation.
    4.14 + * 
    4.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
    4.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    4.17 + * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    4.18 + * details.
    4.19 + *
    4.20 + * You should have received a copy of the GNU General Public License along with
    4.21 + * this program.  If not, see <http://www.gnu.org/licenses/>.
    4.22 + *
    4.23 + * As a special exception, AlliedModders LLC gives you permission to link the
    4.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
    4.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    4.26 + * by the Valve Corporation.  You must obey the GNU General Public License in
    4.27 + * all respects for all other code used.  Additionally, AlliedModders LLC grants
    4.28 + * this exception to all derivative works.  AlliedModders LLC defines further
    4.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    4.30 + * or <http://www.sourcemod.net/license.php>.
    4.31 + *
    4.32 + * Version: $Id$
    4.33 + */
    4.34 +
    4.35 +#include "PhraseCollection.h"
    4.36 +#include "Translator.h"
    4.37 +#include "sm_stringutil.h"
    4.38 +
    4.39 +CPhraseCollection::CPhraseCollection()
    4.40 +{
    4.41 +}
    4.42 +
    4.43 +CPhraseCollection::~CPhraseCollection()
    4.44 +{
    4.45 +}
    4.46 +
    4.47 +void CPhraseCollection::Destroy()
    4.48 +{
    4.49 +	delete this;
    4.50 +}
    4.51 +
    4.52 +IPhraseFile *CPhraseCollection::AddPhraseFile(const char *filename)
    4.53 +{
    4.54 +	size_t i;
    4.55 +	unsigned int fid;
    4.56 +	IPhraseFile *pFile;
    4.57 +	char full_name[PLATFORM_MAX_PATH];
    4.58 +
    4.59 +	/* No compat shim here.  The user should have read the doc. */
    4.60 +	UTIL_Format(full_name, sizeof(full_name), "%s.txt", filename);
    4.61 +	
    4.62 +	fid = g_Translator.FindOrAddPhraseFile(full_name);
    4.63 +	pFile = g_Translator.GetFileByIndex(fid);
    4.64 +
    4.65 +	for (i = 0; i < m_Files.size(); i++)
    4.66 +	{
    4.67 +		if (m_Files[i] == pFile)
    4.68 +		{
    4.69 +			return pFile;
    4.70 +		}
    4.71 +	}
    4.72 +
    4.73 +	m_Files.push_back(pFile);
    4.74 +
    4.75 +	return pFile;
    4.76 +}
    4.77 +
    4.78 +unsigned int CPhraseCollection::GetFileCount()
    4.79 +{
    4.80 +	return (unsigned int)m_Files.size();
    4.81 +}
    4.82 +
    4.83 +IPhraseFile *CPhraseCollection::GetFile(unsigned int file)
    4.84 +{
    4.85 +	if (file >= m_Files.size())
    4.86 +	{
    4.87 +		return NULL;
    4.88 +	}
    4.89 +
    4.90 +	return m_Files[file];
    4.91 +}
    4.92 +
    4.93 +TransError CPhraseCollection::FindTranslation(const char *key, unsigned int langid, Translation *pTrans)
    4.94 +{
    4.95 +	size_t i;
    4.96 +
    4.97 +	for (i = 0; i < m_Files.size(); i++)
    4.98 +	{
    4.99 +		if (m_Files[i]->GetTranslation(key, langid, pTrans) == Trans_Okay)
   4.100 +		{
   4.101 +			return Trans_Okay;
   4.102 +		}
   4.103 +	}
   4.104 +
   4.105 +	return Trans_BadPhrase;
   4.106 +}
   4.107 +
   4.108 +bool CPhraseCollection::FormatString(char *buffer,
   4.109 +								 size_t maxlength,
   4.110 +								 const char *format,
   4.111 +								 void **params,
   4.112 +								 unsigned int numparams,
   4.113 +								 size_t *pOutLength,
   4.114 +								 const char **pFailPhrase)
   4.115 +{
   4.116 +	unsigned int arg;
   4.117 +
   4.118 +	arg = 0;
   4.119 +	if (!gnprintf(buffer, maxlength, format, this, params, numparams, arg, pOutLength, pFailPhrase))
   4.120 +	{
   4.121 +		return false;
   4.122 +	}
   4.123 +
   4.124 +	if (arg != numparams)
   4.125 +	{
   4.126 +		if (pFailPhrase != NULL)
   4.127 +		{
   4.128 +			*pFailPhrase = NULL;
   4.129 +		}
   4.130 +		return false;
   4.131 +	}
   4.132 +
   4.133 +	return true;
   4.134 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/core/PhraseCollection.h	Sat May 10 09:23:55 2008 +0000
     5.3 @@ -0,0 +1,65 @@
     5.4 +/**
     5.5 + * vim: set ts=4 :
     5.6 + * =============================================================================
     5.7 + * SourceMod
     5.8 + * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
     5.9 + * =============================================================================
    5.10 + *
    5.11 + * This program is free software; you can redistribute it and/or modify it under
    5.12 + * the terms of the GNU General Public License, version 3.0, as published by the
    5.13 + * Free Software Foundation.
    5.14 + * 
    5.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
    5.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    5.17 + * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    5.18 + * details.
    5.19 + *
    5.20 + * You should have received a copy of the GNU General Public License along with
    5.21 + * this program.  If not, see <http://www.gnu.org/licenses/>.
    5.22 + *
    5.23 + * As a special exception, AlliedModders LLC gives you permission to link the
    5.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
    5.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    5.26 + * by the Valve Corporation.  You must obey the GNU General Public License in
    5.27 + * all respects for all other code used.  Additionally, AlliedModders LLC grants
    5.28 + * this exception to all derivative works.  AlliedModders LLC defines further
    5.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    5.30 + * or <http://www.sourcemod.net/license.php>.
    5.31 + *
    5.32 + * Version: $Id$
    5.33 + */
    5.34 +
    5.35 +#ifndef _INCLUDE_SOURCEMOD_PHRASECOLLECTION_H_
    5.36 +#define _INCLUDE_SOURCEMOD_PHRASECOLLECTION_H_
    5.37 +
    5.38 +#include <string.h>
    5.39 +#include <sh_vector.h>
    5.40 +#include <ITranslator.h>
    5.41 +
    5.42 +using namespace SourceHook;
    5.43 +using namespace SourceMod;
    5.44 +
    5.45 +class CPhraseCollection : public IPhraseCollection
    5.46 +{
    5.47 +public:
    5.48 +	CPhraseCollection();
    5.49 +	~CPhraseCollection();
    5.50 +public:
    5.51 +	IPhraseFile *AddPhraseFile(const char *filename);
    5.52 +	unsigned int GetFileCount();
    5.53 +	IPhraseFile *GetFile(unsigned int file);
    5.54 +	void Destroy();
    5.55 +	TransError FindTranslation(const char *key, unsigned int langid, Translation *pTrans);
    5.56 +	bool FormatString(
    5.57 +		char *buffer,
    5.58 +		size_t maxlength,
    5.59 +		const char *format,
    5.60 +		void **params,
    5.61 +		unsigned int numparams,
    5.62 +		size_t *pOutLength,
    5.63 +		const char **pFailPhrase);
    5.64 +private:
    5.65 +	CVector<IPhraseFile *> m_Files;
    5.66 +};
    5.67 +
    5.68 +#endif //_INCLUDE_SOURCEMOD_PHRASECOLLECTION_H_
     6.1 --- a/core/PlayerManager.cpp	Fri May 09 08:22:39 2008 +0000
     6.2 +++ b/core/PlayerManager.cpp	Sat May 10 09:23:55 2008 +0000
     6.3 @@ -1203,7 +1203,7 @@
     6.4  	m_bAdminCheckSignalled = false;
     6.5  	m_bIsInKickQueue = false;
     6.6  	m_LastPassword.clear();
     6.7 -	m_LangId = LANGUAGE_ENGLISH;
     6.8 +	m_LangId = SOURCEMOD_LANGUAGE_ENGLISH;
     6.9  }
    6.10  
    6.11  void CPlayer::Initialize(const char *name, const char *ip, edict_t *pEntity)
     7.1 --- a/core/Translator.cpp	Fri May 09 08:22:39 2008 +0000
     7.2 +++ b/core/Translator.cpp	Sat May 10 09:23:55 2008 +0000
     7.3 @@ -38,9 +38,11 @@
     7.4  #include "sm_stringutil.h"
     7.5  #include "sourcemod.h"
     7.6  #include "PlayerManager.h"
     7.7 +#include "PhraseCollection.h"
     7.8 +#include "ShareSys.h"
     7.9  
    7.10  Translator g_Translator;
    7.11 -CPhraseFile *g_pCorePhrases = NULL;
    7.12 +IPhraseCollection *g_pCorePhrases = NULL;
    7.13  unsigned int g_pCorePhraseID = 0;
    7.14  
    7.15  struct trans_t
    7.16 @@ -663,7 +665,7 @@
    7.17   ** MAIN TRANSLATOR CODE **
    7.18   **************************/
    7.19  
    7.20 -Translator::Translator() : m_ServerLang(LANGUAGE_ENGLISH)
    7.21 +Translator::Translator() : m_ServerLang(SOURCEMOD_LANGUAGE_ENGLISH)
    7.22  {
    7.23  	m_pStringTab = new BaseStringTable(2048);
    7.24  	m_pLCodeLookup = sm_trie_create();
    7.25 @@ -727,11 +729,15 @@
    7.26  {
    7.27  	AddLanguage("en", "English");
    7.28  
    7.29 -	unsigned int id;
    7.30 +	g_pCorePhrases = CreatePhraseCollection();
    7.31 +	g_pCorePhrases->AddPhraseFile("core.phrases");
    7.32  
    7.33 -	id = FindOrAddPhraseFile("core.phrases.txt");
    7.34 -	g_pCorePhraseID = id;
    7.35 -	g_pCorePhrases = GetFileByIndex(id);
    7.36 +	g_ShareSys.AddInterface(NULL, this);
    7.37 +}
    7.38 +
    7.39 +void Translator::OnSourceModShutdown()
    7.40 +{
    7.41 +	g_pCorePhrases->Destroy();
    7.42  }
    7.43  
    7.44  bool Translator::GetLanguageByCode(const char *code, unsigned int *index)
    7.45 @@ -842,7 +848,7 @@
    7.46  		g_Logger.LogError("Server language was set to bad language \"%s\" -- reverting to English", m_InitialLang);
    7.47  
    7.48  		strncopy(m_InitialLang, "en", sizeof(m_InitialLang));
    7.49 -		m_ServerLang = LANGUAGE_ENGLISH;
    7.50 +		m_ServerLang = SOURCEMOD_LANGUAGE_ENGLISH;
    7.51  	}
    7.52  
    7.53  	m_ServerLang = reinterpret_cast<unsigned int>(serverLang);
    7.54 @@ -936,61 +942,6 @@
    7.55  	return m_Files[index];
    7.56  }
    7.57  
    7.58 -size_t Translator::Translate(char *buffer, size_t maxlength, void **params, const Translation *pTrans)
    7.59 -{
    7.60 -	void *new_params[MAX_TRANSLATE_PARAMS];
    7.61 -
    7.62 -	/* Rewrite the parameter order */
    7.63 -	for (unsigned int i=0; i<pTrans->fmt_count; i++)
    7.64 -	{
    7.65 -		new_params[i] = params[pTrans->fmt_order[i]];
    7.66 -	}
    7.67 -
    7.68 -	return gnprintf(buffer, maxlength, pTrans->szPhrase, new_params);
    7.69 -}
    7.70 -
    7.71 -TransError Translator::CoreTransEx(CPhraseFile *pFile,
    7.72 -								   int client, 
    7.73 -								   char *buffer, 
    7.74 -								   size_t maxlength, 
    7.75 -								   const char *phrase, 
    7.76 -								   void **params, 
    7.77 -								   size_t *outlen)
    7.78 -{
    7.79 -	Translation trans;
    7.80 -	TransError err;
    7.81 -
    7.82 -	/* Using server lang temporarily until client lang stuff is implemented */
    7.83 -	if ((err = pFile->GetTranslation(phrase, m_ServerLang, &trans)) != Trans_Okay)
    7.84 -	{
    7.85 -		return err;
    7.86 -	}
    7.87 -
    7.88 -	size_t len = Translate(buffer, maxlength, params, &trans);
    7.89 -
    7.90 -	if (outlen)
    7.91 -	{
    7.92 -		*outlen = len;
    7.93 -	}
    7.94 -
    7.95 -	return Trans_Okay;
    7.96 -}
    7.97 -
    7.98 -TransError Translator::CoreTrans(int client, 
    7.99 -								  char *buffer, 
   7.100 -								  size_t maxlength, 
   7.101 -								  const char *phrase, 
   7.102 -								  void **params, 
   7.103 -								  size_t *outlen)
   7.104 -{
   7.105 -	if (!g_pCorePhrases)
   7.106 -	{
   7.107 -		return Trans_BadPhraseFile;
   7.108 -	}
   7.109 -
   7.110 -	return CoreTransEx(g_pCorePhrases, client, buffer, maxlength, phrase, params, outlen);
   7.111 -}
   7.112 -
   7.113  unsigned int Translator::GetServerLanguage()
   7.114  {
   7.115  	return m_ServerLang;
   7.116 @@ -1021,3 +972,105 @@
   7.117  
   7.118  	return true;
   7.119  }
   7.120 +
   7.121 +const char *Translator::GetInterfaceName()
   7.122 +{
   7.123 +	return SMINTERFACE_TRANSLATOR_NAME;
   7.124 +}
   7.125 +
   7.126 +unsigned int Translator::GetInterfaceVersion()
   7.127 +{
   7.128 +	return SMINTERFACE_TRANSLATOR_VERSION;
   7.129 +}
   7.130 +
   7.131 +IPhraseCollection *Translator::CreatePhraseCollection()
   7.132 +{
   7.133 +	return new CPhraseCollection();
   7.134 +}
   7.135 +
   7.136 +int Translator::SetGlobalTarget(int index)
   7.137 +{
   7.138 +	return g_SourceMod.SetGlobalTarget(index);
   7.139 +}
   7.140 +
   7.141 +int Translator::GetGlobalTarget() const
   7.142 +{
   7.143 +	return g_SourceMod.GetGlobalTarget();
   7.144 +}
   7.145 +
   7.146 +bool CoreTranslate(char *buffer, 
   7.147 +				   size_t maxlength,
   7.148 +				   const char *format,
   7.149 +				   unsigned int numparams,
   7.150 +				   size_t *pOutLength,
   7.151 +				   ...)
   7.152 +{
   7.153 +	va_list ap;
   7.154 +	unsigned int i;
   7.155 +	const char *fail_phrase;
   7.156 +	void *params[MAX_TRANSLATE_PARAMS];
   7.157 +
   7.158 +	if (numparams > MAX_TRANSLATE_PARAMS)
   7.159 +	{
   7.160 +		assert(false);
   7.161 +		return false;
   7.162 +	}
   7.163 +
   7.164 +	va_start(ap, pOutLength);
   7.165 +	for (i = 0; i < numparams; i++)
   7.166 +	{
   7.167 +		params[i] = va_arg(ap, void *);
   7.168 +	}
   7.169 +	va_end(ap);
   7.170 +
   7.171 +	if (!g_pCorePhrases->FormatString(buffer,
   7.172 +		maxlength, 
   7.173 +		format, 
   7.174 +		params,
   7.175 +		numparams,
   7.176 +		pOutLength,
   7.177 +		&fail_phrase))
   7.178 +	{
   7.179 +		if (fail_phrase != NULL)
   7.180 +		{
   7.181 +			g_Logger.LogError("[SM] Could not find core phrase: %s", fail_phrase);
   7.182 +		}
   7.183 +		else
   7.184 +		{
   7.185 +			g_Logger.LogError("[SM] Unknown fatal error while translating a core phrase.");
   7.186 +		}
   7.187 +
   7.188 +		return false;
   7.189 +	}
   7.190 +
   7.191 +	return true;
   7.192 +}
   7.193 +
   7.194 +bool Translator::FormatString(char *buffer,
   7.195 +							  size_t maxlength,
   7.196 +							  const char *format,
   7.197 +							  IPhraseCollection *pPhrases,
   7.198 +							  void **params,
   7.199 +							  unsigned int numparams,
   7.200 +							  size_t *pOutLength,
   7.201 +							  const char **pFailPhrase)
   7.202 +{
   7.203 +	unsigned int arg;
   7.204 +
   7.205 +	arg = 0;
   7.206 +	if (!gnprintf(buffer, maxlength, format, pPhrases, params, numparams, arg, pOutLength, pFailPhrase))
   7.207 +	{
   7.208 +		return false;
   7.209 +	}
   7.210 +
   7.211 +	if (arg != numparams)
   7.212 +	{
   7.213 +		if (pFailPhrase != NULL)
   7.214 +		{
   7.215 +			*pFailPhrase = NULL;
   7.216 +		}
   7.217 +		return false;
   7.218 +	}
   7.219 +
   7.220 +	return true;
   7.221 +}
     8.1 --- a/core/Translator.h	Fri May 09 08:22:39 2008 +0000
     8.2 +++ b/core/Translator.h	Sat May 10 09:23:55 2008 +0000
     8.3 @@ -38,6 +38,7 @@
     8.4  #include "sm_globals.h"
     8.5  #include "sm_memtable.h"
     8.6  #include "ITextParsers.h"
     8.7 +#include <ITranslator.h>
     8.8  
     8.9  #define MAX_TRANSLATE_PARAMS		32
    8.10  #define CORELANG_ENGLISH			0
    8.11 @@ -60,25 +61,9 @@
    8.12  	int m_FullName;
    8.13  };
    8.14  
    8.15 -struct Translation
    8.16 -{
    8.17 -	const char *szPhrase;		/**< Translated phrase. */
    8.18 -	unsigned int fmt_count;		/**< Number of format parameters. */
    8.19 -	int *fmt_order;				/**< Format phrase order. */
    8.20 -};
    8.21 -
    8.22 -#define LANGUAGE_ENGLISH			0
    8.23 -
    8.24 -enum TransError
    8.25 -{
    8.26 -	Trans_Okay = 0,
    8.27 -	Trans_BadLanguage = 1,
    8.28 -	Trans_BadPhrase = 2,
    8.29 -	Trans_BadPhraseLanguage = 3,
    8.30 -	Trans_BadPhraseFile = 4,
    8.31 -};
    8.32 -
    8.33 -class CPhraseFile : public ITextListener_SMC
    8.34 +class CPhraseFile : 
    8.35 +	public ITextListener_SMC,
    8.36 +	public IPhraseFile
    8.37  {
    8.38  public:
    8.39  	CPhraseFile(Translator *pTranslator, const char *file);
    8.40 @@ -112,7 +97,8 @@
    8.41  
    8.42  class Translator : 
    8.43  	public ITextListener_SMC,
    8.44 -	public SMGlobalClass
    8.45 +	public SMGlobalClass,
    8.46 +	public ITranslator
    8.47  {
    8.48  public:
    8.49  	Translator();
    8.50 @@ -125,6 +111,7 @@
    8.51  		size_t maxlength);
    8.52  	void OnSourceModAllInitialized();
    8.53  	void OnSourceModLevelChange(const char *mapName);
    8.54 +	void OnSourceModShutdown();
    8.55  public: // ITextListener_SMC
    8.56  	void ReadSMC_ParseStart();
    8.57  	SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
    8.58 @@ -138,23 +125,30 @@
    8.59  	bool GetLanguageInfo(unsigned int number, const char **code, const char **name);
    8.60  	bool GetLanguageByCode(const char *code, unsigned int *index);
    8.61  	bool GetLanguageByName(const char *name, unsigned int *index);
    8.62 -	size_t Translate(char *buffer, size_t maxlength, void **params, const Translation *pTrans);
    8.63  	CPhraseFile *GetFileByIndex(unsigned int index);
    8.64 -	TransError CoreTransEx(CPhraseFile *pFile,
    8.65 -		int client, 
    8.66 +public: //ITranslator
    8.67 +	unsigned int GetServerLanguage();
    8.68 +	unsigned int GetClientLanguage(int client);
    8.69 +	const char *GetInterfaceName();
    8.70 +	unsigned int GetInterfaceVersion();
    8.71 +	IPhraseCollection *CreatePhraseCollection();
    8.72 +	int SetGlobalTarget(int index);
    8.73 +	int GetGlobalTarget() const;
    8.74 +	size_t FormatString(
    8.75  		char *buffer, 
    8.76  		size_t maxlength, 
    8.77 -		const char *phrase, 
    8.78 -		void **params, 
    8.79 -		size_t *outlen=NULL);
    8.80 -	TransError CoreTrans(int client, 
    8.81 -						 char *buffer, 
    8.82 -						 size_t maxlength, 
    8.83 -						 const char *phrase, 
    8.84 -						 void **params, 
    8.85 -						 size_t *outlen=NULL);
    8.86 -	unsigned int GetServerLanguage();
    8.87 -	unsigned int GetClientLanguage(int client);
    8.88 +		SourcePawn::IPluginContext *pContext,
    8.89 +		const cell_t *params,
    8.90 +		unsigned int param);
    8.91 +	bool FormatString(
    8.92 +		char *buffer,
    8.93 +		size_t maxlength,
    8.94 +		const char *format,
    8.95 +		IPhraseCollection *pPhrases,
    8.96 +		void **params,
    8.97 +		unsigned int numparams,
    8.98 +		size_t *pOutLength,
    8.99 +		const char **pFailPhrase);
   8.100  private:
   8.101  	bool AddLanguage(const char *langcode, const char *description);
   8.102  private:
   8.103 @@ -168,7 +162,15 @@
   8.104  	char m_InitialLang[3];
   8.105  };
   8.106  
   8.107 -extern CPhraseFile *g_pCorePhrases;
   8.108 +/* Nice little wrapper to handle error logging and whatnot */
   8.109 +bool CoreTranslate(char *buffer, 
   8.110 +				   size_t maxlength,
   8.111 +				   const char *format,
   8.112 +				   unsigned int numparams,
   8.113 +				   size_t *pOutLength,
   8.114 +				   ...);
   8.115 +
   8.116 +extern IPhraseCollection *g_pCorePhrases;
   8.117  extern unsigned int g_pCorePhraseID;
   8.118  extern Translator g_Translator;
   8.119  
     9.1 --- a/core/msvc8/sourcemod_mm.vcproj	Fri May 09 08:22:39 2008 +0000
     9.2 +++ b/core/msvc8/sourcemod_mm.vcproj	Sat May 10 09:23:55 2008 +0000
     9.3 @@ -902,6 +902,10 @@
     9.4  				>
     9.5  			</File>
     9.6  			<File
     9.7 +				RelativePath="..\PhraseCollection.cpp"
     9.8 +				>
     9.9 +			</File>
    9.10 +			<File
    9.11  				RelativePath="..\PlayerManager.cpp"
    9.12  				>
    9.13  			</File>
    9.14 @@ -1064,6 +1068,10 @@
    9.15  				>
    9.16  			</File>
    9.17  			<File
    9.18 +				RelativePath="..\PhraseCollection.h"
    9.19 +				>
    9.20 +			</File>
    9.21 +			<File
    9.22  				RelativePath="..\PlayerManager.h"
    9.23  				>
    9.24  			</File>
    9.25 @@ -1233,6 +1241,10 @@
    9.26  				>
    9.27  			</File>
    9.28  			<File
    9.29 +				RelativePath="..\..\public\ITranslator.h"
    9.30 +				>
    9.31 +			</File>
    9.32 +			<File
    9.33  				RelativePath="..\..\public\IUserMessages.h"
    9.34  				>
    9.35  			</File>
    10.1 --- a/core/sm_stringutil.cpp	Fri May 09 08:22:39 2008 +0000
    10.2 +++ b/core/sm_stringutil.cpp	Sat May 10 09:23:55 2008 +0000
    10.3 @@ -50,43 +50,6 @@
    10.4  		return 0; \
    10.5  	}
    10.6  
    10.7 -size_t CorePlayerTranslate(int client, char *buffer, size_t maxlength, const char *phrase, void **params)
    10.8 -{
    10.9 -	Translation pTrans;
   10.10 -	TransError err;
   10.11 -
   10.12 -	err = g_pCorePhrases->GetTranslation(phrase, g_Translator.GetClientLanguage(client), &pTrans);
   10.13 -	if (err != Trans_Okay)
   10.14 -	{
   10.15 -		err = g_pCorePhrases->GetTranslation(phrase, g_Translator.GetServerLanguage(), &pTrans);
   10.16 -		if (err != Trans_Okay && g_Translator.GetServerLanguage() != CORELANG_ENGLISH)
   10.17 -		{
   10.18 -			err = g_pCorePhrases->GetTranslation(phrase, CORELANG_ENGLISH, &pTrans);
   10.19 -		}
   10.20 -	}
   10.21 -
   10.22 -	if (err != Trans_Okay)
   10.23 -	{
   10.24 -		return UTIL_Format(buffer, maxlength, "%s", phrase);
   10.25 -	}
   10.26 -
   10.27 -	return g_Translator.Translate(buffer, maxlength, params, &pTrans);
   10.28 -}
   10.29 -
   10.30 -inline bool TryTranslation(CPlugin *pl, const char *key, unsigned int langid, unsigned int langcount, Translation *pTrans)
   10.31 -{
   10.32 -	TransError err = Trans_BadLanguage;
   10.33 -	CPhraseFile *phrfl;
   10.34 -
   10.35 -	for (size_t i=0; i<langcount && err!=Trans_Okay; i++)
   10.36 -	{
   10.37 -		phrfl = g_Translator.GetFileByIndex(pl->GetLangFileByIndex(i));
   10.38 -		err = phrfl->GetTranslation(key, langid, pTrans);
   10.39 -	}
   10.40 -
   10.41 -	return (err == Trans_Okay) ? true : false;
   10.42 -}
   10.43 -
   10.44  inline void ReorderTranslationParams(const Translation *pTrans, cell_t *params)
   10.45  {
   10.46  	cell_t new_params[MAX_TRANSLATE_PARAMS];
   10.47 @@ -110,11 +73,13 @@
   10.48  	*error = false;
   10.49  	Translation pTrans;
   10.50  	CPlugin *pl = (CPlugin *)g_PluginSys.FindPluginByContext(pCtx->GetContext());
   10.51 -	size_t langcount = pl->GetLangFileCount();
   10.52  	unsigned int max_params = 0;
   10.53 +	IPhraseCollection *pPhrases;
   10.54 +
   10.55 +	pPhrases = pl->GetPhrases();
   10.56  
   10.57  try_serverlang:
   10.58 -	if (target == LANG_SERVER)
   10.59 +	if (target == SOURCEMOD_SERVER_LANGUAGE)
   10.60  	{
   10.61  		langid = g_Translator.GetServerLanguage();
   10.62   	}
   10.63 @@ -128,16 +93,16 @@
   10.64  		goto error_out;
   10.65  	}
   10.66  
   10.67 -	if (!TryTranslation(pl, key, langid, langcount, &pTrans))
   10.68 +	if (pPhrases->FindTranslation(key, langid, &pTrans) != Trans_Okay)
   10.69  	{
   10.70 -		if (target != LANG_SERVER && langid != g_Translator.GetServerLanguage())
   10.71 +		if (target != SOURCEMOD_SERVER_LANGUAGE && langid != g_Translator.GetServerLanguage())
   10.72  		{
   10.73 -			target = LANG_SERVER;
   10.74 +			target = SOURCEMOD_SERVER_LANGUAGE;
   10.75  			goto try_serverlang;
   10.76  		}
   10.77 -		else if (langid != LANGUAGE_ENGLISH)
   10.78 +		else if (langid != SOURCEMOD_LANGUAGE_ENGLISH)
   10.79  		{
   10.80 -			if (!TryTranslation(pl, key, LANGUAGE_ENGLISH, langcount, &pTrans))
   10.81 +			if (!pPhrases->FindTranslation(key, SOURCEMOD_LANGUAGE_ENGLISH, &pTrans))
   10.82  			{
   10.83  				pCtx->ThrowNativeErrorEx(SP_ERROR_PARAM, "Language phrase \"%s\" not found", key);
   10.84  				goto error_out;
   10.85 @@ -575,11 +540,32 @@
   10.86  	*buf_p = buf;
   10.87  }
   10.88  
   10.89 -size_t gnprintf(char *buffer, size_t maxlen, const char *format, void **args)
   10.90 +bool gnprintf(char *buffer,
   10.91 +			  size_t maxlen,
   10.92 +			  const char *format,
   10.93 +			  IPhraseCollection *pPhrases,
   10.94 +			  void **params,
   10.95 +			  unsigned int numparams,
   10.96 +			  unsigned int &curparam,
   10.97 +			  size_t *pOutLength,
   10.98 +			  const char **pFailPhrase)
   10.99  {
  10.100  	if (!buffer || !maxlen)
  10.101  	{
  10.102 -		return 0;
  10.103 +		if (pOutLength != NULL)
  10.104 +		{
  10.105 +			*pOutLength = 0;
  10.106 +		}
  10.107 +		return true;
  10.108 +	}
  10.109 +
  10.110 +	if (numparams > MAX_TRANSLATE_PARAMS)
  10.111 +	{
  10.112 +		if (pFailPhrase != NULL)
  10.113 +		{
  10.114 +			*pFailPhrase = NULL;
  10.115 +		}
  10.116 +		return false;
  10.117  	}
  10.118  
  10.119  	int arg = 0;
  10.120 @@ -668,7 +654,16 @@
  10.121  				{
  10.122  					goto done;
  10.123  				}
  10.124 -				char *c = (char *)args[arg];
  10.125 +				if (curparam >= numparams)
  10.126 +				{
  10.127 +					if (pFailPhrase != NULL)
  10.128 +					{
  10.129 +						*pFailPhrase = NULL;
  10.130 +					}
  10.131 +					return false;
  10.132 +				}
  10.133 +				char *c = (char *)params[curparam];
  10.134 +				curparam++;
  10.135  				*buf_p++ = *c;
  10.136  				llen--;
  10.137  				arg++;
  10.138 @@ -676,7 +671,16 @@
  10.139  			}
  10.140  		case 'b':
  10.141  			{
  10.142 -				int *value = (int *)args[arg];
  10.143 +				if (curparam >= numparams)
  10.144 +				{
  10.145 +					if (pFailPhrase != NULL)
  10.146 +					{
  10.147 +						*pFailPhrase = NULL;
  10.148 +					}
  10.149 +					return false;
  10.150 +				}
  10.151 +				int *value = (int *)params[curparam];
  10.152 +				curparam++;
  10.153  				AddBinary(&buf_p, llen, *value, width, flags);
  10.154  				arg++;
  10.155  				break;
  10.156 @@ -684,35 +688,224 @@
  10.157  		case 'd':
  10.158  		case 'i':
  10.159  			{
  10.160 -				int *value = (int *)args[arg];
  10.161 +				if (curparam >= numparams)
  10.162 +				{
  10.163 +					if (pFailPhrase != NULL)
  10.164 +					{
  10.165 +						*pFailPhrase = NULL;
  10.166 +					}
  10.167 +					return false;
  10.168 +				}
  10.169 +				int *value = (int *)params[curparam];
  10.170 +				curparam++;
  10.171  				AddInt(&buf_p, llen, *value, width, flags);
  10.172  				arg++;
  10.173  				break;
  10.174  			}
  10.175  		case 'u':
  10.176  			{
  10.177 -				unsigned int *value = (unsigned int *)args[arg];
  10.178 +				if (curparam >= numparams)
  10.179 +				{
  10.180 +					if (pFailPhrase != NULL)
  10.181 +					{
  10.182 +						*pFailPhrase = NULL;
  10.183 +					}
  10.184 +					return false;
  10.185 +				}
  10.186 +				unsigned int *value = (unsigned int *)params[curparam];
  10.187 +				curparam++;
  10.188  				AddUInt(&buf_p, llen, *value, width, flags);
  10.189  				arg++;
  10.190  				break;
  10.191  			}
  10.192  		case 'f':
  10.193  			{
  10.194 -				float *value = (float *)args[arg];
  10.195 +				if (curparam >= numparams)
  10.196 +				{
  10.197 +					if (pFailPhrase != NULL)
  10.198 +					{
  10.199 +						*pFailPhrase = NULL;
  10.200 +					}
  10.201 +					return false;
  10.202 +				}
  10.203 +				float *value = (float *)params[curparam];
  10.204 +				curparam++;
  10.205  				AddFloat(&buf_p, llen, *value, width, prec, flags);
  10.206  				arg++;
  10.207  				break;
  10.208  			}
  10.209  		case 's':
  10.210  			{
  10.211 -				const char *str = (const char *)args[arg];
  10.212 +				if (curparam >= numparams)
  10.213 +				{
  10.214 +					if (pFailPhrase != NULL)
  10.215 +					{
  10.216 +						*pFailPhrase = NULL;
  10.217 +					}
  10.218 +					return false;
  10.219 +				}
  10.220 +				const char *str = (const char *)params[curparam];
  10.221 +				curparam++;
  10.222  				AddString(&buf_p, llen, str, width, prec);
  10.223  				arg++;
  10.224  				break;
  10.225  			}
  10.226 +		case 'T':
  10.227 +		case 't':
  10.228 +			{
  10.229 +				int target;
  10.230 +				const char *key;
  10.231 +				size_t out_length;
  10.232 +				Translation trans;
  10.233 +				unsigned int lang_id;
  10.234 +
  10.235 +				if (curparam >= numparams)
  10.236 +				{
  10.237 +					if (pFailPhrase != NULL)
  10.238 +					{
  10.239 +						*pFailPhrase = NULL;
  10.240 +					}
  10.241 +					return false;
  10.242 +				}
  10.243 +				key = (const char *)(params[curparam]);
  10.244 +				curparam++;
  10.245 +
  10.246 +				if (ch == 'T')
  10.247 +				{
  10.248 +					if (curparam >= numparams)
  10.249 +					{
  10.250 +						if (pFailPhrase != NULL)
  10.251 +						{
  10.252 +							*pFailPhrase = NULL;
  10.253 +						}
  10.254 +						return false;
  10.255 +					}
  10.256 +					target = *((int *)(params[curparam]));
  10.257 +					curparam++;
  10.258 +				}
  10.259 +				else
  10.260 +				{
  10.261 +					target = g_Translator.GetGlobalTarget();
  10.262 +				}
  10.263 +
  10.264 +try_again:
  10.265 +				if (target == SOURCEMOD_SERVER_LANGUAGE)
  10.266 +				{
  10.267 +					lang_id = g_Translator.GetServerLanguage();
  10.268 +				}
  10.269 +				else if (target >= 1 && target <= g_Players.GetMaxClients())
  10.270 +				{
  10.271 +					lang_id = g_Translator.GetClientLanguage(target);
  10.272 +				}
  10.273 +				else
  10.274 +				{
  10.275 +					lang_id = g_Translator.GetServerLanguage();
  10.276 +				}
  10.277 +
  10.278 +				if (pPhrases == NULL)
  10.279 +				{
  10.280 +					if (pFailPhrase != NULL)
  10.281 +					{
  10.282 +						*pFailPhrase = key;
  10.283 +					}
  10.284 +					return false;
  10.285 +				}
  10.286 +
  10.287 +				if (pPhrases->FindTranslation(key, lang_id, &trans) != Trans_Okay)
  10.288 +				{
  10.289 +					if (target != SOURCEMOD_SERVER_LANGUAGE && lang_id != g_Translator.GetServerLanguage())
  10.290 +					{
  10.291 +						target = SOURCEMOD_SERVER_LANGUAGE;
  10.292 +						goto try_again;
  10.293 +					}
  10.294 +					else if (lang_id != SOURCEMOD_LANGUAGE_ENGLISH)
  10.295 +					{
  10.296 +						if (pPhrases->FindTranslation(key, SOURCEMOD_LANGUAGE_ENGLISH, &trans) != Trans_Okay)
  10.297 +						{
  10.298 +							if (pFailPhrase != NULL)
  10.299 +							{
  10.300 +								*pFailPhrase = key;
  10.301 +							}
  10.302 +							return false;
  10.303 +						}
  10.304 +					}
  10.305 +					else
  10.306 +					{
  10.307 +						if (pFailPhrase != NULL)
  10.308 +						{
  10.309 +							*pFailPhrase = key;
  10.310 +						}
  10.311 +						return false;
  10.312 +					}
  10.313 +				}
  10.314 +
  10.315 +				if (trans.fmt_count)
  10.316 +				{
  10.317 +					unsigned int i;
  10.318 +					void *new_params[MAX_TRANSLATE_PARAMS];
  10.319 +
  10.320 +					if (curparam + trans.fmt_count > numparams)
  10.321 +					{
  10.322 +						if (pFailPhrase != NULL)
  10.323 +						{
  10.324 +							*pFailPhrase = NULL;
  10.325 +						}
  10.326 +						return false;
  10.327 +					}
  10.328 +
  10.329 +					/* Copy the array and re-order the stack */
  10.330 +					memcpy(new_params, params, sizeof(void *) * numparams);
  10.331 +					for (i = 0; i < trans.fmt_count; i++)
  10.332 +					{
  10.333 +						new_params[i] = const_cast<void *>(params[curparam + trans.fmt_order[i]]);
  10.334 +					}
  10.335 +
  10.336 +					if (!gnprintf(buf_p,
  10.337 +							llen,
  10.338 +							trans.szPhrase,
  10.339 +							pPhrases,
  10.340 +							new_params,
  10.341 +							numparams,
  10.342 +							curparam,
  10.343 +							&out_length,
  10.344 +							pFailPhrase))
  10.345 +					{
  10.346 +						return false;
  10.347 +					}
  10.348 +				}
  10.349 +				else
  10.350 +				{
  10.351 +					if (!gnprintf(buf_p,
  10.352 +						llen,
  10.353 +						trans.szPhrase,
  10.354 +						pPhrases,
  10.355 +						params,
  10.356 +						numparams,
  10.357 +						curparam,
  10.358 +						&out_length,
  10.359 +						pFailPhrase))
  10.360 +					{
  10.361 +						return false;
  10.362 +					}
  10.363 +				}
  10.364 +
  10.365 +				buf_p += out_length;
  10.366 +				llen -= out_length;
  10.367 +
  10.368 +				break;
  10.369 +			}
  10.370  		case 'X':
  10.371  			{
  10.372 -				unsigned int *value = (unsigned int *)args[arg];
  10.373 +				if (curparam >= numparams)
  10.374 +				{
  10.375 +					if (pFailPhrase != NULL)
  10.376 +					{
  10.377 +						*pFailPhrase = NULL;
  10.378 +					}
  10.379 +					return false;
  10.380 +				}
  10.381 +				unsigned int *value = (unsigned int *)params[curparam];
  10.382 +				curparam++;
  10.383  				flags |= UPPERDIGITS;
  10.384  				AddHex(&buf_p, llen, *value, width, flags);
  10.385  				arg++;
  10.386 @@ -720,7 +913,16 @@
  10.387  			}
  10.388  		case 'x':
  10.389  			{
  10.390 -				unsigned int *value = (unsigned int *)args[arg];
  10.391 +				if (curparam >= numparams)
  10.392 +				{
  10.393 +					if (pFailPhrase != NULL)
  10.394 +					{
  10.395 +						*pFailPhrase = NULL;
  10.396 +					}
  10.397 +					return false;
  10.398 +				}
  10.399 +				unsigned int *value = (unsigned int *)params[curparam];
  10.400 +				curparam++;
  10.401  				AddHex(&buf_p, llen, *value, width, flags);
  10.402  				arg++;
  10.403  				break;
  10.404 @@ -761,7 +963,12 @@
  10.405  done:
  10.406  	*buf_p = '\0';
  10.407  
  10.408 -	return (maxlen - llen - 1);
  10.409 +	if (pOutLength != NULL)
  10.410 +	{
  10.411 +		*pOutLength = (maxlen - llen - 1);
  10.412 +	}
  10.413 +
  10.414 +	return true;
  10.415  }
  10.416  
  10.417  size_t atcprintf(char *buffer, size_t maxlen, const char *format, IPluginContext *pCtx, const cell_t *params, int *param)
    11.1 --- a/core/sm_stringutil.h	Fri May 09 08:22:39 2008 +0000
    11.2 +++ b/core/sm_stringutil.h	Sat May 10 09:23:55 2008 +0000
    11.3 @@ -33,23 +33,30 @@
    11.4  #define _INCLUDE_SOURCEMOD_STRINGUTIL_H_
    11.5  
    11.6  #include <math.h>
    11.7 -#include "sp_vm_api.h"
    11.8 -#include "sp_typeutil.h"
    11.9 +#include <sp_vm_api.h>
   11.10 +#include <sp_typeutil.h>
   11.11 +#include <ITranslator.h>
   11.12  
   11.13  using namespace SourcePawn;
   11.14 -
   11.15 -#define LANG_SERVER		0
   11.16 +using namespace SourceMod;
   11.17  
   11.18  #define IS_STR_FILLED(var) (var[0] != '\0')
   11.19  
   11.20  size_t atcprintf(char *buffer, size_t maxlen, const char *format, IPluginContext *pCtx, const cell_t *params, int *param);
   11.21  const char *stristr(const char *str, const char *substr);
   11.22  unsigned int strncopy(char *dest, const char *src, size_t count);
   11.23 -size_t gnprintf(char *buffer, size_t maxlen, const char *format, void **args);
   11.24 +bool gnprintf(char *buffer,
   11.25 +			  size_t maxlen,
   11.26 +			  const char *format,
   11.27 +			  IPhraseCollection *pPhrases,
   11.28 +			  void **params,
   11.29 +			  unsigned int numparams,
   11.30 +			  unsigned int &curparam,
   11.31 +			  size_t *pOutLength,
   11.32 +			  const char **pFailPhrase);
   11.33  size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...);
   11.34  size_t UTIL_FormatArgs(char *buffer, size_t maxlength, const char *fmt, va_list ap);
   11.35  char *sm_strdup(const char *str);
   11.36 -size_t CorePlayerTranslate(int client, char *buffer, size_t maxlength, const char *phrase, void **params);
   11.37  unsigned int UTIL_ReplaceAll(char *subject, size_t maxlength, const char *search, const char *replace);
   11.38  char *UTIL_ReplaceEx(char *subject, size_t maxLen, const char *search, size_t searchLen, const char *replace, size_t replaceLen);
   11.39  char *UTIL_TrimWhitespace(char *str, size_t &len);
    12.1 --- a/core/smn_console.cpp	Fri May 09 08:22:39 2008 +0000
    12.2 +++ b/core/smn_console.cpp	Sat May 10 09:23:55 2008 +0000
    12.3 @@ -828,7 +828,7 @@
    12.4  
    12.5  static cell_t sm_ServerCommand(IPluginContext *pContext, const cell_t *params)
    12.6  {
    12.7 -	g_SourceMod.SetGlobalTarget(LANG_SERVER);
    12.8 +	g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
    12.9  
   12.10  	char buffer[1024];
   12.11  	size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1);
   12.12 @@ -849,7 +849,7 @@
   12.13  
   12.14  static cell_t sm_InsertServerCommand(IPluginContext *pContext, const cell_t *params)
   12.15  {
   12.16 -	g_SourceMod.SetGlobalTarget(LANG_SERVER);
   12.17 +	g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
   12.18  
   12.19  	char buffer[1024];
   12.20  	size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer)-2, pContext, params, 1);
    13.1 --- a/core/smn_core.cpp	Fri May 09 08:22:39 2008 +0000
    13.2 +++ b/core/smn_core.cpp	Sat May 10 09:23:55 2008 +0000
    13.3 @@ -126,7 +126,7 @@
    13.4  {
    13.5  	char buffer[512];
    13.6  
    13.7 -	g_SourceMod.SetGlobalTarget(LANG_SERVER);
    13.8 +	g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
    13.9  
   13.10  	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
   13.11  
   13.12 @@ -502,7 +502,7 @@
   13.13  static cell_t sm_LogAction(IPluginContext *pContext, const cell_t *params)
   13.14  {
   13.15  	char buffer[2048];
   13.16 -	g_SourceMod.SetGlobalTarget(LANG_SERVER);
   13.17 +	g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
   13.18  	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 3);
   13.19  
   13.20  	if (pContext->GetContext()->n_err != SP_ERROR_NONE)
   13.21 @@ -532,7 +532,7 @@
   13.22  	}
   13.23  
   13.24  	char buffer[2048];
   13.25 -	g_SourceMod.SetGlobalTarget(LANG_SERVER);
   13.26 +	g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
   13.27  	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
   13.28  
   13.29  	if (pContext->GetContext()->n_err != SP_ERROR_NONE)
   13.30 @@ -565,7 +565,7 @@
   13.31  	}
   13.32  
   13.33  	char buffer[2048];
   13.34 -	g_SourceMod.SetGlobalTarget(LANG_SERVER);
   13.35 +	g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
   13.36  	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
   13.37  
   13.38  	if (pContext->GetContext()->n_err != SP_ERROR_NONE)
    14.1 --- a/core/smn_fakenatives.cpp	Fri May 09 08:22:39 2008 +0000
    14.2 +++ b/core/smn_fakenatives.cpp	Sat May 10 09:23:55 2008 +0000
    14.3 @@ -136,7 +136,7 @@
    14.4  		return pContext->ThrowNativeError("Not called from inside a native function");
    14.5  	}
    14.6  
    14.7 -	g_SourceMod.SetGlobalTarget(LANG_SERVER);
    14.8 +	g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
    14.9  
   14.10  	char buffer[512];
   14.11  
    15.1 --- a/core/smn_filesystem.cpp	Fri May 09 08:22:39 2008 +0000
    15.2 +++ b/core/smn_filesystem.cpp	Sat May 10 09:23:55 2008 +0000
    15.3 @@ -568,7 +568,7 @@
    15.4  
    15.5  static cell_t sm_LogToGame(IPluginContext *pContext, const cell_t *params)
    15.6  {
    15.7 -	g_SourceMod.SetGlobalTarget(LANG_SERVER);
    15.8 +	g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
    15.9  
   15.10  	char buffer[1024];
   15.11  	size_t len = g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
   15.12 @@ -594,7 +594,7 @@
   15.13  
   15.14  static cell_t sm_LogMessage(IPluginContext *pContext, const cell_t *params)
   15.15  {
   15.16 -	g_SourceMod.SetGlobalTarget(LANG_SERVER);
   15.17 +	g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
   15.18  
   15.19  	char buffer[1024];
   15.20  	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
   15.21 @@ -612,7 +612,7 @@
   15.22  
   15.23  static cell_t sm_LogError(IPluginContext *pContext, const cell_t *params)
   15.24  {
   15.25 -	g_SourceMod.SetGlobalTarget(LANG_SERVER);
   15.26 +	g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
   15.27  
   15.28  	char buffer[1024];
   15.29  	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 1);
   15.30 @@ -667,7 +667,7 @@
   15.31  	}
   15.32  
   15.33  	char buffer[2048];
   15.34 -	g_SourceMod.SetGlobalTarget(LANG_SERVER);
   15.35 +	g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
   15.36  	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
   15.37  
   15.38  	if (pContext->GetContext()->n_err != SP_ERROR_NONE)
   15.39 @@ -698,7 +698,7 @@
   15.40  	}
   15.41  
   15.42  	char buffer[2048];
   15.43 -	g_SourceMod.SetGlobalTarget(LANG_SERVER);
   15.44 +	g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
   15.45  	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
   15.46  
   15.47  	if (pContext->GetContext()->n_err != SP_ERROR_NONE)
    16.1 --- a/core/smn_lang.cpp	Fri May 09 08:22:39 2008 +0000
    16.2 +++ b/core/smn_lang.cpp	Sat May 10 09:23:55 2008 +0000
    16.3 @@ -37,24 +37,25 @@
    16.4  
    16.5  static cell_t sm_LoadTranslations(IPluginContext *pCtx, const cell_t *params)
    16.6  {
    16.7 -	char *filename;
    16.8 -	unsigned int index;
    16.9 +	char *filename, *ext;
   16.10 +	char buffer[PLATFORM_MAX_PATH];
   16.11  	CPlugin *pl = (CPlugin *)g_PluginSys.FindPluginByContext(pCtx->GetContext());
   16.12  
   16.13  	pCtx->LocalToString(params[1], &filename);
   16.14 +	UTIL_Format(buffer, sizeof(buffer), "%s", filename);
   16.15  
   16.16 -	/* Check if there is no extension */
   16.17 -	const char *ext = g_LibSys.GetFileExtension(filename);
   16.18 -	if (!ext || (strcmp(ext, "cfg") && strcmp(ext, "txt")))
   16.19 +	/* Make sure there is no extension */
   16.20 +	if ((ext = strstr(buffer, ".txt")) != NULL
   16.21 +		|| (ext = strstr(buffer, ".cfg")) != NULL)
   16.22  	{
   16.23 -		/* Append one */
   16.24 -		static char new_file[PLATFORM_MAX_PATH];
   16.25 -		UTIL_Format(new_file, sizeof(new_file), "%s.txt", filename);
   16.26 -		filename = new_file;
   16.27 +		/* Simple heuristic -- just see if it's at the end and terminate if so */
   16.28 +		if (ext - buffer == strlen(buffer) - 4)
   16.29 +		{
   16.30 +			*ext = '\0';
   16.31 +		}
   16.32  	}
   16.33  
   16.34 -	index = g_Translator.FindOrAddPhraseFile(filename);
   16.35 -	pl->AddLangFile(index);
   16.36 +	pl->GetPhrases()->AddPhraseFile(buffer);
   16.37  
   16.38  	return 1;
   16.39  }
    17.1 --- a/core/smn_menus.cpp	Fri May 09 08:22:39 2008 +0000
    17.2 +++ b/core/smn_menus.cpp	Sat May 10 09:23:55 2008 +0000
    17.3 @@ -838,7 +838,7 @@
    17.4  		return pContext->ThrowNativeError("Menu handle %x is invalid (error %d)", hndl, err);
    17.5  	}
    17.6  
    17.7 -	g_SourceMod.SetGlobalTarget(LANG_SERVER);
    17.8 +	g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
    17.9  
   17.10  	char buffer[1024];
   17.11  	g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, 2);
    18.1 --- a/core/smn_player.cpp	Fri May 09 08:22:39 2008 +0000
    18.2 +++ b/core/smn_player.cpp	Sat May 10 09:23:55 2008 +0000
    18.3 @@ -928,7 +928,7 @@
    18.4  	}
    18.5  	else
    18.6  	{
    18.7 -		g_SourceMod.SetGlobalTarget(LANG_SERVER);
    18.8 +		g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
    18.9  		g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
   18.10  
   18.11  		if (pContext->GetContext()->n_err != SP_ERROR_NONE)
   18.12 @@ -1065,7 +1065,7 @@
   18.13  	}
   18.14  	else
   18.15  	{
   18.16 -		g_SourceMod.SetGlobalTarget(LANG_SERVER);
   18.17 +		g_SourceMod.SetGlobalTarget(SOURCEMOD_SERVER_LANGUAGE);
   18.18  		g_SourceMod.FormatString(buffer, sizeof(buffer), pContext, params, fmt_param);
   18.19  
   18.20  		if (pContext->GetContext()->n_err != SP_ERROR_NONE)
    19.1 --- a/core/systems/PluginSys.cpp	Fri May 09 08:22:39 2008 +0000
    19.2 +++ b/core/systems/PluginSys.cpp	Sat May 10 09:23:55 2008 +0000
    19.3 @@ -67,6 +67,7 @@
    19.4  	m_FakeNativesMissing = false;
    19.5  	m_LibraryMissing = false;
    19.6  	m_bGotAllLoaded = false;
    19.7 +	m_pPhrases = g_Translator.CreatePhraseCollection();
    19.8  }
    19.9  
   19.10  CPlugin::~CPlugin()
   19.11 @@ -111,6 +112,11 @@
   19.12  		delete m_configs[i];
   19.13  	}
   19.14  	m_configs.clear();
   19.15 +	if (m_pPhrases != NULL)
   19.16 +	{
   19.17 +		m_pPhrases->Destroy();
   19.18 +		m_pPhrases = NULL;
   19.19 +	}
   19.20  }
   19.21  
   19.22  void CPlugin::InitIdentity()
   19.23 @@ -128,7 +134,6 @@
   19.24  	unsigned int base_size = 
   19.25  		sizeof(CPlugin) 
   19.26  		+ sizeof(IdentityToken_t)
   19.27 -		+ (m_PhraseFiles.size() * sizeof(unsigned int))
   19.28  		+ (m_dependents.size() * sizeof(CPlugin *))
   19.29  		+ (m_dependsOn.size() * sizeof(CPlugin *))
   19.30  		+ (m_fakeNatives.size() * (sizeof(FakeNative *) + sizeof(FakeNative)))
   19.31 @@ -710,19 +715,9 @@
   19.32  	m_LastAccess = t;
   19.33  }
   19.34  
   19.35 -void CPlugin::AddLangFile(unsigned int index)
   19.36 -{
   19.37 -	m_PhraseFiles.push_back(index);
   19.38 -}
   19.39 -
   19.40 -size_t CPlugin::GetLangFileCount()
   19.41 +IPhraseCollection *CPlugin::GetPhrases()
   19.42  {
   19.43 -	return m_PhraseFiles.size();
   19.44 -}
   19.45 -
   19.46 -unsigned int CPlugin::GetLangFileByIndex(unsigned int index)
   19.47 -{
   19.48 -	return m_PhraseFiles.at(index);
   19.49 +	return m_pPhrases;
   19.50  }
   19.51  
   19.52  void CPlugin::DependencyDropped(CPlugin *pOwner)
   19.53 @@ -1488,8 +1483,8 @@
   19.54  		OnLibraryAction((*s_iter).c_str(), true, false);
   19.55  	}
   19.56  
   19.57 -	/* Finally, add the core language file */
   19.58 -	pPlugin->AddLangFile(g_pCorePhraseID);
   19.59 +	/* :TODO: optimize? does this even matter? */
   19.60 +	pPlugin->GetPhrases()->AddPhraseFile("core.phrases");
   19.61  
   19.62  	return true;
   19.63  }
    20.1 --- a/core/systems/PluginSys.h	Fri May 09 08:22:39 2008 +0000
    20.2 +++ b/core/systems/PluginSys.h	Sat May 10 09:23:55 2008 +0000
    20.3 @@ -53,6 +53,7 @@
    20.4  #else
    20.5  #include "convar_sm.h"
    20.6  #endif
    20.7 +#include "ITranslator.h"
    20.8  
    20.9  using namespace SourceHook;
   20.10  
   20.11 @@ -244,19 +245,9 @@
   20.12  	bool IsRunnable();
   20.13  
   20.14  	/**
   20.15 -	 * Adds a language file index to the plugin's list.
   20.16 -	 */
   20.17 -	void AddLangFile(unsigned int index);
   20.18 -
   20.19 -	/**
   20.20 -	 * Get language file count for this plugin.
   20.21 +	 * Get languages info.
   20.22  	 */
   20.23 -	size_t GetLangFileCount();
   20.24 -
   20.25 -	/**
   20.26 -	 * Get language file index based on the vector index.
   20.27 -	 */
   20.28 -	unsigned int GetLangFileByIndex(unsigned int index);
   20.29 +	IPhraseCollection *GetPhrases();
   20.30  public:
   20.31  	/**
   20.32  	 * Returns the modification time during last plugin load.
   20.33 @@ -300,7 +291,7 @@
   20.34  	IdentityToken_t *m_ident;
   20.35  	Handle_t m_handle;
   20.36  	bool m_WasRunning;
   20.37 -	CVector<unsigned int> m_PhraseFiles;
   20.38 +	IPhraseCollection *m_pPhrases;
   20.39  	List<CPlugin *> m_dependents;
   20.40  	List<CPlugin *> m_dependsOn;
   20.41  	List<FakeNative *> m_fakeNatives;
    21.1 --- a/public/ISourceMod.h	Fri May 09 08:22:39 2008 +0000
    21.2 +++ b/public/ISourceMod.h	Sat May 10 09:23:55 2008 +0000
    21.3 @@ -221,6 +221,7 @@
    21.4  		 * translations (that is, %t).
    21.5  		 *
    21.6  		 * @param index		Client index.
    21.7 +		 * @deprecated		Use ITranslator::GetGlobalTarget() instead.
    21.8  		 * @return			Old global client value.
    21.9  		 */
   21.10  		virtual unsigned int SetGlobalTarget(unsigned int index) =0;
   21.11 @@ -229,6 +230,7 @@
   21.12  		 * @brief Returns the global client SourceMod is currently using 
   21.13  		 * for assisted translations (that is, %t).
   21.14  		 *
   21.15 +		 * @deprecated		Use ITranslator::GetGlobalTarget() instead.
   21.16  		 * @return			Global client value.
   21.17  		 */
   21.18  		virtual unsigned int GetGlobalTarget() const =0;
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/public/ITranslator.h	Sat May 10 09:23:55 2008 +0000
    22.3 @@ -0,0 +1,329 @@
    22.4 +/**
    22.5 + * vim: set ts=4 :
    22.6 + * =============================================================================
    22.7 + * SourceMod
    22.8 + * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
    22.9 + * =============================================================================
   22.10 + *
   22.11 + * This program is free software; you can redistribute it and/or modify it under
   22.12 + * the terms of the GNU General Public License, version 3.0, as published by the
   22.13 + * Free Software Foundation.
   22.14 + * 
   22.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
   22.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   22.17 + * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
   22.18 + * details.
   22.19 + *
   22.20 + * You should have received a copy of the GNU General Public License along with
   22.21 + * this program.  If not, see <http://www.gnu.org/licenses/>.
   22.22 + *
   22.23 + * As a special exception, AlliedModders LLC gives you permission to link the
   22.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
   22.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
   22.26 + * by the Valve Corporation.  You must obey the GNU General Public License in
   22.27 + * all respects for all other code used.  Additionally, AlliedModders LLC grants
   22.28 + * this exception to all derivative works.  AlliedModders LLC defines further
   22.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
   22.30 + * or <http://www.sourcemod.net/license.php>.
   22.31 + *
   22.32 + * Version: $Id$
   22.33 + */
   22.34 +
   22.35 +#ifndef _INCLUDE_SOURCEMOD_TRANSLATOR_INTERFACE_H_
   22.36 +#define _INCLUDE_SOURCEMOD_TRANSLATOR_INTERFACE_H_
   22.37 +
   22.38 +#include <IShareSys.h>
   22.39 +
   22.40 +#define SMINTERFACE_TRANSLATOR_NAME		"ITranslator"
   22.41 +#define SMINTERFACE_TRANSLATOR_VERSION	1
   22.42 +
   22.43 +/**
   22.44 + * @file ITranslator.h
   22.45 + * @brief Defines interfaces related to translation files.
   22.46 + */
   22.47 +
   22.48 +namespace SourceMod
   22.49 +{
   22.50 +	/**
   22.51 +	 * @brief SourceMod hardcodes the English language (default) to ID 0.
   22.52 +	 * This cannot be changed and languages.cfg should never have it as anything 
   22.53 +	 * other than the first index.
   22.54 +	 */
   22.55 +	#define SOURCEMOD_LANGUAGE_ENGLISH			0
   22.56 +
   22.57 +	/**
   22.58 +	 * @brief For %T formats, specifies that the language should be that of the 
   22.59 +	 * server and not a specific client.
   22.60 +	 */
   22.61 +	#define SOURCEMOD_SERVER_LANGUAGE			0
   22.62 +
   22.63 +	/**
   22.64 +	 * @brief Translation error codes.
   22.65 +	 */
   22.66 +	enum TransError
   22.67 +	{
   22.68 +		Trans_Okay = 0,					/**< Translation succeeded. */
   22.69 +		Trans_BadLanguage = 1,			/**< Bad language ID. */
   22.70 +		Trans_BadPhrase = 2,			/**< Phrase not found. */
   22.71 +		Trans_BadPhraseLanguage = 3,	/**< Phrase not found in the given language. */
   22.72 +		Trans_BadPhraseFile = 4,		/**< Phrase file was unreadable. */
   22.73 +	};
   22.74 +
   22.75 +	/**
   22.76 +	 * @brief Contains information about a translation phrase.
   22.77 +	 */
   22.78 +	struct Translation
   22.79 +	{
   22.80 +		const char *szPhrase;		/**< Translated phrase. */
   22.81 +		unsigned int fmt_count;		/**< Number of format parameters. */
   22.82 +		int *fmt_order;				/**< Array of size fmt_count where each 
   22.83 +										 element is the numerical order of 
   22.84 +										 parameter insertion, starting from 
   22.85 +										 0.
   22.86 +										 */
   22.87 +	};
   22.88 +
   22.89 +	/**
   22.90 +	 * @brief Represents a phrase file from SourceMod's "translations" folder.
   22.91 +	 */
   22.92 +	class IPhraseFile
   22.93 +	{
   22.94 +	public:
   22.95 +		/**
   22.96 +		 * @brief Attempts to find a translation phrase in a phrase file.
   22.97 +		 *
   22.98 +		 * @param szPhrase			String containing the phrase name.
   22.99 +		 * @param lang_id			Language ID.
  22.100 +		 * @param pTrans			Buffer to store translation info.
  22.101 +		 * @return					Translation error code indicating success 
  22.102 +		 *							(pTrans is filled) or failure (pTrans 
  22.103 +		 *							contents is undefined).
  22.104 +		 */
  22.105 +		virtual TransError GetTranslation(
  22.106 +			const char *szPhrase, 
  22.107 +			unsigned int lang_id, 
  22.108 +			Translation *pTrans) =0;
  22.109 +
  22.110 +		/**
  22.111 +		 * @brief Returns the file name of this translation file.
  22.112 +		 *
  22.113 +		 * @return					File name.
  22.114 +		 */
  22.115 +		virtual const char *GetFilename() =0;
  22.116 +	};
  22.117 +
  22.118 +	/**
  22.119 +	 * Represents a collection of phrase files.
  22.120 +	 */
  22.121 +	class IPhraseCollection
  22.122 +	{
  22.123 +	public:
  22.124 +		/**
  22.125 +		 * @brief Adds a phrase file to the collection, using a cached one 
  22.126 +		 * if already found.  The return value is provided for informational 
  22.127 +		 * purposes and does not need to be saved.  The life time of the 
  22.128 +		 * return pointer is equal to the life time of the collection.
  22.129 +		 *
  22.130 +		 * This function will internally ignore dupliate additions but still 
  22.131 +		 * return a valid pointer.
  22.132 +		 *
  22.133 +		 * @param filename			File name, without the ".txt" extension, of 
  22.134 +		 *							the phrase file in the translations folder.
  22.135 +		 * @return					An IPhraseFile pointer, even if the file does 
  22.136 +		 *							not exist.
  22.137 +		 */
  22.138 +		virtual IPhraseFile *AddPhraseFile(const char *filename) =0;
  22.139 +
  22.140 +		/**
  22.141 +		 * @brief Returns the number of contained phrase files.
  22.142 +		 *
  22.143 +		 * @return					Number of contained phrase files.
  22.144 +		 */
  22.145 +		virtual unsigned int GetFileCount() =0;
  22.146 +		
  22.147 +		/**
  22.148 +		 * @brief Returns the pointer to a contained phrase file.
  22.149 +		 *
  22.150 +		 * @param file				File index, from 0 to GetFileCount()-1.
  22.151 +		 * @return					IPhraseFile pointer, or NULL if out of 
  22.152 +		 *							range.
  22.153 +		 */
  22.154 +		virtual IPhraseFile *GetFile(unsigned int file) =0;
  22.155 +
  22.156 +		/**
  22.157 +		 * @brief Destroys the phrase collection, freeing all internal 
  22.158 +		 * resources and invalidating the object.
  22.159 +		 */
  22.160 +		virtual void Destroy() =0;
  22.161 +
  22.162 +		/**
  22.163 +		 * @brief Attempts a translation across a given language.  All 
  22.164 +		 * contained files are searched for an appropriate match; the 
  22.165 +		 * first valid match is returned.
  22.166 +		 *
  22.167 +		 * @param key				String containing the phrase name.
  22.168 +		 * @param langid			Language ID to translate to.
  22.169 +		 * @param pTrans			Translation buffer.
  22.170 +		 * @return					Translation error code; on success, 
  22.171 +		 *							pTrans is valid.  On failure, the 
  22.172 +		 *							contents of pTrans is undefined.
  22.173 +		 */
  22.174 +		virtual TransError FindTranslation(
  22.175 +			const char *key,
  22.176 +			unsigned int langid,
  22.177 +			Translation *pTrans) =0;
  22.178 +
  22.179 +		/**
  22.180 +		 * @brief Formats a phrase given a parameter stack.  The parameter 
  22.181 +		 * stack size must exactly match the expected parameter count.  If 
  22.182 +		 * this count is too small or too large, the format fails.
  22.183 +		 *
  22.184 +		 * @param buffer			Buffer to store formatted text.
  22.185 +		 * @param maxlength			Maximum length of the buffer.
  22.186 +		 * @param format			String containing format information.  
  22.187 +		 *							This is equivalent to SourceMod's Format() 
  22.188 +		 *							native, and sub-translations are acceptable. 
  22.189 +		 * @param params			An array of pointers to each parameter. 
  22.190 +		 *							Integer parameters must have a pointer to the integer.
  22.191 +		 *							Float parameters must have a pointer to a float.
  22.192 +		 *							String parameters must be a string pointer.
  22.193 +		 *							Char parameters must be a pointer to a char.
  22.194 +		 *							Translation parameters fill multiple indexes in the 
  22.195 +		 *							array.  For %T translations, the expected stack is:
  22.196 +		 *							[phrase string pointer] [int target id pointer] [...] 
  22.197 +		 *							Where [...] is the required parameters for the translation,  
  22.198 +		 *							in the order expected by the phrase, not the phrase's 
  22.199 +		 *							translation.  For example, say the format is:
  22.200 +		 *							"%d %T" and the phrase's format is {1:s,2:f}, then the 
  22.201 +		 *							parameter stack should be:
  22.202 +		 *							int *, const char *, int *, const char *, float *
  22.203 +		 *							The %t modifier is the same except the target id pointer 
  22.204 +		 *							would be removed:
  22.205 +		 *							int *, const char *, const char *, float *
  22.206 +		 * @param numparams			Number of parameters in the params array.
  22.207 +		 * @param pOutLength		Optional pointer filled with output length on success.
  22.208 +		 * @param pFailPhrase		Optional pointer; on failure, is filled with NULL if the 
  22.209 +		 *							failure was not due to a failed translation phrase.  
  22.210 +		 *							Otherwise, it is filled with the given phrase name pointer 
  22.211 +		 *							from the parameter stack.  Undefined on success.
  22.212 +		 * @return					True on success.  False if the parameter stack was not 
  22.213 +		 *							exactly the right length, or if a translation phrase 
  22.214 +		 *							could not be found.
  22.215 +		 */
  22.216 +		virtual bool FormatString(
  22.217 +			char *buffer,
  22.218 +			size_t maxlength,
  22.219 +			const char *format,
  22.220 +			void **params,
  22.221 +			unsigned int numparams,
  22.222 +			size_t *pOutLength,
  22.223 +			const char **pFailPhrase) =0;
  22.224 +	};
  22.225 +
  22.226 +	/**
  22.227 +	 * @brief Provides functions for translation.
  22.228 +	 */
  22.229 +	 class ITranslator : public SMInterface
  22.230 +	{
  22.231 +	public:
  22.232 +		virtual const char *GetInterfaceName() =0;
  22.233 +		virtual unsigned int GetInterfaceVersion() =0;
  22.234 +	public:
  22.235 +		/**
  22.236 +		 * @brief Creates a new phrase collection object.
  22.237 +		 *
  22.238 +		 * @return			A new phrase collection object, which must be 
  22.239 +		 *					destroyed via IPhraseCollection::Destroy() when 
  22.240 +		 *					no longer needed.
  22.241 +		 */
  22.242 +		virtual IPhraseCollection *CreatePhraseCollection() =0;
  22.243 +
  22.244 +		/**
  22.245 +		 * @brief Returns the server language.
  22.246 +		 *
  22.247 +		 * @return			Server language index.
  22.248 +		 */
  22.249 +		virtual unsigned int GetServerLanguage() =0;
  22.250 +
  22.251 +		/**
  22.252 +		 * @brief Returns a client's language.
  22.253 +		 *
  22.254 +		 * @param client	Client index.
  22.255 +		 * @return			Client language index, or server's if client's is 
  22.256 +		 *					not known.
  22.257 +		 */
  22.258 +		virtual unsigned int GetClientLanguage(int client) =0;
  22.259 +
  22.260 +		/**
  22.261 +		 * @brief Sets the global client SourceMod will use for assisted 
  22.262 +		 * translations (that is, %t).
  22.263 +		 *
  22.264 +		 * @param index		Client index (0 for server).
  22.265 +		 * @return			Old global client value.
  22.266 +		 */
  22.267 +		virtual int SetGlobalTarget(int index) =0;
  22.268 +
  22.269 +		/**
  22.270 +		 * @brief Returns the global client SourceMod is currently using 
  22.271 +		 * for assisted translations (that is, %t).
  22.272 +		 *
  22.273 +		 * @return			Global client index (0 for server).
  22.274 +		 */
  22.275 +		virtual int GetGlobalTarget() const =0;
  22.276 +
  22.277 +		/**
  22.278 +		 * @brief Formats a phrase given a parameter stack.  The parameter 
  22.279 +		 * stack size must exactly match the expected parameter count.  If 
  22.280 +		 * this count is too small or too large, the format fails.
  22.281 +		 *
  22.282 +		 * Note: This is the same as IPhraseCollection::FormatString(), except 
  22.283 +		 * that the IPhraseCollection parameter is explicit instead of implicit.
  22.284 +		 *
  22.285 +		 * @param buffer			Buffer to store formatted text.
  22.286 +		 * @param maxlength			Maximum length of the buffer.
  22.287 +		 * @param format			String containing format information.  
  22.288 +		 *							This is equivalent to SourceMod's Format() 
  22.289 +		 *							native, and sub-translations are acceptable. 
  22.290 +		 * @param pPhrases			Optional phrase collection pointer to search for 
  22.291 +		 *							phrases.
  22.292 +		 * @param params			An array of pointers to each parameter. 
  22.293 +		 *							Integer parameters must have a pointer to the integer.
  22.294 +		 *							Float parameters must have a pointer to a float.
  22.295 +		 *							String parameters must be a string pointer.
  22.296 +		 *							Char parameters must be a pointer to a char.
  22.297 +		 *							Translation parameters fill multiple indexes in the 
  22.298 +		 *							array.  For %T translations, the expected stack is:
  22.299 +		 *							[phrase string pointer] [int target id pointer] [...] 
  22.300 +		 *							Where [...] is the required parameters for the translation,  
  22.301 +		 *							in the order expected by the phrase, not the phrase's 
  22.302 +		 *							translation.  For example, say the format is:
  22.303 +		 *							"%d %T" and the phrase's format is {1:s,2:f}, then the 
  22.304 +		 *							parameter stack should be:
  22.305 +		 *							int *, const char *, int *, const char *, float *
  22.306 +		 *							The %t modifier is the same except the target id pointer 
  22.307 +		 *							would be removed:
  22.308 +		 *							int *, const char *, const char *, float *
  22.309 +		 * @param numparams			Number of parameters in the params array.
  22.310 +		 * @param pOutLength		Optional pointer filled with output length on success.
  22.311 +		 * @param pFailPhrase		Optional pointer; on failure, is filled with NULL if the 
  22.312 +		 *							failure was not due to a failed translation phrase.  
  22.313 +		 *							Otherwise, it is filled with the given phrase name pointer 
  22.314 +		 *							from the parameter stack.  Undefined on success.
  22.315 +		 * @return					True on success.  False if the parameter stack was not 
  22.316 +		 *							exactly the right length, or if a translation phrase 
  22.317 +		 *							could not be found.
  22.318 +		 */
  22.319 +		virtual bool FormatString(
  22.320 +			char *buffer,
  22.321 +			size_t maxlength,
  22.322 +			const char *format,
  22.323 +			IPhraseCollection *pPhrases,
  22.324 +			void **params,
  22.325 +			unsigned int numparams,
  22.326 +			size_t *pOutLength,
  22.327 +			const char **pFailPhrase) =0;
  22.328 +	};
  22.329 +}
  22.330 +
  22.331 +#endif //_INCLUDE_SOURCEMOD_TRANSLATOR_INTERFACE_H_
  22.332 +
    23.1 --- a/public/mms_sample_ext/sm_sdk_config.cpp	Fri May 09 08:22:39 2008 +0000
    23.2 +++ b/public/mms_sample_ext/sm_sdk_config.cpp	Sat May 10 09:23:55 2008 +0000
    23.3 @@ -79,6 +79,9 @@
    23.4  #if defined SMEXT_ENABLE_TEXTPARSERS
    23.5  	SM_FIND_IFACE_OR_FAIL(TEXTPARSERS, sm_text, error, maxlength);
    23.6  #endif
    23.7 +#if defined SMEXT_ENABLE_TRANSLATOR
    23.8 +	SM_FIND_IFACE_OR_FAIL(TRANSLATOR, sm_translator, error, maxlength);
    23.9 +#endif
   23.10  
   23.11  	return true;
   23.12  }
   23.13 @@ -131,6 +134,9 @@
   23.14  #if defined SMEXT_ENABLE_TEXTPARSERS
   23.15  	sm_text = NULL;
   23.16  #endif
   23.17 +#if defined SMEXT_ENABLE_TRANSLATOR
   23.18 +	sm_translator = NULL;
   23.19 +#endif
   23.20  }
   23.21  
   23.22  IExtension *myself = NULL;
   23.23 @@ -179,4 +185,6 @@
   23.24  #if defined SMEXT_ENABLE_TEXTPARSERS
   23.25  SourceMod::ITextParsers *sm_text = NULL;
   23.26  #endif
   23.27 -
   23.28 +#if defined SMEXT_ENABLE_TRANSLATOR
   23.29 +SourceMod::ITranslator *sm_translator = NULL;
   23.30 +#endif
    24.1 --- a/public/mms_sample_ext/sm_sdk_config.h	Fri May 09 08:22:39 2008 +0000
    24.2 +++ b/public/mms_sample_ext/sm_sdk_config.h	Sat May 10 09:23:55 2008 +0000
    24.3 @@ -70,6 +70,7 @@
    24.4  //#define SMEXT_ENABLE_PLUGINSYS
    24.5  //#define SMEXT_ENABLE_ADMINSYS
    24.6  //#define SMEXT_ENABLE_TEXTPARSERS
    24.7 +//#define SMEXT_ENABLE_TRANSLATOR
    24.8  
    24.9  
   24.10  /**
   24.11 @@ -155,5 +156,10 @@
   24.12  extern SourceMod::ITextParsers *sm_text;
   24.13  #endif
   24.14  
   24.15 +#if defined SMEXT_ENABLE_TRANSLATOR
   24.16 +#include <ITranslator.h>
   24.17 +extern SourceMod::ITranslator *sm_translator;
   24.18 +#endif
   24.19 +
   24.20  #endif //_INCLUDE_SOURCEMOD_CONFIG_H_
   24.21  
    25.1 --- a/public/sample_ext/sdk/smsdk_config.h	Fri May 09 08:22:39 2008 +0000
    25.2 +++ b/public/sample_ext/sdk/smsdk_config.h	Sat May 10 09:23:55 2008 +0000
    25.3 @@ -75,5 +75,6 @@
    25.4  //#define SMEXT_ENABLE_ADMINSYS
    25.5  //#define SMEXT_ENABLE_TEXTPARSERS
    25.6  //#define SMEXT_ENABLE_USERMSGS
    25.7 +//#define SMEXT_ENABLE_TRANSLATOR
    25.8  
    25.9  #endif // _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_
    26.1 --- a/public/sample_ext/sdk/smsdk_ext.cpp	Fri May 09 08:22:39 2008 +0000
    26.2 +++ b/public/sample_ext/sdk/smsdk_ext.cpp	Sat May 10 09:23:55 2008 +0000
    26.3 @@ -94,6 +94,9 @@
    26.4  #if defined SMEXT_ENABLE_USERMSGS
    26.5  IUserMessages *usermsgs = NULL;
    26.6  #endif
    26.7 +#if defined SMEXT_ENABLE_TRANSLATOR
    26.8 +ITranslator *translator = NULL;
    26.9 +#endif
   26.10  
   26.11  /** Exports the main interface */
   26.12  PLATFORM_EXTERN_C IExtensionInterface *GetSMExtAPI()
   26.13 @@ -179,6 +182,9 @@
   26.14  #if defined SMEXT_ENABLE_USERMSGS
   26.15  	SM_GET_IFACE(USERMSGS, usermsgs);
   26.16  #endif
   26.17 +#if defined SMEXT_ENABLE_TRANSLATOR
   26.18 +	SM_GET_IFACE(TRANSLATOR, translator);
   26.19 +#endif
   26.20  
   26.21  	if (SDK_OnLoad(error, maxlength, late))
   26.22  	{
    27.1 --- a/public/sample_ext/sdk/smsdk_ext.h	Fri May 09 08:22:39 2008 +0000
    27.2 +++ b/public/sample_ext/sdk/smsdk_ext.h	Sat May 10 09:23:55 2008 +0000
    27.3 @@ -88,6 +88,9 @@
    27.4  #if defined SMEXT_ENABLE_USERMSGS
    27.5  #include <IUserMessages.h>
    27.6  #endif
    27.7 +#if defined SMEXT_ENABLE_TRANSLATOR
    27.8 +#include <ITranslator.h>
    27.9 +#endif
   27.10  
   27.11  #if defined SMEXT_CONF_METAMOD
   27.12  #include <ISmmPlugin.h>
   27.13 @@ -283,6 +286,9 @@
   27.14  #if defined SMEXT_ENABLE_USERMSGS
   27.15  extern IUserMessages *usermsgs;
   27.16  #endif
   27.17 +#if defined SMEXT_ENABLE_TRANSLATOR
   27.18 +extern ITranslator *translator;
   27.19 +#endif
   27.20  
   27.21  #if defined SMEXT_CONF_METAMOD
   27.22  PLUGIN_GLOBALVARS();