0

Merge branch 'feature/messages' into develop

This commit is contained in:
2021-02-04 11:34:44 +03:00
3 changed files with 183 additions and 49 deletions

102
README.MD
View File

@@ -18,7 +18,7 @@ _Основан на версии Bukkit API 1.12._
8. [JdbcTemplate](#jdbctemplate) 8. [JdbcTemplate](#jdbctemplate)
9. [ScheduleManager](#schedulemanager) 9. [ScheduleManager](#schedulemanager)
10. [ScheduleTask](#scheduletask) 10. [ScheduleTask](#scheduletask)
11. [I18n](#i18n) 11. [Messages](#messages)
12. [XLog](#xlog) 12. [XLog](#xlog)
13. [Подключение](#подключение) 13. [Подключение](#подключение)
1. [Gradle](#gradle) 1. [Gradle](#gradle)
@@ -532,93 +532,97 @@ ScheduleTask scheduleTask = ...;
scheduleTask.cancel(); scheduleTask.cancel();
``` ```
## I18n ## Messages
Инструмент для работы с мультиязыковыми сообщениями или просто сообщениями, которые храняться в отдельном файле. Инструмент для работы с параметизированными сообщениями или просто сообщениями, которые храняться в отдельном файле.
Позволяет использовать шаблонизированные сообщения вида `Привет, {player}!`. Параметизированные сообщения имеют следующий вид: `Привет, {player}!`.
### loadMessages ### load
Загрузка сообщений в инструмент. Загрузка сообщений в инструмент.
Передать можно как "мапу" с перечислением ключ-сообщение, так и `Reader` на файл в формате `key=message` (как у `Properties`). Есть три варианта: через `Properties`
```java ```java
Map<String, String> messagesMap = ...; Properties properties = ...;
I18n.loadMessages(messagesMap); Messages.load(properties);
``` ```
через `Map<String, String>`
```java ```java
Reader reader = AssetsManager.getAsReader("messages.properties"); Map<String, String> map = ...;
I18n.loadMessages(reader); Messages.load(map);
``` ```
В первом параметре можно указать код языка, для которого загружаются сообщения. По-умолчанию будет "en". через `Reader`
```java ```java
Map<String, String> enMessagesMap = ...; Reader reader = ...;
Map<String, String> ruMessagesMap = ...; Messages.load(reader);
I18n.loadMessages("en", enMessagesMap);
I18n.loadMessages("ru", ruMessagesMap);
``` ```
```java Следует учесть, про при работе через `Reader`, **Messages** ожидает там обнаружить список строк в формате `key=value`.
Reader readerEn = AssetsManager.getAsReader("messages.properties");
Reader readerRu = AssetsManager.getAsReader("messages.ru.properties");
I18n.loadMessages("en", readerEn);
I18n.loadMessages("ru", readerRu);
```
### get ### get
Получение сообщения по его ключу. Получение обычноего или параметизированного сообщения.
```java Для примера, пусть у нас будут такие сообщения:
String msg = I18n.get("player.join.msg");
```properties
simple=Простое сообщение
welcome=Приветствуем, {player}!
``` ```
Если следующим сообщением указать `Map<String, Object>`, то можно будет воспользоваться шаблонизатором. Для получения простого сообщения, просто указываем его ключ:
```java ```java
Map<String, String> messagesMap = new HashMap<>(); String message = Messages.get("simple");
messagesMap.put("player.join.msg", "Привет, {player}!"); // Простое сообщение
I18n.loadMessages(messagesMap);
Map<String, String> params = new HashMap<>();
params.put("player", event.getPlayer().getName());
String msg = I18n.get("player.join.msg", params);
``` ```
Однако можно создавать `Map<String, String> params` явно, а воспользоваться [paramBuilder()](#parambuilder) Для получения параметизированного сообщения, нужно помимо ключа передать параметры.
Есть два способа: через `Map<String, Object>`
```java ```java
String msg = I18n.get("player.join.msg", I18n.paramBuilder() Map<String, Object> = map = new HashMap<>(1);
.add("player", event.getPlayer().getName()) map.put("player", "David");
.build());
String message = Messages.get("welcome", map);
// Приветствуем, David!
``` ```
Можно первым параметром указать код языка. через попарное перечисление параметров
```java ```java
String msg = I18n.get("ru", "player.join.msg"); String message = Messages.get("welcome", "player", "David");
// Приветствуем, David!
``` ```
### paramBuilder Если по указанному ключу сообщение отсутствует, то **Messages** вернёт значение самого ключа
Инструмент для параметизирования шаблонов сообщений.
```java ```java
Map<String, Object> params = I18n.paramBuilder() String message = Messages.get("not_exists_key");
.add("player", event.getPlayer().getName()) // not_exists_key
.build();
String msg = I18n.get("player.join.msg", params); message = Messages.get("not_exists_key", "player", "David");
// not_exists_key
``` ```
Если параметр, который указан в шаблоне не был указан/определён, то параметр останется как есть
```java
String message = Messages.get("welcome");
// Приветствуем, {player}!
message = Messages.get("welcome", "unknown_param_key", 123);
// Приветствуем, {player}!
```
## XLog ## XLog
Замена стандартному `getLogger()`, который использует `java.utils.Logger` и не всегда удобен для логирования. Замена стандартному `getLogger()`, который использует `java.utils.Logger` и не всегда удобен для логирования.

View File

@@ -14,8 +14,12 @@ import java.io.Reader;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
/**
* @deprecated use {@link Messages}
*/
@UtilityClass @UtilityClass
@SuppressWarnings("unused") @SuppressWarnings("unused")
@Deprecated
public class I18n { public class I18n {
private final String DEFAULT_LANG = "en"; private final String DEFAULT_LANG = "en";

View File

@@ -0,0 +1,126 @@
package ghast;
import lombok.experimental.UtilityClass;
import org.apache.commons.text.StringSubstitutor;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
@UtilityClass
public class Messages {
private final Map<String/*Key*/, String/*Template|Message*/> MESSAGES_MAP = new HashMap<>();
//region Load messages
/**
* Загрузка сообщений из {@link Properties}
*
* @param properties список сообщений и шаблонов
*/
public void load(Properties properties) {
MESSAGES_MAP.clear();
properties.forEach((key, value) -> MESSAGES_MAP.put(key.toString().trim().toLowerCase(), value.toString().trim()));
}
/**
* Загрузка сообщений из {@link Reader}.
* <p>
* Формат строк: {@code key=value}
* </p>
*
* @param reader {@link Reader} со списоком сообщений и шаблонов
*/
public void load(Reader reader) {
MESSAGES_MAP.clear();
try {
BufferedReader bufferedReader = new BufferedReader(reader);
String line;
while ((line = bufferedReader.readLine()) != null) {
String[] split = line.split("=", 2);
MESSAGES_MAP.put(split[0].trim().toLowerCase(), split[1].trim());
}
} catch (IOException e) {
//TODO заменить на специализированный Exception
throw new RuntimeException("Error load messages: " + e.getMessage(), e);
}
}
/**
* Загрузка сообщений из {@link Map}<{@link String}, {@link String}>.
*
* @param messages список сообщений и шаблонов
*/
public void load(Map<String, String> messages) {
MESSAGES_MAP.clear();
MESSAGES_MAP.putAll(messages);
}
//endregion
//region Get messages
/**
* Получить обычное сообщение по ключу/коду.
*
* @param key ключ/код
* @return сообщение, если таковое задано. Иначе - ключ
*/
public String get(String key) {
String keyLc = key.toLowerCase();
return MESSAGES_MAP.getOrDefault(keyLc, keyLc);
}
/**
* Получить параметизированное сообщение по ключу/коду.
*
* @param key ключ/код
* @param params список параметров
* @return сообщение, если таковое задано. Иначе - ключ
*/
public String get(String key, Map<String, Object> params) {
String keyLc = key.toLowerCase();
if (MESSAGES_MAP.containsKey(keyLc)) {
return formatMessage(MESSAGES_MAP.get(keyLc), params);
} else {
return keyLc;
}
}
/**
* Получить параметизированное сообщение по ключу/коду.
*
* @param key ключ/код
* @param params чередующийся по парный список параметров: {@link String (str)param_name}, {@link Object (obj)param_value} и т.д.
* @return сообщение, если таковое задано. Иначе - ключ
*/
public String get(String key, Object... params) {
String keyLc = key.toLowerCase();
if (MESSAGES_MAP.containsKey(keyLc)) {
int len;
if ((params.length % 2) == 1) {
len = params.length - 1;
} else {
len = params.length;
}
Map<String, Object> mapParams = new HashMap<>(len / 2);
for (int i = 0; i < len; i = i + 2) {
mapParams.put((String) params[i], params[i + 1]);
}
return formatMessage(MESSAGES_MAP.get(keyLc), mapParams);
} else {
return keyLc;
}
}
//endregion
private String formatMessage(String format, Map<String, Object> params) {
return StringSubstitutor.replace(format, params, "{", "}");
}
}