Configured ⚙️ (Library)
Config files have never been easier!
Configured is a format-independent configuration library for Java that allows you to generate
versioned and documented configuration files directly from code in multiple formats such as YAML,
JSON, and more.
It also comes with an easy to use, enum-based
Localization library built on top of Configured! Having plugins with language support was never easier. Scroll down to the
Getting Started: Localization section for more details.
And it's
perfect for
plugins ✨
Getting Started: Configuration ️
You can specify a config and register its options like this:
Code (Java):
public
static
final Config CONFIG
=
Config.
of
(
"config.yml"
)
// Format inferred from the file extension
.
version
(
1
)
.
header
(
""
"
Example configuration file
Generated using Configured!
"
""
)
;
public
static
final ConfigOption
<String
> NAME
=
CONFIG.
optionOf
(
"name",
"John Smith"
)
.
description
(
"Name of the user"
)
.
appendDefaultValue
(
)
;
public
static
final ConfigOption
<Integer
> AGE
=
CONFIG.
optionOf
(
"age",
18
)
.
description
(
"Age of the user"
)
.
appendDefaultValue
(
)
;
public
static
final ConfigOption
<Boolean
> STUDENT
=
CONFIG.
optionOf
(
"student",
true
)
.
description
(
"Whether the user is a student or not"
)
.
appendDefaultValue
(
)
;
@Override
public
void onEnable
(
)
{
CONFIG.
load
(
)
;
}
Which will generate a `config.yml` file like this:
Code (YAML):
# Example configuration file
# Using "Configured"!
_version
: 1
# Name of the user
# Default: John Smith
name
: John Smith
# Age of the user
# Default: 18
age
: 18
You can change the config format to JSONC (JSON with comments)
just by changing the file extension to `.jsonc`:
Code (Java):
Config.
of
(
"config.jsonc"
)
Which will generate a `config.jsonc` file like this:
Code (YAML):
{
// Example configuration file
// Using
"Configured"!
"_version"
: 1,
// Name of the user
// Default
: John Smith
"name"
:
"John Smith",
// Age of the user
// Default
: 18
"age"
: 18
}
Getting Started: Localization
Localization is a powerful feature of Configured that allows you to manage translations and internationalization in a simple way.
It is based on enums, which makes it easy to work with and allows you to avoid common pitfalls like mistyped keys or missing translations. Thanks to enums, you will also catch errors in compile-time and have autocompletion in your IDE.
It also comes with annotation based parameter support, which allows you to pass parameters to your translations, making it easy to create dynamic messages.
You can define a localization enum by implementing the LocalizationKey interface:
Code (Java):
enum Message
implements LocalizationKey
{
USER_NOT_FOUND,
CONFIGURATION_ERROR,
INVALID_INPUT,
OPERATION_SUCCESS,
OPERATION_FAILED,
}
You can then create a Localization instance like this:
Code (Java):
public
static
final Localization LOCALIZATION
=
Localization.
of
(lang
-> lang
+
".json"
)
// Format inferred from the file extension
.
resourceProvider
(Main.
class, lang
->
"/"
+ lang
+
".json"
)
.
fallbackLanguage
(
"en_US"
)
.
version
(
1
)
.
load
(
)
;
And receive translations like this:
Code (Java):
public
static
void main
(
String
[
] args
)
{
LOCALIZATION.
get
(Message.
USER_NOT_FOUND
)
;
// Returns the translation for USER_NOT_FOUND
LOCALIZATION.
get
(Message.
INVALID_INPUT
)
;
// Returns the translation for INVALID_INPUT
}
The resourceProvider method lets you "deploy" your localization files directly from the classpath, (i.E. from the resources/ folder, as done here), making it easy to bundle localization files with your application.
In this example, the localization file en_US.json will be loaded from the classpath's resources/ directory, and it will be used as the fallback language, and be copied as en_US.json in the working directory.
Parameterized Translations
Parameterized translations allow you to create dynamic messages by passing parameters to your translations. You can use the
@Parameters(...) annotation to define parameters in your translations:
Code (Java):
enum Message
implements LocalizationKey
{
@Parameters
(
"username"
)
USER_NOT_FOUND,
CONFIGURATION_ERROR,
INVALID_INPUT,
@Parameters
(
{
"player",
"action"
}
)
OPERATION_SUCCESS,
@Parameters
(
{
"reason",
"details"
}
)
OPERATION_FAILED,
}
You can then pass parameters to your translations like this, in the
exact
order they were declared in the annotation. This allows you to easily pass parameters to your translations without worrying about the parameter name or key:
Code (Java):
LOCALIZATION.
get
(Message.
USER_NOT_FOUND,
"Clickism"
)
;
LOCALIZATION.
get
(Message.
OPERATION_SUCCESS,
"Clickism",
"Creating a new config"
)
;
LOCALIZATION.
get
(Message.
OPERATION_FAILED,
"Invalid data",
"Data does not match expected format"
)
;
This will return the translation for USER_NOT_FOUND with the placeholder {username} replaced with "Clickism".
And for OPERATION_SUCCESS with the placeholders {player} and {action} replaced with "Clickism" and "created a new config", respectively.
And for OPERATION_FAILED with the placeholders {reason} and {details} replaced with "Invalid data"and "Data does not match expected format", respectively.
i.E, for a given localization file:
Code (YAML):
{
"user_not_found"
:
"User {username} not found.",
"operation_success"
:
"{player} successfully performed an operation: {action}.",
"operation_failed"
:
"Operation failed, reason: {reason}, details: {details}."
}
This will return the following messages:
Code (Text):
User Clickism not found.
Clickism successfully performed an operation: Creating a new config.
Operation failed, reason: Invalid data, details: Data does not match expected format.
If you have any feedback, feel free to share!
For more details:
https://github.com/Clickism/Configured