Skip to content

Commit 476b7dc

Browse files
committed
refactor: Dialog now support translations
1 parent 3a70cb7 commit 476b7dc

56 files changed

Lines changed: 1259 additions & 177 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

authme-core/src/main/java/fr/xephi/authme/message/MessageKey.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,45 @@ public enum MessageKey {
233233
/** Invalid code! */
234234
TWO_FACTOR_INVALID_CODE("two_factor.invalid_code"),
235235

236+
/** Login dialog title. */
237+
DIALOG_LOGIN_TITLE("dialog.login.title"),
238+
239+
/** Login dialog password field label. */
240+
DIALOG_LOGIN_PASSWORD("dialog.login.password"),
241+
242+
/** Login dialog submit button label. */
243+
DIALOG_LOGIN_BUTTON("dialog.login.button"),
244+
245+
/** Register dialog title. */
246+
DIALOG_REGISTER_TITLE("dialog.register.title"),
247+
248+
/** Register dialog password field label. */
249+
DIALOG_REGISTER_PASSWORD("dialog.register.password"),
250+
251+
/** Register dialog password confirmation field label. */
252+
DIALOG_REGISTER_CONFIRM_PASSWORD("dialog.register.confirm_password"),
253+
254+
/** Register dialog email field label. */
255+
DIALOG_REGISTER_EMAIL("dialog.register.email"),
256+
257+
/** Register dialog email confirmation field label. */
258+
DIALOG_REGISTER_CONFIRM_EMAIL("dialog.register.confirm_email"),
259+
260+
/** Register dialog submit button label. */
261+
DIALOG_REGISTER_BUTTON("dialog.register.button"),
262+
263+
/** Two-factor dialog title. */
264+
DIALOG_TWO_FACTOR_TITLE("dialog.two_factor.title"),
265+
266+
/** Two-factor dialog code field label. */
267+
DIALOG_TWO_FACTOR_CODE("dialog.two_factor.code"),
268+
269+
/** Two-factor dialog submit button label. */
270+
DIALOG_TWO_FACTOR_BUTTON("dialog.two_factor.button"),
271+
272+
/** Generic dialog cancel button label. */
273+
DIALOG_CANCEL_BUTTON("dialog.button.cancel"),
274+
236275
/** You are not the owner of this account. Please choose another name! */
237276
NOT_OWNER_ERROR("on_join_validation.not_owner_error"),
238277

authme-core/src/main/java/fr/xephi/authme/message/updater/MessageUpdater.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ public static MessageKeyConfigurationData createConfigurationData() {
149149
.put("verification", "Verification code")
150150
.put("time", "Time units")
151151
.put("two_factor", "Two-factor authentication")
152+
.put("dialog", "Dialog UI")
152153
.put("command", "Command validation messages")
153154
.put("admin", "Admin command messages")
154155
.build();

authme-core/src/main/java/fr/xephi/authme/platform/DialogAdapter.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,25 +23,29 @@ default boolean isDialogSupported() {
2323
* Shows the login dialog to the given player.
2424
*
2525
* @param player the player to show the dialog to
26+
* @param dialog the resolved dialog text and UX options
2627
*/
27-
default void showLoginDialog(Player player) {
28+
default void showLoginDialog(Player player, DialogWindowSpec dialog) {
2829
}
2930

3031
/**
3132
* Shows the two-factor authentication dialog to the given player.
3233
*
3334
* @param player the player to show the dialog to
35+
* @param dialog the resolved dialog text and UX options
3436
*/
35-
default void showTotpDialog(Player player) {
37+
default void showTotpDialog(Player player, DialogWindowSpec dialog) {
3638
}
3739

3840
/**
3941
* Shows the register dialog to the given player.
4042
*
41-
* @param player the player to show the dialog to
42-
* @param type the registration type (password or email)
43+
* @param player the player to show the dialog to
44+
* @param type the registration type (password or email)
4345
* @param secondArg the secondary argument type for registration
46+
* @param dialog the resolved dialog text and UX options
4447
*/
45-
default void showRegisterDialog(Player player, RegistrationType type, RegisterSecondaryArgument secondArg) {
48+
default void showRegisterDialog(Player player, RegistrationType type,
49+
RegisterSecondaryArgument secondArg, DialogWindowSpec dialog) {
4650
}
4751
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package fr.xephi.authme.platform;
2+
3+
import java.util.Objects;
4+
5+
/**
6+
* Description of one text input displayed in a dialog.
7+
*
8+
* @param id the field identifier submitted by the client
9+
* @param label the translated field label
10+
* @param maxLength the maximum input length
11+
*/
12+
public record DialogInputSpec(String id, String label, int maxLength) {
13+
14+
public DialogInputSpec {
15+
Objects.requireNonNull(id, "id");
16+
Objects.requireNonNull(label, "label");
17+
}
18+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package fr.xephi.authme.platform;
2+
3+
import java.util.List;
4+
import java.util.Objects;
5+
6+
/**
7+
* Resolved dialog text and UX options shared across platform-specific renderers.
8+
*
9+
* @param title the dialog title
10+
* @param inputs the dialog inputs
11+
* @param primaryButtonLabel the main action button label
12+
* @param secondaryButtonLabel the optional secondary button label
13+
* @param showSecondaryButton whether a secondary button should be rendered
14+
* @param canCloseWithEscape whether the dialog may be dismissed with escape when the platform supports it
15+
*/
16+
public record DialogWindowSpec(String title,
17+
List<DialogInputSpec> inputs,
18+
String primaryButtonLabel,
19+
String secondaryButtonLabel,
20+
boolean showSecondaryButton,
21+
boolean canCloseWithEscape) {
22+
23+
public DialogWindowSpec {
24+
Objects.requireNonNull(title, "title");
25+
Objects.requireNonNull(inputs, "inputs");
26+
Objects.requireNonNull(primaryButtonLabel, "primaryButtonLabel");
27+
Objects.requireNonNull(secondaryButtonLabel, "secondaryButtonLabel");
28+
inputs = List.copyOf(inputs);
29+
}
30+
}

authme-core/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import fr.xephi.authme.process.register.executors.RegistrationMethod;
2121
import fr.xephi.authme.service.BukkitService;
2222
import fr.xephi.authme.service.CommonService;
23+
import fr.xephi.authme.service.DialogWindowService;
2324
import fr.xephi.authme.service.PreJoinDialogService;
2425
import fr.xephi.authme.service.PluginHookService;
2526
import fr.xephi.authme.service.SessionService;
@@ -99,6 +100,9 @@ public class AsynchronousJoin implements AsynchronousProcess {
99100
@Inject
100101
private DialogAdapter dialogAdapter;
101102

103+
@Inject
104+
private DialogWindowService dialogWindowService;
105+
102106
@Inject
103107
private PreJoinDialogService preJoinDialogService;
104108

@@ -253,11 +257,14 @@ private void showPostJoinDialogIfNecessary(Player player, boolean isAuthAvailabl
253257
}
254258

255259
if (isAuthAvailable) {
256-
dialogAdapter.showLoginDialog(player);
260+
dialogAdapter.showLoginDialog(player, dialogWindowService.createLoginDialog(player));
257261
} else {
262+
RegistrationType registrationType = service.getProperty(RegistrationSettings.REGISTRATION_TYPE);
263+
RegisterSecondaryArgument secondArg = service.getProperty(RegistrationSettings.REGISTER_SECOND_ARGUMENT);
258264
dialogAdapter.showRegisterDialog(player,
259-
service.getProperty(RegistrationSettings.REGISTRATION_TYPE),
260-
service.getProperty(RegistrationSettings.REGISTER_SECOND_ARGUMENT));
265+
registrationType,
266+
secondArg,
267+
dialogWindowService.createRegisterDialog(player, registrationType, secondArg));
261268
}
262269
}
263270

authme-core/src/main/java/fr/xephi/authme/process/login/AsynchronousLogin.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import fr.xephi.authme.security.PasswordSecurity;
2525
import fr.xephi.authme.service.BukkitService;
2626
import fr.xephi.authme.service.CommonService;
27+
import fr.xephi.authme.service.DialogWindowService;
2728
import fr.xephi.authme.service.SessionService;
2829
import fr.xephi.authme.service.bungeecord.BungeeSender;
2930
import fr.xephi.authme.service.bungeecord.MessageType;
@@ -90,6 +91,9 @@ public class AsynchronousLogin implements AsynchronousProcess {
9091
@Inject
9192
private DialogAdapter dialogAdapter;
9293

94+
@Inject
95+
private DialogWindowService dialogWindowService;
96+
9397
AsynchronousLogin() {
9498
}
9599

@@ -274,7 +278,7 @@ private void showTotpDialogIfEnabled(Player player) {
274278
if (!player.isOnline() || playerCache.isAuthenticated(player.getName())) {
275279
return;
276280
}
277-
dialogAdapter.showTotpDialog(player);
281+
dialogAdapter.showTotpDialog(player, dialogWindowService.createTotpDialog(player));
278282
}, 1L);
279283
}
280284

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
package fr.xephi.authme.service;
2+
3+
import fr.xephi.authme.message.MessageKey;
4+
import fr.xephi.authme.message.Messages;
5+
import fr.xephi.authme.platform.DialogInputSpec;
6+
import fr.xephi.authme.platform.DialogWindowSpec;
7+
import fr.xephi.authme.process.register.RegisterSecondaryArgument;
8+
import fr.xephi.authme.process.register.RegistrationType;
9+
import fr.xephi.authme.settings.properties.RegistrationSettings;
10+
import org.bukkit.entity.Player;
11+
12+
import javax.inject.Inject;
13+
import java.util.ArrayList;
14+
import java.util.List;
15+
import java.util.function.Function;
16+
17+
/**
18+
* Builds translated dialog specs shared by all platform-specific dialog renderers.
19+
*/
20+
public class DialogWindowService {
21+
22+
private static final int DEFAULT_MAX_INPUT_LENGTH = 100;
23+
private static final int TOTP_CODE_MAX_INPUT_LENGTH = 16;
24+
25+
@Inject
26+
private CommonService commonService;
27+
28+
@Inject
29+
private Messages messages;
30+
31+
DialogWindowService() {
32+
}
33+
34+
public DialogWindowSpec createLoginDialog(Player player) {
35+
return createLoginDialogSpec(key -> getPostJoinMessage(player, key), false, false);
36+
}
37+
38+
public DialogWindowSpec createPreJoinLoginDialog(String playerName) {
39+
return createLoginDialogSpec(key -> messages.retrieveSingle(playerName, key),
40+
commonService.getProperty(RegistrationSettings.PRE_JOIN_DIALOG_SHOW_CANCEL_BUTTON),
41+
commonService.getProperty(RegistrationSettings.PRE_JOIN_DIALOG_ALLOW_CLOSE_WITH_ESCAPE));
42+
}
43+
44+
public DialogWindowSpec createTotpDialog(Player player) {
45+
return new DialogWindowSpec(
46+
getPostJoinMessage(player, MessageKey.DIALOG_TWO_FACTOR_TITLE),
47+
List.of(new DialogInputSpec("code",
48+
getPostJoinMessage(player, MessageKey.DIALOG_TWO_FACTOR_CODE),
49+
TOTP_CODE_MAX_INPUT_LENGTH)),
50+
getPostJoinMessage(player, MessageKey.DIALOG_TWO_FACTOR_BUTTON),
51+
getPostJoinMessage(player, MessageKey.DIALOG_CANCEL_BUTTON),
52+
false,
53+
false);
54+
}
55+
56+
public DialogWindowSpec createRegisterDialog(Player player,
57+
RegistrationType type,
58+
RegisterSecondaryArgument secondArg) {
59+
return createRegisterDialogSpec(type, secondArg, key -> getPostJoinMessage(player, key), false, false);
60+
}
61+
62+
public DialogWindowSpec createPreJoinRegisterDialog(String playerName,
63+
RegistrationType type,
64+
RegisterSecondaryArgument secondArg) {
65+
return createRegisterDialogSpec(type, secondArg, key -> messages.retrieveSingle(playerName, key),
66+
commonService.getProperty(RegistrationSettings.PRE_JOIN_DIALOG_SHOW_CANCEL_BUTTON),
67+
commonService.getProperty(RegistrationSettings.PRE_JOIN_DIALOG_ALLOW_CLOSE_WITH_ESCAPE));
68+
}
69+
70+
private DialogWindowSpec createLoginDialogSpec(Function<MessageKey, String> textResolver,
71+
boolean showSecondaryButton,
72+
boolean canCloseWithEscape) {
73+
return new DialogWindowSpec(
74+
textResolver.apply(MessageKey.DIALOG_LOGIN_TITLE),
75+
List.of(new DialogInputSpec("password",
76+
textResolver.apply(MessageKey.DIALOG_LOGIN_PASSWORD),
77+
DEFAULT_MAX_INPUT_LENGTH)),
78+
textResolver.apply(MessageKey.DIALOG_LOGIN_BUTTON),
79+
textResolver.apply(MessageKey.DIALOG_CANCEL_BUTTON),
80+
showSecondaryButton,
81+
canCloseWithEscape);
82+
}
83+
84+
private DialogWindowSpec createRegisterDialogSpec(RegistrationType type,
85+
RegisterSecondaryArgument secondArg,
86+
Function<MessageKey, String> textResolver,
87+
boolean showSecondaryButton,
88+
boolean canCloseWithEscape) {
89+
List<DialogInputSpec> inputs = new ArrayList<>();
90+
if (type == RegistrationType.EMAIL) {
91+
inputs.add(new DialogInputSpec("email",
92+
textResolver.apply(MessageKey.DIALOG_REGISTER_EMAIL),
93+
DEFAULT_MAX_INPUT_LENGTH));
94+
if (secondArg == RegisterSecondaryArgument.CONFIRMATION) {
95+
inputs.add(new DialogInputSpec("confirm",
96+
textResolver.apply(MessageKey.DIALOG_REGISTER_CONFIRM_EMAIL),
97+
DEFAULT_MAX_INPUT_LENGTH));
98+
}
99+
} else {
100+
inputs.add(new DialogInputSpec("password",
101+
textResolver.apply(MessageKey.DIALOG_REGISTER_PASSWORD),
102+
DEFAULT_MAX_INPUT_LENGTH));
103+
if (secondArg == RegisterSecondaryArgument.CONFIRMATION) {
104+
inputs.add(new DialogInputSpec("confirm",
105+
textResolver.apply(MessageKey.DIALOG_REGISTER_CONFIRM_PASSWORD),
106+
DEFAULT_MAX_INPUT_LENGTH));
107+
} else if (secondArg == RegisterSecondaryArgument.EMAIL_MANDATORY
108+
|| secondArg == RegisterSecondaryArgument.EMAIL_OPTIONAL) {
109+
inputs.add(new DialogInputSpec("email",
110+
textResolver.apply(MessageKey.DIALOG_REGISTER_EMAIL),
111+
DEFAULT_MAX_INPUT_LENGTH));
112+
}
113+
}
114+
115+
return new DialogWindowSpec(
116+
textResolver.apply(MessageKey.DIALOG_REGISTER_TITLE),
117+
inputs,
118+
textResolver.apply(MessageKey.DIALOG_REGISTER_BUTTON),
119+
textResolver.apply(MessageKey.DIALOG_CANCEL_BUTTON),
120+
showSecondaryButton,
121+
canCloseWithEscape);
122+
}
123+
124+
private String getPostJoinMessage(Player player, MessageKey key) {
125+
return commonService.retrieveSingleMessage(player, key);
126+
}
127+
}

authme-core/src/main/java/fr/xephi/authme/settings/properties/RegistrationSettings.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,19 @@ public final class RegistrationSettings implements SettingsHolder {
121121
public static final Property<Boolean> USE_PREJOIN_DIALOG_UI =
122122
newProperty("settings.registration.usePreJoinDialogUi", true);
123123

124+
@Comment({
125+
"Show a cancel button in Paper/Folia pre-join dialogs.",
126+
"If disabled, players must submit the dialog or disconnect instead."})
127+
public static final Property<Boolean> PRE_JOIN_DIALOG_SHOW_CANCEL_BUTTON =
128+
newProperty("settings.registration.preJoinDialog.showCancelButton", true);
129+
130+
@Comment({
131+
"Allow closing Paper/Folia pre-join dialogs with Escape.",
132+
"If disabled, the dialog stays open until it is submitted,",
133+
"cancelled, or the timeout disconnects the player."})
134+
public static final Property<Boolean> PRE_JOIN_DIALOG_ALLOW_CLOSE_WITH_ESCAPE =
135+
newProperty("settings.registration.preJoinDialog.allowCloseWithEscape", false);
136+
124137

125138
private RegistrationSettings() {
126139
}

authme-core/src/main/resources/messages/messages_bg.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,26 @@ verification:
132132
code_expired: '&3Вашият код е изтекъл. Изпълнете друга чувствителна команда за да генерирате нов код!'
133133
email_needed: '&3За да потвърдите Вашата самоличност е необходимо да добавите имейл адрес към Вашият акаунт!!'
134134

135+
# Dialog UI
136+
dialog:
137+
login:
138+
title: '&6Вход'
139+
password: '&fПарола'
140+
button: '&aВход'
141+
register:
142+
title: '&6Регистрация'
143+
password: '&fПарола'
144+
confirm_password: '&fПотвърди паролата'
145+
email: '&fИмейл'
146+
confirm_email: '&fПотвърди имейла'
147+
button: '&aРегистриране'
148+
two_factor:
149+
title: '&6Двуфакторна автентикация'
150+
code: '&f2FA код'
151+
button: '&aПотвърди'
152+
button:
153+
cancel: '&cОтказ'
154+
135155
# Time units
136156
time:
137157
second: 'секунда'

0 commit comments

Comments
 (0)