diff --git a/NoSoliciting.Lite/NoSoliciting.Lite.csproj b/NoSoliciting.Lite/NoSoliciting.Lite.csproj index 463838a..1cff6ba 100755 --- a/NoSoliciting.Lite/NoSoliciting.Lite.csproj +++ b/NoSoliciting.Lite/NoSoliciting.Lite.csproj @@ -39,6 +39,6 @@ - + diff --git a/NoSoliciting.Trainer/NoSoliciting.Trainer.csproj b/NoSoliciting.Trainer/NoSoliciting.Trainer.csproj index 5323995..31295c3 100755 --- a/NoSoliciting.Trainer/NoSoliciting.Trainer.csproj +++ b/NoSoliciting.Trainer/NoSoliciting.Trainer.csproj @@ -9,7 +9,7 @@ - + diff --git a/NoSoliciting/ContextMenu.cs b/NoSoliciting/ContextMenu.cs index 4a80ef6..acca3d2 100755 --- a/NoSoliciting/ContextMenu.cs +++ b/NoSoliciting/ContextMenu.cs @@ -50,21 +50,7 @@ namespace NoSoliciting { return; } - Task.Run(async () => { - var status = await this.Plugin.Ui.Report.ReportMessageAsync(message); - switch (status) { - case ReportStatus.Successful: { - var msg = Language.ReportToastSuccess; - this.Plugin.Interface.Framework.Gui.Toast.ShowNormal(string.Format(msg, listing.Name)); - break; - } - case ReportStatus.Failure: { - var msg = Language.ReportToastFailure; - this.Plugin.Interface.Framework.Gui.Toast.ShowError(string.Format(msg, listing.Name)); - break; - } - } - }); + this.Plugin.Ui.Report.ToShowModal = message; } } } diff --git a/NoSoliciting/Filter.cs b/NoSoliciting/Filter.cs index 736ae84..23ce6cd 100644 --- a/NoSoliciting/Filter.cs +++ b/NoSoliciting/Filter.cs @@ -84,23 +84,20 @@ namespace NoSoliciting { this.LastBatch = args.BatchNumber; var version = this.Plugin.MlFilter?.Version; - var reason = this.MlListingFilterReason(listing); - - if (version == null) { - return; - } + var (category, reason) = this.MlListingFilterReason(listing); this.Plugin.AddPartyFinderHistory(new Message( - version.Value, + version, ChatType.None, listing.ContentIdLower, listing.Name, listing.Description, - true, - reason + category, + reason == "custom", + reason == "ilvl" )); - if (reason == null) { + if (category == null && reason == null) { return; } @@ -123,10 +120,6 @@ namespace NoSoliciting { } private bool MlFilterMessage(XivChatType type, uint senderId, SeString sender, SeString message) { - if (this.Plugin.MlFilter == null) { - return false; - } - var chatType = ChatTypeExt.FromDalamud(type); // NOTE: don't filter on user-controlled chat types here because custom filters are supposed to check all @@ -137,80 +130,81 @@ namespace NoSoliciting { var text = message.TextValue; - string? reason = null; + var custom = false; + MessageCategory? classification = null; // step 1. check for custom filters if enabled - var filter = this.Plugin.Config.CustomChatFilter - && Chat.MatchesCustomFilters(text, this.Plugin.Config) - && SetReason(out reason, "custom"); + var filter = false; + if (this.Plugin.Config.CustomChatFilter && Chat.MatchesCustomFilters(text, this.Plugin.Config)) { + filter = true; + custom = true; + } // only look at ml if message >= min words - if (!filter && text.Trim().Split(' ').Length >= MinWords) { + if (!filter && this.Plugin.MlFilter != null && text.Trim().Split(' ').Length >= MinWords) { // step 2. classify the message using the model var category = this.Plugin.MlFilter.ClassifyMessage((ushort) chatType, text); // step 2a. only filter if configured to act on this channel - filter = category != MessageCategory.Normal - && this.Plugin.Config.MlEnabledOn(category, chatType) - && SetReason(out reason, category.Name()); + if (category != MessageCategory.Normal && this.Plugin.Config.MlEnabledOn(category, chatType)) { + filter = true; + classification = category; + } } - this.Plugin.AddMessageHistory(new Message( - this.Plugin.MlFilter.Version, + var history = new Message( + this.Plugin.MlFilter?.Version, ChatTypeExt.FromDalamud(type), senderId, sender, message, - true, - reason - )); + classification, + custom, + false + ); + this.Plugin.AddMessageHistory(history); if (filter && this.Plugin.Config.LogFilteredChat) { - PluginLog.Log($"Filtered chat message ({reason}): {text}"); + PluginLog.Log($"Filtered chat message ({history.FilterReason ?? "unknown"}): {text}"); } return filter; } - private string? MlListingFilterReason(PartyFinderListing listing) { + private (MessageCategory?, string?) MlListingFilterReason(PartyFinderListing listing) { if (this.Plugin.MlFilter == null) { - return null; + return (null, null); } // ignore private listings if configured if (!this.Plugin.Config.ConsiderPrivatePfs && listing[SearchAreaFlags.Private]) { - return null; + return (null, null); } var desc = listing.Description.TextValue; // step 1. check if pf has an item level that's too high if (this.Plugin.Config.FilterHugeItemLevelPFs && listing.MinimumItemLevel > FilterUtil.MaxItemLevelAttainable(this.Plugin.Interface.Data)) { - return "ilvl"; + return (null, "ilvl"); } // step 2. check custom filters if (this.Plugin.Config.CustomPFFilter && PartyFinder.MatchesCustomFilters(desc, this.Plugin.Config)) { - return "custom"; + return (null, "custom"); } // only look at ml for pfs >= min words if (desc.Trim().Spacify().Split(' ').Length < MinWords) { - return null; + return (null, null); } var category = this.Plugin.MlFilter.ClassifyMessage((ushort) ChatType.None, desc); if (category != MessageCategory.Normal && this.Plugin.Config.MlEnabledOn(category, ChatType.None)) { - return category.Name(); + return (category, null); } - return null; - } - - private static bool SetReason(out string reason, string value) { - reason = value; - return true; + return (null, null); } } } diff --git a/NoSoliciting/Interface/Report.cs b/NoSoliciting/Interface/Report.cs index f82a4e1..c706014 100755 --- a/NoSoliciting/Interface/Report.cs +++ b/NoSoliciting/Interface/Report.cs @@ -3,12 +3,12 @@ using System.Globalization; using System.Linq; using System.Net; using System.Numerics; -using System.Text; using System.Threading.Tasks; using Dalamud.Game.Text.SeStringHandling; using Dalamud.Game.Text.SeStringHandling.Payloads; using Dalamud.Plugin; using ImGuiNET; +using NoSoliciting.Ml; using NoSoliciting.Resources; namespace NoSoliciting.Interface { @@ -34,6 +34,8 @@ namespace NoSoliciting.Interface { set => this._showReporting = value; } + internal Message? ToShowModal { get; set; } + public Report(Plugin plugin) { this.Plugin = plugin; } @@ -47,6 +49,13 @@ namespace NoSoliciting.Interface { } public void Draw() { + var toShow = this.ToShowModal; + if (toShow != null) { + if (!this.SetUpReportModal(toShow)) { + ImGui.OpenPopup($"###modal-message-{toShow.Id}"); + } + } + if (!this.ShowReporting) { return; } @@ -102,7 +111,7 @@ namespace NoSoliciting.Interface { foreach (var message in this.Plugin.MessageHistory) { ImGui.TableNextRow(); - if (message.FilterReason != null) { + if (message.Filtered) { ImGui.PushStyleColor(ImGuiCol.Text, new Vector4(238f / 255f, 71f / 255f, 71f / 255f, 1f)); } @@ -112,11 +121,11 @@ namespace NoSoliciting.Interface { .Select(payload => payload.Text) .FirstOrDefault() ?? ""; - if (AddRow(message.Timestamp.ToString(CultureInfo.CurrentCulture), message.ChatType.Name(this.Plugin.Interface.Data), message.FilterReason ?? "", sender, message.Content.TextValue)) { + if (AddRow(message.Timestamp.ToString(CultureInfo.CurrentCulture), message.ChatType.Name(this.Plugin.Interface.Data), message.FilterReason ?? string.Empty, sender, message.Content.TextValue)) { ImGui.OpenPopup($"###modal-message-{message.Id}"); } - if (message.FilterReason != null) { + if (message.Filtered) { ImGui.PopStyleColor(); } @@ -142,7 +151,7 @@ namespace NoSoliciting.Interface { var builder = new StringBuilder(); foreach (var message in this.Plugin.PartyFinderHistory) { - if (message.FilterReason == null) { + if (message.Classification == null) { continue; } @@ -165,7 +174,7 @@ namespace NoSoliciting.Interface { foreach (var message in this.Plugin.PartyFinderHistory) { ImGui.TableNextRow(); - if (message.FilterReason != null) { + if (message.Filtered) { ImGui.PushStyleColor(ImGuiCol.Text, new Vector4(238f / 255f, 71f / 255f, 71f / 255f, 1f)); } @@ -175,11 +184,11 @@ namespace NoSoliciting.Interface { .Select(payload => payload.Text) .FirstOrDefault() ?? ""; - if (AddRow(message.Timestamp.ToString(CultureInfo.CurrentCulture), message.FilterReason ?? "", sender, message.Content.TextValue)) { + if (AddRow(message.Timestamp.ToString(CultureInfo.CurrentCulture), message.FilterReason ?? string.Empty, sender, message.Content.TextValue)) { ImGui.OpenPopup($"###modal-message-{message.Id}"); } - if (message.FilterReason != null) { + if (message.Filtered) { ImGui.PopStyleColor(); } @@ -197,50 +206,129 @@ namespace NoSoliciting.Interface { #region Modal - private void SetUpReportModal(Message message) { + private MessageCategory? _reportCategory; + + /// + /// + /// + /// + /// true if modal is closing + private bool SetUpReportModal(Message message) { + var closing = false; + ImGui.SetNextWindowSize(new Vector2(350, -1)); var modalTitle = string.Format(Language.ReportModalTitle, this.Plugin.Name); if (!ImGui.BeginPopupModal($"{modalTitle}###modal-message-{message.Id}")) { - return; + return false; + } + + if (this._reportCategory == null) { + if (message.Classification != null) { + this._reportCategory = message.Classification; + } else if (message.Classification == null && !message.Custom && !message.ItemLevel) { + this._reportCategory = MessageCategory.Normal; + } } ImGui.PushTextWrapPos(); ImGui.TextUnformatted(Language.ReportModalHelp1); - ImGui.TextUnformatted(message.FilterReason != null - ? Language.ReportModalWasFiltered - : Language.ReportModalWasNotFiltered); - ImGui.Separator(); ImGui.TextUnformatted(message.Content.TextValue); ImGui.Separator(); + ImGui.TextUnformatted(string.Format(Language.ReportModalOriginalClassification, message.FilterReason ?? MessageCategory.Normal.Name())); + + ImGui.TextUnformatted(Language.ReportModalSuggestedClassification); + + ImGui.SetNextItemWidth(-1); + if (ImGui.BeginCombo($"##modal-classification-{message.Id}", this._reportCategory?.Name() ?? string.Empty)) { + foreach (var category in (MessageCategory[]) Enum.GetValues(typeof(MessageCategory))) { + if (ImGui.Selectable($"{category.Name()}##modal-option-{message.Id}", this._reportCategory == category)) { + this._reportCategory = category; + } + + if (!ImGui.IsItemHovered()) { + continue; + } + + ImGui.BeginTooltip(); + ImGui.PushTextWrapPos(ImGui.GetFontSize() * 24); + ImGui.TextUnformatted(category.Description()); + ImGui.PopTextWrapPos(); + ImGui.EndTooltip(); + } + + ImGui.EndCombo(); + } + + ImGui.Separator(); + ImGui.PushStyleColor(ImGuiCol.Text, new Vector4(1f, 0f, 0f, 1f)); ImGui.TextUnformatted(Language.ReportModalHelp2); ImGui.PopStyleColor(); ImGui.Separator(); - if (message.FilterReason == "custom") { + string? errorText = null; + if (message.Custom) { + errorText = Language.ReportModalDisabledCustom; + } else if (message.ItemLevel) { + errorText = Language.ReportModalDisabledItemLevel; + } else if (message.ModelVersion == null) { + errorText = Language.ReportModalDisabledBadModel; + } else if (this._reportCategory == message.Classification) { + errorText = Language.ReportModalDisabledSameClassification; + } else { + switch (this.Plugin.Config.AdvancedMode) { + case true when this.Plugin.Config.MlFilters.Values.All(set => set.Count == 0): + case false when this.Plugin.Config.BasicMlFilters.Count == 0: + errorText = Language.ReportModalDisabledNoFilters; + break; + } + } + + if (errorText != null) { ImGui.PushStyleColor(ImGuiCol.Text, new Vector4(1f, 0f, 0f, 1f)); - ImGui.TextUnformatted(Language.ReportModalCustom); + ImGui.TextUnformatted(errorText); ImGui.PopStyleColor(); } else { - var buttonTitle =Language.ReportModalReport; - if (ImGui.Button($"{buttonTitle}##report-submit-{message.Id}")) { - this.ReportMessage(message); + if (ImGui.Button($"{Language.ReportModalReport}##report-submit-{message.Id}")) { + var suggested = this._reportCategory?.ToModelName() ?? "none (this is a bug)"; + this._reportCategory = null; + if (message == this.ToShowModal) { + Task.Run(async () => { + var status = await this.Plugin.Ui.Report.ReportMessageAsync(message, suggested); + switch (status) { + case ReportStatus.Successful: { + var msg = Language.ReportToastSuccess; + this.Plugin.Interface.Framework.Gui.Toast.ShowNormal(string.Format(msg, message.Sender)); + break; + } + case ReportStatus.Failure: { + var msg = Language.ReportToastFailure; + this.Plugin.Interface.Framework.Gui.Toast.ShowError(string.Format(msg, message.Sender)); + break; + } + } + }); + this.ToShowModal = null; + } else { + this.ReportMessage(message, suggested); + } + ImGui.CloseCurrentPopup(); + closing = true; } ImGui.SameLine(); } - var copyButton = Language.ReportModalCopy; - if (ImGui.Button($"{copyButton}##report-copy-{message.Id}")) { + if (ImGui.Button($"{Language.ReportModalCopy}##report-copy-{message.Id}")) { ImGui.SetClipboardText(message.Content.TextValue); } @@ -255,12 +343,20 @@ namespace NoSoliciting.Interface { var cancelButton = Language.ReportModalCancel; if (ImGui.Button($"{cancelButton}##report-cancel-{message.Id}")) { + this._reportCategory = null; + if (message == this.ToShowModal) { + this.ToShowModal = null; + } + ImGui.CloseCurrentPopup(); + closing = true; } ImGui.PopTextWrapPos(); ImGui.EndPopup(); + + return closing; } #endregion @@ -292,18 +388,21 @@ namespace NoSoliciting.Interface { return clicked; } - internal void ReportMessage(Message message) { - Task.Run(async () => await this.ReportMessageAsync(message)); + private void ReportMessage(Message message, string suggested) { + Task.Run(async () => await this.ReportMessageAsync(message, suggested)); } - internal async Task ReportMessageAsync(Message message) { + private async Task ReportMessageAsync(Message message, string suggested) { string? resp = null; try { using var client = new WebClient(); this.LastReportStatus = ReportStatus.InProgress; var reportUrl = this.Plugin.MlFilter?.ReportUrl; if (reportUrl != null) { - resp = await client.UploadStringTaskAsync(reportUrl, message.ToJson()).ConfigureAwait(true); + var json = message.ToJson(suggested); + if (json != null) { + resp = await client.UploadStringTaskAsync(reportUrl, json).ConfigureAwait(true); + } } } catch (Exception) { // ignored diff --git a/NoSoliciting/Message.cs b/NoSoliciting/Message.cs index 6920b53..45610da 100644 --- a/NoSoliciting/Message.cs +++ b/NoSoliciting/Message.cs @@ -6,66 +6,87 @@ using System.Linq; using Dalamud.Data; using Dalamud.Game.Text; using Dalamud.Game.Text.SeStringHandling; -using Dalamud.Game.Text.SeStringHandling.Payloads; using Lumina.Excel.GeneratedSheets; +using NoSoliciting.Ml; + #if DEBUG using System.Text; -using NoSoliciting.Ml; #endif namespace NoSoliciting { [Serializable] public class Message { public Guid Id { get; } + [JsonIgnore] public uint ActorId { get; } - public uint DefinitionsVersion { get; } + + public uint? ModelVersion { get; } public DateTime Timestamp { get; } public ChatType ChatType { get; } public SeString Sender { get; } public SeString Content { get; } - public bool Ml { get; } - public string? FilterReason { get; } - public Message(uint defsVersion, ChatType type, uint actorId, SeString sender, SeString content, bool ml, string? reason) { + public MessageCategory? Classification { get; } + + public bool Custom { get; } + public bool ItemLevel { get; } + + public bool Filtered => this.Custom || this.ItemLevel || this.Classification != null; + + public string? FilterReason => this.Custom + ? "custom" + : this.ItemLevel + ? "ilvl" + : this.Classification?.Name(); + + internal Message(uint? defsVersion, ChatType type, uint actorId, SeString sender, SeString content, MessageCategory? classification, bool custom, bool ilvl) { this.Id = Guid.NewGuid(); - this.DefinitionsVersion = defsVersion; + this.ModelVersion = defsVersion; this.Timestamp = DateTime.Now; this.ChatType = type; this.ActorId = actorId; this.Sender = sender; this.Content = content; - this.Ml = ml; - this.FilterReason = reason; + this.Classification = classification; + this.Custom = custom; + this.ItemLevel = ilvl; } [Serializable] [JsonObject(NamingStrategyType = typeof(SnakeCaseNamingStrategy))] private class JsonMessage { - public Guid Id { get; set; } - public uint DefinitionsVersion { get; set; } + public uint ReportVersion { get; } = 2; + public uint ModelVersion { get; set; } public DateTime Timestamp { get; set; } public ushort Type { get; set; } // note: cannot use byte[] because Newtonsoft thinks it's a good idea to always base64 byte[] - // and I don't want to write a custom converter to overwrite their stupiditiy + // and I don't want to write a custom converter to overwrite their stupidity public List Sender { get; set; } public List Content { get; set; } - public bool Ml { get; set; } public string? Reason { get; set; } + public string? SuggestedClassification { get; set; } } - public string ToJson() { + public string? ToJson(string suggested) { + if (this.ModelVersion == null) { + return null; + } + var msg = new JsonMessage { - Id = this.Id, - DefinitionsVersion = this.DefinitionsVersion, + ModelVersion = this.ModelVersion.Value, Timestamp = this.Timestamp, Type = (ushort) this.ChatType, Sender = this.Sender.Encode().ToList(), Content = this.Content.Encode().ToList(), - Ml = this.Ml, - Reason = this.FilterReason, + Reason = this.Custom + ? "custom" + : this.ItemLevel + ? "ilvl" + : this.Classification?.ToModelName() ?? "unknown", + SuggestedClassification = suggested, }; return JsonConvert.SerializeObject(msg, new JsonSerializerSettings { @@ -77,9 +98,7 @@ namespace NoSoliciting { public StringBuilder ToCsv(StringBuilder? builder = null) { builder ??= new StringBuilder(); - var category = MessageCategoryExt.FromName(this.FilterReason) ?? MessageCategory.Normal; - - builder.Append(category.ToModelName()); + builder.Append(this.Classification?.ToModelName()); builder.Append(','); builder.Append((int) this.ChatType); builder.Append(",\""); diff --git a/NoSoliciting/Ml/Models.cs b/NoSoliciting/Ml/Models.cs index 188f589..34289fa 100644 --- a/NoSoliciting/Ml/Models.cs +++ b/NoSoliciting/Ml/Models.cs @@ -43,20 +43,6 @@ namespace NoSoliciting.Ml { }; #if DEBUG - public static string ToModelName(this MessageCategory category) => category switch { - MessageCategory.Trade => "TRADE", - MessageCategory.FreeCompany => "FC", - MessageCategory.Normal => "NORMAL", - MessageCategory.Phishing => "PHISH", - MessageCategory.RmtContent => "RMT_C", - MessageCategory.RmtGil => "RMT_G", - MessageCategory.Roleplaying => "RP", - MessageCategory.Static => "STATIC", - MessageCategory.Community => "COMMUNITY", - MessageCategory.StaticSub => "STATIC_SUB", - _ => throw new ArgumentException("Invalid category", nameof(category)), - }; - public static MessageCategory? FromName(string? category) => category switch { "Trade ads" => MessageCategory.Trade, "Free Company ads" => MessageCategory.FreeCompany, @@ -70,9 +56,22 @@ namespace NoSoliciting.Ml { "Static substitutes" => MessageCategory.StaticSub, _ => null, }; - #endif + public static string ToModelName(this MessageCategory category) => category switch { + MessageCategory.Trade => "TRADE", + MessageCategory.FreeCompany => "FC", + MessageCategory.Normal => "NORMAL", + MessageCategory.Phishing => "PHISH", + MessageCategory.RmtContent => "RMT_C", + MessageCategory.RmtGil => "RMT_G", + MessageCategory.Roleplaying => "RP", + MessageCategory.Static => "STATIC", + MessageCategory.Community => "COMMUNITY", + MessageCategory.StaticSub => "STATIC_SUB", + _ => throw new ArgumentException("Invalid category", nameof(category)), + }; + public static string Name(this MessageCategory category) => category switch { MessageCategory.Trade => Language.TradeCategory, MessageCategory.FreeCompany => Language.FreeCompanyCategory, diff --git a/NoSoliciting/NoSoliciting.csproj b/NoSoliciting/NoSoliciting.csproj index cb093ec..e14afcc 100755 --- a/NoSoliciting/NoSoliciting.csproj +++ b/NoSoliciting/NoSoliciting.csproj @@ -41,7 +41,7 @@ - + diff --git a/NoSoliciting/Resources/Language.Designer.cs b/NoSoliciting/Resources/Language.Designer.cs index 731d55b..7ae2d61 100755 --- a/NoSoliciting/Resources/Language.Designer.cs +++ b/NoSoliciting/Resources/Language.Designer.cs @@ -474,12 +474,48 @@ namespace NoSoliciting.Resources { } } + /// + /// Looks up a localized string similar to Reporting is disabled because your ML model was not functioning when you saw this message.. + /// + internal static string ReportModalDisabledBadModel { + get { + return ResourceManager.GetString("ReportModalDisabledBadModel", resourceCulture); + } + } + /// /// Looks up a localized string similar to You cannot report messages filtered because of a custom filter.. /// - internal static string ReportModalCustom { + internal static string ReportModalDisabledCustom { get { - return ResourceManager.GetString("ReportModalCustom", resourceCulture); + return ResourceManager.GetString("ReportModalDisabledCustom", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You cannot report messages filtered because of item level.. + /// + internal static string ReportModalDisabledItemLevel { + get { + return ResourceManager.GetString("ReportModalDisabledItemLevel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Reporting is disabled because you do not have any filters enabled.. + /// + internal static string ReportModalDisabledNoFilters { + get { + return ResourceManager.GetString("ReportModalDisabledNoFilters", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Reporting is disabled because you must choose a different classification than the original.. + /// + internal static string ReportModalDisabledSameClassification { + get { + return ResourceManager.GetString("ReportModalDisabledSameClassification", resourceCulture); } } @@ -501,6 +537,15 @@ namespace NoSoliciting.Resources { } } + /// + /// Looks up a localized string similar to This message's original classification: {0}. + /// + internal static string ReportModalOriginalClassification { + get { + return ResourceManager.GetString("ReportModalOriginalClassification", resourceCulture); + } + } + /// /// Looks up a localized string similar to Report. /// @@ -510,6 +555,15 @@ namespace NoSoliciting.Resources { } } + /// + /// Looks up a localized string similar to How do you think this message should have been classified?. + /// + internal static string ReportModalSuggestedClassification { + get { + return ResourceManager.GetString("ReportModalSuggestedClassification", resourceCulture); + } + } + /// /// Looks up a localized string similar to Report to {0}. /// diff --git a/NoSoliciting/Resources/Language.de.resx b/NoSoliciting/Resources/Language.de.resx index 2029657..c5bd924 100644 --- a/NoSoliciting/Resources/Language.de.resx +++ b/NoSoliciting/Resources/Language.de.resx @@ -132,7 +132,7 @@ Melden - + Du kannst Nachrichten, die aufgrund von benutzerdefinierten Filtern gefiltert wurden, nicht melden. diff --git a/NoSoliciting/Resources/Language.es.resx b/NoSoliciting/Resources/Language.es.resx index 0fae03e..c638fad 100644 --- a/NoSoliciting/Resources/Language.es.resx +++ b/NoSoliciting/Resources/Language.es.resx @@ -172,7 +172,7 @@ NoSoliciting sólo funciona con mensajes en inglés. No informes de mensajes en otros idiomas. - + No puedes informar de mensajes que han sido filtrados debido a un filtro personalizado. diff --git a/NoSoliciting/Resources/Language.fr.resx b/NoSoliciting/Resources/Language.fr.resx index e1f4a5d..776002a 100644 --- a/NoSoliciting/Resources/Language.fr.resx +++ b/NoSoliciting/Resources/Language.fr.resx @@ -219,7 +219,7 @@ NoSoliciting n'est fonctionnel que pour les messages en anglais. Veuillez ne pas signaler des messages qui ne sont pas en anglais. - + Vous ne pouvez pas signaler de messages filtrés à cause d'un filtre personnalisé. diff --git a/NoSoliciting/Resources/Language.ja.resx b/NoSoliciting/Resources/Language.ja.resx index 98e1efa..f020805 100644 --- a/NoSoliciting/Resources/Language.ja.resx +++ b/NoSoliciting/Resources/Language.ja.resx @@ -172,7 +172,7 @@ NoSolicitingは英語のメッセージにのみ有効です。 他の言語でメッセージを報告しないでください。 - + カスタムフィルタでフィルタリングされたメッセージを報告することはできません。 diff --git a/NoSoliciting/Resources/Language.pt-BR.resx b/NoSoliciting/Resources/Language.pt-BR.resx index a180f0e..1d77197 100644 --- a/NoSoliciting/Resources/Language.pt-BR.resx +++ b/NoSoliciting/Resources/Language.pt-BR.resx @@ -181,7 +181,7 @@ De maneira específica, essa mensagem NÃO FOI filtrada, mas deveria ter sido. - + Voçê não pode relatar as mensagens filtradas por causa de um filtro personalizado. diff --git a/NoSoliciting/Resources/Language.resx b/NoSoliciting/Resources/Language.resx index d1b4476..c7e7063 100755 --- a/NoSoliciting/Resources/Language.resx +++ b/NoSoliciting/Resources/Language.resx @@ -3,7 +3,7 @@ - + @@ -153,7 +153,7 @@ NoSoliciting only works for English messages. Do not report non-English messages. - + You cannot report messages filtered because of a custom filter. @@ -255,4 +255,22 @@ Initialised - \ No newline at end of file + + Reporting is disabled because your ML model was not functioning when you saw this message. + + + Reporting is disabled because you do not have any filters enabled. + + + Reporting is disabled because you must choose a different classification than the original. + + + You cannot report messages filtered because of item level. + + + This message's original classification: {0} + + + How do you think this message should have been classified? + + diff --git a/NoSoliciting/Resources/Language.zh-hans.resx b/NoSoliciting/Resources/Language.zh-hans.resx index d9e6bc8..043a019 100644 --- a/NoSoliciting/Resources/Language.zh-hans.resx +++ b/NoSoliciting/Resources/Language.zh-hans.resx @@ -175,7 +175,7 @@ 具体来说,这是一条应该被过滤的消息,但它被放过了。 - + 你不能报告被自定义过滤规则过滤的消息。 diff --git a/NoSoliciting/Resources/Language.zh-hant.resx b/NoSoliciting/Resources/Language.zh-hant.resx index d8136e0..e19ed4a 100644 --- a/NoSoliciting/Resources/Language.zh-hant.resx +++ b/NoSoliciting/Resources/Language.zh-hant.resx @@ -64,7 +64,7 @@ 報告此消息將使開發人員知道此消息被錯誤歸類。 - + 你不能報告被客製化過濾規則過濾的消息。