diff --git a/src/d_main.c b/src/d_main.c
index 80907a013d9c6586c3b0d7cb828404e8d5214d67..9c3053a93eef976b412773a38cb7dbd12ab8b7b4 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -50,6 +50,7 @@
 #include "p_saveg.h"
 #include "r_main.h"
 #include "r_local.h"
+#include "r_translation.h"
 #include "s_sound.h"
 #include "st_stuff.h"
 #include "v_video.h"
@@ -1475,6 +1476,8 @@ void D_SRB2Main(void)
 	// setup loading screen
 	SCR_Startup();
 
+	PaletteRemap_Init();
+
 	HU_Init();
 
 	CON_Init();
diff --git a/src/deh_lua.c b/src/deh_lua.c
index 0b789547b266aeb238701ca6b34c4f8702c334fb..8135a77ff981329ada656e1196f4afc83039ae05 100644
--- a/src/deh_lua.c
+++ b/src/deh_lua.c
@@ -572,7 +572,8 @@ static int ScanConstants(lua_State *L, boolean mathlib, const char *word)
 		if (mathlib) return luaL_error(L, "NiGHTS grade '%s' could not be found.\n", word);
 		return 0;
 	}
-	else if (fastncmp("MN_",word,3)) {
+	else if (fastncmp("MN_",word,3))
+	{
 		p = word+3;
 		for (i = 0; i < NUMMENUTYPES; i++)
 			if (fastcmp(p, MENUTYPES_LIST[i])) {
@@ -582,6 +583,19 @@ static int ScanConstants(lua_State *L, boolean mathlib, const char *word)
 		if (mathlib) return luaL_error(L, "menutype '%s' could not be found.\n", word);
 		return 0;
 	}
+	else if (mathlib && fastncmp("TRANSLATION_",word,12))
+	{
+		p = word+12;
+		for (i = 0; i < (signed)numcustomtranslations; i++)
+		{
+			if (fasticmp(p, customtranslations[i].name) == 0)
+			{
+				lua_pushinteger(L, (int)customtranslations[i].id);
+				return 1;
+			}
+		}
+		return luaL_error(L, "translation '%s' could not be found.\n", word);
+	}
 
 	if (fastcmp(word, "BT_USE")) // Remove case when 2.3 nears release...
 	{
diff --git a/src/deh_lua.h b/src/deh_lua.h
index 1bec371ccb42d5b76549103d9068c5e471825c98..9c6fb6257413aefa47f87766a72d7ca0402c8264 100644
--- a/src/deh_lua.h
+++ b/src/deh_lua.h
@@ -20,6 +20,7 @@
 #include "m_misc.h"
 #include "p_local.h"
 #include "st_stuff.h"
+#include "r_translation.h"
 #include "fastcmp.h"
 #include "lua_script.h"
 #include "lua_libs.h"
diff --git a/src/deh_tables.c b/src/deh_tables.c
index 7012ede466b2a1734fc9a47d9e63591ed900a05d..1223f0f2c8909e0a7d9960cb45d20d6dd5446797 100644
--- a/src/deh_tables.c
+++ b/src/deh_tables.c
@@ -219,6 +219,7 @@ actionpointer_t actionpointers[] =
 	{{A_ChangeColorRelative},    "A_CHANGECOLORRELATIVE"},
 	{{A_ChangeColorAbsolute},    "A_CHANGECOLORABSOLUTE"},
 	{{A_Dye},                    "A_DYE"},
+	{{A_SetTranslation},         "A_SETTRANSLATION"},
 	{{A_MoveRelative},           "A_MOVERELATIVE"},
 	{{A_MoveAbsolute},           "A_MOVEABSOLUTE"},
 	{{A_Thrust},                 "A_THRUST"},
diff --git a/src/info.h b/src/info.h
index 5c7a9f3fd428579c674c7f969db44f7d71b88f07..4cd6c77b6f5ab65afa35f91eabf03834150a65a8 100644
--- a/src/info.h
+++ b/src/info.h
@@ -173,6 +173,7 @@ enum actionnum
 	A_CHANGECOLORRELATIVE,
 	A_CHANGECOLORABSOLUTE,
 	A_DYE,
+	A_SETTRANSLATION,
 	A_MOVERELATIVE,
 	A_MOVEABSOLUTE,
 	A_THRUST,
@@ -445,6 +446,7 @@ void A_SetRandomTics();
 void A_ChangeColorRelative();
 void A_ChangeColorAbsolute();
 void A_Dye();
+void A_SetTranslation();
 void A_MoveRelative();
 void A_MoveAbsolute();
 void A_Thrust();
diff --git a/src/p_enemy.c b/src/p_enemy.c
index 93c828fbecd1394e1adbeac6aa3fd43cc43437b6..5e546f64a8b1cde1e853526b0fdb84c87edffcea 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -196,6 +196,7 @@ void A_SetRandomTics(mobj_t *actor);
 void A_ChangeColorRelative(mobj_t *actor);
 void A_ChangeColorAbsolute(mobj_t *actor);
 void A_Dye(mobj_t *actor);
+void A_SetTranslation(mobj_t *actor);
 void A_MoveRelative(mobj_t *actor);
 void A_MoveAbsolute(mobj_t *actor);
 void A_Thrust(mobj_t *actor);
@@ -9068,6 +9069,27 @@ void A_Dye(mobj_t *actor)
 	}
 }
 
+// Function: A_SetTranslation
+//
+// Description: Changes the translation of an actor.
+//
+// var1 = translation ID
+// var2 = unused
+//
+void A_SetTranslation(mobj_t *actor)
+{
+	INT32 locvar1 = var1;
+
+	mobj_t *target = actor;
+	if (LUA_CallAction(A_SETTRANSLATION, actor))
+		return;
+
+	if (R_TranslationIsValid(locvar1))
+		actor->translation = (UINT32)locvar1;
+	else
+		actor->translation = 0;
+}
+
 // Function: A_MoveRelative
 //
 // Description: Moves an object (wrapper for P_Thrust)
diff --git a/src/p_setup.c b/src/p_setup.c
index e0b6e902d3498cea629cb55840a0622ebd34d909..908c6f031b81e007b12a373f590a35103dcbfaad 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -8165,7 +8165,7 @@ static boolean P_LoadAddon(UINT16 numlumps)
 		HWR_ClearAllTextures();
 #endif
 
-	R_LoadTrnslateLumps();
+	R_LoadParsedTranslations();
 
 	//
 	// search for sprite replacements
diff --git a/src/r_data.c b/src/r_data.c
index 8a7a4dd6fa4e441cd1e31c94bb3102573d77f483..08624b454ed39efa4cf2735dab39ae911aa3df14 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -1209,11 +1209,8 @@ void R_InitData(void)
 		R_Init8to16();
 	}
 
-	CONS_Printf("PaletteRemap_Init()...\n");
-	PaletteRemap_Init();
-
-	CONS_Printf("R_LoadTrnslateLumps()...\n");
-	R_LoadTrnslateLumps();
+	CONS_Printf("R_LoadParsedTranslations()...\n");
+	R_LoadParsedTranslations();
 
 	CONS_Printf("R_LoadTextures()...\n");
 	R_LoadTextures();
diff --git a/src/r_translation.c b/src/r_translation.c
index f43ff53d26e9280a4e1b4ba6a6bf6477280d1f0a..4125ea94f2611441933838cd3a341aca8084cb89 100644
--- a/src/r_translation.c
+++ b/src/r_translation.c
@@ -140,7 +140,7 @@ boolean PaletteRemap_AddIndexRange(remaptable_t *tr, int start, int end, int pal
 	return true;
 }
 
-boolean PaletteRemap_AddColorRange(remaptable_t *tr, int start, int end, int _r1,int _g1, int _b1, int _r2, int _g2, int _b2)
+boolean PaletteRemap_AddColorRange(remaptable_t *tr, int start, int end, int _r1, int _g1, int _b1, int _r2, int _g2, int _b2)
 {
 	if (IndicesOutOfRange(start, end))
 		return false;
@@ -295,6 +295,91 @@ boolean PaletteRemap_AddTint(remaptable_t *tr, int start, int end, int r, int g,
 	return true;
 }
 
+struct ParsedTranslation
+{
+	struct ParsedTranslation *next;
+	remaptable_t *remap;
+	remaptable_t *baseTranslation;
+	struct PaletteRemapParseResult *data;
+};
+
+static struct ParsedTranslation *parsedTranslationListHead = NULL;
+static struct ParsedTranslation *parsedTranslationListTail = NULL;
+
+static void AddParsedTranslation(unsigned id, int base_translation, struct PaletteRemapParseResult *data)
+{
+	struct ParsedTranslation *node = Z_Calloc(sizeof(struct ParsedTranslation), PU_STATIC, NULL);
+
+	node->remap = paletteremaps[id];
+	node->data = data;
+
+	if (base_translation != -1)
+		node->baseTranslation = paletteremaps[base_translation];
+
+	if (parsedTranslationListHead == NULL)
+		parsedTranslationListHead = parsedTranslationListTail = node;
+	else
+	{
+		parsedTranslationListTail->next = node;
+		parsedTranslationListTail = node;
+	}
+}
+
+void PaletteRemap_ApplyResult(remaptable_t *tr, struct PaletteRemapParseResult *data)
+{
+	int start = data->start;
+	int end = data->end;
+
+	switch (data->type)
+	{
+	case REMAP_ADD_INDEXRANGE:
+		PaletteRemap_AddIndexRange(tr, start, end, data->indexRange.pal1, data->indexRange.pal2);
+		break;
+	case REMAP_ADD_COLORRANGE:
+		PaletteRemap_AddColorRange(tr, start, end,
+			data->colorRange.r1, data->colorRange.g1, data->colorRange.b1,
+			data->colorRange.r2, data->colorRange.g2, data->colorRange.b2);
+		break;
+	case REMAP_ADD_COLOURISATION:
+		PaletteRemap_AddColourisation(tr, start, end,
+			data->colourisation.r, data->colourisation.g, data->colourisation.b);
+		break;
+	case REMAP_ADD_DESATURATION:
+		PaletteRemap_AddDesaturation(tr, start, end,
+			data->desaturation.r1, data->desaturation.g1, data->desaturation.b1,
+			data->desaturation.r2, data->desaturation.g2, data->desaturation.b2);
+		break;
+	case REMAP_ADD_TINT:
+		PaletteRemap_AddTint(tr, start, end, data->tint.r, data->tint.g, data->tint.b, data->tint.amount);
+		break;
+	}
+}
+
+void R_LoadParsedTranslations(void)
+{
+	struct ParsedTranslation *node = parsedTranslationListHead;
+	while (node)
+	{
+		struct PaletteRemapParseResult *result = node->data;
+		struct ParsedTranslation *next = node->next;
+
+		remaptable_t *tr = node->remap;
+		PaletteRemap_SetIdentity(tr);
+
+		if (node->baseTranslation)
+			memcpy(tr, node->baseTranslation, sizeof(remaptable_t));
+
+		PaletteRemap_ApplyResult(tr, result);
+
+		Z_Free(result);
+		Z_Free(node);
+
+		node = next;
+	}
+
+	parsedTranslationListHead = parsedTranslationListTail = NULL;
+}
+
 static boolean ExpectToken(tokenizer_t *sc, const char *expect)
 {
 	return strcmp(sc->get(sc, 0), expect) == 0;
@@ -360,10 +445,21 @@ static struct PaletteRemapParseResult *ThrowError(const char *format, ...)
 	vsprintf(err->error, format, argptr);
 	va_end(argptr);
 
+	err->has_error = true;
+
 	return err;
 }
 
-static struct PaletteRemapParseResult *PaletteRemap_ParseString(remaptable_t *tr, tokenizer_t *sc)
+static struct PaletteRemapParseResult *MakeResult(enum PaletteRemapType type, int start, int end)
+{
+	struct PaletteRemapParseResult *tr = Z_Calloc(sizeof(struct PaletteRemapParseResult), PU_STATIC, NULL);
+	tr->type = type;
+	tr->start = start;
+	tr->end = end;
+	return tr;
+}
+
+static struct PaletteRemapParseResult *PaletteRemap_ParseString(tokenizer_t *sc)
 {
 	int start, end;
 
@@ -426,7 +522,14 @@ static struct PaletteRemapParseResult *PaletteRemap_ParseString(remaptable_t *tr
 		if (!ExpectToken(sc, "]"))
 			return ThrowError("expected ']'");
 
-		PaletteRemap_AddColorRange(tr, start, end, r1, g1, b1, r2, g2, b2);
+		struct PaletteRemapParseResult *tr = MakeResult(REMAP_ADD_COLORRANGE, start, end);
+		tr->colorRange.r1 = r1;
+		tr->colorRange.g1 = g1;
+		tr->colorRange.b1 = b1;
+		tr->colorRange.r2 = r2;
+		tr->colorRange.g2 = g2;
+		tr->colorRange.b2 = b2;
+		return tr;
 	}
 	else if (strcmp(tkn, "%") == 0)
 	{
@@ -474,7 +577,14 @@ static struct PaletteRemapParseResult *PaletteRemap_ParseString(remaptable_t *tr
 		if (!ExpectToken(sc, "]"))
 			return ThrowError("expected ']'");
 
-		PaletteRemap_AddDesaturation(tr, start, end, r1, g1, b1, r2, g2, b2);
+		struct PaletteRemapParseResult *tr = MakeResult(REMAP_ADD_DESATURATION, start, end);
+		tr->desaturation.r1 = r1;
+		tr->desaturation.g1 = g1;
+		tr->desaturation.b1 = b1;
+		tr->desaturation.r2 = r2;
+		tr->desaturation.g2 = g2;
+		tr->desaturation.b2 = b2;
+		return tr;
 	}
 	else if (strcmp(tkn, "#") == 0)
 	{
@@ -496,7 +606,11 @@ static struct PaletteRemapParseResult *PaletteRemap_ParseString(remaptable_t *tr
 		if (!ExpectToken(sc, "]"))
 			return ThrowError("expected ']'");
 
-		PaletteRemap_AddColourisation(tr, start, end, r, g, b);
+		struct PaletteRemapParseResult *tr = MakeResult(REMAP_ADD_COLOURISATION, start, end);
+		tr->colourisation.r = r;
+		tr->colourisation.g = g;
+		tr->colourisation.b = b;
+		return tr;
 	}
 	else if (strcmp(tkn, "@") == 0)
 	{
@@ -522,7 +636,12 @@ static struct PaletteRemapParseResult *PaletteRemap_ParseString(remaptable_t *tr
 		if (!ExpectToken(sc, "]"))
 			return ThrowError("expected ']'");
 
-		PaletteRemap_AddTint(tr, start, end, r, g, b, a);
+		struct PaletteRemapParseResult *tr = MakeResult(REMAP_ADD_TINT, start, end);
+		tr->tint.r = r;
+		tr->tint.g = g;
+		tr->tint.b = b;
+		tr->tint.amount = a;
+		return tr;
 	}
 	else
 	{
@@ -535,21 +654,24 @@ static struct PaletteRemapParseResult *PaletteRemap_ParseString(remaptable_t *tr
 		if (!ParseNumber(sc, &pal2))
 			return ThrowError("expected a number for ending index");
 
-		PaletteRemap_AddIndexRange(tr, start, end, pal1, pal2);
+		struct PaletteRemapParseResult *tr = MakeResult(REMAP_ADD_INDEXRANGE, start, end);
+		tr->indexRange.pal1 = pal1;
+		tr->indexRange.pal2 = pal2;
+		return tr;
 	}
 
 	return NULL;
 }
 
-struct PaletteRemapParseResult *PaletteRemap_ParseTranslation(remaptable_t *tr, const char *translation)
+struct PaletteRemapParseResult *PaletteRemap_ParseTranslation(const char *translation)
 {
 	tokenizer_t *sc = Tokenizer_Open(translation, 1);
-	struct PaletteRemapParseResult *error = PaletteRemap_ParseString(tr, sc);
+	struct PaletteRemapParseResult *result = PaletteRemap_ParseString(sc);
 	Tokenizer_Close(sc);
-	return error;
+	return result;
 }
 
-static void P_ParseTrnslate(INT32 wadNum, UINT16 lumpnum)
+void R_ParseTrnslate(INT32 wadNum, UINT16 lumpnum)
 {
 	char *lumpData = (char *)W_CacheLumpNumPwad(wadNum, lumpnum, PU_STATIC);
 	size_t lumpLength = W_LumpLengthPwad(wadNum, lumpnum);
@@ -562,7 +684,7 @@ static void P_ParseTrnslate(INT32 wadNum, UINT16 lumpnum)
 	const char *tkn = sc->get(sc, 0);
 	while (tkn != NULL)
 	{
-		remaptable_t *tr = NULL;
+		int base_translation = -1;
 
 		char *name = Z_StrDup(tkn);
 
@@ -571,10 +693,8 @@ static void P_ParseTrnslate(INT32 wadNum, UINT16 lumpnum)
 		{
 			tkn = sc->get(sc, 0);
 
-			remaptable_t *tbl = R_GetTranslationByID(R_FindCustomTranslation(tkn));
-			if (tbl)
-				tr = PaletteRemap_Copy(tbl);
-			else
+			base_translation = R_FindCustomTranslation(tkn);
+			if (base_translation == -1)
 			{
 				CONS_Alert(CONS_ERROR, "Error parsing translation '%s': No translation named '%s'\n", name, tkn);
 				goto fail;
@@ -582,11 +702,6 @@ static void P_ParseTrnslate(INT32 wadNum, UINT16 lumpnum)
 
 			tkn = sc->get(sc, 0);
 		}
-		else
-		{
-			tr = PaletteRemap_New();
-			PaletteRemap_SetIdentity(tr);
-		}
 
 		if (strcmp(tkn, "=") != 0)
 		{
@@ -595,12 +710,13 @@ static void P_ParseTrnslate(INT32 wadNum, UINT16 lumpnum)
 		}
 		tkn = sc->get(sc, 0);
 
+		struct PaletteRemapParseResult *result = NULL;
 		do {
-			struct PaletteRemapParseResult *error = PaletteRemap_ParseTranslation(tr, tkn);
-			if (error)
+			result = PaletteRemap_ParseTranslation(tkn);
+			if (result->has_error)
 			{
-				CONS_Alert(CONS_ERROR, "Error parsing translation '%s': %s\n", name, error->error);
-				Z_Free(error);
+				CONS_Alert(CONS_ERROR, "Error parsing translation '%s': %s\n", name, result->error);
+				Z_Free(result);
 				goto fail;
 			}
 
@@ -614,10 +730,17 @@ static void P_ParseTrnslate(INT32 wadNum, UINT16 lumpnum)
 			tkn = sc->get(sc, 0);
 		} while (true);
 
-		// add it
+		// Allocate it and register it
+		remaptable_t *tr = PaletteRemap_New();
 		unsigned id = PaletteRemap_Add(tr);
 		R_AddCustomTranslation(name, id);
+
+		// Free this, since it's no longer needed
 		Z_Free(name);
+
+		// The translation is not generated until later, because the palette may not have been loaded.
+		// We store the result for when it's needed.
+		AddParsedTranslation(id, base_translation, result);
 	}
 
 fail:
@@ -625,29 +748,8 @@ fail:
 	Z_Free(text);
 }
 
-void R_LoadTrnslateLumps(void)
-{
-	for (INT32 w = numwadfiles-1; w >= 0; w--)
-	{
-		UINT16 lump = W_CheckNumForNamePwad("TRNSLATE", w, 0);
-
-		while (lump != INT16_MAX)
-		{
-			P_ParseTrnslate(w, lump);
-			lump = W_CheckNumForNamePwad("TRNSLATE", (UINT16)w, lump + 1);
-		}
-	}
-}
-
-struct CustomTranslation
-{
-	char *name;
-	unsigned id;
-	UINT32 hash;
-};
-
-static struct CustomTranslation *customtranslations = NULL;
-static unsigned numcustomtranslations = 0;
+customtranslation_t *customtranslations = NULL;
+unsigned numcustomtranslations = 0;
 
 int R_FindCustomTranslation(const char *name)
 {
@@ -664,12 +766,12 @@ int R_FindCustomTranslation(const char *name)
 
 void R_AddCustomTranslation(const char *name, int trnum)
 {
-	struct CustomTranslation *tr = NULL;
+	customtranslation_t *tr = NULL;
 	UINT32 hash = quickncasehash(name, strlen(name));
 
 	for (unsigned i = 0; i < numcustomtranslations; i++)
 	{
-		struct CustomTranslation *lookup = &customtranslations[i];
+		customtranslation_t *lookup = &customtranslations[i];
 		if (hash == lookup->hash && strcmp(name, lookup->name) == 0)
 		{
 			tr = lookup;
@@ -680,7 +782,7 @@ void R_AddCustomTranslation(const char *name, int trnum)
 	if (tr == NULL)
 	{
 		numcustomtranslations++;
-		customtranslations = Z_Realloc(customtranslations, sizeof(struct CustomTranslation) * numcustomtranslations, PU_STATIC, NULL);
+		customtranslations = Z_Realloc(customtranslations, sizeof(customtranslation_t) * numcustomtranslations, PU_STATIC, NULL);
 		tr = &customtranslations[numcustomtranslations - 1];
 	}
 
@@ -696,8 +798,16 @@ unsigned R_NumCustomTranslations(void)
 
 remaptable_t *R_GetTranslationByID(int id)
 {
-	if (id < 0 || id >= (signed)numpaletteremaps)
+	if (!R_TranslationIsValid(id))
 		return NULL;
 
 	return paletteremaps[id];
 }
+
+boolean R_TranslationIsValid(int id)
+{
+	if (id < 0 || id >= (signed)numpaletteremaps)
+		return false;
+
+	return true;
+}
diff --git a/src/r_translation.h b/src/r_translation.h
index e9ca0219f99d01a3c3e64d2d05697887aa4952ce..8fb00660d3a937a90f5d3bc6dc0117a66db4f1b4 100644
--- a/src/r_translation.h
+++ b/src/r_translation.h
@@ -29,23 +29,75 @@ boolean PaletteRemap_IsIdentity(remaptable_t *tr);
 unsigned PaletteRemap_Add(remaptable_t *tr);
 
 boolean PaletteRemap_AddIndexRange(remaptable_t *tr, int start, int end, int pal1, int pal2);
-boolean PaletteRemap_AddColorRange(remaptable_t *tr, int start, int end, int _r1,int _g1, int _b1, int _r2, int _g2, int _b2);
+boolean PaletteRemap_AddColorRange(remaptable_t *tr, int start, int end, int _r1, int _g1, int _b1, int _r2, int _g2, int _b2);
 boolean PaletteRemap_AddDesaturation(remaptable_t *tr, int start, int end, double r1, double g1, double b1, double r2, double g2, double b2);
 boolean PaletteRemap_AddColourisation(remaptable_t *tr, int start, int end, int r, int g, int b);
 boolean PaletteRemap_AddTint(remaptable_t *tr, int start, int end, int r, int g, int b, int amount);
 
+enum PaletteRemapType
+{
+	REMAP_ADD_INDEXRANGE,
+	REMAP_ADD_COLORRANGE,
+	REMAP_ADD_COLOURISATION,
+	REMAP_ADD_DESATURATION,
+	REMAP_ADD_TINT
+};
+
 struct PaletteRemapParseResult
 {
+	int start, end;
+	enum PaletteRemapType type;
+	union
+	{
+		struct
+		{
+			int pal1, pal2;
+		} indexRange;
+		struct
+		{
+			int r1, g1, b1;
+			int r2, g2, b2;
+		} colorRange;
+		struct
+		{
+			double r1, g1, b1;
+			double r2, g2, b2;
+		} desaturation;
+		struct
+		{
+			int r, g, b;
+		} colourisation;
+		struct
+		{
+			int r, g, b, amount;
+		} tint;
+	};
+
+	boolean has_error;
 	char error[4096];
 };
 
-struct PaletteRemapParseResult *PaletteRemap_ParseTranslation(remaptable_t *tr, const char *translation);
+struct PaletteRemapParseResult *PaletteRemap_ParseTranslation(const char *translation);
+
+void PaletteRemap_ApplyResult(remaptable_t *tr, struct PaletteRemapParseResult *data);
+
+typedef struct CustomTranslation
+{
+	char *name;
+	unsigned id;
+	UINT32 hash;
+} customtranslation_t;
+
+extern customtranslation_t *customtranslations;
+extern unsigned numcustomtranslations;
 
 int R_FindCustomTranslation(const char *name);
 void R_AddCustomTranslation(const char *name, int trnum);
 unsigned R_NumCustomTranslations(void);
 remaptable_t *R_GetTranslationByID(int id);
+boolean R_TranslationIsValid(int id);
 
-void R_LoadTrnslateLumps(void);
+void R_ParseTrnslate(INT32 wadNum, UINT16 lumpnum);
+void R_LoadParsedTranslations(void);
 
 #endif
diff --git a/src/w_wad.c b/src/w_wad.c
index d012182f18208bd05435c9f7ee8e43d0f27256e2..87f99a5ed3332a7945f421f05b3701cfaeaf70d4 100644
--- a/src/w_wad.c
+++ b/src/w_wad.c
@@ -59,6 +59,7 @@
 #include "r_textures.h"
 #include "r_patch.h"
 #include "r_picformats.h"
+#include "r_translation.h"
 #include "i_time.h"
 #include "i_system.h"
 #include "i_video.h" // rendermode
@@ -829,6 +830,16 @@ static void W_ReadFileShaders(wadfile_t *wadfile)
 #endif
 }
 
+static void W_LoadTrnslateLumps(UINT16 w)
+{
+	UINT16 lump = W_CheckNumForNamePwad("TRNSLATE", w, 0);
+	while (lump != INT16_MAX)
+	{
+		R_ParseTrnslate(w, lump);
+		lump = W_CheckNumForNamePwad("TRNSLATE", (UINT16)w, lump + 1);
+	}
+}
+
 //  Allocate a wadfile, setup the lumpinfo (directory) and
 //  lumpcache, add the wadfile to the current active wadfiles
 //
@@ -979,6 +990,9 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
 	// Read shaders from file
 	W_ReadFileShaders(wadfile);
 
+	// The below hack makes me load this here.
+	W_LoadTrnslateLumps(numwadfiles - 1);
+
 	// TODO: HACK ALERT - Load Lua & SOC stuff right here. I feel like this should be out of this place, but... Let's stick with this for now.
 	switch (wadfile->type)
 	{