diff --git a/aegisub/src/aegisublocale.cpp b/aegisub/src/aegisublocale.cpp
index 6d5cf2b6ae176e2029593e71a4f03d86dd7c9c40..4b80ffd257b04a2f79482ebf78da24e7056be3a3 100644
--- a/aegisub/src/aegisublocale.cpp
+++ b/aegisub/src/aegisublocale.cpp
@@ -36,6 +36,8 @@
 
 #include "config.h"
 
+#include "aegisublocale.h"
+
 #ifndef AGI_PRE
 #include <algorithm>
 #include <functional>
@@ -48,97 +50,59 @@
 #include <wx/choicdlg.h> // Keep this last so wxUSE_CHOICEDLG is set.
 #endif
 
-#include "aegisublocale.h"
 #include "standard_paths.h"
 
-AegisubLocale::~AegisubLocale() {
-}
-
-int AegisubLocale::EnglishId() const {
-	static const int english_ids[] = {
-		wxLANGUAGE_ENGLISH,
-		wxLANGUAGE_ENGLISH_US,
-		wxLANGUAGE_ENGLISH_UK,
-		wxLANGUAGE_ENGLISH_AUSTRALIA,
-		wxLANGUAGE_ENGLISH_BELIZE,
-		wxLANGUAGE_ENGLISH_BOTSWANA,
-		wxLANGUAGE_ENGLISH_CANADA,
-		wxLANGUAGE_ENGLISH_CARIBBEAN,
-		wxLANGUAGE_ENGLISH_DENMARK,
-		wxLANGUAGE_ENGLISH_EIRE,
-		wxLANGUAGE_ENGLISH_JAMAICA,
-		wxLANGUAGE_ENGLISH_NEW_ZEALAND,
-		wxLANGUAGE_ENGLISH_PHILIPPINES,
-		wxLANGUAGE_ENGLISH_SOUTH_AFRICA,
-		wxLANGUAGE_ENGLISH_TRINIDAD,
-		wxLANGUAGE_ENGLISH_ZIMBABWE,
-		0
-	};
-
-	for (const int *id = english_ids; *id; ++id) {
-		if (wxLocale::IsAvailable(*id)) {
-			return *id;
-		}
-	}
+#ifndef AEGISUB_CATALOG
+#define AEGISUB_CATALOG "aegisub"
+#endif
 
-	return -1;
+AegisubLocale::AegisubLocale() {
+	wxTranslations::Set(new wxTranslations);
+	wxFileTranslationsLoader::AddCatalogLookupPathPrefix(StandardPaths::DecodePath("?data/locale/"));
 }
 
-void AegisubLocale::Init(int language) {
-	if (language == -1)
-		language = EnglishId();
-
-	if (!wxLocale::IsAvailable(language))
-		language = wxLANGUAGE_UNKNOWN;
-
-	locale.reset(new wxLocale(language));
-
-#ifdef __WINDOWS__
-	locale->AddCatalogLookupPathPrefix(StandardPaths::DecodePath("?data/locale/"));
-	locale->AddCatalog("aegisub");
-#else
-	locale->AddCatalog(AEGISUB_CATALOG);
-#endif
+void AegisubLocale::Init(wxString const& language) {
+	wxTranslations *translations = wxTranslations::Get();
+	translations->SetLanguage(language);
+	translations->AddCatalog(AEGISUB_CATALOG);
+	translations->AddStdCatalog();
 
-	locale->AddCatalog("wxstd");
 	setlocale(LC_NUMERIC, "C");
 	setlocale(LC_CTYPE, "C");
+	active_language = language;
 }
 
-int AegisubLocale::PickLanguage() {
-	wxArrayInt langs = GetAvailableLanguages();
-
-	// Check if english is in it, else add it
-	if (langs.Index(wxLANGUAGE_ENGLISH) == wxNOT_FOUND) {
-		int id = EnglishId();
-		if (id)
-			langs.Insert(id, 0);
-	}
+wxString AegisubLocale::PickLanguage() {
+	wxArrayString langs = wxTranslations::Get()->GetAvailableTranslations(AEGISUB_CATALOG);
+	langs.insert(langs.begin(), "en_US");
 
 	// Check if user local language is available, if so, make it first
-	int user = wxLocale::GetSystemLanguage();
-	if (langs.Index(user) != wxNOT_FOUND) {
-		langs.Remove(user);
-		langs.Insert(user, 0);
+	const wxLanguageInfo *info = wxLocale::GetLanguageInfo(wxLocale::GetSystemLanguage());
+	if (info) {
+		wxArrayString::iterator it = std::find(langs.begin(), langs.end(), info->CanonicalName);
+		if (it != langs.end())
+			std::rotate(langs.begin(), it, it + 1);
 	}
 
-	// Remove languages which won't work due to the locale not being  installed
-	langs.erase(remove_if(langs.begin(), langs.end(), not1(std::ptr_fun(&wxLocale::IsAvailable))), langs.end());
-
 	// Nothing to pick
-	if (langs.empty()) return -1;
+	if (langs.empty()) return "";
 
 	// Only one language, so don't bother asking the user
-	if (langs.size() == 1 && !locale)
+	if (langs.size() == 1 && !active_language)
 		return langs[0];
 
 	// Generate names
 	wxArrayString langNames;
-	for (size_t i = 0; i < langs.size(); ++i)
-		langNames.Add(wxLocale::GetLanguageName(langs[i]));
+	for (size_t i = 0; i < langs.size(); ++i) {
+		const wxLanguageInfo *info = wxLocale::FindLanguageInfo(langs[i]);
+		if (info)
+			langNames.push_back(wxLocale::GetLanguageName(info->Language));
+		else
+			langNames.push_back(langs[i]);
+	}
 
 	long style = wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxOK | wxCENTRE;
-	if (locale)
+	if (!active_language.empty())
 		style |= wxCANCEL;
 
 	wxSingleChoiceDialog dialog(NULL, "Please choose a language:", "Language", langNames,
@@ -150,75 +114,9 @@ int AegisubLocale::PickLanguage() {
 			style);
 	if (dialog.ShowModal() == wxID_OK) {
 		int picked = dialog.GetSelection();
-		if (locale && langs[picked] == locale->GetLanguage())
-			return -1;
-		return langs[picked];
+		if (langs[picked] != active_language)
+			return langs[picked];
 	}
 
-	return -1;
-}
-
-wxArrayInt AegisubLocale::GetAvailableLanguages() {
-	wxArrayInt final;
-
-#ifdef __WINDOWS__
-	// Open directory
-	wxString folder = StandardPaths::DecodePath("?data/locale/");
-	wxDir dir;
-	if (!dir.Exists(folder)) return final;
-	if (!dir.Open(folder)) return final;
-
-	// Enumerate folders
-	wxString temp1;
-	for (bool cont = dir.GetFirst(&temp1, "", wxDIR_DIRS); cont; cont = dir.GetNext(&temp1)) {
-		// Check if .so exists inside folder
-		if (wxFileName::FileExists(folder + temp1 + "/aegisub.mo")) {
-			const wxLanguageInfo *lang = wxLocale::FindLanguageInfo(temp1);
-			if (lang) {
-				final.Add(lang->Language);
-			}
-		}
-	}
-#else
-	const char* langs[] = {
-		"ca",
-		"cs",
-		"da",
-		"de",
-		"el",
-		"es",
-		"eu",
-		"fa",
-		"fi",
-		"fr_FR",
-		"hu",
-		"id",
-		"it",
-		"ja",
-		"ko",
-		"pl",
-		"pt_BR",
-		"pt_PT",
-		"ru",
-		"sr_RS",
-		"sr_RS@latin",
-		"sr_YU",
-		"sr_YU@latin",
-		"vi",
-		"zh_CN",
-		"zh_TW"
-	};
-
-	size_t len = sizeof(langs)/sizeof(char*);
-	for (size_t i=0; i<len; i++) {
-		const wxLanguageInfo *lang = wxLocale::FindLanguageInfo(langs[i]);
-
-		// If the locale file doesn't exist then don't list it as an option.
-		wxString locDir = wxStandardPaths::Get().GetLocalizedResourcesDir(langs[i], wxStandardPathsBase::ResourceCat_Messages);
-		wxFileName file(wxString::Format("%s/%s.mo", locDir, AEGISUB_CATALOG));
-		if (lang && file.FileExists()) final.Add(lang->Language);
-	}
-#endif
-
-	return final;
+	return "";
 }
diff --git a/aegisub/src/aegisublocale.h b/aegisub/src/aegisublocale.h
index 0e9d103d7f081b3a4bd642bac01682eab5311df6..a57b29ee393fea8c75b96d27b809f1ec1af20e15 100644
--- a/aegisub/src/aegisublocale.h
+++ b/aegisub/src/aegisublocale.h
@@ -34,22 +34,15 @@
 /// @ingroup utility
 ///
 
-#include <libaegisub/scoped_ptr.h>
-
-class wxLocale;
-
 /// DOCME
 /// @class AegisubLocale
 /// @brief DOCME
 ///
 /// DOCME
 class AegisubLocale {
-	agi::scoped_ptr<wxLocale> locale;
-	wxArrayInt GetAvailableLanguages();
-	int EnglishId() const;
-
+	wxString active_language;
 public:
-	~AegisubLocale();
-	void Init(int language);
-	int PickLanguage();
+	AegisubLocale();
+	void Init(wxString const& language);
+	wxString PickLanguage();
 };
diff --git a/aegisub/src/command/app.cpp b/aegisub/src/command/app.cpp
index 0efad2119351093f900fb2b35e618c5eaf1a7331..0236f852a3d5669aa77c4d015867df697bbfff15 100644
--- a/aegisub/src/command/app.cpp
+++ b/aegisub/src/command/app.cpp
@@ -50,6 +50,7 @@
 #include "../main.h"
 
 #include "../audio_controller.h"
+#include "../compat.h"
 #include "../dialog_about.h"
 #include "../dialog_detached_video.h"
 #include "../dialog_manager.h"
@@ -185,19 +186,17 @@ struct app_language : public Command {
 
 	void operator()(agi::Context *c) {
 		// Get language
-		int newCode = wxGetApp().locale.PickLanguage();
-		// Is OK?
-		if (newCode != -1) {
-			// Set code
-			OPT_SET("App/Locale")->SetInt(newCode);
-
-			// Ask to restart program
-			int result = wxMessageBox("Aegisub needs to be restarted so that the new language can be applied. Restart now?", "Restart Aegisub?", wxYES_NO | wxICON_QUESTION |  wxCENTER);
-			if (result == wxYES) {
-				// Restart Aegisub
-				if (wxGetApp().frame->Close()) {
-					RestartAegisub();
-				}
+		wxString new_language = wxGetApp().locale.PickLanguage();
+		if (!new_language) return;
+
+		OPT_SET("App/Language")->SetString(STD_STR(new_language));
+
+		// Ask to restart program
+		int result = wxMessageBox("Aegisub needs to be restarted so that the new language can be applied. Restart now?", "Restart Aegisub?", wxYES_NO | wxICON_QUESTION |  wxCENTER);
+		if (result == wxYES) {
+			// Restart Aegisub
+			if (wxGetApp().frame->Close()) {
+				RestartAegisub();
 			}
 		}
 	}
diff --git a/aegisub/src/libresrc/default_config.json b/aegisub/src/libresrc/default_config.json
index 7598a5f62cc65f9261f5a418ff39c3baa2e903d0..b13fd3068d2d86cd338df6a6e7007dfe32b06c7b 100644
--- a/aegisub/src/libresrc/default_config.json
+++ b/aegisub/src/libresrc/default_config.json
@@ -10,7 +10,7 @@
 		},
 		"Call Tips" : false,
 		"First Start" : true,
-		"Locale" : -1,
+		"Language" : "",
 		"Maximized" : false,
 		"Save Charset" : "UTF-8",
 		"Show Toolbar" : true,
diff --git a/aegisub/src/libresrc/osx/default_config.json b/aegisub/src/libresrc/osx/default_config.json
index 852db6e3f2faf97c59f88c37b248145364795d64..7f6800fe8b13690d45ccf6414aaa595413fb1ba8 100644
--- a/aegisub/src/libresrc/osx/default_config.json
+++ b/aegisub/src/libresrc/osx/default_config.json
@@ -10,7 +10,7 @@
 		},
 		"Call Tips" : false,
 		"First Start" : true,
-		"Locale" : -1,
+		"Language" : "",
 		"Maximized" : false,
 		"Save Charset" : "UTF-8",
 		"Show Toolbar" : true,
diff --git a/aegisub/src/main.cpp b/aegisub/src/main.cpp
index 858ae824bf66a6dd41ca3d9d8c9eb29402201414..ec58a57e24ee3165e29e447cba9194a551aea554 100644
--- a/aegisub/src/main.cpp
+++ b/aegisub/src/main.cpp
@@ -233,10 +233,10 @@ bool AegisubApp::OnInit() {
 		StartupLog("Initialize final locale");
 
 		// Set locale
-		int lang = OPT_GET("App/Locale")->GetInt();
-		if (lang == -1) {
+		wxString lang = lagi_wxString(OPT_GET("App/Language")->GetString());
+		if (!lang) {
 			lang = locale.PickLanguage();
-			OPT_SET("App/Locale")->SetInt(lang);
+			OPT_SET("App/Language")->SetString(STD_STR(lang));
 		}
 		locale.Init(lang);