Add basic internationalization support
This commit is contained in:
parent
bcb9d7505b
commit
d77887fd2c
@ -103,6 +103,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot {
|
||||
protected static final String COMMANDS = "commands";
|
||||
|
||||
// Messages
|
||||
// TODO replace hardcoded messages...
|
||||
protected static final String RECOVERY_MESSAGE = "I am ready to receive the backup file. Please reply to this message with the backup file attached.";
|
||||
protected static final String RECOVER_SUCCESS = "I have successfully recovered.";
|
||||
|
||||
@ -306,7 +307,7 @@ public abstract class AbilityBot extends TelegramLongPollingBot {
|
||||
})
|
||||
.sorted()
|
||||
.reduce((a, b) -> format("%s%n%s", a, b))
|
||||
.orElse("No public commands found.");
|
||||
.orElse(getLocalizedMessage("ability.commands.notFound", ctx.user().locale()));
|
||||
|
||||
silent.send(commands, ctx.chatId());
|
||||
})
|
||||
@ -371,11 +372,13 @@ public abstract class AbilityBot extends TelegramLongPollingBot {
|
||||
if (db.recover(backupData)) {
|
||||
silent.send(RECOVER_SUCCESS, chatId);
|
||||
} else {
|
||||
silent.send("Oops, something went wrong during recovery.", chatId);
|
||||
silent.send(getLocalizedMessage("ability.recover.fail",
|
||||
AbilityUtils.getUser(update).getLanguageCode()), chatId);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
BotLogger.error("Could not recover DB from backup", TAG, e);
|
||||
silent.send("I have failed to recover.", chatId);
|
||||
silent.send(getLocalizedMessage("ability.recover.error",
|
||||
AbilityUtils.getUser(update).getLanguageCode()), chatId);
|
||||
}
|
||||
}, MESSAGE, DOCUMENT, REPLY, isReplyTo(RECOVERY_MESSAGE))
|
||||
.build();
|
||||
@ -411,10 +414,10 @@ public abstract class AbilityBot extends TelegramLongPollingBot {
|
||||
|
||||
Set<Integer> blacklist = blacklist();
|
||||
if (blacklist.contains(userId))
|
||||
silent.sendMd(format("%s is already *banned*.", escape(bannedUser)), ctx.chatId());
|
||||
silent.sendMd(getLocalizedMessage("ability.ban.alreadyBanned", ctx.user().locale(), escape(bannedUser)), ctx.chatId());
|
||||
else {
|
||||
blacklist.add(userId);
|
||||
silent.sendMd(format("%s is now *banned*.", escape(bannedUser)), ctx.chatId());
|
||||
silent.sendMd(getLocalizedMessage("ability.ban.banned", ctx.user().locale(), escape(bannedUser)), ctx.chatId());
|
||||
}
|
||||
})
|
||||
.post(commitTo(db))
|
||||
@ -439,9 +442,9 @@ public abstract class AbilityBot extends TelegramLongPollingBot {
|
||||
Set<Integer> blacklist = blacklist();
|
||||
|
||||
if (!blacklist.remove(userId))
|
||||
silent.sendMd(format("@%s is *not* on the *blacklist*.", escape(username)), ctx.chatId());
|
||||
silent.sendMd(getLocalizedMessage("ability.unban.notBanned", ctx.user().locale(), escape(username)), ctx.chatId());
|
||||
else {
|
||||
silent.sendMd(format("@%s, your ban has been *lifted*.", escape(username)), ctx.chatId());
|
||||
silent.sendMd(getLocalizedMessage("ability.unban.lifted", ctx.user().locale(), escape(username)), ctx.chatId());
|
||||
}
|
||||
})
|
||||
.post(commitTo(db))
|
||||
@ -463,10 +466,10 @@ public abstract class AbilityBot extends TelegramLongPollingBot {
|
||||
|
||||
Set<Integer> admins = admins();
|
||||
if (admins.contains(userId))
|
||||
silent.sendMd(format("@%s is already an *admin*.", escape(username)), ctx.chatId());
|
||||
silent.sendMd(getLocalizedMessage("ability.promote.alreadyPromoted", ctx.user().locale(), escape(username)), ctx.chatId());
|
||||
else {
|
||||
admins.add(userId);
|
||||
silent.sendMd(format("@%s has been *promoted*.", escape(username)), ctx.chatId());
|
||||
silent.sendMd(getLocalizedMessage("ability.promote.promoted", ctx.user().locale(), escape(username)), ctx.chatId());
|
||||
}
|
||||
}).post(commitTo(db))
|
||||
.build();
|
||||
@ -487,9 +490,9 @@ public abstract class AbilityBot extends TelegramLongPollingBot {
|
||||
|
||||
Set<Integer> admins = admins();
|
||||
if (admins.remove(userId)) {
|
||||
silent.sendMd(format("@%s has been *demoted*.", escape(username)), ctx.chatId());
|
||||
silent.sendMd(getLocalizedMessage("ability.demote.demoted", ctx.user().locale(), escape(username)), ctx.chatId());
|
||||
} else {
|
||||
silent.sendMd(format("@%s is *not* an *admin*.", escape(username)), ctx.chatId());
|
||||
silent.sendMd(getLocalizedMessage("ability.demote.alreadyDemoted", ctx.user().locale(), escape(username)), ctx.chatId());
|
||||
}
|
||||
})
|
||||
.post(commitTo(db))
|
||||
@ -514,10 +517,10 @@ public abstract class AbilityBot extends TelegramLongPollingBot {
|
||||
long chatId = ctx.chatId();
|
||||
|
||||
if (admins.contains(id))
|
||||
silent.send("You're already my master.", chatId);
|
||||
silent.send(getLocalizedMessage("ability.claim.alreadyClaimed", ctx.user().locale()), chatId);
|
||||
else {
|
||||
admins.add(id);
|
||||
silent.send("You're now my master.", chatId);
|
||||
silent.send(getLocalizedMessage("ability.claim.claimed", ctx.user().locale()), chatId);
|
||||
}
|
||||
} else {
|
||||
// This is not a joke
|
||||
@ -615,7 +618,12 @@ public abstract class AbilityBot extends TelegramLongPollingBot {
|
||||
boolean isOk = abilityTokens == 0 || (tokens.length > 0 && tokens.length == abilityTokens);
|
||||
|
||||
if (!isOk)
|
||||
silent.send(format("Sorry, this feature requires %d additional %s.", abilityTokens, abilityTokens == 1 ? "input" : "inputs"), getChatId(trio.a()));
|
||||
silent.send(
|
||||
getLocalizedMessage(
|
||||
"checkInput.fail",
|
||||
AbilityUtils.getUser(trio.a()).getLanguageCode(),
|
||||
abilityTokens, abilityTokens == 1 ? "input" : "inputs"),
|
||||
getChatId(trio.a()));
|
||||
return isOk;
|
||||
}
|
||||
|
||||
@ -627,7 +635,12 @@ public abstract class AbilityBot extends TelegramLongPollingBot {
|
||||
boolean isOk = abilityLocality == ALL || locality == abilityLocality;
|
||||
|
||||
if (!isOk)
|
||||
silent.send(format("Sorry, %s-only feature.", abilityLocality.toString().toLowerCase()), getChatId(trio.a()));
|
||||
silent.send(
|
||||
getLocalizedMessage(
|
||||
"checkLocality.fail",
|
||||
AbilityUtils.getUser(trio.a()).getLanguageCode(),
|
||||
abilityLocality.toString().toLowerCase()),
|
||||
getChatId(trio.a()));
|
||||
return isOk;
|
||||
}
|
||||
|
||||
@ -642,8 +655,11 @@ public abstract class AbilityBot extends TelegramLongPollingBot {
|
||||
boolean isOk = privacy.compareTo(trio.b().privacy()) >= 0;
|
||||
|
||||
if (!isOk)
|
||||
silent.send("Sorry, you don't have the required access level to do that.", getChatId(trio.a()));
|
||||
|
||||
silent.send(
|
||||
getLocalizedMessage(
|
||||
"checkPrivacy.fail",
|
||||
AbilityUtils.getUser(trio.a()).getLanguageCode()),
|
||||
getChatId(trio.a()));
|
||||
return isOk;
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,14 @@
|
||||
package org.telegram.abilitybots.api.objects;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.base.Strings;
|
||||
import org.telegram.telegrambots.api.objects.User;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
@ -27,12 +30,15 @@ public final class EndUser implements Serializable {
|
||||
private final String lastName;
|
||||
@JsonProperty("username")
|
||||
private final String username;
|
||||
@JsonIgnore
|
||||
private Locale locale;
|
||||
|
||||
private EndUser(Integer id, String firstName, String lastName, String username) {
|
||||
private EndUser(Integer id, String firstName, String lastName, String username, Locale locale) {
|
||||
this.id = id;
|
||||
this.firstName = firstName;
|
||||
this.lastName = lastName;
|
||||
this.username = username;
|
||||
this.locale = locale != null? locale : Locale.ENGLISH;
|
||||
}
|
||||
|
||||
@JsonCreator
|
||||
@ -40,7 +46,7 @@ public final class EndUser implements Serializable {
|
||||
@JsonProperty("firstName") String firstName,
|
||||
@JsonProperty("lastName") String lastName,
|
||||
@JsonProperty("username") String username) {
|
||||
return new EndUser(id, firstName, lastName, username);
|
||||
return new EndUser(id, firstName, lastName, username, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -50,7 +56,8 @@ public final class EndUser implements Serializable {
|
||||
* @return an augmented end-user
|
||||
*/
|
||||
public static EndUser fromUser(User user) {
|
||||
return new EndUser(user.getId(), user.getFirstName(), user.getLastName(), user.getUserName());
|
||||
Locale locale = Strings.isNullOrEmpty(user.getLanguageCode()) ? null : Locale.forLanguageTag(user.getLanguageCode());
|
||||
return new EndUser(user.getId(), user.getFirstName(), user.getLastName(), user.getUserName(), locale);
|
||||
}
|
||||
|
||||
public int id() {
|
||||
@ -69,6 +76,8 @@ public final class EndUser implements Serializable {
|
||||
return username;
|
||||
}
|
||||
|
||||
public Locale locale() { return locale; }
|
||||
|
||||
/**
|
||||
* The full name is identified as the concatenation of the first and last name, separated by a space.
|
||||
* This method can return an empty name if both first and last name are empty.
|
||||
@ -118,12 +127,13 @@ public final class EndUser implements Serializable {
|
||||
return Objects.equals(id, endUser.id) &&
|
||||
Objects.equals(firstName, endUser.firstName) &&
|
||||
Objects.equals(lastName, endUser.lastName) &&
|
||||
Objects.equals(username, endUser.username);
|
||||
Objects.equals(username, endUser.username) &&
|
||||
Objects.equals(locale, endUser.locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, firstName, lastName, username);
|
||||
return Objects.hash(id, firstName, lastName, username, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -133,6 +143,7 @@ public final class EndUser implements Serializable {
|
||||
.add("firstName", firstName)
|
||||
.add("lastName", lastName)
|
||||
.add("username", username)
|
||||
.add("locale", locale.toString())
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,15 @@
|
||||
package org.telegram.abilitybots.api.util;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import org.telegram.abilitybots.api.db.DBContext;
|
||||
import org.telegram.abilitybots.api.objects.MessageContext;
|
||||
import org.telegram.telegrambots.api.objects.Update;
|
||||
import org.telegram.telegrambots.api.objects.User;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Locale;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@ -172,4 +177,25 @@ public final class AbilityUtils {
|
||||
public static Predicate<Update> isReplyTo(String msg) {
|
||||
return update -> update.getMessage().getReplyToMessage().getText().equals(msg);
|
||||
}
|
||||
|
||||
public static String getLocalizedMessage(String messageCode, Locale locale, Object...arguments) {
|
||||
ResourceBundle bundle;
|
||||
if(locale == null){
|
||||
bundle = ResourceBundle.getBundle("default_messages");
|
||||
}else {
|
||||
try {
|
||||
bundle = ResourceBundle.getBundle("messages", locale);
|
||||
} catch (MissingResourceException e) {
|
||||
bundle = ResourceBundle.getBundle("default_messages");
|
||||
}
|
||||
}
|
||||
String message = bundle.getString(messageCode);
|
||||
return MessageFormat.format(message, arguments);
|
||||
}
|
||||
|
||||
public static String getLocalizedMessage(String messageCode, String languageCode, Object...arguments){
|
||||
Locale locale = Strings.isNullOrEmpty(languageCode) ? null : Locale.forLanguageTag(languageCode);
|
||||
return getLocalizedMessage(messageCode, locale, arguments);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,22 @@
|
||||
ability.commands.notFound=No public commands found.
|
||||
ability.recover.fail=Oops, something went wrong during recovery.
|
||||
ability.recover.error=I have failed to recover.
|
||||
|
||||
ability.ban.alreadyBanned={0} is already *banned*.
|
||||
ability.ban.banned={0} is now *banned*.
|
||||
|
||||
ability.unban.notBanned=@{0} is *not* on the *blacklist*.
|
||||
ability.unban.lifted=@{0}, your ban has been *lifted*.
|
||||
|
||||
ability.promote.alreadyPromoted=@{0} is already an *admin*.
|
||||
ability.promote.promoted=@{0} has been *promoted*.
|
||||
|
||||
ability.demote.alreadyDemoted=@{0} is *not* an *admin*.
|
||||
ability.demote.demoted=@{0} has been *demoted*.
|
||||
|
||||
ability.claim.alreadyClaimed=You''re already my master.
|
||||
ability.claim.claimed=You''re now my master.
|
||||
|
||||
checkInput.fail=Sorry, this feature requires {0,number,integer} additional {1}.
|
||||
checkLocality.fail=Sorry, {0}-only feature.
|
||||
checkPrivacy.fail=Sorry, you don''t have the required access level to do that.
|
@ -556,6 +556,7 @@ public class AbilityBotTest {
|
||||
when(message.hasText()).thenReturn(true);
|
||||
MessageContext context = mock(MessageContext.class);
|
||||
when(context.chatId()).thenReturn(GROUP_ID);
|
||||
when(context.user()).thenReturn(MUSER);
|
||||
|
||||
bot.reportCommands().action().accept(context);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user