add localization

This commit is contained in:
Mister_Nebula 2022-06-04 16:19:55 +01:00
parent e909bab960
commit feda78d405
10 changed files with 367 additions and 178 deletions

View File

@ -1,155 +1,18 @@
using System;
using QSB.Localisation;
using System;
using System.Collections.Generic;
namespace QSB.DeathSync;
public static class Necronomicon
{
private static readonly Dictionary<DeathType, string[]> Darkhold = new()
{
{
DeathType.Default,
new[] // Running out of health
{
"{0} died",
"{0} was killed"
}
},
{
DeathType.Impact,
new[] // Hitting the ground/wall/object
{
"{0} forgot to use retro-rockets",
"{0} bonked into the ground too hard",
"{0} hit the ground too hard",
"{0} went splat",
"{0} died",
"{0} was killed",
"{0} died due to impact",
"{0} impacted the ground too hard"
}
},
{
DeathType.Asphyxiation,
new[] // Running out of oxygen
{
"{0} forgot to breathe",
"{0} asphyxiated",
"{0} died due to asphyxiation",
"{0} forgot how to breathe",
"{0} forgot to check their oxygen",
"{0} ran out of air",
"{0} ran out of oxygen",
"{0} didn't need air anyway"
}
},
{
DeathType.Energy,
new[] // Electricity, sun, etc.
{
"{0} was cooked",
"{0} died",
"{0} was killed"
}
},
{
DeathType.Supernova,
new[] // Supernova
{
"{0} ran out of time",
"{0} burnt up",
"{0} got vaporized",
"{0} lost track of time",
"{0} got front row seats to the supernova",
"{0} heard the music",
"{0} watched the sun go kaboom",
"{0} became cosmic marshmallow",
"{0} photosynthesized too much",
"{0} died due to the supernova"
}
},
{
DeathType.Digestion,
new[] // Anglerfish
{
"{0} was eaten",
"{0} found a fish",
"{0} encountered an evil creature",
"{0} messed with the wrong fish",
"{0} was digested",
"{0} died due to digestion"
}
},
{
DeathType.Crushed,
new[] // Crushed in sand
{
"{0} went through the tunnel too slow",
"{0} didn't make it out in time",
"{0} was squished",
"{0} was crushed",
"{0} was buried",
"{0} went swimming in the sand",
"{0} underestimated the danger of sand",
"{0} died due to being crushed"
}
},
{
DeathType.Lava,
new[] // Lava
{
"{0} died in lava",
"{0} was melted",
"{0} tried to swim in lava",
"{0} didn't know what the glowy orange liquid was",
"{0} fell into lava",
"{0} became one with the glowing gooey rock",
"{0} died due to lava",
"{0} got burnt in the lava"
}
},
{
DeathType.BlackHole,
new[] // ATP core black hole
{
"{0} should visit the Ash Twin Project again",
"{0} waited inside the Ash Twin Project",
"{0} chased their memories"
}
},
{
DeathType.DreamExplosion,
new[] // using the prototype
{
"{0} exploded",
"{0} was an early adopter",
"{0} went kaboom",
"{0} was fried",
"{0} died due to explosion",
"{0} used the wrong artifact"
}
},
{
DeathType.CrushedByElevator,
new[] // elevator-induced pancakeness
{
"{0} was crushed",
"{0} was squished",
"{0} was crushed by an elevator",
"{0} stood under an elevator",
"{0} became a flat-hearther",
"{0} was squished by an elevator"
}
},
};
public static string GetPhrase(DeathType deathType, int index)
=> Darkhold.ContainsKey(deathType)
? Darkhold[deathType][index]
=> QSBLocalisation.Current.DeathMessages.ContainsKey(deathType)
? QSBLocalisation.Current.DeathMessages[deathType][index]
: null;
public static int GetRandomIndex(DeathType deathType)
=> Darkhold.ContainsKey(deathType)
? new Random().Next(0, Darkhold[deathType].Length)
=> QSBLocalisation.Current.DeathMessages.ContainsKey(deathType)
? new Random().Next(0, QSBLocalisation.Current.DeathMessages[deathType].Length)
: -1;
}

View File

@ -0,0 +1,55 @@
using QSB.Utility;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace QSB.Localisation;
public static class QSBLocalisation
{
private readonly static List<Translation> _translations = new();
public static Translation Current;
public static Action LanguageChanged;
public static void Init()
{
// get all translation files
var directory = new DirectoryInfo(Path.Combine(QSBCore.Helper.Manifest.ModFolderPath, "Translations\\"));
var files = directory.GetFiles("*.json");
foreach (var file in files)
{
var translation = QSBCore.Helper.Storage.Load<Translation>($"Translations\\{file.Name}");
_translations.Add(translation);
DebugLog.DebugWrite($"- Added translation for language {translation.Language}");
}
if (_translations.Count == 0)
{
DebugLog.ToConsole($"FATAL - No translation files found!", OWML.Common.MessageType.Fatal);
return;
}
// hack to stop things from breaking
Current = _translations[0];
TextTranslation.Get().OnLanguageChanged += OnLanguageChanged;
}
private static void OnLanguageChanged()
{
var language = TextTranslation.Get().GetLanguage();
DebugLog.DebugWrite($"Language changed to {language}");
var newTranslation = _translations.FirstOrDefault(x => x.Language == language);
if (newTranslation == default)
{
DebugLog.ToConsole($"Error - Could not find translation for language {language}! Defaulting to English.");
newTranslation = _translations.First(x => x.Language == TextTranslation.Language.ENGLISH);
}
Current = newTranslation;
LanguageChanged?.Invoke();
}
}

View File

@ -0,0 +1,104 @@
using Newtonsoft.Json;
using System.Collections.Generic;
namespace QSB.Localisation;
[JsonObject]
public class Translation
{
[JsonProperty]
public TextTranslation.Language Language;
[JsonProperty]
public string MainMenuHost;
[JsonProperty]
public string MainMenuConnect;
[JsonProperty]
public string PauseMenuDisconnect;
[JsonProperty]
public string PauseMenuStopHosting;
[JsonProperty]
public string PublicIPAddress;
[JsonProperty]
public string ProductUserID;
[JsonProperty]
public string Connect;
[JsonProperty]
public string Cancel;
[JsonProperty]
public string HostExistingOrNew;
[JsonProperty]
public string ExistingSave;
[JsonProperty]
public string NewSave;
[JsonProperty]
public string DisconnectAreYouSure;
[JsonProperty]
public string Yes;
[JsonProperty]
public string No;
[JsonProperty]
public string StopHostingAreYouSure;
[JsonProperty]
public string CopyProductUserIDToClipboard;
[JsonProperty]
public string Connecting;
[JsonProperty]
public string OK;
[JsonProperty]
public string ServerRefusedConnection;
[JsonProperty]
public string ClientDisconnectWithError;
[JsonProperty]
public string QSBVersionMismatch;
[JsonProperty]
public string OWVersionMismatch;
[JsonProperty]
public string DLCMismatch;
[JsonProperty]
public string GameProgressLimit;
[JsonProperty]
public string AddonMismatch;
[JsonProperty]
public string IncompatibleMod;
[JsonProperty]
public string PlayerJoinedTheGame;
[JsonProperty]
public string PlayerWasKicked;
[JsonProperty]
public string KickedFromServer;
[JsonProperty]
public string RespawnPlayer;
[JsonProperty]
public Dictionary<DeathType, string[]> DeathMessages;
}

View File

@ -1,9 +1,11 @@
using EpicTransport;
using Mirror;
using QSB.Localisation;
using QSB.Messaging;
using QSB.Player.TransformSync;
using QSB.SaveSync.Messages;
using QSB.Utility;
using QSB.WorldSync;
using System;
using System.Linq;
using System.Text;
@ -37,11 +39,6 @@ internal class MenuManager : MonoBehaviour, IAddComponentOnStart
private const int _titleButtonIndex = 2;
private float _connectPopupOpenTime;
private const string HostString = "OPEN TO MULTIPLAYER";
private const string ConnectString = "CONNECT TO MULTIPLAYER";
private const string DisconnectString = "DISCONNECT";
private const string StopHostingString = "STOP HOSTING";
private const string UpdateChangelog = $"QSB Version 0.20.0\r\nThis updates brings better ship syncing (including destruction), more things around the village being synced, and general bug fixes.";
private Action<bool> PopupClose;
@ -70,6 +67,8 @@ internal class MenuManager : MonoBehaviour, IAddComponentOnStart
QSBCore.Helper.Storage.Save(QSBCore.Storage, "storage.json");
QSBCore.MenuApi.RegisterStartupPopup(UpdateChangelog);
}
QSBLocalisation.LanguageChanged += OnLanguageChanged;
}
private void OnSceneLoaded(OWScene oldScene, OWScene newScene, bool isUniverse)
@ -99,6 +98,30 @@ internal class MenuManager : MonoBehaviour, IAddComponentOnStart
_nowLoadingSB.Length = 0;
}
private void OnLanguageChanged()
{
if (QSBSceneManager.CurrentScene != OWScene.TitleScreen)
{
DebugLog.ToConsole($"Error - Language changed while not in title screen?! Should be impossible!", OWML.Common.MessageType.Error);
return;
}
HostButton.transform.GetChild(0).GetChild(1).GetComponent<Text>().text = QSBLocalisation.Current.MainMenuHost;
ConnectButton.transform.GetChild(0).GetChild(1).GetComponent<Text>().text = QSBLocalisation.Current.MainMenuConnect;
var text = QSBCore.DebugSettings.UseKcpTransport ? QSBLocalisation.Current.PublicIPAddress : QSBLocalisation.Current.ProductUserID;
ConnectPopup.SetUpPopup(text, InputLibrary.menuConfirm, InputLibrary.cancel, new ScreenPrompt(QSBLocalisation.Current.Connect), new ScreenPrompt(QSBLocalisation.Current.Cancel), true, true);
ConnectPopup.SetInputFieldPlaceholderText(text);
HostGameTypePopup.SetUpPopup(QSBLocalisation.Current.HostExistingOrNew,
InputLibrary.menuConfirm,
InputLibrary.confirm2,
InputLibrary.cancel,
new ScreenPrompt(QSBLocalisation.Current.ExistingSave),
new ScreenPrompt(QSBLocalisation.Current.NewSave),
new ScreenPrompt(QSBLocalisation.Current.Cancel),
true,
true);
}
private void Update()
{
if ((LoadManager.GetLoadingScene() == OWScene.SolarSystem || LoadManager.GetLoadingScene() == OWScene.EyeOfTheUniverse)
@ -228,8 +251,8 @@ internal class MenuManager : MonoBehaviour, IAddComponentOnStart
private void CreateCommonPopups()
{
var text = QSBCore.DebugSettings.UseKcpTransport ? "Public IP Address" : "Product User ID";
ConnectPopup = QSBCore.MenuApi.MakeInputFieldPopup(text, text, "Connect", "Cancel");
var text = QSBCore.DebugSettings.UseKcpTransport ? QSBLocalisation.Current.PublicIPAddress : QSBLocalisation.Current.ProductUserID;
ConnectPopup = QSBCore.MenuApi.MakeInputFieldPopup(text, text, QSBLocalisation.Current.Connect, QSBLocalisation.Current.Cancel);
ConnectPopup.CloseMenuOnOk(false);
ConnectPopup.OnPopupConfirm += () =>
{
@ -251,7 +274,7 @@ internal class MenuManager : MonoBehaviour, IAddComponentOnStart
TwoButtonInfoPopup.OnPopupConfirm += () => OnCloseInfoPopup(true);
TwoButtonInfoPopup.OnPopupCancel += () => OnCloseInfoPopup(false);
HostGameTypePopup = CreateThreeChoicePopup("Do you want to host an existing expedition, or host a new expedition?", "EXISTING SAVE", "NEW SAVE", "CANCEL");
HostGameTypePopup = CreateThreeChoicePopup(QSBLocalisation.Current.HostExistingOrNew, QSBLocalisation.Current.ExistingSave, QSBLocalisation.Current.NewSave, QSBLocalisation.Current.Cancel);
HostGameTypePopup.OnPopupConfirm1 += () => Host(false);
HostGameTypePopup.OnPopupConfirm2 += () => Host(true);
}
@ -275,10 +298,10 @@ internal class MenuManager : MonoBehaviour, IAddComponentOnStart
{
CreateCommonPopups();
DisconnectPopup = QSBCore.MenuApi.MakeTwoChoicePopup("Are you sure you want to disconnect?\r\nThis will send you back to the main menu.", "YES", "NO");
DisconnectPopup = QSBCore.MenuApi.MakeTwoChoicePopup(QSBLocalisation.Current.DisconnectAreYouSure, QSBLocalisation.Current.Yes, QSBLocalisation.Current.No);
DisconnectPopup.OnPopupConfirm += Disconnect;
DisconnectButton = QSBCore.MenuApi.PauseMenu_MakeMenuOpenButton(DisconnectString, DisconnectPopup);
DisconnectButton = QSBCore.MenuApi.PauseMenu_MakeMenuOpenButton(QSBLocalisation.Current.PauseMenuDisconnect, DisconnectPopup);
QuitButton = FindObjectOfType<PauseMenuManager>()._exitToMainMenuAction.gameObject;
@ -294,24 +317,30 @@ internal class MenuManager : MonoBehaviour, IAddComponentOnStart
}
var text = QSBCore.IsHost
? StopHostingString
: DisconnectString;
? QSBLocalisation.Current.PauseMenuStopHosting
: QSBLocalisation.Current.PauseMenuDisconnect;
DisconnectButton.transform.GetChild(0).GetChild(1).GetComponent<Text>().text = text;
var popupText = QSBCore.IsHost
? "Are you sure you want to stop hosting?\r\nThis will disconnect all clients and send everyone back to the main menu."
: "Are you sure you want to disconnect?\r\nThis will send you back to the main menu.";
DisconnectPopup._labelText.text = popupText;
var langController = QSBWorldSync.GetUnityObject<PauseMenuManager>().transform.GetChild(0).GetComponent<FontAndLanguageController>();
langController.AddTextElement(DisconnectButton.transform.GetChild(0).GetChild(1).GetComponent<Text>(), true, true, false);
langController.AddTextElement(DisconnectPopup._labelText, false, true, false);
langController.AddTextElement(DisconnectPopup._confirmButton._buttonText, false, true, false);
langController.AddTextElement(DisconnectPopup._cancelButton._buttonText, false, true, false);
}
private void MakeTitleMenus()
{
CreateCommonPopups();
HostButton = QSBCore.MenuApi.TitleScreen_MakeSimpleButton(HostString, _titleButtonIndex);
HostButton = QSBCore.MenuApi.TitleScreen_MakeSimpleButton(QSBLocalisation.Current.MainMenuHost, _titleButtonIndex);
HostButton.onClick.AddListener(PreHost);
ConnectButton = QSBCore.MenuApi.TitleScreen_MakeMenuOpenButton(ConnectString, _titleButtonIndex + 1, ConnectPopup);
ConnectButton = QSBCore.MenuApi.TitleScreen_MakeMenuOpenButton(QSBLocalisation.Current.MainMenuConnect, _titleButtonIndex + 1, ConnectPopup);
ResumeGameButton = GameObject.Find("MainMenuLayoutGroup/Button-ResumeGame");
NewGameButton = GameObject.Find("MainMenuLayoutGroup/Button-NewGame");
@ -338,6 +367,26 @@ internal class MenuManager : MonoBehaviour, IAddComponentOnStart
titleAnimationController._optionsFadeDuration = small;
titleAnimationController._optionsFadeSpacing = small;
}
var mainMenuFontController = GameObject.Find("MainMenu").GetComponent<FontAndLanguageController>();
mainMenuFontController.AddTextElement(HostButton.transform.GetChild(0).GetChild(1).GetComponent<Text>(), true, true, false);
mainMenuFontController.AddTextElement(ConnectButton.transform.GetChild(0).GetChild(1).GetComponent<Text>(), true, true, false);
mainMenuFontController.AddTextElement(OneButtonInfoPopup._labelText, false, true, false);
mainMenuFontController.AddTextElement(OneButtonInfoPopup._confirmButton._buttonText, false, true, false);
mainMenuFontController.AddTextElement(TwoButtonInfoPopup._labelText, false, true, false);
mainMenuFontController.AddTextElement(TwoButtonInfoPopup._confirmButton._buttonText, false, true, false);
mainMenuFontController.AddTextElement(TwoButtonInfoPopup._cancelButton._buttonText, false, true, false);
mainMenuFontController.AddTextElement(ConnectPopup._labelText, false, true, false);
mainMenuFontController.AddTextElement(ConnectPopup._confirmButton._buttonText, false, true, false);
mainMenuFontController.AddTextElement(ConnectPopup._cancelButton._buttonText, false, true, false);
mainMenuFontController.AddTextElement(HostGameTypePopup._labelText, false, true, false);
mainMenuFontController.AddTextElement(HostGameTypePopup._confirmButton1._buttonText, false, true, false);
mainMenuFontController.AddTextElement(HostGameTypePopup._confirmButton2._buttonText, false, true, false);
mainMenuFontController.AddTextElement(HostGameTypePopup._cancelButton._buttonText, false, true, false);
}
private void Disconnect()
@ -397,11 +446,9 @@ internal class MenuManager : MonoBehaviour, IAddComponentOnStart
Delay.RunWhen(() => TimeLoop._initialized, QSBNetworkManager.singleton.StartHost);
};
OpenInfoPopup("Hosting server.\r\nClients will connect using your product user id, which is :\r\n" +
$"{productUserId}\r\n" +
"Do you want to copy this to the clipboard?"
, "YES"
, "NO");
OpenInfoPopup(QSBLocalisation.Current.CopyProductUserIDToClipboard
, QSBLocalisation.Current.Yes
, QSBLocalisation.Current.No);
}
else
{
@ -424,7 +471,7 @@ internal class MenuManager : MonoBehaviour, IAddComponentOnStart
SetButtonActive(ResumeGameButton, false);
SetButtonActive(NewGameButton, false);
_loadingText = ConnectButton.transform.GetChild(0).GetChild(1).GetComponent<Text>();
_loadingText.text = "CONNECTING...";
_loadingText.text = QSBLocalisation.Current.Connecting;
Locator.GetMenuInputModule().DisableInputs();
QSBNetworkManager.singleton.networkAddress = address;
@ -454,7 +501,7 @@ internal class MenuManager : MonoBehaviour, IAddComponentOnStart
}
};
OpenInfoPopup($"Server refused connection.\r\n{reason}", "OK");
OpenInfoPopup(QSBLocalisation.Current.ServerRefusedConnection, QSBLocalisation.Current.OK);
}
private void OnDisconnected(string error)
@ -474,7 +521,7 @@ internal class MenuManager : MonoBehaviour, IAddComponentOnStart
}
};
OpenInfoPopup($"Client disconnected with error!\r\n{error}", "OK");
OpenInfoPopup(string.Format(QSBLocalisation.Current.ClientDisconnectWithError, error), QSBLocalisation.Current.OK);
}
SetButtonActive(DisconnectButton, false);
@ -485,12 +532,12 @@ internal class MenuManager : MonoBehaviour, IAddComponentOnStart
SetButtonActive(NewGameButton, true);
if (ConnectButton)
{
ConnectButton.transform.GetChild(0).GetChild(1).GetComponent<Text>().text = ConnectString;
ConnectButton.transform.GetChild(0).GetChild(1).GetComponent<Text>().text = QSBLocalisation.Current.MainMenuConnect;
}
if (HostButton)
{
HostButton.transform.GetChild(0).GetChild(1).GetComponent<Text>().text = HostString;
HostButton.transform.GetChild(0).GetChild(1).GetComponent<Text>().text = QSBLocalisation.Current.MainMenuHost;
}
_loadingText = null;

View File

@ -1,6 +1,7 @@
using HarmonyLib;
using Mirror;
using OWML.Common;
using QSB.Localisation;
using QSB.Messaging;
using QSB.Utility;
using System.Linq;
@ -73,28 +74,28 @@ public class PlayerJoinMessage : QSBMessage
if (QSBVersion != QSBCore.QSBVersion)
{
DebugLog.ToConsole($"Error - Client {PlayerName} connecting with wrong QSB version. (Client:{QSBVersion}, Server:{QSBCore.QSBVersion})", MessageType.Error);
new PlayerKickMessage(From, $"QSB version does not match. (Client:{QSBVersion}, Server:{QSBCore.QSBVersion})").Send();
new PlayerKickMessage(From, string.Format(QSBLocalisation.Current.QSBVersionMismatch, QSBVersion, QSBCore.QSBVersion)).Send();
return;
}
if (GameVersion != QSBCore.GameVersion)
{
DebugLog.ToConsole($"Error - Client {PlayerName} connecting with wrong game version. (Client:{GameVersion}, Server:{QSBCore.GameVersion})", MessageType.Error);
new PlayerKickMessage(From, $"Outer Wilds version does not match. (Client:{GameVersion}, Server:{QSBCore.GameVersion})").Send();
new PlayerKickMessage(From, string.Format(QSBLocalisation.Current.OWVersionMismatch, GameVersion, QSBCore.GameVersion)).Send();
return;
}
if (DlcInstalled != QSBCore.DLCInstalled)
{
DebugLog.ToConsole($"Error - Client {PlayerName} connecting with wrong DLC installation state. (Client:{DlcInstalled}, Server:{QSBCore.DLCInstalled})", MessageType.Error);
new PlayerKickMessage(From, $"DLC installation state does not match. (Client:{DlcInstalled}, Server:{QSBCore.DLCInstalled})").Send();
new PlayerKickMessage(From, string.Format(QSBLocalisation.Current.DLCMismatch, DlcInstalled, QSBCore.DLCInstalled)).Send();
return;
}
if (QSBPlayerManager.PlayerList.Any(x => x.EyeState >= EyeState.Observatory))
{
DebugLog.ToConsole($"Error - Client {PlayerName} connecting too late into eye scene.", MessageType.Error);
new PlayerKickMessage(From, "Game has progressed too far.").Send();
new PlayerKickMessage(From, QSBLocalisation.Current.GameProgressLimit).Send();
return;
}
@ -104,14 +105,14 @@ public class PlayerJoinMessage : QSBMessage
if (!AddonHashes.SequenceEqual(addonHashes))
{
DebugLog.ToConsole($"Error - Client {PlayerName} connecting with addon mismatch. (Client:{AddonHashes.Join()}, Server:{addonHashes.Join()})", MessageType.Error);
new PlayerKickMessage(From, $"Addon mismatch. (Client:{AddonHashes.Length} addons, Server:{addonHashes.Length} addons)").Send();
new PlayerKickMessage(From, string.Format(QSBLocalisation.Current.AddonMismatch, AddonHashes.Length, addonHashes.Length)).Send();
return;
}
if (FirstIncompatibleMod != "" && !QSBCore.IncompatibleModsAllowed)
{
DebugLog.ToConsole($"Error - Client {PlayerName} connecting with incompatible mod. (First mod found was {FirstIncompatibleMod})");
new PlayerKickMessage(From, $"Using an incompatible/disallowed mod. First mod found was {FirstIncompatibleMod}").Send();
new PlayerKickMessage(From, string.Format(QSBLocalisation.Current.IncompatibleMod, FirstIncompatibleMod)).Send();
}
}

View File

@ -1,4 +1,5 @@
using Mirror;
using QSB.Localisation;
using QSB.Menus;
using QSB.Messaging;
using QSB.Utility;
@ -46,15 +47,15 @@ internal class PlayerKickMessage : QSBMessage<string>
{
if (QSBPlayerManager.PlayerExists(PlayerId))
{
DebugLog.ToAll($"{QSBPlayerManager.GetPlayer(PlayerId).Name} was kicked.");
DebugLog.ToAll(string.Format(QSBLocalisation.Current.PlayerWasKicked, QSBPlayerManager.GetPlayer(PlayerId).Name));
return;
}
DebugLog.ToAll($"Player id:{PlayerId} was kicked.");
DebugLog.ToAll(string.Format(QSBLocalisation.Current.PlayerWasKicked, PlayerId));
return;
}
DebugLog.ToAll($"Kicked from server. Reason : {Data}");
DebugLog.ToAll(string.Format(QSBLocalisation.Current.KickedFromServer, Data));
MenuManager.Instance.OnKicked(Data);
}
}

View File

@ -77,6 +77,9 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Remove="Assets\*.pdn" />
<None Include="Translations\*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="AssetBundles\*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>

View File

@ -2,6 +2,7 @@
using Mirror;
using OWML.Common;
using OWML.ModHelper;
using QSB.Localisation;
using QSB.Menus;
using QSB.Patches;
using QSB.QuantumSync;
@ -122,6 +123,7 @@ public class QSBCore : ModBehaviour
QSBPatchManager.Init();
DeterministicManager.Init();
QSBLocalisation.Init();
var components = typeof(IAddComponentOnStart).GetDerivedTypes()
.Select(x => gameObject.AddComponent(x))

View File

@ -1,4 +1,5 @@
using QSB.ShipSync;
using QSB.Localisation;
using QSB.ShipSync;
using UnityEngine;
namespace QSB.RespawnSync;
@ -11,7 +12,7 @@ public class RespawnHUDMarker : HUDDistanceMarker
{
_markerRadius = 0.2f;
_markerTarget = transform;
_markerLabel = "RESPAWN PLAYER";
_markerLabel = QSBLocalisation.Current.RespawnPlayer;
_isReady = true;
base.InitCanvasMarker();

112
QSB/Translations/en.json Normal file
View File

@ -0,0 +1,112 @@
{
"Language": "ENGLISH",
"MainMenuHost": "OPEN TO MULTIPLAYER",
"MainMenuConnect": "CONNECT TO MULTIPLAYER",
"PauseMenuDisconnect": "DISCONNECT",
"PauseMenuStopHosting": "STOP HOSTING",
"PublicIPAddress": "Public IP Address",
"ProductUserID": "Product User ID",
"Connect": "CONNECT",
"Cancel": "CANCEL",
"HostExistingOrNew": "Do you want to host an existing expedition, or host a new expedition?",
"ExistingSave": "EXISTING SAVE",
"NewSave": "NEW SAVE",
"DisconnectAreYouSure": "Are you sure you want to disconnect?\r\nThis will send you back to the main menu.",
"Yes": "YES",
"No": "NO",
"StopHostingAreYouSure": "Are you sure you want to stop hosting?\r\nThis will disconnect all clients and send everyone back to the main menu.",
"CopyProductUserIDToClipboard": "Hosting server.\r\nClients will connect using your product user id, which is :\r\n{0}\r\nDo you want to copy this to the clipboard?",
"Connecting": "CONNECTING...",
"OK": "OK",
"ServerRefusedConnection": "Server refused connection.\r\n{0}",
"ClientDisconnectWithError": "Client disconnected with error!\r\n{0}",
"QSBVersionMismatch": "QSB version does not match. (Client:{0}, Server:{1})",
"OWVersionMismatch": "Outer Wilds version does not match. (Client:{0}, Server:{1})",
"DLCMismatch": "DLC installation state does not match. (Client:{0}, Server:{1})",
"GameProgressLimit": "Game has progressed too far.",
"AddonMismatch": "Addon mismatch. (Client:{0} addons, Server:{1} addons)",
"IncompatibleMod": "Using an incompatible/disallowed mod. First mod found was {0}",
"PlayerJoinedTheGame": "{0} joined!",
"PlayerWasKicked": "{0} was kicked.",
"KickedFromServer": "Kicked from server. Reason : {0}",
"RespawnPlayer": "Respawn Player",
"DeathMessages": {
"Default": [
"{0} died",
"{0} was killed"
],
"Impact": [
"{0} forgot to use retro-rockets",
"{0} bonked into the ground too hard",
"{0} hit the ground too hard",
"{0} went splat",
"{0} died due to impact",
"{0} impacted the ground too hard"
],
"Asphyxiation": [
"{0} forgot to breathe",
"{0} asphyxiated",
"{0} died due to asphyxiation",
"{0} forgot how to breathe",
"{0} forgot to check their oxygen",
"{0} ran out of air",
"{0} ran out of oxygen",
"{0} didn't need air anyway"
],
"Energy": [
"{0} was cooked"
],
"Supernova": [
"{0} ran out of time",
"{0} burnt up",
"{0} was cooked",
"{0} got vaporized",
"{0} lost track of time"
],
"Digestion": [
"{0} was eaten",
"{0} found a fish",
"{0} encountered an evil creature",
"{0} messed with the wrong fish",
"{0} was digested",
"{0} died due to digestion"
],
"Crushed": [
"{0} was crushed",
"{0} was squished",
"{0} was buried",
"{0} didn't make it out in time",
"{0} went swimming in the sand",
"{0} underestimated sand",
"{0} got trapped under the sand"
],
"Lava": [
"{0} died in lava",
"{0} was melted",
"{0} tried to swim in lava",
"{0} fell into lava",
"{0} died due to lava",
"{0} took a swim in lava",
"{0} got burnt in the lava"
],
"BlackHole": [
"{0} chased their memories"
],
"DreamExplosion": [
"{0} exploded",
"{0} was an early adopter",
"{0} went kaboom",
"{0} was fried",
"{0} died due to explosion",
"{0} used the wrong artifact"
],
"CrushedByElevator": [
"{0} was crushed",
"{0} was squished",
"{0} was crushed by an elevator",
"{0} stood under an elevator",
"{0} became a flat-hearther",
"{0} was squished by an elevator"
]
}
}