mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-10 17:28:27 -04:00
Nuked humanizer. Some of the strings might look worse but the output directory will no longer look terrible. Added stats for todo list command
This commit is contained in:
@@ -3,7 +3,6 @@ global using NonBlocking;
|
|||||||
|
|
||||||
// packages
|
// packages
|
||||||
global using Serilog;
|
global using Serilog;
|
||||||
global using Humanizer;
|
|
||||||
|
|
||||||
// nadekobot
|
// nadekobot
|
||||||
global using NadekoBot;
|
global using NadekoBot;
|
||||||
|
@@ -344,7 +344,7 @@ public sealed class SelfService : IExecNoCommand, IReadyExecutor, INService
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sr.GetContentLength() > 8.Megabytes().Bytes)
|
if (sr.GetContentLength() > 8.Megabytes())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
#nullable disable
|
#nullable disable
|
||||||
using CommandLine;
|
using CommandLine;
|
||||||
using Humanizer.Localisation;
|
|
||||||
using NadekoBot.Common.TypeReaders.Models;
|
using NadekoBot.Common.TypeReaders.Models;
|
||||||
using NadekoBot.Modules.Administration.Services;
|
using NadekoBot.Modules.Administration.Services;
|
||||||
using NadekoBot.Db.Models;
|
using NadekoBot.Db.Models;
|
||||||
@@ -458,7 +457,7 @@ public partial class Administration
|
|||||||
.AddField(GetText(strs.username), user?.ToString() ?? userId.ToString(), true)
|
.AddField(GetText(strs.username), user?.ToString() ?? userId.ToString(), true)
|
||||||
.AddField("ID", userId.ToString(), true)
|
.AddField("ID", userId.ToString(), true)
|
||||||
.AddField(GetText(strs.duration),
|
.AddField(GetText(strs.duration),
|
||||||
time.Time.Humanize(3, minUnit: TimeUnit.Minute, culture: Culture),
|
time.Time.ToPrettyStringHm(),
|
||||||
true);
|
true);
|
||||||
|
|
||||||
if (dmFailed)
|
if (dmFailed)
|
||||||
|
@@ -396,8 +396,8 @@ public partial class Gambling : GamblingModule<GamblingService>
|
|||||||
("rps", _, _) => $"Rock Paper Scissors - {subType}",
|
("rps", _, _) => $"Rock Paper Scissors - {subType}",
|
||||||
(null, _, _) => null,
|
(null, _, _) => null,
|
||||||
(_, null, _) => null,
|
(_, null, _) => null,
|
||||||
(_, _, ulong userId) => $"{type.Titleize()} - {subType.Titleize()} | [{userId}]",
|
(_, _, ulong userId) => $"{type} - {subType} | [{userId}]",
|
||||||
_ => $"{type.Titleize()} - {subType.Titleize()}"
|
_ => $"{type} - {subType}"
|
||||||
};
|
};
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
#nullable disable
|
#nullable disable
|
||||||
using Humanizer.Localisation;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using NadekoBot.Common.TypeReaders;
|
using NadekoBot.Common.TypeReaders;
|
||||||
using NadekoBot.Db;
|
using NadekoBot.Db;
|
||||||
@@ -81,7 +80,6 @@ public partial class Permissions
|
|||||||
if (--page < 0)
|
if (--page < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var channel = (ITextChannel)ctx.Channel;
|
|
||||||
var localSet = _service.GetCommandCooldowns(ctx.Guild.Id);
|
var localSet = _service.GetCommandCooldowns(ctx.Guild.Id);
|
||||||
|
|
||||||
if (!localSet.Any())
|
if (!localSet.Any())
|
||||||
@@ -96,7 +94,7 @@ public partial class Permissions
|
|||||||
.Page((items, _) =>
|
.Page((items, _) =>
|
||||||
{
|
{
|
||||||
var output = items.Select(x =>
|
var output = items.Select(x =>
|
||||||
$"{Format.Code(x.CommandName)}: {x.Seconds.Seconds().Humanize(maxUnit: TimeUnit.Second, culture: Culture)}");
|
$"{Format.Code(x.CommandName)}: {x.Seconds}s");
|
||||||
|
|
||||||
return _sender.CreateEmbed()
|
return _sender.CreateEmbed()
|
||||||
.WithOkColor()
|
.WithOkColor()
|
||||||
|
@@ -105,10 +105,7 @@ public sealed class DefaultStockDataService : IStockDataService, INService
|
|||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CsvConfiguration _csvConfig = new(CultureInfo.InvariantCulture)
|
private static CsvConfiguration _csvConfig = new(CultureInfo.InvariantCulture);
|
||||||
{
|
|
||||||
PrepareHeaderForMatch = args => args.Header.Humanize(LetterCasing.Title)
|
|
||||||
};
|
|
||||||
|
|
||||||
public async Task<IReadOnlyCollection<CandleData>> GetCandleDataAsync(string query)
|
public async Task<IReadOnlyCollection<CandleData>> GetCandleDataAsync(string query)
|
||||||
{
|
{
|
||||||
|
@@ -1,9 +1,7 @@
|
|||||||
#nullable disable
|
#nullable disable
|
||||||
using Humanizer.Localisation;
|
|
||||||
using NadekoBot.Db;
|
using NadekoBot.Db;
|
||||||
using NadekoBot.Modules.Utility.Services;
|
using NadekoBot.Modules.Utility.Services;
|
||||||
using NadekoBot.Db.Models;
|
using NadekoBot.Db.Models;
|
||||||
using System.Resources;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Utility;
|
namespace NadekoBot.Modules.Utility;
|
||||||
|
|
||||||
@@ -118,7 +116,7 @@ public partial class Utility
|
|||||||
var diff = when - DateTime.UtcNow;
|
var diff = when - DateTime.UtcNow;
|
||||||
embed.AddField(
|
embed.AddField(
|
||||||
$"#{++i + (page * 10)} {rem.When:HH:mm yyyy-MM-dd} UTC "
|
$"#{++i + (page * 10)} {rem.When:HH:mm yyyy-MM-dd} UTC "
|
||||||
+ $"(in {diff.Humanize(2, minUnit: TimeUnit.Minute, culture: Culture)})",
|
+ $"(in {diff.ToPrettyStringHm()})",
|
||||||
$@"`Target:` {(rem.IsPrivate ? "DM" : "Channel")}
|
$@"`Target:` {(rem.IsPrivate ? "DM" : "Channel")}
|
||||||
`TargetId:` {rem.ChannelId}
|
`TargetId:` {rem.ChannelId}
|
||||||
`Message:` {rem.Message?.TrimTo(50)}");
|
`Message:` {rem.Message?.TrimTo(50)}");
|
||||||
@@ -212,7 +210,7 @@ public partial class Utility
|
|||||||
.Confirm($"\u23f0 {GetText(strs.remind(
|
.Confirm($"\u23f0 {GetText(strs.remind(
|
||||||
Format.Bold(!isPrivate ? $"<#{targetId}>" : ctx.User.Username),
|
Format.Bold(!isPrivate ? $"<#{targetId}>" : ctx.User.Username),
|
||||||
Format.Bold(message),
|
Format.Bold(message),
|
||||||
ts.Humanize(3, minUnit: TimeUnit.Second, culture: Culture),
|
ts.ToPrettyStringHm(),
|
||||||
gTime,
|
gTime,
|
||||||
gTime))}")
|
gTime))}")
|
||||||
.SendAsync();
|
.SendAsync();
|
||||||
|
@@ -11,8 +11,7 @@ namespace NadekoBot.Modules.Utility.Services;
|
|||||||
public class RemindService : INService, IReadyExecutor, IRemindService
|
public class RemindService : INService, IReadyExecutor, IRemindService
|
||||||
{
|
{
|
||||||
private readonly Regex _regex =
|
private readonly Regex _regex =
|
||||||
new(
|
new(@"^(?:(?:at|on(?:\sthe)?)?\s*(?<date>(?:\d{2}:\d{2}\s)?\d{1,2}\.\d{1,2}(?:\.\d{2,4})?)|(?:in\s?)?\s*(?:(?<mo>\d+)(?:\s?(?:months?|mos?),?))?(?:(?:\sand\s|\s*)?(?<w>\d+)(?:\s?(?:weeks?|w),?))?(?:(?:\sand\s|\s*)?(?<d>\d+)(?:\s?(?:days?|d),?))?(?:(?:\sand\s|\s*)?(?<h>\d+)(?:\s?(?:hours?|h),?))?(?:(?:\sand\s|\s*)?(?<m>\d+)(?:\s?(?:minutes?|mins?|m),?))?)\s+(?:to:?\s+)?(?<what>(?:\r\n|[\r\n]|.)+)",
|
||||||
@"^(?:(?:at|on(?:\sthe)?)?\s*(?<date>(?:\d{2}:\d{2}\s)?\d{1,2}\.\d{1,2}(?:\.\d{2,4})?)|(?:in\s?)?\s*(?:(?<mo>\d+)(?:\s?(?:months?|mos?),?))?(?:(?:\sand\s|\s*)?(?<w>\d+)(?:\s?(?:weeks?|w),?))?(?:(?:\sand\s|\s*)?(?<d>\d+)(?:\s?(?:days?|d),?))?(?:(?:\sand\s|\s*)?(?<h>\d+)(?:\s?(?:hours?|h),?))?(?:(?:\sand\s|\s*)?(?<m>\d+)(?:\s?(?:minutes?|mins?|m),?))?)\s+(?:to:?\s+)?(?<what>(?:\r\n|[\r\n]|.)+)",
|
|
||||||
RegexOptions.Compiled | RegexOptions.Multiline);
|
RegexOptions.Compiled | RegexOptions.Multiline);
|
||||||
|
|
||||||
private readonly DiscordSocketClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
|
@@ -44,7 +44,26 @@ public partial class Utility
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await ShowTodosAsync(todos);
|
await Response()
|
||||||
|
.Paginated()
|
||||||
|
.Items(todos)
|
||||||
|
.PageSize(9)
|
||||||
|
.AddFooter(false)
|
||||||
|
.Page((items, _) =>
|
||||||
|
{
|
||||||
|
var eb = _sender.CreateEmbed()
|
||||||
|
.WithOkColor()
|
||||||
|
.WithTitle(GetText(strs.todo_list));
|
||||||
|
|
||||||
|
ShowTodoItem(items, eb);
|
||||||
|
|
||||||
|
eb.WithFooter(GetText(strs.todo_stats(todos.Length,
|
||||||
|
todos.Count(x => x.IsDone),
|
||||||
|
todos.Count(x => !x.IsDone))));
|
||||||
|
|
||||||
|
return eb;
|
||||||
|
})
|
||||||
|
.SendAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -81,23 +100,6 @@ public partial class Utility
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private Task ShowTodosAsync(TodoModel[] todos)
|
|
||||||
=> Response()
|
|
||||||
.Paginated()
|
|
||||||
.Items(todos)
|
|
||||||
.PageSize(9)
|
|
||||||
.Page((items, _) =>
|
|
||||||
{
|
|
||||||
var eb = _sender.CreateEmbed()
|
|
||||||
.WithOkColor()
|
|
||||||
.WithTitle(GetText(strs.todo_list));
|
|
||||||
|
|
||||||
ShowTodoItem(items, eb);
|
|
||||||
|
|
||||||
return eb;
|
|
||||||
})
|
|
||||||
.SendAsync();
|
|
||||||
|
|
||||||
private static void ShowTodoItem(IReadOnlyCollection<TodoModel> todos, EmbedBuilder eb)
|
private static void ShowTodoItem(IReadOnlyCollection<TodoModel> todos, EmbedBuilder eb)
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
@@ -182,14 +184,19 @@ public partial class Utility
|
|||||||
.Paginated()
|
.Paginated()
|
||||||
.Items(list.Items)
|
.Items(list.Items)
|
||||||
.PageSize(9)
|
.PageSize(9)
|
||||||
|
.AddFooter(false)
|
||||||
.Page((items, _) =>
|
.Page((items, _) =>
|
||||||
{
|
{
|
||||||
var eb = _sender.CreateEmbed()
|
var eb = _sender.CreateEmbed()
|
||||||
.WithOkColor()
|
.WithOkColor()
|
||||||
.WithTitle(GetText(strs.todo_list));
|
.WithTitle(GetText(strs.todo_archived_list));
|
||||||
|
|
||||||
ShowTodoItem(items, eb);
|
ShowTodoItem(items, eb);
|
||||||
|
|
||||||
|
eb.WithFooter(GetText(strs.todo_stats(list.Items.Count,
|
||||||
|
list.Items.Count(x => x.IsDone),
|
||||||
|
list.Items.Count(x => !x.IsDone))));
|
||||||
|
|
||||||
return eb;
|
return eb;
|
||||||
})
|
})
|
||||||
.SendAsync();
|
.SendAsync();
|
||||||
|
@@ -110,7 +110,7 @@ public class ClubService : INService, IClubService
|
|||||||
if (!temp.IsImage())
|
if (!temp.IsImage())
|
||||||
return SetClubIconResult.InvalidFileType;
|
return SetClubIconResult.InvalidFileType;
|
||||||
|
|
||||||
if (temp.GetContentLength() > 5.Megabytes().Bytes)
|
if (temp.GetContentLength() > 5.Megabytes())
|
||||||
return SetClubIconResult.TooLarge;
|
return SetClubIconResult.TooLarge;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -127,7 +127,7 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand
|
|||||||
{
|
{
|
||||||
_ = Task.Run(() => _levelUpQueue.RunAsync());
|
_ = Task.Run(() => _levelUpQueue.RunAsync());
|
||||||
|
|
||||||
using var timer = new PeriodicTimer(5.Seconds());
|
using var timer = new PeriodicTimer(TimeSpan.FromSeconds(5));
|
||||||
while (await timer.WaitForNextTickAsync())
|
while (await timer.WaitForNextTickAsync())
|
||||||
{
|
{
|
||||||
await UpdateXp();
|
await UpdateXp();
|
||||||
@@ -1364,7 +1364,7 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand
|
|||||||
using (var http = _httpFactory.CreateClient())
|
using (var http = _httpFactory.CreateClient())
|
||||||
using (var temp = await http.GetAsync(imgUrl, HttpCompletionOption.ResponseHeadersRead))
|
using (var temp = await http.GetAsync(imgUrl, HttpCompletionOption.ResponseHeadersRead))
|
||||||
{
|
{
|
||||||
if (!temp.IsImage() || temp.GetContentLength() > 11.Megabytes().Bytes)
|
if (!temp.IsImage() || temp.GetContentLength() > 11 * 1024 * 1024)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var imgData = await temp.Content.ReadAsByteArrayAsync();
|
var imgData = await temp.Content.ReadAsByteArrayAsync();
|
||||||
|
@@ -77,11 +77,6 @@
|
|||||||
<PackageReference Include="YamlDotNet" Version="15.1.2" />
|
<PackageReference Include="YamlDotNet" Version="15.1.2" />
|
||||||
<PackageReference Include="SharpToken" Version="2.0.2" />
|
<PackageReference Include="SharpToken" Version="2.0.2" />
|
||||||
|
|
||||||
<PackageReference Include="Humanizer" Version="2.14.1">
|
|
||||||
<PrivateAssets>all</PrivateAssets>
|
|
||||||
<Publish>True</Publish>
|
|
||||||
</PackageReference>
|
|
||||||
|
|
||||||
<PackageReference Include="JetBrains.Annotations" Version="2023.3.0" />
|
<PackageReference Include="JetBrains.Annotations" Version="2023.3.0" />
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,6 +1,3 @@
|
|||||||
using Humanizer.Localisation;
|
|
||||||
using System.Resources;
|
|
||||||
|
|
||||||
var pid = Environment.ProcessId;
|
var pid = Environment.ProcessId;
|
||||||
|
|
||||||
var shardId = 0;
|
var shardId = 0;
|
||||||
|
@@ -35,7 +35,7 @@ public sealed class ImageCache : IImageCache, INService
|
|||||||
var bytes = await http.GetByteArrayAsync(url);
|
var bytes = await http.GetByteArrayAsync(url);
|
||||||
return bytes;
|
return bytes;
|
||||||
},
|
},
|
||||||
expiry: 48.Hours());
|
expiry: TimeSpan.FromHours(48));
|
||||||
|
|
||||||
private async Task<byte[]?> GetRandomImageDataAsync(Uri[] urls)
|
private async Task<byte[]?> GetRandomImageDataAsync(Uri[] urls)
|
||||||
{
|
{
|
||||||
|
@@ -29,7 +29,17 @@ public static class StringExtensions
|
|||||||
=> Regex.Replace(input, "<.*?>", string.Empty);
|
=> Regex.Replace(input, "<.*?>", string.Empty);
|
||||||
|
|
||||||
public static string? TrimTo(this string? str, int maxLength, bool hideDots = false)
|
public static string? TrimTo(this string? str, int maxLength, bool hideDots = false)
|
||||||
=> hideDots ? str?.Truncate(maxLength, string.Empty) : str?.Truncate(maxLength);
|
{
|
||||||
|
if (hideDots)
|
||||||
|
{
|
||||||
|
return str?.Substring(0, maxLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str is null || str.Length <= maxLength)
|
||||||
|
return str;
|
||||||
|
|
||||||
|
return string.Concat(str.AsSpan(0, maxLength - 1), "…");
|
||||||
|
}
|
||||||
|
|
||||||
public static string ToTitleCase(this string str)
|
public static string ToTitleCase(this string str)
|
||||||
{
|
{
|
||||||
|
@@ -9,7 +9,13 @@ public static class PatronExtensions
|
|||||||
};
|
};
|
||||||
|
|
||||||
public static string ToFullName(this QuotaPer per)
|
public static string ToFullName(this QuotaPer per)
|
||||||
=> per.Humanize(LetterCasing.LowerCase);
|
=> per switch
|
||||||
|
{
|
||||||
|
QuotaPer.PerDay => "per day",
|
||||||
|
QuotaPer.PerHour => "per hour",
|
||||||
|
QuotaPer.PerMonth => "per month",
|
||||||
|
_ => "Unknown",
|
||||||
|
};
|
||||||
|
|
||||||
public static DateTime DayOfNextMonth(this DateTime date, int day)
|
public static DateTime DayOfNextMonth(this DateTime date, int day)
|
||||||
{
|
{
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
#nullable disable
|
#nullable disable
|
||||||
using Humanizer.Localisation;
|
|
||||||
using NadekoBot.Common.ModuleBehaviors;
|
using NadekoBot.Common.ModuleBehaviors;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
@@ -178,13 +177,23 @@ public sealed class StatsService : IStatsService, IReadyExecutor, INService
|
|||||||
public string GetUptimeString(string separator = ", ")
|
public string GetUptimeString(string separator = ", ")
|
||||||
{
|
{
|
||||||
var time = GetUptime();
|
var time = GetUptime();
|
||||||
return time.Humanize(3, maxUnit: TimeUnit.Day, minUnit: TimeUnit.Minute);
|
|
||||||
|
if (time.Days > 0)
|
||||||
|
return $"{time.Days}d {time.Hours}h {time.Minutes}m";
|
||||||
|
|
||||||
|
if (time.Hours > 0)
|
||||||
|
return $"{time.Hours}h {time.Minutes}m";
|
||||||
|
|
||||||
|
if (time.Minutes > 0)
|
||||||
|
return $"{time.Minutes}m {time.Seconds}s";
|
||||||
|
|
||||||
|
return $"{time.Seconds}s";
|
||||||
}
|
}
|
||||||
|
|
||||||
public double GetPrivateMemoryMegabytes()
|
public double GetPrivateMemoryMegabytes()
|
||||||
{
|
{
|
||||||
_currentProcess.Refresh();
|
_currentProcess.Refresh();
|
||||||
return _currentProcess.PrivateMemorySize64 / 1.Megabytes().Bytes;
|
return _currentProcess.PrivateMemorySize64 / 1.Megabytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
public GuildInfo GetGuildInfo(string name)
|
public GuildInfo GetGuildInfo(string name)
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
using Humanizer.Localisation;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
@@ -60,7 +59,30 @@ public static class Extensions
|
|||||||
/// <param name="span">Timespan to convert to string</param>
|
/// <param name="span">Timespan to convert to string</param>
|
||||||
/// <returns>Formatted duration string</returns>
|
/// <returns>Formatted duration string</returns>
|
||||||
public static string ToPrettyStringHm(this TimeSpan span)
|
public static string ToPrettyStringHm(this TimeSpan span)
|
||||||
=> span.Humanize(2, minUnit: TimeUnit.Second);
|
{
|
||||||
|
if(span > TimeSpan.FromHours(24))
|
||||||
|
return $"{span.Days:00}d:{span.Hours:00}h";
|
||||||
|
|
||||||
|
if (span > TimeSpan.FromMinutes(2))
|
||||||
|
return $"{span.Hours:00}h:{span.Minutes:00}m";
|
||||||
|
|
||||||
|
return $"{span.Minutes:00}m:{span.Seconds:00}s";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double Megabytes(this int mb)
|
||||||
|
=> mb * 1024d * 1024;
|
||||||
|
|
||||||
|
public static TimeSpan Hours(this int hours)
|
||||||
|
=> TimeSpan.FromHours(hours);
|
||||||
|
|
||||||
|
public static TimeSpan Minutes(this int minutes)
|
||||||
|
=> TimeSpan.FromMinutes(minutes);
|
||||||
|
|
||||||
|
public static TimeSpan Days(this int days)
|
||||||
|
=> TimeSpan.FromDays(days);
|
||||||
|
|
||||||
|
public static TimeSpan Seconds(this int seconds)
|
||||||
|
=> TimeSpan.FromSeconds(seconds);
|
||||||
|
|
||||||
public static bool TryGetUrlPath(this string input, out string path)
|
public static bool TryGetUrlPath(this string input, out string path)
|
||||||
{
|
{
|
||||||
|
@@ -1080,12 +1080,14 @@
|
|||||||
"giveaway_list": "List of active giveways",
|
"giveaway_list": "List of active giveways",
|
||||||
"todo_list_empty": "Your todo list is empty." ,
|
"todo_list_empty": "Your todo list is empty." ,
|
||||||
"todo_list": "Todo List",
|
"todo_list": "Todo List",
|
||||||
"todo_add_max_limit": "You've reached the maximum amount of todos you can have.",
|
"todo_stats": "{0} items | {1} completed | {2} remaining",
|
||||||
|
"todo_add_max_limit": "You'reached the maximum amount of todos you can have.",
|
||||||
"todo_not_found": "Todo not found.",
|
"todo_not_found": "Todo not found.",
|
||||||
"todo_cleared": "All unarchived todos have been cleared.",
|
"todo_cleared": "All unarchived todos have been cleared.",
|
||||||
"todo_no_todos": "There are no todos in your todo list.",
|
"todo_no_todos": "There are no todos in your todo list.",
|
||||||
"todo_archive_max_limit": "You've reached the maximum amount of archived todos you can have.",
|
"todo_archive_max_limit": "You've reached the maximum amount of archived todos you can have.",
|
||||||
"todo_archive_empty": "You have no archived todos.",
|
"todo_archive_empty": "You have no archived todos.",
|
||||||
"todo_archive_list": "Archived Todo Lists",
|
"todo_archive_list": "Archived Todo Lists",
|
||||||
"todo_archive_not_found": "Archived todo list not found."
|
"todo_archive_not_found": "Archived todo list not found.",
|
||||||
|
"todo_archived_list": "Archived Todo List"
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user