ColorAPI (1.18+) Spigot API

public class ColorAPI {
    
    private static final Pattern PATTERN = Pattern.compile(
            "<(#[a-fA-F0-9]{6}|aqua|black|blue|dark_(aqua|blue|gray|green|purple|red)|gray|gold|green|light_purple|red|white|yellow)>",
            Pattern.CASE_INSENSITIVE
    );

    public static String translateColors(String text) {
        if (text == null || text.isEmpty()) {
            return "";
        }

        final Matcher matcher = PATTERN.matcher(text);

        while (matcher.find()) {
            String match = matcher.group(1);
            if (match.startsWith("#")) {
                String hex = match.substring(1);
                StringBuilder formattedHex = new StringBuilder("§x");
                for (char c : hex.toCharArray()) {
                    formattedHex.append("§").append(c);
                }
                text = text.replace(matcher.group(), formattedHex.toString());
            } else {
                try {
                    final ChatColor chatColor = ChatColor.valueOf(match.toUpperCase().replace("DARK_", "DARK").replace("_", ""));
                    text = StringAPI.replace(text, matcher.group(), chatColor.toString());
                } catch (IllegalArgumentException ignored) {
                }
            }
        }
        return ChatColor.translateAlternateColorCodes('&', text);
    }

    public static List<String> translateColors(List<String> lines) {
        if (lines == null || lines.isEmpty()) return List.of();
        return lines.stream()
                .map(ColorAPI::translateColors)
                .collect(Collectors.toList());
    }

    public static String stripColors(String text) {
        if (text == null || text.isEmpty()) {
            return "";
        }

        text = ChatColor.stripColor(text);
        text = text.replaceAll("&[0-9a-fk-orA-FK-OR]", "");
        text = text.replaceAll("&#[a-fA-F0-9]{6}", "");
        text = PATTERN.matcher(text).replaceAll("");

        return text;
    }
}

You can then use different color codes in the config.yml file:

Normal: <aqua>, <black>, <blue>, <gray>, <gold>, <green>, <light_purple>, <red>, <white>, <yellow>

Dark: <dark_aqua>, <dark_blue>, <dark_gray>, <dark_green>, <dark_purple>, <dark_red>

Hex: <#RRGGBB>

and the regular color codes (&).

Use cases:

// Single Message
player.sendMessage(ColorAPI.translateColors("<gold>&lHello &r<gray>World"));
// Hex Color
player.sendMessage(ColorAPI.translateColors("<#FF8800>Orange Text"));
// Default & Codes
player.sendMessage(ColorAPI.translateColors("&6Gold &lBold &r&7Normal"));

// Colored List
List<String> lore = List.of("<gray>Line 1", "<yellow>Line 2");
itemMeta.setLore(ColorAPI.translateColors(lore));
item.setItemMeta(itemMeta);

// Load and color from config
String raw = getConfig().getString("messages.welcome", "<green>Welcome!");
player.sendMessage(ColorAPI.translateColors(raw));

// Broadcast
Bukkit.getServer().broadcastMessage(ColorAPI.translateColors("<red>Maintenance &ein 5 minutes"));

// Remove color formatting
String plain = ColorAPI.stripColors("<#12ABEF>Text &lBold");