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

Multiple languages & Language adaptation #224

Open
wants to merge 2 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 42 additions & 3 deletions SharedClasses/ConfigManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using CitizenFX.Core;
using static CitizenFX.Core.Native.API;
using Newtonsoft.Json;
using System.Collections;

namespace vMenuShared
{
Expand Down Expand Up @@ -93,12 +94,50 @@ public static bool IsClientDebugModeEnabled()
return GetResourceMetadata("vMenu", "client_debug_mode", 0).ToLower() == "true";
}

#region Get saved locations from the locations.json
#region Get localization from the languages.json
/// <summary>
/// Gets the locations.json data.
/// Gets the languages.json data.
/// </summary>
/// <returns></returns>
public static Locations GetLocations()
public static Dictionary<string, Hashtable> GetLanguages()
{
Dictionary<string, Hashtable> data = new Dictionary<string, Hashtable>();

string jsonFile = LoadResourceFile(GetCurrentResourceName(), "config/languages.json");
try
{
if (string.IsNullOrEmpty(jsonFile))
{
#if CLIENT
vMenuClient.Notify.Error("The languages.json file is empty or does not exist, please tell the server owner to fix this.");
#endif
#if SERVER
vMenuServer.DebugLog.Log("The languages.json file is empty or does not exist, please fix this.", vMenuServer.DebugLog.LogLevel.error);
#endif
}
else
{
data = JsonConvert.DeserializeObject<Dictionary<string, Hashtable>>(jsonFile);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please only try/catch the necessary code. Only the JSON conversion could crash here, so that's what needs to be caught.

}
}
catch (Exception e)
{
#if CLIENT
vMenuClient.Notify.Error("An error occurred while processing the languages.json file. Language will set to English. Please correct any errors in the languages.json file.");
#endif
Debug.WriteLine($"[vMenu] json exception details: {e.Message}\nStackTrace:\n{e.StackTrace}");
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Notify.Error() already prints an error in the console, so you only need to log this to the console on the server side here.

}

return data;
}
#endregion

#region Get saved locations from the locations.json
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is there an additional indentation level here?

/// <summary>
/// Gets the locations.json data.
/// </summary>
/// <returns></returns>
public static Locations GetLocations()
{
Locations data = new Locations();

Expand Down
1 change: 1 addition & 0 deletions SharedClasses/PermissionsManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public enum Permission
// Global
#region global
Everything,
DumpLanguages,
DontKickMe,
DontBanMe,
NoClip,
Expand Down
45 changes: 45 additions & 0 deletions vMenu/LanguageManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MenuAPI;
using Newtonsoft.Json;
using CitizenFX.Core;
using static CitizenFX.Core.UI.Screen;
using static CitizenFX.Core.Native.API;
using static vMenuClient.CommonFunctions;
using static vMenuShared.ConfigManager;
using static vMenuShared.PermissionsManager;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is all this really necessary?


namespace vMenuClient
{
public class LanguageManager : BaseScript
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this use BaseScript?
Please make it a static class instead with static functions.

{
public string Get (string originalText) {

string transText = originalText;

if (!MainMenu.DumpedData.ContainsKey(originalText))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the "DumpedData" in MainMenu?
Seems best to keep all language data in one place, like here in the LanguageManager.

{
MainMenu.DumpedData.Add(originalText, "");
}

if (MainMenu.CurrentLanguage.ContainsKey(originalText)) {
try {
transText = (string)MainMenu.CurrentLanguage[originalText];
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This try / catch is not needed, you've already checked if the text is in there so nothing should raise an exception here.

if (transText == "")
{
transText = originalText;
}
} catch (Exception ex)
{
// Not need this because it will generate lot of logs and fill your disk xD
// Debug.WriteLine($"Cannot found translate: {originalText}");
}
}

return transText;
}
}
}
93 changes: 65 additions & 28 deletions vMenu/MainMenu.cs

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions vMenu/Noclip.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public class NoClip : BaseScript
private static int Scale { get; set; } = -1;
private static bool FollowCamMode { get; set; } = false;

private static LanguageManager LM = new LanguageManager();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems a bit useless? 🤔

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to add a translation for the NoClip button, but it crashed, seemingly because it was loaded earlier than the main menu.


private List<string> speeds = new List<string>()
{
Expand Down
9 changes: 5 additions & 4 deletions vMenu/menus/About.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,23 @@ public class About
// Variables
private Menu menu;

private static LanguageManager LM = new LanguageManager();
private void CreateMenu()
{
// Create the menu.
menu = new Menu("vMenu", "About vMenu");
menu = new Menu(LM.Get("vMenu"), LM.Get("About vMenu"));

// Create menu items.
MenuItem version = new MenuItem("vMenu Version", $"This server is using vMenu ~b~~h~{MainMenu.Version}~h~~s~.")
MenuItem version = new MenuItem(LM.Get("vMenu Version"), $"This server is using vMenu ~b~~h~{MainMenu.Version}~h~~s~.")
{
Label = $"~h~{MainMenu.Version}~h~"
};
MenuItem credits = new MenuItem("About vMenu / Credits", "vMenu is made by ~b~Vespura~s~. For more info, checkout ~b~www.vespura.com/vmenu~s~. Thank you to: Deltanic, Brigliar, IllusiveTea, Shayan Doust and zr0iq for your contributions.");
MenuItem credits = new MenuItem(LM.Get("About vMenu / Credits"), LM.Get("vMenu is made by ~b~Vespura~s~. For more info, checkout ~b~www.vespura.com/vmenu~s~. Thank you to: Deltanic, Brigliar, IllusiveTea, Shayan Doust and zr0iq for your contributions."));
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Credits shouldn't need to be translated or possibly removed.


string serverInfoMessage = vMenuShared.ConfigManager.GetSettingsString(vMenuShared.ConfigManager.Setting.vmenu_server_info_message);
if (!string.IsNullOrEmpty(serverInfoMessage))
{
MenuItem serverInfo = new MenuItem("Server Info", serverInfoMessage);
MenuItem serverInfo = new MenuItem(LM.Get("Server Info"), serverInfoMessage);
string siteUrl = vMenuShared.ConfigManager.GetSettingsString(vMenuShared.ConfigManager.Setting.vmenu_server_info_website_url);
if (!string.IsNullOrEmpty(siteUrl))
{
Expand Down
48 changes: 25 additions & 23 deletions vMenu/menus/BannedPlayers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public class BannedPlayers
// Variables
private Menu menu;

private static LanguageManager LM = new LanguageManager();

/// <summary>
/// Struct used to store bans.
/// </summary>
Expand All @@ -34,47 +36,47 @@ public struct BanRecord

public List<BanRecord> banlist = new List<BanRecord>();

Menu bannedPlayer = new Menu("Banned Player", "Ban Record: ");
Menu bannedPlayer = new Menu(LM.Get("Banned Player"), LM.Get("Ban Record: "));

/// <summary>
/// Creates the menu.
/// </summary>
private void CreateMenu()
{
menu = new Menu(Game.Player.Name, "Banned Players Management");
menu = new Menu(Game.Player.Name, LM.Get("Banned Players Management"));

menu.InstructionalButtons.Add(Control.Jump, "Filter Options");
menu.InstructionalButtons.Add(Control.Jump, LM.Get("Filter Options"));
menu.ButtonPressHandlers.Add(new Menu.ButtonPressHandler(Control.Jump, Menu.ControlPressCheckType.JUST_RELEASED, new Action<Menu, Control>(async (a, b) =>
{
if (banlist.Count > 1)
{
string filterText = await GetUserInput("Filter List By Username (leave this empty to reset the filter!)");
string filterText = await GetUserInput(LM.Get("Filter List By Username (leave this empty to reset the filter!)"));
if (string.IsNullOrEmpty(filterText))
{
Subtitle.Custom("Filters have been cleared.");
Subtitle.Custom(LM.Get("Filters have been cleared."));
menu.ResetFilter();
UpdateBans();
}
else
{
menu.FilterMenuItems(item => item.ItemData is BanRecord br && br.playerName.ToLower().Contains(filterText.ToLower()));
Subtitle.Custom("Username filter has been applied.");
Subtitle.Custom(LM.Get("Username filter has been applied."));
}
}
else
{
Notify.Error("At least 2 players need to be banned in order to use the filter function.");
Notify.Error(LM.Get("At least 2 players need to be banned in order to use the filter function."));
}

Log($"Button pressed: {a} {b}");
}), true));

bannedPlayer.AddMenuItem(new MenuItem("Player Name"));
bannedPlayer.AddMenuItem(new MenuItem("Banned By"));
bannedPlayer.AddMenuItem(new MenuItem("Banned Until"));
bannedPlayer.AddMenuItem(new MenuItem("Player Identifiers"));
bannedPlayer.AddMenuItem(new MenuItem("Banned For"));
bannedPlayer.AddMenuItem(new MenuItem("~r~Unban", "~r~Warning, unbanning the player can NOT be undone. You will NOT be able to ban them again until they re-join the server. Are you absolutely sure you want to unban this player? ~s~Tip: Tempbanned players will automatically get unbanned if they log on to the server after their ban date has expired."));
bannedPlayer.AddMenuItem(new MenuItem(LM.Get("Player Name")));
bannedPlayer.AddMenuItem(new MenuItem(LM.Get("Banned By")));
bannedPlayer.AddMenuItem(new MenuItem(LM.Get("Banned Until")));
bannedPlayer.AddMenuItem(new MenuItem(LM.Get("Player Identifiers")));
bannedPlayer.AddMenuItem(new MenuItem(LM.Get("Banned For")));
bannedPlayer.AddMenuItem(new MenuItem(LM.Get("~r~Unban"), LM.Get("~r~Warning, unbanning the player can NOT be undone. You will NOT be able to ban them again until they re-join the server. Are you absolutely sure you want to unban this player? ~s~Tip: Tempbanned players will automatically get unbanned if they log on to the server after their ban date has expired.")));

// should be enough for now to cover all possible identifiers.
List<string> colors = new List<string>() { "~r~", "~g~", "~b~", "~o~", "~y~", "~p~", "~s~", "~t~", };
Expand All @@ -95,7 +97,7 @@ private void CreateMenu()
{
if (index == 5 && IsAllowed(Permission.OPUnban))
{
if (item.Label == "Are you sure?")
if (item.Label == LM.Get("Are you sure?"))
{
if (banlist.Contains(currentRecord))
{
Expand All @@ -105,12 +107,12 @@ private void CreateMenu()
}
else
{
Notify.Error("Somehow you managed to click the unban button but this ban record you're apparently viewing does not even exist. Weird...");
Notify.Error(LM.Get("Somehow you managed to click the unban button but this ban record you're apparently viewing does not even exist. Weird..."));
}
}
else
{
item.Label = "Are you sure?";
item.Label = LM.Get("Are you sure?");
}
}
else
Expand All @@ -126,21 +128,21 @@ private void CreateMenu()
//{
currentRecord = item.ItemData;

bannedPlayer.MenuSubtitle = "Ban Record: ~y~" + currentRecord.playerName;
bannedPlayer.MenuSubtitle = LM.Get("Ban Record: ~y~") + currentRecord.playerName;
var nameItem = bannedPlayer.GetMenuItems()[0];
var bannedByItem = bannedPlayer.GetMenuItems()[1];
var bannedUntilItem = bannedPlayer.GetMenuItems()[2];
var playerIdentifiersItem = bannedPlayer.GetMenuItems()[3];
var banReasonItem = bannedPlayer.GetMenuItems()[4];
nameItem.Label = currentRecord.playerName;
nameItem.Description = "Player name: ~y~" + currentRecord.playerName;
nameItem.Description = LM.Get("Player name: ~y~") + currentRecord.playerName;
bannedByItem.Label = currentRecord.bannedBy;
bannedByItem.Description = "Player banned by: ~y~" + currentRecord.bannedBy;
bannedByItem.Description = LM.Get("Player banned by: ~y~") + currentRecord.bannedBy;
if (currentRecord.bannedUntil.Date.Year == 3000)
bannedUntilItem.Label = "Forever";
bannedUntilItem.Label = LM.Get("Forever");
else
bannedUntilItem.Label = currentRecord.bannedUntil.Date.ToString();
bannedUntilItem.Description = "This player is banned until: " + currentRecord.bannedUntil.Date.ToString();
bannedUntilItem.Description = LM.Get("This player is banned until: ") + currentRecord.bannedUntil.Date.ToString();
playerIdentifiersItem.Description = "";

int i = 0;
Expand All @@ -159,14 +161,14 @@ private void CreateMenu()
}
i++;
}
banReasonItem.Description = "Banned for: " + currentRecord.banReason;
banReasonItem.Description = LM.Get("Banned for: ") + currentRecord.banReason;

var unbanPlayerBtn = bannedPlayer.GetMenuItems()[5];
unbanPlayerBtn.Label = "";
if (!IsAllowed(Permission.OPUnban))
{
unbanPlayerBtn.Enabled = false;
unbanPlayerBtn.Description = "You are not allowed to unban players. You are only allowed to view their ban record.";
unbanPlayerBtn.Description = LM.Get("You are not allowed to unban players. You are only allowed to view their ban record.");
unbanPlayerBtn.LeftIcon = MenuItem.Icon.LOCK;
}

Expand Down
Loading