diff --git a/ModConfig.cs b/ModConfig.cs index 0a359d8..88ad598 100644 --- a/ModConfig.cs +++ b/ModConfig.cs @@ -13,11 +13,11 @@ internal class ModConfig internal class MenuPresence { - public bool ForceSmallImage = false; public string State = "In Menus"; public string Details = ""; public string LargeImageText = "{ Activity }"; public string SmallImageText = ""; + public bool ForceSmallImage = false; } internal class GamePresence : MenuPresence diff --git a/RichPresenceMod.cs b/RichPresenceMod.cs index 91a5bf0..85e8b78 100644 --- a/RichPresenceMod.cs +++ b/RichPresenceMod.cs @@ -25,6 +25,7 @@ public class RichPresenceMod : Mod public override void Entry(IModHelper helper) { + I18n.Init(Helper.Translation); api = new RichPresenceAPI(this); client = new DiscordRpcClient( clientId, @@ -34,39 +35,37 @@ public override void Entry(IModHelper helper) client.SetSubscription(EventType.Join); client.RegisterUriScheme(steamId); client.OnReady += (sender, e) => - Monitor.Log("Connected to Discord: " + e.User.ToString(), LogLevel.Info); + Monitor.Log(I18n.Console_DiscordConnected(e.User.ToString()), LogLevel.Info); client.Initialize(); #region Console Commands Helper.ConsoleCommands.Add( "DiscordReload", - "Reloads the config for Discord Rich Presence.", + I18n.Command_Reload_Desc(), (string command, string[] args) => { LoadConfig(); - Monitor.Log("Config reloaded.", LogLevel.Info); } ); Helper.ConsoleCommands.Add( "DiscordFormat", - "Formats and prints a provided configuration string.", + I18n.Command_Format_Desc(), (string command, string[] args) => { string text = this.api.FormatText(string.Join(" ", args)); - Monitor.Log("Result: " + text, LogLevel.Info); + Monitor.Log(I18n.Command_Format_Result(text), LogLevel.Info); } ); Helper.ConsoleCommands.Add( "DiscordTags", - "Lists tags usable for configuration strings.", + I18n.Command_Tags_Desc(), (string command, string[] args) => { bool all = string.Join("", args).ToLower().StartsWith("all"); - string output = "Available tags:\n"; - output += FormatTags(out _, out int nulls, format: " {{{0}}}: {1}", pad: true, all: all); + string output = $"{I18n.TagList_Header()}\n"; + output += FormatTags(out int nulls, format: " {{{0}}}: {1}", pad: true, all: all); if (nulls > 0) - output += - $"\n\n{nulls} tag{(nulls != 1 ? "s" : "")} unavailable; type `DiscordTags all` to show all"; + output += $"\n\n{I18n.Command_Tags_Nulls(nulls)}"; Monitor.Log(output, LogLevel.Info); } ); @@ -79,9 +78,9 @@ public override void Entry(IModHelper helper) Helper.Events.GameLoop.SaveLoaded += SetTimestamp; Helper.Events.GameLoop.ReturnedToTitle += SetTimestamp; Helper.Events.GameLoop.SaveLoaded += (object sender, SaveLoadedEventArgs e) => - api.GamePresence = "Getting Started"; + api.GamePresence = I18n.GamePresence_GettingStarted(); Helper.Events.GameLoop.SaveCreated += (object sender, SaveCreatedEventArgs e) => - api.GamePresence = "Starting a New Game"; + api.GamePresence = I18n.GamePresence_StartingNewGame(); Helper.Events.GameLoop.GameLaunched += (object sender, GameLaunchedEventArgs e) => { SetTimestamp(); @@ -179,9 +178,9 @@ public override void Entry(IModHelper helper) () => Context.IsMultiplayer ? Context.IsMainPlayer - ? "Hosting Co-op" - : "Playing Co-op" - : "Playing Solo" + ? I18n.HostingCoop() + : I18n.PlayingCoop() + : I18n.PlayingSolo() ); #endregion } @@ -200,7 +199,6 @@ private void WTag(string tag, Func func) => ); private string FormatTags( - out int count, out int nulls, string format = "{{{0}}}: {1}", bool pad = false, @@ -209,7 +207,6 @@ private string FormatTags( { var tags = api.ResolveAllTags(); nulls = 0; - count = 0; Dictionary> groups = new(); foreach (var tag in tags) @@ -229,7 +226,6 @@ private string FormatTags( if (!tag.Value.Success) val = "[ERROR]"; groups[owner][tag.Key] = val; - count++; } } @@ -249,12 +245,11 @@ void section(Dictionary group, string name) if (count == 0) return; - string head = $"{count} tag"; - if (count != 1) - head += "s"; - head += $" from {name}:"; output.Add(""); - output.Add(head); + if (name != "") + output.Add(I18n.TagList_ModHeader(count, name)); + else + output.Add(I18n.TagList_UnknownModsHeader(count)); list(group); } @@ -268,7 +263,7 @@ void section(Dictionary group, string name) continue; section(group.Value, group.Key); } - section(groups[""], "unknown mods"); + section(groups[""], ""); return string.Join("\n", output); } @@ -289,121 +284,115 @@ private void RegisterConfigMenu(object sender, GameLaunchedEventArgs e) configMenu.AddBoolOption( mod, - name: () => "Show global playtime", + name: () => I18n.Options_ShowGlobalPlayTime(), getValue: () => Config.ShowGlobalPlayTime, setValue: value => Config.ShowGlobalPlayTime = value ); configMenu.AddBoolOption( mod, - name: () => "Add Get Mod Button", - tooltip: () => "Support the mod by adding a link to it on your rich presence.", + name: () => I18n.Options_AddGetModButton(), + tooltip: () => I18n.Options_AddGetModButton_Desc(), getValue: () => Config.AddGetModButton, setValue: value => Config.AddGetModButton = value ); - configMenu.AddSectionTitle(mod, () => "Preview"); + configMenu.AddSectionTitle(mod, () => I18n.Options_Preview()); configMenu.AddParagraph( mod, () => { - var text = api.FormatText(Conf.State) + "\n"; - text += api.FormatText(Conf.Details) + "\n"; - var large = api.FormatText(Conf.LargeImageText); - if (large.Length > 0) - text += $"Large image text: {large}\n"; - var small = api.FormatText(Conf.SmallImageText); - if (small.Length > 0) - text += $"Small image text: {small}\n"; + var text = $"{api.FormatText(Conf.State)}\n"; + text += $"{api.FormatText(Conf.Details)}\n"; + text += $"{api.FormatText(Conf.LargeImageText)}\n"; + text += $"{api.FormatText(Conf.SmallImageText)}\n"; return text; } ); - configMenu.AddSectionTitle(mod, () => "Customize Presence in Menus"); + configMenu.AddSectionTitle(mod, () => I18n.Options_MenuPresence()); RPCModMenuSection(configMenu, Config.MenuPresence); - configMenu.AddSectionTitle(mod, () => "Customize Presence in Game"); + configMenu.AddSectionTitle(mod, () => I18n.Options_GamePresence()); RPCModMenuSection(configMenu, Config.GamePresence); configMenu.AddBoolOption( mod, - name: () => "Show season", - tooltip: () => "Show the current season on large image", + name: () => I18n.Options_ShowSeason(), + tooltip: () => I18n.Options_ShowSeason_Desc(), getValue: () => Config.GamePresence.ShowSeason, setValue: value => Config.GamePresence.ShowSeason = value ); configMenu.AddBoolOption( mod, - name: () => "Show farm type", - tooltip: () => "Show the farm type on large image", + name: () => I18n.Options_ShowFarmType(), + tooltip: () => I18n.Options_ShowFarmType_Desc(), getValue: () => Config.GamePresence.ShowFarmType, setValue: value => Config.GamePresence.ShowFarmType = value ); configMenu.AddBoolOption( mod, - name: () => "Show weather", - tooltip: () => "Show the current weather on small image", + name: () => I18n.Options_ShowWeather(), + tooltip: () => I18n.Options_ShowWeather_Desc(), getValue: () => Config.GamePresence.ShowWeather, setValue: value => Config.GamePresence.ShowWeather = value ); configMenu.AddBoolOption( mod, - name: () => "Show play time", - tooltip: () => "Show how long you've been playing", + name: () => I18n.Options_ShowPlayTime(), + tooltip: () => I18n.Options_ShowPlayTime_Desc(), getValue: () => Config.GamePresence.ShowPlayTime, setValue: value => Config.GamePresence.ShowPlayTime = value ); - configMenu.AddPage(mod, "tags", () => "Tags"); + // Tags Page + configMenu.AddPage(mod, "tags", () => I18n.Options_Page_Tags()); configMenu.AddParagraph( mod, () => { - string output = FormatTags(out _, out int nulls, pad: false); - output += $"\n\n{nulls} tag{(nulls != 1 ? "s" : "")} unavailable."; + string output = FormatTags(out int nulls, pad: false); + output += $"\n\n{I18n.Options_UnavailableTags(nulls)}"; return output; } ); - configMenu.AddPageLink(mod, "alltags", () => "Click here to show all tags."); + configMenu.AddPageLink(mod, "alltags", () => I18n.Options_ShowAllTags()); - configMenu.AddPage(mod, "alltags", () => "All Tags"); - configMenu.AddParagraph( - mod, - () => FormatTags(out _, out _, format: "{{{0}}}: {1}", pad: false, all: true) - ); + // All Tags Page + configMenu.AddPage(mod, "alltags", () => I18n.Options_Page_AllTags()); + configMenu.AddParagraph(mod, () => FormatTags(out _, "{{{0}}}: {1}", pad: false, all: true)); } private void RPCModMenuSection(IGenericModConfigMenuApi api, MenuPresence conf) { var mod = ModManifest; - api.AddPageLink(mod, "tags", () => "Show available tags"); + api.AddPageLink(mod, "tags", () => I18n.Options_ShowAvailableTags()); api.AddTextOption( mod, - name: () => "Line 1 (State)", + name: () => I18n.Options_State(), getValue: () => conf.State, setValue: value => conf.State = value ); api.AddTextOption( mod, - name: () => "Line 2 (Details)", + name: () => I18n.Options_Details(), getValue: () => conf.Details, setValue: value => conf.Details = value ); api.AddTextOption( mod, - name: () => "Large Image Text", + name: () => I18n.Options_LargeImageText(), getValue: () => conf.LargeImageText, setValue: value => conf.LargeImageText = value ); api.AddTextOption( mod, - name: () => "Small Image Text", + name: () => I18n.Options_SmallImageText(), getValue: () => conf.SmallImageText, setValue: value => conf.SmallImageText = value ); api.AddBoolOption( mod, - name: () => "Force small image", - tooltip: () => - "Always show small image, even if small text is empty and weather isn't shown.", + name: () => I18n.Options_ForceSmallImage(), + tooltip: () => I18n.Options_ForceSmallImage_Desc(), getValue: () => conf.ForceSmallImage, setValue: value => conf.ForceSmallImage = value ); @@ -416,12 +405,12 @@ private void HandleButton(object sender, ButtonReleasedEventArgs e) try { LoadConfig(); - Game1.addHUDMessage(new HUDMessage("DiscordRP config reloaded.", HUDMessage.newQuest_type)); + Game1.addHUDMessage(new HUDMessage(I18n.Notify_ReloadConfig(), HUDMessage.newQuest_type)); } catch (Exception err) { Game1.addHUDMessage( - new HUDMessage("Failed to reload DiscordRP config. Check console.", HUDMessage.error_type) + new HUDMessage(I18n.Notify_ReloadConfig_Failed(), HUDMessage.error_type) ); Monitor.Log(err.ToString(), LogLevel.Error); } @@ -491,7 +480,7 @@ private RichPresence GetPresence() if (Config.AddGetModButton) presence.Buttons = new Button[] { - new() { Label = "Get SDV Rich Presence Mod", Url = ModURL } + new() { Label = I18n.GetModButton(), Url = ModURL } }; presence.Assets = assets; diff --git a/SVRichPresence.csproj b/SVRichPresence.csproj index 1a0a8e8..fa38715 100644 --- a/SVRichPresence.csproj +++ b/SVRichPresence.csproj @@ -6,5 +6,6 @@ + diff --git a/i18n/default.json b/i18n/default.json new file mode 100644 index 0000000..1ec2f6f --- /dev/null +++ b/i18n/default.json @@ -0,0 +1,55 @@ +{ + // Commands + "command.reload.desc": "Reloads the config for Discord Rich Presence.", + "command.format.desc": "Formats and prints a provided configuration string.", + "command.format.result": "Result: {{result}}", + "command.tags.desc": "Lists tags usable for configuration strings.", + "command.tags.nulls": "{{count}} tags are unavailable; type `discordtags all` to show all", + + // Console Output + "console.discordConnected": "Connected to Discord: {{user}}", + "notify.reloadConfig": "DiscordRP config reloaded.", + "notify.reloadConfig.failed": "Failed to reload Discord RPC config. Check console.", + + // Config Menu + "options.ShowGlobalPlayTime": "Show global playtime", + "options.AddGetModButton": "Add Get Mod Button", + "options.AddGetModButton.desc": "Support the mod by adding a link to it on your rich presence.", + "options.preview": "Preview", + "options.MenuPresence": "Customize Presence in Menus", + "options.GamePresence": "Customize Presence in Game", + "options.State": "Line 1 (State)", + "options.Details": "Line 2 (Details)", + "options.largeImageText": "Large image text", + "options.SmallImageText": "Small image text", + "options.ForceSmallImage": "Force small image", + "options.ForceSmallImage.desc": "Always show small image, even if small text is empty and weather isn't shown.", + "options.ShowSeason": "Show season", + "options.ShowSeason.desc": "Show the current season on large image", + "options.ShowFarmType": "Show farm type", + "options.ShowFarmType.desc": "Show the farm type on large image", + "options.ShowWeather": "Show weather", + "options.ShowWeather.desc": "Show the current weather on small image", + "options.ShowPlayTime": "Show play time", + "options.ShowPlayTime.desc": "Show how long you've been playing", + "options.showAvailableTags": "Show available tags", + "options.showAllTags": "Click here to show all tags", + "options.unavailableTags": "{{count}} tags are unavailable", + + "options.page.tags": "Tags", + "options.page.allTags": "All Tags", + + "tagList.header": "Available tags:", + "tagList.modHeader": "{{count}} tags from {{name}}:", + "tagList.unknownModsHeader": "{{count}} tags from unknown mods:", + + // GamePresence + "gamePresence.gettingStarted": "Getting Started", + "gamePresence.startingNewGame": "Starting a New Game", + + "hostingCoop": "Hosting coop", + "playingCoop": "Playing coop", + "playingSolo": "Playing solo", + + "getModButton": "Get SDV Rich Presence Mod" +} \ No newline at end of file diff --git a/i18n/fr.json b/i18n/fr.json new file mode 100644 index 0000000..a901698 --- /dev/null +++ b/i18n/fr.json @@ -0,0 +1,55 @@ +{ + // Commands + "command.reload.desc": "Recharge la configuration pour Discord Rich Presence.", + "command.format.desc": "Met en forme et affiche le résultat de la configuration donnée.", + "command.format.result": "Resultat: {{result}}", + "command.tags.desc": "Liste les tags utilisables pour la configuration.", + "command.tags.nulls": "{{count}} tags indisponibles; Faites `discordtags all` pour tout afficher", + + // Console Output + "console.discordConnected": "Connecté à Discord: {{user}}", + "notify.reloadConfig": "DiscordRP configuration rechargée.", + "notify.reloadConfig.failed": "Échec du rechargement de la configuration de Discord RP. Consultez la console.", + + // Config Menu + "options.ShowGlobalPlayTime": "Affiche le temps de jeu global", + "options.AddGetModButton": "Ajoute un bouton 'Obtenir le mod'", + "options.AddGetModButton.desc": "Supporter le mod en ajoutant un lien pour le télécharger dans l'activité.", + "options.preview": "Aperçu", + "options.MenuPresence": "Personnaliser l'Activité dans le menu", + "options.GamePresence": "Personnaliser l'Activité dans le jeu", + "options.State": "Ligne 1 (État)", + "options.Details": "Ligne 2 (Détails)", + "options.LargeImageText": "Texte de la grande image", + "options.SmallImageText": "Texte de la petite image", + "options.ForceSmallImage": "Forcer la petite image", + "options.ForceSmallImage.desc": "Toujours forcer la petite image, même si le texte est vide et que la météo ne s'affiche pas.", + "options.ShowSeason": "Afficher la saison", + "options.ShowSeason.desc": "Affiche la saison actuelle sur la grande image.", + "options.ShowFarmType": "Afficher le type de ferme", + "options.ShowFarmType.desc": "Affiche le type de ferme actuelle sur la grande image.", + "options.ShowWeather": "Afficher la météo", + "options.ShowWeather.desc": "Affiche la météo actuelle sur la grande image.", + "options.ShowPlayTime": "Afficher le temps de jeu", + "options.ShowPlayTime.desc": "Affiche depuis combien de temps vous jouez.", + "options.showAvailableTags": "Afficher les tags disponibles", + "options.showAllTags": "Cliquer ici pour afficher tous les tags", + "options.unavailableTags": "{{count}} tags indisponibles", + + "options.page.tags": "Tags", + "options.page.allTags": "Tous les Tags", + + "tagList.header": "Tags disponibles:", + "tagList.modHeader": "{{count}} tags de {{name}}:", + "tagList.unknownModsHeader": "{{count}} tags de mods inconnus:", + + // GamePresence + "gamePresence.gettingStarted": "Vient de commencer", + "gamePresence.startingNewGame": "Démarre une nouvelle partie", + + "hostingCoop": "Héberge en co-op", + "playingCoop": "Joue en co-op", + "playingSolo": "Joue en solo", + + "getModButton": "Obtenir SDV Rich Presence" +} \ No newline at end of file