Implement localisation for displaying durations

This commit is contained in:
Luck 2020-10-25 13:39:14 +00:00
parent ab0e25a56d
commit ad174742e9
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
5 changed files with 99 additions and 87 deletions

View File

@ -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));
}

View File

@ -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)
)

View File

@ -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));
}
}

View File

@ -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()

View File

@ -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