Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement i18n #36

Merged
merged 14 commits into from
Mar 25, 2024
2 changes: 1 addition & 1 deletion ModConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
121 changes: 55 additions & 66 deletions RichPresenceMod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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);
}
);
Expand All @@ -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();
Expand Down Expand Up @@ -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
}
Expand All @@ -200,7 +199,6 @@ private void WTag(string tag, Func<string> func) =>
);

private string FormatTags(
out int count,
out int nulls,
string format = "{{{0}}}: {1}",
bool pad = false,
Expand All @@ -209,7 +207,6 @@ private string FormatTags(
{
var tags = api.ResolveAllTags();
nulls = 0;
count = 0;

Dictionary<string, Dictionary<string, string>> groups = new();
foreach (var tag in tags)
Expand All @@ -229,7 +226,6 @@ private string FormatTags(
if (!tag.Value.Success)
val = "[ERROR]";
groups[owner][tag.Key] = val;
count++;
}
}

Expand All @@ -249,12 +245,11 @@ void section(Dictionary<string, string> 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);
}
Expand All @@ -268,7 +263,7 @@ void section(Dictionary<string, string> group, string name)
continue;
section(group.Value, group.Key);
}
section(groups[""], "unknown mods");
section(groups[""], "");

return string.Join("\n", output);
}
Expand All @@ -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
);
Expand All @@ -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);
}
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions SVRichPresence.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
<ItemGroup>
<PackageReference Include="Pathoschild.Stardew.ModBuildConfig" Version="4.1.1" />
<PackageReference Include="DiscordRichPresence" Version="1.2.1.24" />
<PackageReference Include="Pathoschild.Stardew.ModTranslationClassBuilder" Version="2.0.1" />
</ItemGroup>
</Project>
55 changes: 55 additions & 0 deletions i18n/default.json
Original file line number Diff line number Diff line change
@@ -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"
}
Loading