mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2024-12-29 12:37:40 +01:00
Implement localisation for displaying durations
This commit is contained in:
parent
ab0e25a56d
commit
ad174742e9
@ -339,7 +339,7 @@ public class LoggedAction implements Action {
|
||||
parts.add(context.getKey() + "=" + context.getValue());
|
||||
}
|
||||
} else if (o instanceof Duration) {
|
||||
parts.add(DurationFormatter.CONCISE.format((Duration) o));
|
||||
parts.add(DurationFormatter.CONCISE.formatString((Duration) o));
|
||||
} else {
|
||||
parts.add(String.valueOf(o));
|
||||
}
|
||||
|
@ -776,7 +776,7 @@ public interface Message {
|
||||
.key("luckperms.command.generic.info.expires-in")
|
||||
.color(GRAY)
|
||||
.append(space())
|
||||
.append(text(DurationFormatter.LONG.format(node.getExpiryDuration())))
|
||||
.append(DurationFormatter.LONG.format(node.getExpiryDuration()))
|
||||
)
|
||||
.append(CLOSE_BRACKET)
|
||||
);
|
||||
@ -820,7 +820,7 @@ public interface Message {
|
||||
.key("luckperms.command.generic.info.expires-in")
|
||||
.color(GRAY)
|
||||
.append(space())
|
||||
.append(text(DurationFormatter.LONG.format(node.getExpiryDuration())))
|
||||
.append(DurationFormatter.LONG.format(node.getExpiryDuration()))
|
||||
)
|
||||
.append(CLOSE_BRACKET)
|
||||
);
|
||||
@ -966,7 +966,7 @@ public interface Message {
|
||||
builder.append(text()
|
||||
.color(GRAY)
|
||||
.append(OPEN_BRACKET)
|
||||
.append(text(DurationFormatter.CONCISE.format(node.getExpiryDuration())))
|
||||
.append(DurationFormatter.CONCISE.format(node.getExpiryDuration()))
|
||||
.append(CLOSE_BRACKET)
|
||||
);
|
||||
}
|
||||
@ -1456,7 +1456,7 @@ public interface Message {
|
||||
.append(text(" "))
|
||||
.append(translatable("luckperms.command.info.uptime-key"))
|
||||
.append(text(": "))
|
||||
.append(text(DurationFormatter.CONCISE_LOW_ACCURACY.format(Duration.between(plugin.getBootstrap().getStartupTime(), Instant.now())), GRAY))),
|
||||
.append(text().color(GRAY).append(DurationFormatter.CONCISE_LOW_ACCURACY.format(Duration.between(plugin.getBootstrap().getStartupTime(), Instant.now()))))),
|
||||
prefixed(text()
|
||||
.color(DARK_AQUA)
|
||||
.append(text(" "))
|
||||
@ -1621,7 +1621,7 @@ public interface Message {
|
||||
.append(text("- "))
|
||||
.append(translatable("luckperms.command.generic.info.expires-in"))
|
||||
.append(space())
|
||||
.append(text(DurationFormatter.LONG.format(node.getExpiryDuration())))
|
||||
.append(DurationFormatter.LONG.format(node.getExpiryDuration()))
|
||||
.build()
|
||||
);
|
||||
|
||||
@ -1726,7 +1726,7 @@ public interface Message {
|
||||
.append(text("- "))
|
||||
.append(translatable("luckperms.command.generic.info.expires-in"))
|
||||
.append(space())
|
||||
.append(text(DurationFormatter.LONG.format(node.getExpiryDuration())))
|
||||
.append(DurationFormatter.LONG.format(node.getExpiryDuration()))
|
||||
.build()
|
||||
);
|
||||
|
||||
@ -1822,7 +1822,7 @@ public interface Message {
|
||||
text(permission, AQUA),
|
||||
text(value, AQUA),
|
||||
text().color(AQUA).append(holder.getFormattedDisplayName()),
|
||||
text(DurationFormatter.LONG.format(duration), AQUA),
|
||||
text().color(AQUA).append(DurationFormatter.LONG.format(duration)),
|
||||
formatContextSet(context)
|
||||
)
|
||||
.append(FULL_STOP)
|
||||
@ -1884,9 +1884,9 @@ public interface Message {
|
||||
text(permission, AQUA),
|
||||
text(value, AQUA),
|
||||
text().color(AQUA).append(holder.getFormattedDisplayName()),
|
||||
text(DurationFormatter.LONG.format(duration), AQUA),
|
||||
text().color(AQUA).append(DurationFormatter.LONG.format(duration)),
|
||||
formatContextSet(context),
|
||||
text(DurationFormatter.LONG.format(durationLess), AQUA)
|
||||
text().color(AQUA).append(DurationFormatter.LONG.format(durationLess))
|
||||
)
|
||||
.append(FULL_STOP)
|
||||
);
|
||||
@ -1922,7 +1922,7 @@ public interface Message {
|
||||
.args(
|
||||
text().color(AQUA).append(holder.getFormattedDisplayName()),
|
||||
text().color(AQUA).append(parent.getFormattedDisplayName()),
|
||||
text(DurationFormatter.LONG.format(duration), AQUA),
|
||||
text().color(AQUA).append(DurationFormatter.LONG.format(duration)),
|
||||
formatContextSet(context)
|
||||
)
|
||||
.append(FULL_STOP)
|
||||
@ -1984,9 +1984,9 @@ public interface Message {
|
||||
.args(
|
||||
text().color(AQUA).append(holder.getFormattedDisplayName()),
|
||||
text().color(AQUA).append(parent),
|
||||
text(DurationFormatter.LONG.format(duration), AQUA),
|
||||
text().color(AQUA).append(DurationFormatter.LONG.format(duration)),
|
||||
formatContextSet(context),
|
||||
text(DurationFormatter.LONG.format(durationLess), AQUA)
|
||||
text().color(AQUA).append(DurationFormatter.LONG.format(durationLess))
|
||||
)
|
||||
.append(FULL_STOP)
|
||||
);
|
||||
@ -2155,7 +2155,7 @@ public interface Message {
|
||||
.key("luckperms.command.generic.info.expires-in")
|
||||
.color(GRAY)
|
||||
.append(space())
|
||||
.append(text(DurationFormatter.CONCISE.format(node.getExpiryDuration()), AQUA))
|
||||
.append(text().color(AQUA).append(DurationFormatter.CONCISE.format(node.getExpiryDuration())))
|
||||
)
|
||||
.append(CLOSE_BRACKET)
|
||||
);
|
||||
@ -2223,7 +2223,7 @@ public interface Message {
|
||||
.key("luckperms.command.generic.info.expires-in")
|
||||
.color(GRAY)
|
||||
.append(space())
|
||||
.append(text(DurationFormatter.CONCISE.format(node.getExpiryDuration()), AQUA))
|
||||
.append(text().color(AQUA).append(DurationFormatter.CONCISE.format(node.getExpiryDuration())))
|
||||
)
|
||||
.append(CLOSE_BRACKET)
|
||||
);
|
||||
@ -2388,7 +2388,7 @@ public interface Message {
|
||||
text(type.toString()),
|
||||
text().color(WHITE).append(text('\'')).append(formatColoredValue(value)).append(text('\'')),
|
||||
text(priority, AQUA),
|
||||
text(DurationFormatter.LONG.format(duration), AQUA),
|
||||
text().color(AQUA).append(DurationFormatter.LONG.format(duration)),
|
||||
formatContextSet(context)
|
||||
)
|
||||
.append(FULL_STOP)
|
||||
@ -2519,7 +2519,7 @@ public interface Message {
|
||||
text().color(WHITE).append(text('\'')).append(text(key)).append(text('\'')),
|
||||
text().color(WHITE).append(text('\'')).append(formatColoredValue(value)).append(text('\'')),
|
||||
text().color(AQUA).append(holder.getFormattedDisplayName()),
|
||||
text(DurationFormatter.LONG.format(duration), AQUA),
|
||||
text().color(AQUA).append(DurationFormatter.LONG.format(duration)),
|
||||
formatContextSet(context)
|
||||
)
|
||||
.append(FULL_STOP)
|
||||
@ -2927,7 +2927,7 @@ public interface Message {
|
||||
.append(text(" - "))
|
||||
.append(translatable("luckperms.command.generic.info.expires-in"))
|
||||
.append(space())
|
||||
.append(text(DurationFormatter.LONG.format(node.getExpiryDuration()))))
|
||||
.append(DurationFormatter.LONG.format(node.getExpiryDuration())))
|
||||
);
|
||||
|
||||
Args0 USER_REMOVEGROUP_ERROR_PRIMARY = () -> prefixed(translatable()
|
||||
@ -3385,9 +3385,10 @@ public interface Message {
|
||||
.append(text()
|
||||
.color(DARK_GRAY)
|
||||
.append(OPEN_BRACKET)
|
||||
.append(text()
|
||||
.content(DurationFormatter.CONCISE_LOW_ACCURACY.format(action.getDurationSince()) + " ago")
|
||||
.append(translatable()
|
||||
.color(GRAY)
|
||||
.key("luckperms.duration.since")
|
||||
.args(DurationFormatter.CONCISE_LOW_ACCURACY.format(action.getDurationSince()))
|
||||
)
|
||||
.append(CLOSE_BRACKET)
|
||||
)
|
||||
|
@ -25,54 +25,43 @@
|
||||
|
||||
package me.lucko.luckperms.common.util;
|
||||
|
||||
import me.lucko.luckperms.common.locale.TranslationManager;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.TranslatableComponent;
|
||||
import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
|
||||
/**
|
||||
* Formats durations to a readable form
|
||||
*/
|
||||
public enum DurationFormatter {
|
||||
LONG,
|
||||
CONCISE {
|
||||
@Override
|
||||
protected String formatUnitPlural(ChronoUnit unit) {
|
||||
return String.valueOf(Character.toLowerCase(unit.name().charAt(0)));
|
||||
}
|
||||
public class DurationFormatter {
|
||||
public static final DurationFormatter LONG = new DurationFormatter(false);
|
||||
public static final DurationFormatter CONCISE = new DurationFormatter(true);
|
||||
public static final DurationFormatter CONCISE_LOW_ACCURACY = new DurationFormatter(true, 3);
|
||||
|
||||
@Override
|
||||
protected String formatUnitSingular(ChronoUnit unit) {
|
||||
return formatUnitPlural(unit);
|
||||
}
|
||||
},
|
||||
CONCISE_LOW_ACCURACY(3) {
|
||||
@Override
|
||||
protected String formatUnitPlural(ChronoUnit unit) {
|
||||
return String.valueOf(Character.toLowerCase(unit.name().charAt(0)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String formatUnitSingular(ChronoUnit unit) {
|
||||
return formatUnitPlural(unit);
|
||||
}
|
||||
};
|
||||
|
||||
private final Unit[] units = new Unit[]{
|
||||
new Unit(ChronoUnit.YEARS),
|
||||
new Unit(ChronoUnit.MONTHS),
|
||||
new Unit(ChronoUnit.WEEKS),
|
||||
new Unit(ChronoUnit.DAYS),
|
||||
new Unit(ChronoUnit.HOURS),
|
||||
new Unit(ChronoUnit.MINUTES),
|
||||
new Unit(ChronoUnit.SECONDS)
|
||||
private static final ChronoUnit[] UNITS = new ChronoUnit[]{
|
||||
ChronoUnit.YEARS,
|
||||
ChronoUnit.MONTHS,
|
||||
ChronoUnit.WEEKS,
|
||||
ChronoUnit.DAYS,
|
||||
ChronoUnit.HOURS,
|
||||
ChronoUnit.MINUTES,
|
||||
ChronoUnit.SECONDS
|
||||
};
|
||||
|
||||
private final boolean concise;
|
||||
private final int accuracy;
|
||||
|
||||
DurationFormatter() {
|
||||
this(Integer.MAX_VALUE);
|
||||
public DurationFormatter(boolean concise) {
|
||||
this(concise, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
DurationFormatter(int accuracy) {
|
||||
public DurationFormatter(boolean concise, int accuracy) {
|
||||
this.concise = concise;
|
||||
this.accuracy = accuracy;
|
||||
}
|
||||
|
||||
@ -82,16 +71,29 @@ public enum DurationFormatter {
|
||||
* @param duration the duration
|
||||
* @return the formatted string
|
||||
*/
|
||||
public String format(Duration duration) {
|
||||
public String formatString(Duration duration) {
|
||||
return PlainComponentSerializer.plain().serialize(TranslationManager.render(format(duration)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats {@code duration} as a {@link Component}.
|
||||
*
|
||||
* @param duration the duration
|
||||
* @return the formatted component
|
||||
*/
|
||||
public Component format(Duration duration) {
|
||||
long seconds = duration.getSeconds();
|
||||
StringBuilder output = new StringBuilder();
|
||||
TextComponent.Builder builder = Component.text();
|
||||
int outputSize = 0;
|
||||
|
||||
for (Unit unit : this.units) {
|
||||
long n = seconds / unit.duration;
|
||||
for (ChronoUnit unit : UNITS) {
|
||||
long n = seconds / unit.getDuration().getSeconds();
|
||||
if (n > 0) {
|
||||
seconds -= unit.duration * n;
|
||||
output.append(' ').append(n).append(unit.toString(n));
|
||||
seconds -= unit.getDuration().getSeconds() * n;
|
||||
if (outputSize != 0) {
|
||||
builder.append(Component.space());
|
||||
}
|
||||
builder.append(formatPart(n, unit));
|
||||
outputSize++;
|
||||
}
|
||||
if (seconds <= 0 || outputSize >= this.accuracy) {
|
||||
@ -99,35 +101,22 @@ public enum DurationFormatter {
|
||||
}
|
||||
}
|
||||
|
||||
if (output.length() == 0) {
|
||||
return "0" + this.units[this.units.length - 1].stringPlural;
|
||||
if (outputSize == 0) {
|
||||
return formatPart(0, ChronoUnit.SECONDS);
|
||||
}
|
||||
return output.substring(1);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
protected String formatUnitPlural(ChronoUnit unit) {
|
||||
return " " + unit.name().toLowerCase();
|
||||
}
|
||||
// Translation keys are in the format:
|
||||
// luckperms.duration.unit.years.plural={0} years
|
||||
// luckperms.duration.unit.years.singular={0} year
|
||||
// luckperms.duration.unit.years.short={0}y
|
||||
// ... and so on
|
||||
|
||||
protected String formatUnitSingular(ChronoUnit unit) {
|
||||
String s = unit.name().toLowerCase();
|
||||
return " " + s.substring(0, s.length() - 1);
|
||||
}
|
||||
|
||||
private final class Unit {
|
||||
private final long duration;
|
||||
private final String stringPlural;
|
||||
private final String stringSingular;
|
||||
|
||||
Unit(ChronoUnit unit) {
|
||||
this.duration = unit.getDuration().getSeconds();
|
||||
this.stringPlural = formatUnitPlural(unit);
|
||||
this.stringSingular = formatUnitSingular(unit);
|
||||
}
|
||||
|
||||
public String toString(long n) {
|
||||
return n == 1 ? this.stringSingular : this.stringPlural;
|
||||
}
|
||||
private TranslatableComponent formatPart(long amount, ChronoUnit unit) {
|
||||
String format = this.concise ? "short" : amount == 1 ? "singular" : "plural";
|
||||
String translationKey = "luckperms.duration.unit." + unit.name().toLowerCase() + "." + format;
|
||||
return Component.translatable(translationKey, Component.text(amount));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -284,7 +284,7 @@ public class VerboseListener {
|
||||
// retrieve variables
|
||||
String startDate = DATE_FORMAT.format(this.startTime);
|
||||
String endDate = DATE_FORMAT.format(Instant.now());
|
||||
String duration = DurationFormatter.CONCISE.format(Duration.between(this.startTime, Instant.now()));
|
||||
String duration = DurationFormatter.CONCISE.formatString(Duration.between(this.startTime, Instant.now()));
|
||||
boolean truncated = this.matchedCounter.get() > this.results.size();
|
||||
|
||||
JObject metadata = new JObject()
|
||||
|
@ -24,6 +24,28 @@ luckperms.login.craftbukkit-offline-mode-error=this is likely due to a conflict
|
||||
luckperms.login.unexpected-error=An unexpected error occurred whilst setting up your permissions data
|
||||
luckperms.opsystem.disabled=The vanilla OP system is disabled on this server
|
||||
luckperms.opsystem.sponge-warning=Please note that Server Operator status has no effect on Sponge permission checks when a permission plugin is installed, you must edit user data directly
|
||||
luckperms.duration.unit.years.plural={0} years
|
||||
luckperms.duration.unit.years.singular={0} year
|
||||
luckperms.duration.unit.years.short={0}y
|
||||
luckperms.duration.unit.months.plural={0} months
|
||||
luckperms.duration.unit.months.singular={0} month
|
||||
luckperms.duration.unit.months.short={0}mo
|
||||
luckperms.duration.unit.weeks.plural={0} weeks
|
||||
luckperms.duration.unit.weeks.singular={0} week
|
||||
luckperms.duration.unit.weeks.short={0}w
|
||||
luckperms.duration.unit.days.plural={0} days
|
||||
luckperms.duration.unit.days.singular={0} day
|
||||
luckperms.duration.unit.days.short={0}d
|
||||
luckperms.duration.unit.hours.plural={0} hours
|
||||
luckperms.duration.unit.hours.singular={0} hour
|
||||
luckperms.duration.unit.hours.short={0}h
|
||||
luckperms.duration.unit.minutes.plural={0} minutes
|
||||
luckperms.duration.unit.minutes.singular={0} minute
|
||||
luckperms.duration.unit.minutes.short={0}m
|
||||
luckperms.duration.unit.seconds.plural={0} seconds
|
||||
luckperms.duration.unit.seconds.singular={0} second
|
||||
luckperms.duration.unit.seconds.short={0}s
|
||||
luckperms.duration.since={0} ago
|
||||
luckperms.command.misc.invalid-code=Invalid code
|
||||
luckperms.command.misc.response-code-key=response code
|
||||
luckperms.command.misc.error-message-key=message
|
||||
|
Loading…
Reference in New Issue
Block a user