mirror of
https://github.com/smartcmd/MinecraftConsoles.git
synced 2026-08-20 09:57:09 +00:00
Language Switching during Runtime and with start args
Implemented runtime Language Switcher in Settings as well as with start args - System Language currently Crashes TODO: fix - Start args only sometimes trigger correctly idek?
This commit is contained in:
parent
e754bad17e
commit
331f79ef5c
|
|
@ -58,6 +58,9 @@
|
|||
#else
|
||||
#include "UI\UI.h"
|
||||
#include "UI\UIScene_PauseMenu.h"
|
||||
#ifdef _WINDOWS64
|
||||
#include "..\Windows64\Win64LanguageRuntime.h"
|
||||
#endif
|
||||
#endif
|
||||
#ifdef __PS3__
|
||||
#include <sys/tty.h>
|
||||
|
|
@ -1797,6 +1800,15 @@ void CMinecraftApp::SetMinecraftLanguage(int iPad, unsigned char ucLanguage)
|
|||
{
|
||||
GameSettingsA[iPad]->ucLanguage = ucLanguage;
|
||||
GameSettingsA[iPad]->bSettingsChanged = true;
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
DWORD currentLocale = XGetLocale();
|
||||
if (GameSettingsA[iPad]->ucLocale != MINECRAFT_LANGUAGE_DEFAULT)
|
||||
{
|
||||
currentLocale = GameSettingsA[iPad]->ucLocale;
|
||||
}
|
||||
Win64SetLanguageLocale(ucLanguage, currentLocale);
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned char CMinecraftApp::GetMinecraftLanguage(int iPad)
|
||||
|
|
@ -1816,6 +1828,15 @@ void CMinecraftApp::SetMinecraftLocale(int iPad, unsigned char ucLocale)
|
|||
{
|
||||
GameSettingsA[iPad]->ucLocale = ucLocale;
|
||||
GameSettingsA[iPad]->bSettingsChanged = true;
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
DWORD currentLanguage = XGetLanguage();
|
||||
if (GameSettingsA[iPad]->ucLanguage != MINECRAFT_LANGUAGE_DEFAULT)
|
||||
{
|
||||
currentLanguage = GameSettingsA[iPad]->ucLanguage;
|
||||
}
|
||||
Win64SetLanguageLocale(currentLanguage, ucLocale);
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned char CMinecraftApp::GetMinecraftLocale(int iPad)
|
||||
|
|
@ -9601,6 +9622,20 @@ void CMinecraftApp::getLocale(vector<wstring> &vecWstrLocales)
|
|||
vector<eMCLang> locales;
|
||||
|
||||
DWORD dwSystemLanguage = XGetLanguage( );
|
||||
DWORD dwSystemLocale = XGetLocale( );
|
||||
|
||||
int primaryPad = ProfileManager.GetPrimaryPad();
|
||||
if (primaryPad >= 0 && primaryPad < XUSER_MAX_COUNT && GameSettingsA[primaryPad] != NULL)
|
||||
{
|
||||
if (GameSettingsA[primaryPad]->ucLanguage != MINECRAFT_LANGUAGE_DEFAULT)
|
||||
{
|
||||
dwSystemLanguage = GameSettingsA[primaryPad]->ucLanguage;
|
||||
}
|
||||
if (GameSettingsA[primaryPad]->ucLocale != MINECRAFT_LANGUAGE_DEFAULT)
|
||||
{
|
||||
dwSystemLocale = GameSettingsA[primaryPad]->ucLocale;
|
||||
}
|
||||
}
|
||||
|
||||
// 4J-PB - restrict the 360 language until we're ready to have them in
|
||||
|
||||
|
|
@ -9620,7 +9655,7 @@ void CMinecraftApp::getLocale(vector<wstring> &vecWstrLocales)
|
|||
locales.push_back(eMCLang_esES);
|
||||
break;
|
||||
case XC_LANGUAGE_PORTUGUESE :
|
||||
if(XGetLocale()==XC_LOCALE_BRAZIL)
|
||||
if(dwSystemLocale==XC_LOCALE_BRAZIL)
|
||||
{
|
||||
locales.push_back(eMCLang_ptBR);
|
||||
}
|
||||
|
|
@ -9641,7 +9676,7 @@ void CMinecraftApp::getLocale(vector<wstring> &vecWstrLocales)
|
|||
{
|
||||
|
||||
case XC_LANGUAGE_ENGLISH:
|
||||
switch(XGetLocale())
|
||||
switch(dwSystemLocale)
|
||||
{
|
||||
case XC_LOCALE_AUSTRALIA:
|
||||
case XC_LOCALE_CANADA:
|
||||
|
|
@ -9669,7 +9704,7 @@ void CMinecraftApp::getLocale(vector<wstring> &vecWstrLocales)
|
|||
locales.push_back(eMCLang_jaJP);
|
||||
break;
|
||||
case XC_LANGUAGE_GERMAN :
|
||||
switch(XGetLocale())
|
||||
switch(dwSystemLocale)
|
||||
{
|
||||
case XC_LOCALE_AUSTRIA:
|
||||
locales.push_back(eMCLang_deAT);
|
||||
|
|
@ -9683,7 +9718,7 @@ void CMinecraftApp::getLocale(vector<wstring> &vecWstrLocales)
|
|||
locales.push_back(eMCLang_deDE);
|
||||
break;
|
||||
case XC_LANGUAGE_FRENCH :
|
||||
switch(XGetLocale())
|
||||
switch(dwSystemLocale)
|
||||
{
|
||||
case XC_LOCALE_BELGIUM:
|
||||
locales.push_back(eMCLang_frBE);
|
||||
|
|
@ -9700,7 +9735,7 @@ void CMinecraftApp::getLocale(vector<wstring> &vecWstrLocales)
|
|||
locales.push_back(eMCLang_frFR);
|
||||
break;
|
||||
case XC_LANGUAGE_SPANISH :
|
||||
switch(XGetLocale())
|
||||
switch(dwSystemLocale)
|
||||
{
|
||||
case XC_LOCALE_MEXICO:
|
||||
case XC_LOCALE_ARGENTINA:
|
||||
|
|
@ -9723,7 +9758,7 @@ void CMinecraftApp::getLocale(vector<wstring> &vecWstrLocales)
|
|||
locales.push_back(eMCLang_koKR);
|
||||
break;
|
||||
case XC_LANGUAGE_TCHINESE :
|
||||
switch(XGetLocale())
|
||||
switch(dwSystemLocale)
|
||||
{
|
||||
case XC_LOCALE_HONG_KONG:
|
||||
locales.push_back(eMCLang_zhHK);
|
||||
|
|
@ -9739,7 +9774,7 @@ void CMinecraftApp::getLocale(vector<wstring> &vecWstrLocales)
|
|||
locales.push_back(eMCLang_zhCHT);
|
||||
break;
|
||||
case XC_LANGUAGE_PORTUGUESE :
|
||||
if(XGetLocale()==XC_LOCALE_BRAZIL)
|
||||
if(dwSystemLocale==XC_LOCALE_BRAZIL)
|
||||
{
|
||||
locales.push_back(eMCLang_ptBR);
|
||||
}
|
||||
|
|
@ -9764,7 +9799,7 @@ void CMinecraftApp::getLocale(vector<wstring> &vecWstrLocales)
|
|||
locales.push_back(eMCLang_nnNO);
|
||||
break;
|
||||
case XC_LANGUAGE_DUTCH :
|
||||
switch(XGetLocale())
|
||||
switch(dwSystemLocale)
|
||||
{
|
||||
case XC_LOCALE_BELGIUM:
|
||||
locales.push_back(eMCLang_nlBE);
|
||||
|
|
@ -9775,7 +9810,7 @@ void CMinecraftApp::getLocale(vector<wstring> &vecWstrLocales)
|
|||
locales.push_back(eMCLang_nlNL);
|
||||
break;
|
||||
case XC_LANGUAGE_SCHINESE :
|
||||
switch(XGetLocale())
|
||||
switch(dwSystemLocale)
|
||||
{
|
||||
case XC_LOCALE_SINGAPORE:
|
||||
locales.push_back(eMCLang_zhSG);
|
||||
|
|
@ -10205,4 +10240,4 @@ bool CMinecraftApp::HasReachedMainMenu()
|
|||
{
|
||||
return m_hasReachedMainMenu;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
#include "UI.h"
|
||||
#include "UIScene_SettingsOptionsMenu.h"
|
||||
|
||||
#if defined(_XBOX_ONE)
|
||||
#if defined(_XBOX_ONE) || defined(_WINDOWS64)
|
||||
#define _ENABLE_LANGUAGE_SELECT
|
||||
#endif
|
||||
|
||||
|
|
@ -137,14 +137,7 @@ UIScene_SettingsOptionsMenu::UIScene_SettingsOptionsMenu(int iPad, void *initDat
|
|||
// MGH - disabled the language select for the patch build, we'll re-enable afterwards
|
||||
// 4J Stu - Removed it with a preprocessor def as we turn this off in various places
|
||||
#ifdef _ENABLE_LANGUAGE_SELECT
|
||||
if (app.GetGameStarted())
|
||||
{
|
||||
removeControl( &m_buttonLanguageSelect, false );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_buttonLanguageSelect.init(IDS_LANGUAGE_SELECTOR, eControl_Languages);
|
||||
}
|
||||
m_buttonLanguageSelect.init(IDS_LANGUAGE_SELECTOR, eControl_Languages);
|
||||
#else
|
||||
removeControl( &m_buttonLanguageSelect, false );
|
||||
#endif
|
||||
|
|
@ -361,14 +354,7 @@ void UIScene_SettingsOptionsMenu::handleReload()
|
|||
// MGH - disabled the language select for the patch build, we'll re-enable afterwards
|
||||
// 4J Stu - Removed it with a preprocessor def as we turn this off in various places
|
||||
#ifdef _ENABLE_LANGUAGE_SELECT
|
||||
// 4J-JEV: Changing languages in-game will produce many a bug.
|
||||
if (app.GetGameStarted())
|
||||
{
|
||||
removeControl( &m_buttonLanguageSelect, false );
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
// Enabled on Win64/Xbox One for runtime language switching.
|
||||
#else
|
||||
removeControl( &m_buttonLanguageSelect, false );
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include "stdafx.h"
|
||||
#include "Windows64\Win64LanguageRuntime.h"
|
||||
#ifndef __PS3__
|
||||
//#include <compressapi.h>
|
||||
#endif // __PS3__
|
||||
|
|
@ -502,9 +503,67 @@ void XMemDestroyDecompressionContext(XMEMDECOMPRESSION_CONTEXT Context)
|
|||
|
||||
//#ifndef __PS3__
|
||||
#if !(defined _DURANGO || defined __PS3__ || defined __ORBIS__ || defined __PSVITA__)
|
||||
DWORD XGetLanguage() { return 1; }
|
||||
DWORD XGetLocale() { return 0; }
|
||||
static DWORD s_win64Language = XC_LANGUAGE_ENGLISH;
|
||||
static DWORD s_win64Locale = XC_LOCALE_UNITED_STATES;
|
||||
static bool s_win64TryAllLanguagesAtStartup = false;
|
||||
static bool s_win64LanguageValidationFailed = false;
|
||||
static std::wstring s_win64ForceLocaleCode;
|
||||
static std::vector<std::wstring> s_win64ExtraLanguageCodes;
|
||||
|
||||
DWORD XGetLanguage() { return s_win64Language; }
|
||||
DWORD XGetLocale() { return s_win64Locale; }
|
||||
DWORD XEnableGuestSignin(BOOL fEnable) { return 0; }
|
||||
|
||||
void Win64SetLanguageLocale(DWORD language, DWORD locale)
|
||||
{
|
||||
s_win64Language = language;
|
||||
s_win64Locale = locale;
|
||||
}
|
||||
|
||||
void Win64ForceEnglishLanguage()
|
||||
{
|
||||
Win64SetLanguageLocale(XC_LANGUAGE_ENGLISH, XC_LOCALE_UNITED_STATES);
|
||||
}
|
||||
|
||||
void Win64SetForceLocaleCode(const std::wstring& localeCode)
|
||||
{
|
||||
s_win64ForceLocaleCode = localeCode;
|
||||
}
|
||||
|
||||
const std::wstring& Win64GetForceLocaleCode()
|
||||
{
|
||||
return s_win64ForceLocaleCode;
|
||||
}
|
||||
|
||||
void Win64SetTryAllLanguagesAtStartup(bool enabled)
|
||||
{
|
||||
s_win64TryAllLanguagesAtStartup = enabled;
|
||||
}
|
||||
|
||||
bool Win64GetTryAllLanguagesAtStartup()
|
||||
{
|
||||
return s_win64TryAllLanguagesAtStartup;
|
||||
}
|
||||
|
||||
void Win64SetLanguageValidationFailed(bool failed)
|
||||
{
|
||||
s_win64LanguageValidationFailed = failed;
|
||||
}
|
||||
|
||||
bool Win64GetLanguageValidationFailed()
|
||||
{
|
||||
return s_win64LanguageValidationFailed;
|
||||
}
|
||||
|
||||
void Win64SetExtraLanguageCodes(const std::vector<std::wstring>& localeCodes)
|
||||
{
|
||||
s_win64ExtraLanguageCodes = localeCodes;
|
||||
}
|
||||
|
||||
const std::vector<std::wstring>& Win64GetExtraLanguageCodes()
|
||||
{
|
||||
return s_win64ExtraLanguageCodes;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -798,4 +857,4 @@ void StatsCounter::setupStatBoards() {}
|
|||
#ifdef _DEBUG
|
||||
void StatsCounter::WipeLeaderboards() {}
|
||||
#endif
|
||||
*/
|
||||
*/
|
||||
|
|
@ -22090,6 +22090,7 @@ xcopy /q /y /i /s /e $(ProjectDir)Durango\CU $(LayoutDir)Image\Loose\CU</Comman
|
|||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ORBIS'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage_Vita|ORBIS'">true</ExcludedFromBuild>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Windows64\Win64LanguageRuntime.h" />
|
||||
<ClInclude Include="Windows64\Windows64_App.h">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='ContentPackage|Durango'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='CONTENTPACKAGE_SYMBOLS|Durango'">true</ExcludedFromBuild>
|
||||
|
|
|
|||
|
|
@ -3790,6 +3790,9 @@
|
|||
<ClInclude Include="Common\Audio\stb_vorbis.h">
|
||||
<Filter>Common\Source Files\Audio</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Windows64\Win64LanguageRuntime.h">
|
||||
<Filter>Windows64</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
#include "StdAfx.h"
|
||||
#include "StringTable.h"
|
||||
#ifdef _WINDOWS64
|
||||
#include "Windows64\Win64LanguageRuntime.h"
|
||||
#endif
|
||||
|
||||
StringTable::StringTable(void)
|
||||
{
|
||||
|
|
@ -43,6 +46,59 @@ void StringTable::ProcessStringTableData(void)
|
|||
vector<wstring> locales;
|
||||
app.getLocale(locales);
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
std::wstring forcedLocale = Win64GetForceLocaleCode();
|
||||
if (!forcedLocale.empty())
|
||||
{
|
||||
app.DebugPrintf("StringTable:: forced locale request '%ls'.\n", forcedLocale.c_str());
|
||||
locales.insert(locales.begin(), forcedLocale);
|
||||
}
|
||||
|
||||
const std::vector<std::wstring>& extraLocales = Win64GetExtraLanguageCodes();
|
||||
for (size_t i = 0; i < extraLocales.size(); ++i)
|
||||
{
|
||||
if (!extraLocales[i].empty())
|
||||
locales.insert(locales.begin(), extraLocales[i]);
|
||||
}
|
||||
|
||||
if (Win64GetTryAllLanguagesAtStartup() && !Win64GetLanguageValidationFailed())
|
||||
{
|
||||
static const wchar_t* kStandardLocales[] =
|
||||
{
|
||||
L"en-US", L"en-GB", L"de-DE", L"fr-FR", L"es-ES", L"es-MX", L"it-IT", L"pt-PT", L"pt-BR",
|
||||
L"ja-JP", L"ko-KR", L"zh-CHT", L"ru-RU", L"nl-NL", L"pl-PL", L"sv-SE", L"tr-TR", L"nb-NO",
|
||||
L"da-DK", L"fi-FI", L"cs-CZ", L"sk-SK", L"el-GR", L"la-LAS"
|
||||
};
|
||||
|
||||
for (unsigned int i = 0; i < sizeof(kStandardLocales) / sizeof(kStandardLocales[0]); ++i)
|
||||
{
|
||||
const std::wstring localeCode = kStandardLocales[i];
|
||||
bool foundLocale = false;
|
||||
for (size_t j = 0; j < langSizeMap.size(); ++j)
|
||||
{
|
||||
if (langSizeMap[j].first == localeCode)
|
||||
{
|
||||
foundLocale = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundLocale)
|
||||
{
|
||||
std::wstring msg = L"Missing language localization asset for locale: " + localeCode +
|
||||
L"\n\nDefaulting language to English (en-US).";
|
||||
MessageBoxW(NULL, msg.c_str(), L"Minecraft Localization", MB_OK | MB_ICONERROR);
|
||||
Win64SetLanguageValidationFailed(true);
|
||||
Win64ForceEnglishLanguage();
|
||||
locales.clear();
|
||||
locales.push_back(L"en-US");
|
||||
locales.push_back(L"en-EN");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool foundLang = false;
|
||||
int64_t bytesToSkip = 0;
|
||||
int dataSize = 0;
|
||||
|
|
@ -118,6 +174,16 @@ void StringTable::ProcessStringTableData(void)
|
|||
else
|
||||
{
|
||||
app.DebugPrintf("Failed to get language\n");
|
||||
#ifdef _WINDOWS64
|
||||
std::wstring forcedLocale = Win64GetForceLocaleCode();
|
||||
if (!forcedLocale.empty())
|
||||
{
|
||||
std::wstring msg = L"Failed to load locale '" + forcedLocale + L"'.\n\nDefaulting to English (en-US).";
|
||||
MessageBoxW(NULL, msg.c_str(), L"Minecraft Localization", MB_OK | MB_ICONERROR);
|
||||
Win64ForceEnglishLanguage();
|
||||
Win64SetForceLocaleCode(L"");
|
||||
}
|
||||
#endif
|
||||
#ifdef _DEBUG
|
||||
__debugbreak();
|
||||
#endif
|
||||
|
|
@ -181,8 +247,3 @@ LPCWSTR StringTable::getString(int id)
|
|||
else
|
||||
return L"";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
23
Minecraft.Client/Windows64/Win64LanguageRuntime.h
Normal file
23
Minecraft.Client/Windows64/Win64LanguageRuntime.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
DWORD XGetLanguage();
|
||||
DWORD XGetLocale();
|
||||
|
||||
void Win64SetLanguageLocale(DWORD language, DWORD locale);
|
||||
void Win64ForceEnglishLanguage();
|
||||
|
||||
void Win64SetForceLocaleCode(const std::wstring& localeCode);
|
||||
const std::wstring& Win64GetForceLocaleCode();
|
||||
|
||||
void Win64SetTryAllLanguagesAtStartup(bool enabled);
|
||||
bool Win64GetTryAllLanguagesAtStartup();
|
||||
|
||||
void Win64SetLanguageValidationFailed(bool failed);
|
||||
bool Win64GetLanguageValidationFailed();
|
||||
|
||||
void Win64SetExtraLanguageCodes(const std::vector<std::wstring>& localeCodes);
|
||||
const std::vector<std::wstring>& Win64GetExtraLanguageCodes();
|
||||
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <cwctype>
|
||||
#include <ShellScalingApi.h>
|
||||
#include <shellapi.h>
|
||||
#include "GameConfig\Minecraft.spa.h"
|
||||
|
|
@ -47,6 +49,7 @@
|
|||
#include "..\GameRenderer.h"
|
||||
#include "Network\WinsockNetLayer.h"
|
||||
#include "Windows64_Xuid.h"
|
||||
#include "Win64LanguageRuntime.h"
|
||||
|
||||
#include "Xbox/resource.h"
|
||||
|
||||
|
|
@ -116,8 +119,146 @@ struct Win64LaunchOptions
|
|||
int screenMode;
|
||||
bool serverMode;
|
||||
bool fullscreen;
|
||||
bool tryAllLanguages;
|
||||
std::wstring forceLocaleCode;
|
||||
std::vector<std::wstring> extraLocaleCodes;
|
||||
};
|
||||
|
||||
static bool ParseLanguageCode(const std::wstring& localeCode, DWORD& outLanguage, DWORD& outLocale);
|
||||
|
||||
static bool IsOptionToken(const std::wstring& arg, const wchar_t* longName, const wchar_t* shortName)
|
||||
{
|
||||
const std::wstring longDash = L"--" + std::wstring(longName);
|
||||
const std::wstring shortDash = L"-" + std::wstring(shortName);
|
||||
const std::wstring longSlash = L"/" + std::wstring(longName);
|
||||
const std::wstring shortSlash = L"/" + std::wstring(shortName);
|
||||
|
||||
return (_wcsicmp(arg.c_str(), longDash.c_str()) == 0)
|
||||
|| (_wcsicmp(arg.c_str(), shortDash.c_str()) == 0)
|
||||
|| (_wcsicmp(arg.c_str(), longSlash.c_str()) == 0)
|
||||
|| (_wcsicmp(arg.c_str(), shortSlash.c_str()) == 0);
|
||||
}
|
||||
|
||||
static bool TryReadOptionValue(const std::wstring& arg, const wchar_t* longName, const wchar_t* shortName, std::wstring& outValue)
|
||||
{
|
||||
const std::wstring longEq1 = L"--" + std::wstring(longName) + L"=";
|
||||
const std::wstring longEq2 = L"--" + std::wstring(longName) + L":";
|
||||
const std::wstring shortEq1 = L"-" + std::wstring(shortName) + L"=";
|
||||
const std::wstring shortEq2 = L"-" + std::wstring(shortName) + L":";
|
||||
const std::wstring longSlash1 = L"/" + std::wstring(longName) + L":";
|
||||
const std::wstring shortSlash1 = L"/" + std::wstring(shortName) + L":";
|
||||
|
||||
if (arg.size() >= longEq1.size() && _wcsnicmp(arg.c_str(), longEq1.c_str(), (int)longEq1.size()) == 0) { outValue = arg.substr(longEq1.size()); return true; }
|
||||
if (arg.size() >= longEq2.size() && _wcsnicmp(arg.c_str(), longEq2.c_str(), (int)longEq2.size()) == 0) { outValue = arg.substr(longEq2.size()); return true; }
|
||||
if (arg.size() >= shortEq1.size() && _wcsnicmp(arg.c_str(), shortEq1.c_str(), (int)shortEq1.size()) == 0) { outValue = arg.substr(shortEq1.size()); return true; }
|
||||
if (arg.size() >= shortEq2.size() && _wcsnicmp(arg.c_str(), shortEq2.c_str(), (int)shortEq2.size()) == 0) { outValue = arg.substr(shortEq2.size()); return true; }
|
||||
if (arg.size() >= longSlash1.size() && _wcsnicmp(arg.c_str(), longSlash1.c_str(), (int)longSlash1.size()) == 0) { outValue = arg.substr(longSlash1.size()); return true; }
|
||||
if (arg.size() >= shortSlash1.size() && _wcsnicmp(arg.c_str(), shortSlash1.c_str(), (int)shortSlash1.size()) == 0) { outValue = arg.substr(shortSlash1.size()); return true; }
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void DetectWinApiDefaultLanguage(DWORD& outLanguage, DWORD& outLocale)
|
||||
{
|
||||
outLanguage = XC_LANGUAGE_ENGLISH;
|
||||
outLocale = XC_LOCALE_UNITED_STATES;
|
||||
|
||||
wchar_t localeName[LOCALE_NAME_MAX_LENGTH] = { 0 };
|
||||
if (GetUserDefaultLocaleName(localeName, LOCALE_NAME_MAX_LENGTH) <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::wstring detected = localeName;
|
||||
for (size_t i = 0; i < detected.size(); ++i)
|
||||
{
|
||||
if (detected[i] == L'_')
|
||||
detected[i] = L'-';
|
||||
}
|
||||
|
||||
if (!ParseLanguageCode(detected, outLanguage, outLocale))
|
||||
{
|
||||
if (detected.size() >= 2)
|
||||
{
|
||||
std::wstring twoLetter = detected.substr(0, 2);
|
||||
if (twoLetter == L"en") ParseLanguageCode(L"en-US", outLanguage, outLocale);
|
||||
else if (twoLetter == L"de") ParseLanguageCode(L"de-DE", outLanguage, outLocale);
|
||||
else if (twoLetter == L"fr") ParseLanguageCode(L"fr-FR", outLanguage, outLocale);
|
||||
else if (twoLetter == L"es") ParseLanguageCode(L"es-ES", outLanguage, outLocale);
|
||||
else if (twoLetter == L"it") ParseLanguageCode(L"it-IT", outLanguage, outLocale);
|
||||
else if (twoLetter == L"pt") ParseLanguageCode(L"pt-PT", outLanguage, outLocale);
|
||||
else if (twoLetter == L"ja") ParseLanguageCode(L"ja-JP", outLanguage, outLocale);
|
||||
else if (twoLetter == L"ko") ParseLanguageCode(L"ko-KR", outLanguage, outLocale);
|
||||
else if (twoLetter == L"ru") ParseLanguageCode(L"ru-RU", outLanguage, outLocale);
|
||||
else if (twoLetter == L"nl") ParseLanguageCode(L"nl-NL", outLanguage, outLocale);
|
||||
else if (twoLetter == L"pl") ParseLanguageCode(L"pl-PL", outLanguage, outLocale);
|
||||
else if (twoLetter == L"sv") ParseLanguageCode(L"sv-SE", outLanguage, outLocale);
|
||||
else if (twoLetter == L"tr") ParseLanguageCode(L"tr-TR", outLanguage, outLocale);
|
||||
else if (twoLetter == L"da") ParseLanguageCode(L"da-DK", outLanguage, outLocale);
|
||||
else if (twoLetter == L"fi") ParseLanguageCode(L"fi-FI", outLanguage, outLocale);
|
||||
else if (twoLetter == L"el") ParseLanguageCode(L"el-GR", outLanguage, outLocale);
|
||||
else if (twoLetter == L"cs") ParseLanguageCode(L"cs-CZ", outLanguage, outLocale);
|
||||
else if (twoLetter == L"sk") ParseLanguageCode(L"sk-SK", outLanguage, outLocale);
|
||||
else if (twoLetter == L"zh") ParseLanguageCode(L"zh-CHT", outLanguage, outLocale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::wstring TrimArg(const std::wstring& value)
|
||||
{
|
||||
if (value.empty())
|
||||
return value;
|
||||
|
||||
size_t start = 0;
|
||||
while (start < value.size() && iswspace(value[start]))
|
||||
++start;
|
||||
|
||||
size_t end = value.size();
|
||||
while (end > start && iswspace(value[end - 1]))
|
||||
--end;
|
||||
|
||||
return value.substr(start, end - start);
|
||||
}
|
||||
|
||||
static bool ParseLanguageCode(const std::wstring& localeCode, DWORD& outLanguage, DWORD& outLocale)
|
||||
{
|
||||
if (localeCode == L"en-US" || localeCode == L"en")
|
||||
{
|
||||
outLanguage = XC_LANGUAGE_ENGLISH;
|
||||
outLocale = XC_LOCALE_UNITED_STATES;
|
||||
return true;
|
||||
}
|
||||
if (localeCode == L"en-GB")
|
||||
{
|
||||
outLanguage = XC_LANGUAGE_ENGLISH;
|
||||
outLocale = XC_LOCALE_GREAT_BRITAIN;
|
||||
return true;
|
||||
}
|
||||
if (localeCode == L"de-DE") { outLanguage = XC_LANGUAGE_GERMAN; outLocale = XC_LOCALE_GERMANY; return true; }
|
||||
if (localeCode == L"fr-FR") { outLanguage = XC_LANGUAGE_FRENCH; outLocale = XC_LOCALE_FRANCE; return true; }
|
||||
if (localeCode == L"es-ES") { outLanguage = XC_LANGUAGE_SPANISH; outLocale = XC_LOCALE_SPAIN; return true; }
|
||||
if (localeCode == L"es-MX" || localeCode == L"la-LAS") { outLanguage = XC_LANGUAGE_SPANISH; outLocale = XC_LOCALE_LATIN_AMERICA; return true; }
|
||||
if (localeCode == L"it-IT") { outLanguage = XC_LANGUAGE_ITALIAN; outLocale = XC_LOCALE_ITALY; return true; }
|
||||
if (localeCode == L"pt-BR") { outLanguage = XC_LANGUAGE_PORTUGUESE; outLocale = XC_LOCALE_BRAZIL; return true; }
|
||||
if (localeCode == L"pt-PT") { outLanguage = XC_LANGUAGE_PORTUGUESE; outLocale = XC_LOCALE_PORTUGAL; return true; }
|
||||
if (localeCode == L"ja-JP") { outLanguage = XC_LANGUAGE_JAPANESE; outLocale = XC_LOCALE_JAPAN; return true; }
|
||||
if (localeCode == L"ko-KR") { outLanguage = XC_LANGUAGE_KOREAN; outLocale = XC_LOCALE_KOREA; return true; }
|
||||
if (localeCode == L"zh-CHT" || localeCode == L"zh-TW") { outLanguage = XC_LANGUAGE_TCHINESE; outLocale = XC_LOCALE_TAIWAN; return true; }
|
||||
if (localeCode == L"ru-RU") { outLanguage = XC_LANGUAGE_RUSSIAN; outLocale = XC_LOCALE_RUSSIAN_FEDERATION; return true; }
|
||||
if (localeCode == L"nl-NL") { outLanguage = XC_LANGUAGE_DUTCH; outLocale = XC_LOCALE_NETHERLANDS; return true; }
|
||||
if (localeCode == L"pl-PL") { outLanguage = XC_LANGUAGE_POLISH; outLocale = XC_LOCALE_POLAND; return true; }
|
||||
if (localeCode == L"sv-SE") { outLanguage = XC_LANGUAGE_SWEDISH; outLocale = XC_LOCALE_SWEDEN; return true; }
|
||||
if (localeCode == L"tr-TR") { outLanguage = XC_LANGUAGE_TURKISH; outLocale = XC_LOCALE_TURKEY; return true; }
|
||||
if (localeCode == L"nb-NO" || localeCode == L"no-NO") { outLanguage = XC_LANGUAGE_BNORWEGIAN; outLocale = XC_LOCALE_NORWAY; return true; }
|
||||
if (localeCode == L"da-DK" || localeCode == L"da-DA") { outLanguage = XC_LANGUAGE_DANISH; outLocale = XC_LOCALE_DENMARK; return true; }
|
||||
if (localeCode == L"fi-FI") { outLanguage = XC_LANGUAGE_FINISH; outLocale = XC_LOCALE_FINLAND; return true; }
|
||||
if (localeCode == L"el-GR") { outLanguage = XC_LANGUAGE_GREEK; outLocale = XC_LOCALE_GREECE; return true; }
|
||||
if (localeCode == L"cs-CZ") { outLanguage = XC_LANGUAGE_CZECH; outLocale = XC_LOCALE_CZECH_REPUBLIC; return true; }
|
||||
if (localeCode == L"sk-SK") { outLanguage = XC_LANGUAGE_SLOVAK; outLocale = XC_LOCALE_SLOVAK_REPUBLIC; return true; }
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void CopyWideArgToAnsi(LPCWSTR source, char* dest, size_t destSize)
|
||||
{
|
||||
if (destSize == 0)
|
||||
|
|
@ -201,6 +342,8 @@ static Win64LaunchOptions ParseLaunchOptions()
|
|||
Win64LaunchOptions options = {};
|
||||
options.screenMode = 0;
|
||||
options.serverMode = false;
|
||||
options.fullscreen = false;
|
||||
options.tryAllLanguages = false;
|
||||
|
||||
g_Win64MultiplayerJoin = false;
|
||||
g_Win64MultiplayerPort = WIN64_NET_DEFAULT_PORT;
|
||||
|
|
@ -209,6 +352,7 @@ static Win64LaunchOptions ParseLaunchOptions()
|
|||
g_Win64DedicatedServerBindIP[0] = 0;
|
||||
|
||||
int argc = 0;
|
||||
app.DebugPrintf("[Win64] Raw command line: %ls\n", GetCommandLineW());
|
||||
LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc);
|
||||
if (argv == NULL)
|
||||
return options;
|
||||
|
|
@ -232,11 +376,14 @@ static Win64LaunchOptions ParseLaunchOptions()
|
|||
|
||||
for (int i = 1; i < argc; ++i)
|
||||
{
|
||||
if (_wcsicmp(argv[i], L"-name") == 0 && (i + 1) < argc)
|
||||
std::wstring currentArg = argv[i];
|
||||
std::wstring inlineValue;
|
||||
|
||||
if (IsOptionToken(currentArg, L"name", L"name") && (i + 1) < argc)
|
||||
{
|
||||
CopyWideArgToAnsi(argv[++i], g_Win64Username, sizeof(g_Win64Username));
|
||||
}
|
||||
else if (_wcsicmp(argv[i], L"-ip") == 0 && (i + 1) < argc)
|
||||
else if (IsOptionToken(currentArg, L"ip", L"ip") && (i + 1) < argc)
|
||||
{
|
||||
char ipBuf[256];
|
||||
CopyWideArgToAnsi(argv[++i], ipBuf, sizeof(ipBuf));
|
||||
|
|
@ -250,7 +397,7 @@ static Win64LaunchOptions ParseLaunchOptions()
|
|||
g_Win64MultiplayerJoin = true;
|
||||
}
|
||||
}
|
||||
else if (_wcsicmp(argv[i], L"-port") == 0 && (i + 1) < argc)
|
||||
else if (IsOptionToken(currentArg, L"port", L"port") && (i + 1) < argc)
|
||||
{
|
||||
wchar_t* endPtr = NULL;
|
||||
long port = wcstol(argv[++i], &endPtr, 10);
|
||||
|
|
@ -262,8 +409,52 @@ static Win64LaunchOptions ParseLaunchOptions()
|
|||
g_Win64MultiplayerPort = (int)port;
|
||||
}
|
||||
}
|
||||
else if (_wcsicmp(argv[i], L"-fullscreen") == 0)
|
||||
else if (IsOptionToken(currentArg, L"fullscreen", L"fullscreen"))
|
||||
options.fullscreen = true;
|
||||
else if (TryReadOptionValue(currentArg, L"language", L"lang", inlineValue))
|
||||
{
|
||||
options.forceLocaleCode = TrimArg(inlineValue);
|
||||
}
|
||||
else if (IsOptionToken(currentArg, L"language", L"lang") && (i + 1) < argc)
|
||||
{
|
||||
options.forceLocaleCode = TrimArg(argv[++i]);
|
||||
}
|
||||
else if (TryReadOptionValue(currentArg, L"addlanguages", L"languages", inlineValue)
|
||||
|| TryReadOptionValue(currentArg, L"languages", L"languages", inlineValue))
|
||||
{
|
||||
wstring languagesArg = TrimArg(inlineValue);
|
||||
size_t start = 0;
|
||||
while (start < languagesArg.size())
|
||||
{
|
||||
size_t comma = languagesArg.find(L',', start);
|
||||
wstring token = (comma == wstring::npos) ? languagesArg.substr(start) : languagesArg.substr(start, comma - start);
|
||||
if (!token.empty())
|
||||
options.extraLocaleCodes.push_back(token);
|
||||
if (comma == wstring::npos)
|
||||
break;
|
||||
start = comma + 1;
|
||||
}
|
||||
}
|
||||
else if ((IsOptionToken(currentArg, L"addlanguages", L"languages") || IsOptionToken(currentArg, L"languages", L"languages")) && (i + 1) < argc)
|
||||
{
|
||||
wstring languagesArg = TrimArg(argv[++i]);
|
||||
size_t start = 0;
|
||||
while (start < languagesArg.size())
|
||||
{
|
||||
size_t comma = languagesArg.find(L',', start);
|
||||
wstring token = (comma == wstring::npos) ? languagesArg.substr(start) : languagesArg.substr(start, comma - start);
|
||||
token = TrimArg(token);
|
||||
if (!token.empty())
|
||||
options.extraLocaleCodes.push_back(token);
|
||||
if (comma == wstring::npos)
|
||||
break;
|
||||
start = comma + 1;
|
||||
}
|
||||
}
|
||||
else if (IsOptionToken(currentArg, L"tryalllanguages", L"tryalllanguages"))
|
||||
{
|
||||
options.tryAllLanguages = true;
|
||||
}
|
||||
}
|
||||
|
||||
LocalFree(argv);
|
||||
|
|
@ -1240,6 +1431,38 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
|
|||
|
||||
// Load stuff from launch options, including username
|
||||
Win64LaunchOptions launchOptions = ParseLaunchOptions();
|
||||
app.DebugPrintf("[Win64] Launch options parsed: language='%ls', extraLanguages=%d, tryAll=%s\n",
|
||||
launchOptions.forceLocaleCode.c_str(),
|
||||
(int)launchOptions.extraLocaleCodes.size(),
|
||||
launchOptions.tryAllLanguages ? "true" : "false");
|
||||
Win64SetForceLocaleCode(launchOptions.forceLocaleCode);
|
||||
Win64SetExtraLanguageCodes(launchOptions.extraLocaleCodes);
|
||||
Win64SetTryAllLanguagesAtStartup(launchOptions.tryAllLanguages);
|
||||
|
||||
if (!launchOptions.forceLocaleCode.empty())
|
||||
{
|
||||
DWORD language = XC_LANGUAGE_ENGLISH;
|
||||
DWORD locale = XC_LOCALE_UNITED_STATES;
|
||||
if (ParseLanguageCode(launchOptions.forceLocaleCode, language, locale))
|
||||
{
|
||||
Win64SetLanguageLocale(language, locale);
|
||||
}
|
||||
else
|
||||
{
|
||||
app.DebugPrintf("[Win64] Invalid -language argument '%ls' - defaulting to English.\n", launchOptions.forceLocaleCode.c_str());
|
||||
MessageBoxW(NULL, L"Unsupported -language code. Defaulting to English (en-US).", L"Minecraft Localization", MB_OK | MB_ICONWARNING);
|
||||
Win64ForceEnglishLanguage();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD language = XC_LANGUAGE_ENGLISH;
|
||||
DWORD locale = XC_LOCALE_UNITED_STATES;
|
||||
DetectWinApiDefaultLanguage(language, locale);
|
||||
Win64SetLanguageLocale(language, locale);
|
||||
app.DebugPrintf("[Win64] Default locale from WinAPI: lang=%u locale=%u\n", (unsigned int)language, (unsigned int)locale);
|
||||
}
|
||||
|
||||
ApplyScreenMode(launchOptions.screenMode);
|
||||
|
||||
// Ensure uid.dat exists from startup in client mode (before any multiplayer/login path).
|
||||
|
|
@ -1927,4 +2150,4 @@ void MemPixStuff()
|
|||
PIXAddNamedCounter(((float)allSectsTotal)/(4096.0f),"MemSect total pages");
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
Loading…
Reference in a new issue