Skip to content

Commit a0d183b

Browse files
committed
Update readme
1 parent e16b308 commit a0d183b

File tree

1 file changed

+120
-80
lines changed

1 file changed

+120
-80
lines changed

README.md

Lines changed: 120 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -13,45 +13,45 @@
1313
* [Basic usage](#basic-usage)
1414
* [Message formatting](#message-formatting)
1515
* [Message loading](#message-loading)
16-
* [Manual messages creation](#manual-messages-creation)
17-
* [Loading messages from classpath or file system](#loading-messages-from-classpath-or-file-system)
18-
* [Single message file with multiple locales](#single-message-file-with-multiple-locales)
19-
* [Watching for file changes](#watching-for-file-changes)
16+
* [Manual messages creation](#manual-messages-creation)
17+
* [Loading messages from classpath or file system](#loading-messages-from-classpath-or-file-system)
18+
* [Single message file with multiple locales](#single-message-file-with-multiple-locales)
19+
* [Watching for file changes](#watching-for-file-changes)
2020
* [Message resolution](#message-resolution)
21-
* [Message fallbacks](#message-fallbacks)
22-
* [Prefixed queries](#prefixed-queries)
23-
* [Localized queries](#localized-queries)
21+
* [Message fallbacks](#message-fallbacks)
22+
* [Prefixed queries](#prefixed-queries)
23+
* [Localized queries](#localized-queries)
2424
* [Message references](#message-references)
25-
* [Reference resolution order](#reference-resolution-order)
26-
* [References in a prefixed file](#references-in-a-prefixed-file)
25+
* [Reference resolution order](#reference-resolution-order)
26+
* [References in a prefixed file](#references-in-a-prefixed-file)
2727
* [Type based formatters](#type-based-formatters)
2828
* [Missing messages](#missing-messages)
29-
* [Missing message handler](#missing-message-handler)
30-
* [Missing message detection](#missing-message-detection)
29+
* [Missing message handler](#missing-message-handler)
30+
* [Missing message detection](#missing-message-detection)
3131
* [Whitespace normalization](#whitespace-normalization)
3232
* [DevMode](#devmode)
3333

34-
3534
## Installation
3635

3736
Add to your `build.gradle`:
3837

3938
```gradle
4039
dependencies {
41-
implementation "com.coditory.quark:quark-i18n:0.0.8"
40+
implementation "com.coditory.quark:quark-i18n:$version"
4241
}
4342
```
4443

4544
## Basic usage
4645

4746
```java
4847
I18nMessagePack messagePack = I18nMessagePack.builder()
49-
.scanClassPath("/i18n/messages-{locale}.yml")
50-
.setDefaultLocale(Locales.EN_US)
51-
.build();
48+
.scanClassPath("/i18n/messages-{locale}.yml")
49+
.setDefaultLocale(Locales.EN_US)
50+
.build();
5251

5352
// ...when request arrives
5453
I18nMessages messages = messagePack.localize(req.getLocale());
54+
5555
print(messages.getMessage("greeting", userName));
5656
```
5757

@@ -92,31 +92,33 @@ Messages can be created in 3 ways:
9292

9393
```java
9494
I18nMessagePack messages = I18nMessagePack.builder()
95-
.addMessage(Loacles.EN_US, "hello", "Hello {0}")
96-
.addMessage(Loacles.PL_PL, "hello", "Cześć {0}")
97-
.setDefaultLocale(PL_PL)
98-
.build();
95+
.addMessage(Loacles.EN_US, "hello", "Hello {0}")
96+
.addMessage(Loacles.PL_PL, "hello", "Cześć {0}")
97+
.setDefaultLocale(PL_PL)
98+
.build();
9999

100-
messages.getMessage(Loacles.EN_US, "hello", userName);
100+
messages.
101+
102+
getMessage(Loacles.EN_US, "hello",userName);
101103
```
102104

103105
If you want to quickly load messages from a nested map (for example fetched from a document storage)
104106
you can use `I18nParsers.parseEntries(map, locale)` to translate nested the map keys into localized message paths.
105107

106108
```java
107109
I18nMessagePack messages = I18nMessagePack.builder()
108-
.addMessages(I18nParsers.parseEntries(Map.of("hello", "Hello {0}"), EN_US))
109-
.build();
110+
.addMessages(I18nParsers.parseEntries(Map.of("hello", "Hello {0}"), EN_US))
111+
.build();
110112
```
111113

112114
### Loading messages from classpath or file system
113115

114116
```java
115117
I18nMessagePack messages = I18nMessagePack.builder()
116-
.scanClassPath("/i18n/messages-{locale}.yml")
117-
.scanFileSystem("./overriddes/messages-{locale}.yml")
118-
.setDefaultLocale(PL_PL)
119-
.build();
118+
.scanClassPath("/i18n/messages-{locale}.yml")
119+
.scanFileSystem("./overriddes/messages-{locale}.yml")
120+
.setDefaultLocale(PL_PL)
121+
.build();
120122
```
121123

122124
Localization based path placeholders are used to assign all messages in the file to file's locale.
@@ -147,6 +149,7 @@ When path pattern does not contain one of localization placeholders (`{locale}`,
147149
then locale is parsed from the last segment of the message path:
148150

149151
Example in `yml`
152+
150153
```yml
151154
homepage.title:
152155
pl-PL: Strona główna
@@ -159,8 +162,12 @@ To reload messages in file change use:
159162
160163
```java
161164
I18nMessagePack.builder()
162-
.scanFileSystem("i18n/*")
163-
.buildAndWatchForChanges();
165+
.
166+
167+
scanFileSystem("i18n/*")
168+
.
169+
170+
buildAndWatchForChanges();
164171
```
165172

166173
ATM, it works for messages loaded from filesystem only, but for add your own implementation of `WatchableI18nLoader`.
@@ -173,10 +180,10 @@ If there is still no match then the default locale (followed by a less strict de
173180

174181
```java
175182
I18nMessagePack messages = I18nMessagePack.builder()
176-
.scanClassPath("/i18n/messages-{locale}.yml")
177-
.setDefaultLocale(PL_PL)
178-
.addFallbackKeyPrefix("glossary")
179-
.build();
183+
.scanClassPath("/i18n/messages-{locale}.yml")
184+
.setDefaultLocale(PL_PL)
185+
.addFallbackKeyPrefix("glossary")
186+
.build();
180187

181188
String message = messages.getMessage(Locales.en_US, "hello");
182189
```
@@ -194,10 +201,10 @@ Sometimes it is useful to specify a common path prefix for all unmatched queries
194201

195202
```java
196203
I18nMessagePack messages = I18nMessagePack.builder()
197-
.scanClassPath("/i18n/messages-{locale}.yml")
198-
.setDefaultLocale(PL_PL)
199-
.addMessageFallbackKeyPrefix("common")
200-
.build();
204+
.scanClassPath("/i18n/messages-{locale}.yml")
205+
.setDefaultLocale(PL_PL)
206+
.addMessageFallbackKeyPrefix("common")
207+
.build();
201208

202209
String message = messages.getMessage(Locales.en_US, "hello");
203210
```
@@ -217,9 +224,9 @@ Sometimes it's useful to prefix all queries with some path, like in the example:
217224

218225
```java
219226
I18nMessagePack messages = I18nMessagePack.builder()
220-
.scanClassPath("/i18n/messages-{locale}.yml")
221-
.setDefaultLocale(PL_PL)
222-
.build();
227+
.scanClassPath("/i18n/messages-{locale}.yml")
228+
.setDefaultLocale(PL_PL)
229+
.build();
223230

224231
I18nMessagePack homepageMessages = messages.prefixQueries("pages.homepage");
225232
String homepageTitle = homepageMessages.getMessage(en_US, "title");
@@ -241,9 +248,9 @@ Sometimes it's useful to apply common locale to all queries:
241248

242249
```java
243250
I18nMessagePack messagePack = I18nMessagePack.builder()
244-
.scanClassPath("/i18n/messages-{locale}.yml")
245-
.setDefaultLocale(PL_PL)
246-
.build();
251+
.scanClassPath("/i18n/messages-{locale}.yml")
252+
.setDefaultLocale(PL_PL)
253+
.build();
247254

248255
// ...when request arrives
249256
I18nMessages messages = messagePack.localize(req.getLocale());
@@ -255,15 +262,16 @@ Query localization mechanism can be used together with query prefixes:
255262

256263
```java
257264
I18nMessages messages = messagePack
258-
.prefixQueries("pages.homepage")
259-
.localize(req.getLocale());
265+
.prefixQueries("pages.homepage")
266+
.localize(req.getLocale());
260267
```
261268

262269
## Message references
263270

264271
Message references are the way to reuse text across multiple messages.
265272

266273
Example in yml:
274+
267275
```yml
268276
# Common entries
269277
company:
@@ -274,7 +282,7 @@ about-company: "${company.name} was established on ${company.established}"
274282
```
275283
276284
```java
277-
messages.getMessage("about-company") == "ACME was established on 1988"
285+
messages.getMessage("about-company") =="ACME was established on 1988"
278286
```
279287

280288
- It's not a part of ICU standard
@@ -283,7 +291,8 @@ messages.getMessage("about-company") == "ACME was established on 1988"
283291
with `i18nMessagePackBuilder.addReferenceFallbackKeyPrefix()` ([example](#sample-reference-resolution))
284292
- References in prefixed files are prefixed as
285293
well `${foo} -> ${<file-prefix>.foo}` ([example](#sample-reference-resolution-from-a-prefixed-file))
286-
- References can have a short notation `$common.reference` and long one `${common.reference}`. The long one is useful when
294+
- References can have a short notation `$common.reference` and long one `${common.reference}`. The long one is useful
295+
when
287296
there reference is placed next to `[a-zA-Z0-9-_]`, like in `abc${common.reference}abc$`.
288297

289298
### Reference resolution order
@@ -292,11 +301,11 @@ Let's configure messages:
292301

293302
```java
294303
I18nMessagePack messagePack = I18nMessagePack.builder()
295-
.addMessage(EN_US, "msg", "${company.name} was established on 1988")
296-
.scanClassPath("/i18n/messages-{locale}.yml")
297-
.setDefaultLocale(PL_PL)
298-
.addFallbackKeyPrefix("fallback")
299-
.build();
304+
.addMessage(EN_US, "msg", "${company.name} was established on 1988")
305+
.scanClassPath("/i18n/messages-{locale}.yml")
306+
.setDefaultLocale(PL_PL)
307+
.addFallbackKeyPrefix("fallback")
308+
.build();
300309
```
301310

302311
Locations used to find the message:
@@ -314,10 +323,10 @@ If the reference is defined in a message stored in a prefixed file it will be au
314323

315324
```java
316325
I18nMessagePack messagePack = I18nMessagePack.builder()
317-
.scanClassPathLocation("i18n/{prefix}/message_{locale}.yml")
318-
.setDefaultLocale(PL_PL)
319-
.addFallbackKeyPrefix("fallback")
320-
.build();
326+
.scanClassPathLocation("i18n/{prefix}/message_{locale}.yml")
327+
.setDefaultLocale(PL_PL)
328+
.addFallbackKeyPrefix("fallback")
329+
.build();
321330
```
322331

323332
and file `i18n/company/message_en-US.yml` contains
@@ -340,6 +349,7 @@ Locations used to find the message:
340349
## Type based formatters
341350

342351
You can map arguments by their type using argument transformers:
352+
343353
- transformation is located in the definition order
344354
- only the arguments used in the message are transformed
345355
- transformation is transitive - one value can be transformed multiple times
@@ -348,11 +358,13 @@ Example:
348358

349359
```java
350360
I18nMessages messages = I18nMessagePack.builder()
351-
.addMessage(EN, "msg", "{0,number,00000.00000}")
352-
.addArgumentTransformer(Foo, (foo) -> foo.getSomeNumber())
353-
.buildLocalized(EN);
361+
.addMessage(EN, "msg", "{0,number,00000.00000}")
362+
.addArgumentTransformer(Foo, (foo) -> foo.getSomeNumber())
363+
.buildLocalized(EN);
364+
365+
messages.
354366

355-
messages.getMessage("msg", new Foo(123.456)) == "00123.45600"
367+
getMessage("msg",new Foo(123.456))=="00123.45600"
356368
```
357369

358370
## Missing messages
@@ -366,7 +378,9 @@ When message is missing, exception is thrown. This mechanism can be changed with
366378
i18nMessagePackBuilder.setMissingMessageHandler(customHandler);
367379

368380
// ...or simply return message path when message is missing
369-
i18nMessagePackBuilder.usePathOnMissingMessage();
381+
i18nMessagePackBuilder.
382+
383+
usePathOnMissingMessage();
370384
```
371385

372386
### Missing message detection
@@ -375,6 +389,7 @@ It's important to find about missing messages as quickly as possible
375389
and avoid finding them on production.
376390

377391
That's why there is an option to detect them during build phase:
392+
378393
```
379394
i18nMessagePackBuilder.validateNoMissingMessages() - throws exception on missing message
380395
i18nMessagePackBuilder.logMissingMessages() - simply logs a report about missing messages
@@ -384,14 +399,25 @@ i18nMessagePackBuilder.logMissingMessages() - simply logs a report about missing
384399

385400
```java
386401
I18nMessagePack.builder()
387-
.addMessage(EN_US, "hello", "Hello")
388-
.addMessage(PL_PL, "hello", "Cześć")
389-
.addMessage(DE_DE, "bye", "Tschüss")
390-
.logMissingMessages()
391-
.build();
402+
.
403+
404+
addMessage(EN_US, "hello","Hello")
405+
.
406+
407+
addMessage(PL_PL, "hello","Cześć")
408+
.
409+
410+
addMessage(DE_DE, "bye","Tschüss")
411+
.
412+
413+
logMissingMessages()
414+
.
415+
416+
build();
392417
```
393418

394419
Will generate following report:
420+
395421
```
396422
Missing Messages
397423
================
@@ -414,17 +440,31 @@ You can skip them using a custom missing message detector:
414440

415441
```java
416442
I18nMissingMessagesDetector detector = I18nMissingMessagesDetector.builder()
417-
.skipPath(skipPath)
418-
.logMissingMessages()
419-
.build()
443+
.skipPath(skipPath)
444+
.logMissingMessages()
445+
.build()
420446

421-
I18nMessagePack.builder()
422-
.addMessage(EN_US, "a.b.c.d", "MISSING")
423-
.addMessage(EN_US, "x", "X")
424-
.addMessage(EN_GB, "x", "X")
425-
.addMessage(PL_PL, "x", "X")
426-
.detectMissingMessages(detector)
427-
.build();
447+
I18nMessagePack.
448+
449+
builder()
450+
.
451+
452+
addMessage(EN_US, "a.b.c.d","MISSING")
453+
.
454+
455+
addMessage(EN_US, "x","X")
456+
.
457+
458+
addMessage(EN_GB, "x","X")
459+
.
460+
461+
addMessage(PL_PL, "x","X")
462+
.
463+
464+
detectMissingMessages(detector)
465+
.
466+
467+
build();
428468

429469
// to skip a.b.c.d use one of sample path patterns as a skipPath:
430470
// - "a.b.c.d",
@@ -453,12 +493,12 @@ You can use file watching capabilities to speed up the development cycle:
453493

454494
```java
455495
I18nMessagePackBuidler messagesBuilder = I18nMessagePack.builder()
456-
.setDefaultLocale(EN_US);
457-
// ... other common settings
496+
.setDefaultLocale(EN_US);
497+
// ... other common settings
458498

459499
I18nMessagePack messages = devMode
460-
? messagesBuilder.scanFileSystem("src/main/resources/i18n/*").buildAndWatchForChanges()
461-
: messagesBuilder.scanClassPath("i18n/*").build();
500+
? messagesBuilder.scanFileSystem("src/main/resources/i18n/*").buildAndWatchForChanges()
501+
: messagesBuilder.scanClassPath("i18n/*").build();
462502
```
463503

464504
Following setup will load messages directly from project structure and watch for changes.

0 commit comments

Comments
 (0)