Skip to content

Commit f841062

Browse files
committed
chore: license file
1 parent 0f0f701 commit f841062

File tree

7 files changed

+547
-1
lines changed

7 files changed

+547
-1
lines changed

README.MD

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# Translatica
2+
3+
**Translatica** is a lightweight Java library for managing messages and translations using `ResourceBundle`. It allows you to register and retrieve localized messages based on `Locale`, making internationalization of applications easier.
4+
5+
## Installation
6+
7+
### Maven
8+
Add the following dependency to your `pom.xml`:
9+
10+
```xml
11+
<dependency>
12+
<groupId>io.github.mtbarr</groupId>
13+
<artifactId>translatica</artifactId>
14+
<version>1.0-SNAPSHOT</version>
15+
</dependency>
16+
```
17+
18+
### Gradle
19+
Add the following to your `build.gradle`:
20+
21+
```groovy
22+
dependencies {
23+
implementation 'io.github.mtbarr:translatica:1.0-SNAPSHOT'
24+
}
25+
```
26+
27+
## Usage Example
28+
29+
The main class of the project is `MessageRegistry`, which allows you to register and retrieve messages from properties files. Below are some examples of how to use the library.
30+
31+
### Registering Messages
32+
33+
```java
34+
import io.github.mtbarr.translatica.MessageRegistry;
35+
36+
public class Main {
37+
public static void main(String[] args) {
38+
// Create a message registry using the default "messages.properties" file
39+
MessageRegistry registry = new MessageRegistry();
40+
41+
// Alternatively, specify a custom properties file
42+
MessageRegistry customRegistry = new MessageRegistry("customMessages");
43+
}
44+
}
45+
```
46+
47+
### Retrieving Messages
48+
49+
```java
50+
import io.github.mtbarr.translatica.MessageRegistry;
51+
52+
import java.util.Locale;
53+
54+
public class Main {
55+
public static void main(String[] args) {
56+
// Create a registry
57+
// Creating it with no arguments will use the default "messages.properties" file
58+
MessageRegistry registry = new MessageRegistry();
59+
// MessageRegistry registry = new MessageRegistry("custom_messages");
60+
61+
62+
// Retrieve a message with the default locale
63+
String message = registry.get("welcome.message");
64+
65+
// Retrieve a message for a specific locale
66+
String messageInFrench = registry.get(Locale.FRENCH, "welcome.message");
67+
68+
// Retrieve a message with replacements
69+
String formattedMessage = registry.get("welcome.user", "John");
70+
71+
System.out.println(message); // Output: Welcome!
72+
System.out.println(messageInFrench); // Output: Bienvenue!
73+
System.out.println(formattedMessage); // Output: Welcome, John!
74+
}
75+
}
76+
```
77+
78+
### Static Access
79+
80+
You can also use the static methods for accessing messages without needing to instantiate `MessageRegistry`:
81+
82+
```java
83+
import io.github.mtbarr.translatica.MessageRegistry;
84+
85+
public class Main {
86+
public static void main(String[] args) {
87+
// Retrieve a message statically
88+
String message = MessageRegistry.getMessage("welcome.message");
89+
90+
// Retrieve a formatted message statically
91+
String formattedMessage = MessageRegistry.getFormattedMessage("welcome.user", "John");
92+
93+
System.out.println(message); // Output: Welcome!
94+
System.out.println(formattedMessage); // Output: Welcome, John!
95+
}
96+
}
97+
```
98+
99+
## Features
100+
101+
- **Locale-based message retrieval**: Get translated messages based on the `Locale`.
102+
- **Message formatting**: Supports message formatting with dynamic replacements.
103+
- **Simple resource bundle registration**: Easily register message bundles from `.properties` files.
104+
- **Static methods**: Access messages without creating an instance of `MessageRegistry`.
105+
106+
## License
107+
108+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

build.gradle

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,17 @@ repositories {
1212
dependencies {
1313
testImplementation platform('org.junit:junit-bom:5.10.0')
1414
testImplementation 'org.junit.jupiter:junit-jupiter'
15+
16+
compileOnly 'org.jetbrains:annotations:20.1.0'
17+
annotationProcessor 'org.jetbrains:annotations:20.1.0'
18+
}
19+
20+
java {
21+
toolchain {
22+
languageVersion = JavaLanguageVersion.of(8)
23+
}
1524
}
1625

1726
test {
1827
useJUnitPlatform()
19-
}
28+
}
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
package io.github.mtbarr.translatica;
2+
3+
import org.jetbrains.annotations.NotNull;
4+
5+
import java.nio.charset.StandardCharsets;
6+
import java.text.MessageFormat;
7+
import java.util.*;
8+
import java.util.concurrent.ConcurrentHashMap;
9+
import java.util.concurrent.CopyOnWriteArrayList;
10+
11+
/**
12+
* A registry of keyed messages with the source {@link Locale}.
13+
*
14+
* @author Matheus Barreto
15+
*/
16+
public final class MessageRegistry {
17+
18+
19+
private static MessageRegistry instance;
20+
21+
private final Map<Locale, List<ResourceBundle>> bundles = new ConcurrentHashMap<>();
22+
23+
public MessageRegistry(@NotNull String propertiesFileName) {
24+
this.registerMessages(PropertyResourceBundle.getBundle(propertiesFileName));
25+
}
26+
27+
/**
28+
* Default constructor using 'messages' file
29+
*/
30+
public MessageRegistry() {
31+
this("messages");
32+
}
33+
34+
35+
/**
36+
* Register all messages present in the provided resource bundle.
37+
*
38+
* @param resourceBundle ResourceBundle containing all messages.
39+
**/
40+
public void registerMessages(@NotNull ResourceBundle resourceBundle) {
41+
List<ResourceBundle> bundleList = bundles.computeIfAbsent(resourceBundle.getLocale(), key -> new CopyOnWriteArrayList<>());
42+
bundleList.add(resourceBundle);
43+
}
44+
45+
/**
46+
* Register all messages from the provided ResourceBundle that are registered.
47+
*
48+
* @param resourceBundle provided resouce bundle.
49+
*/
50+
public void unregisterMessages(@NotNull ResourceBundle resourceBundle) {
51+
List<ResourceBundle> bundleList = bundles.get(resourceBundle.getLocale());
52+
if (bundleList != null) {
53+
bundleList.removeIf(bundle -> bundle.getLocale().equals(resourceBundle.getLocale()));
54+
}
55+
}
56+
57+
/**
58+
* Gets a keyed message according to the provided Locale.
59+
*
60+
* @param locale message locale.
61+
* @param key message key.
62+
* @return a translated message valued based on {@param locale} provided.
63+
* @throws IllegalArgumentException if the message value is not found.
64+
*/
65+
public String get(Locale locale, String key) {
66+
List<ResourceBundle> bundleList = bundles.get(locale);
67+
if (bundleList == null) {
68+
throw new IllegalArgumentException("Cannot found resource bundle for this locale.");
69+
}
70+
71+
for (ResourceBundle bundle : bundleList) {
72+
return this.findBundleMessage(key, bundle);
73+
}
74+
75+
throw new NullPointerException("Cannot found message keyed with " + key + " key on locale " + locale.getDisplayName());
76+
}
77+
78+
79+
/**
80+
* Gets a keyed message according to the default Locale.
81+
*
82+
* @param key message key.
83+
* @return a translated message valued based on default locale.
84+
* @throws IllegalArgumentException if the message value is not found.
85+
*/
86+
@NotNull
87+
public String get(String key) {
88+
return get(Locale.getDefault(), key);
89+
}
90+
91+
/**
92+
* Equivalent to {@link MessageRegistry#get(Locale, String)}
93+
* but with replacements being provided.
94+
*
95+
* @param locale message locale
96+
* @param key message key
97+
* @param replacements message replacements
98+
* @return a final replaced version of initial keyed message.
99+
* @throws IllegalArgumentException if the message value is not found.
100+
*/
101+
@NotNull
102+
public String get(Locale locale, String key, Object... replacements) {
103+
return String.format(get(locale, key), replacements);
104+
}
105+
106+
107+
/**
108+
* Equivalent to {@link MessageRegistry#get(String)}
109+
* but with replacements being provided.
110+
*
111+
* @param key message key
112+
* @param replacements message replacements
113+
* @return a final replaced version of initial keyed message.
114+
* @throws IllegalArgumentException if the message value is not found.
115+
*/
116+
@NotNull
117+
public String get(String key, Object... replacements) {
118+
return get(Locale.getDefault(), key, replacements);
119+
}
120+
121+
/**
122+
* Gets the main instance of the message registry.
123+
*/
124+
public static MessageRegistry getInstance() {
125+
if (instance == null) {
126+
instance = new MessageRegistry();
127+
}
128+
129+
return instance;
130+
}
131+
132+
/**
133+
* Gets a keyed message according to the provided Locale.
134+
*
135+
* @param locale message locale.
136+
* @param key message key.
137+
* @return a translated message valued based on {@param locale} provided.
138+
* @throws IllegalArgumentException if the message value is not found.
139+
*/
140+
@NotNull
141+
public static String getMessage(@NotNull Locale locale, @NotNull String key) {
142+
return getInstance().get(locale, key);
143+
}
144+
145+
/**
146+
* Equivalent to {@link MessageRegistry#get(Locale, String)}
147+
* but with replacements being provided.
148+
*
149+
* @param locale message locale
150+
* @param key message key
151+
* @param replacements message replacements
152+
* @return a final replaced version of initial keyed message.
153+
* @throws IllegalArgumentException if the message value is not found.
154+
*/
155+
@NotNull
156+
public static String getMessage(@NotNull Locale locale, @NotNull String key, @NotNull Object... replacements) {
157+
return getInstance().get(locale, key, replacements);
158+
}
159+
160+
/**
161+
* Gets a keyed message according to the default Locale.
162+
*
163+
* @param key message key.
164+
* @return a translated message valued based on default locale.
165+
* @throws IllegalArgumentException if the message value is not found.
166+
*/
167+
@NotNull
168+
public static String getMessage(@NotNull String key) {
169+
return getInstance().get(key);
170+
}
171+
172+
/**
173+
* Equivalent to {@link MessageRegistry#get(String)}
174+
* but with replacements being provided.
175+
*
176+
* @param key message key
177+
* @param replacements message replacements
178+
* @return a final replaced version of initial keyed message.
179+
* @throws IllegalArgumentException if the message value is not found.
180+
*/
181+
@NotNull
182+
public static String getMessage(@NotNull String key, @NotNull Object... replacements) {
183+
return getInstance().get(key, replacements);
184+
}
185+
186+
/**
187+
* Equivalent to {@link MessageRegistry#get(String, Object...)}
188+
* but using {@link MessageFormat#format(String, Object...)}
189+
*
190+
* @param key message key
191+
* @param replacements message replacements
192+
* @return a final replaced version of initial keyed message.
193+
* @throws IllegalArgumentException if the message value is not found.
194+
*/
195+
@NotNull
196+
public static String getFormattedMessage(@NotNull String key, Object... replacements) {
197+
return MessageFormat.format(getMessage(key), replacements);
198+
}
199+
200+
/**
201+
* Get a section of the message registry.
202+
* <p>
203+
* Example:
204+
* foo.bar.baz
205+
* <p></>
206+
* Where foo is the section, bar is the subsection and baz is the key.
207+
*
208+
* @param sectionName the section name.
209+
* @return a section of the message registry.
210+
*/
211+
public static MessageSection getSection(String sectionName) {
212+
return new MessageSection(sectionName);
213+
}
214+
215+
private static String encodeToUtf8(String value) {
216+
byte[] bytes = value.getBytes();
217+
return new String(bytes, StandardCharsets.UTF_8);
218+
}
219+
220+
private String findBundleMessage(String key, ResourceBundle bundle) {
221+
try {
222+
return bundle.getString(key);
223+
} catch (Exception e) {
224+
throw new NullPointerException("Cannot found message keyed with " + key + " key on bundle " + bundle.getBaseBundleName());
225+
}
226+
}
227+
}

0 commit comments

Comments
 (0)