You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 68eb11f
Browse filesBrowse the repository at this point in the historyBrowse files
@@ -168,6 +168,8 @@ Messagevisor m = Messagevisor.create(
168
168
169
169
There is also a simpler interpolation module that can be used to interpolate primitive values into messages without the full ICU MessageFormat syntax.
170
170
171
+
The ICU module evaluates only the selected `select`, `plural`, or `selectordinal` branch. Values used exclusively by other branches are not required, and their formatters do not run. A missing argument in the selected branch reports `invalid_message` and throws. Apostrophe quoted ICU syntax stays literal, and inserted values are never parsed again as message syntax.
172
+
171
173
## Translations
172
174
173
175
Now that we have the SDK instance, we can start translating messages.
@@ -298,7 +300,7 @@ Messagevisor m = Messagevisor.create(
298
300
);
299
301
```
300
302
301
-
The generated datafile already contains locale info, so you do not need to pass it manually.
303
+
The generated datafile already contains locale info, so you do not need to pass it manually. An initial datafile establishes the active locale even when a different constructor `locale` is supplied.
302
304
303
305
### Setting datafile afterwards
304
306
@@ -314,7 +316,13 @@ When no locale is active yet, the first successful `setDatafile` call also sets
314
316
315
317
You can keep calling `setDatafile` to update the datafile for a given locale.
316
318
317
-
If the SDK already has a datafile for the incoming locale, `setDatafile` merges the incoming datafile with the existing one by default. Segments, messages, and translations are merged by key, while top-level fields such as `revision`, `target`, and `formats` come from the incoming datafile.
319
+
If the SDK already has a datafile for the incoming locale, `setDatafile` merges the incoming datafile with the existing one by default. Segments, messages, and translations are merged by key, while fields such as `revision` and `target` come from the incoming datafile. Formats merge by family and preset name. Omitted families and presets remain available, and an incoming preset with the same name replaces the whole stored preset. Evaluation still combines default formats, stored formats, and call formats field by field.
320
+
321
+
Typed `DatafileContent` inputs are copied on entry, just like parsed JSON. Loading, merging, or replacing a datafile does not mutate the supplied object or another independent instance that received it. To update stored state, call `setDatafile` again rather than editing the original input.
322
+
323
+
Malformed JSON or an invalid datafile shape reports `invalid_datafile` with the message `could not parse datafile`. The call does not throw or change stored state. A datafile requires `schemaVersion: "1"`, string identity fields, a nonempty `locale`, and object maps for `segments`, `messages`, and `translations`. Optional `formats` must be an object and optional `direction` must be `ltr` or `rtl`. Java also validates values when converting JSON into its typed datafile models.
324
+
325
+
Dictionary keys such as `constructor`, `toString`, and `__proto__` are ordinary keys. They resolve only when present, including in translations, defaults, named presets, segments, and context maps.
318
326
319
327
### Replacing datafile
320
328
@@ -348,7 +356,7 @@ Once you have the desired datafiles set, switch between loaded locales at runtim
348
356
m.setLocale("nl-NL");
349
357
```
350
358
351
-
The SDK switches the active locale to one that already has a datafile loaded. `setLocale` throws if that locale has no datafile yet.
359
+
The SDK switches the active locale to one that already has a datafile loaded. `setLocale`reports `missing_datafile` and throws if that locale has no datafile yet, leaving the active locale unchanged.
352
360
353
361
**NOTE**: `setDatafile` for a new locale does not change the active locale automatically. The first datafile loaded becomes active, and later `setDatafile` calls for other locales only register those datafiles until you call `setLocale`.
354
362
@@ -503,7 +511,7 @@ m.formatDate(
503
511
);
504
512
```
505
513
506
-
Time zone resolution follows the same rules as [Time zone](#time-zone): per-call `timeZone`, then the preset's `timeZone`, then the instance time zone.
514
+
Time zone resolution follows the same rules as [Time zone](#time-zone): the call's`timeZone`, then the preset's `timeZone`, then the instance time zone, then the host default captured when the root instance was created. Children share that captured host default. This also applies to ICU date and time arguments, including bare arguments, styles, skeletons, and nested branches. A bare direct `formatTime` call formats hours, minutes, and seconds. Unknown time zone identifiers are rejected rather than silently becoming GMT.
507
515
508
516
Use `formatDateToParts` for segmented output:
509
517
@@ -584,7 +592,7 @@ m.formatList(
584
592
);
585
593
```
586
594
587
-
Options are mapped to ICU4J list formatting behavior. Use `formatListToParts`for simplified element parts.
595
+
Options are mapped to ICU4J list formatting behaviour. `formatListToParts`returns native element and literal records, preserving conjunctions and separators. Joining the part values reproduces `formatList`; an empty list returns no parts.
// → "other" in English, because the visible number is 1.00
613
624
```
614
625
626
+
The options map accepts plural `type` (`cardinal` or `ordinal`), fraction and significant digit precision, and rounding options. These affect the plural operands, not just display. You can include `locale` in the map or pass a separate `EvaluationOptions`. Children expose the same overloads.
627
+
615
628
You can also pass `EvaluationOptions` when the plural category should use a different locale:
616
629
617
630
```java
@@ -822,9 +835,9 @@ Common built-in codes include:
822
835
-`missing_translation`: key missing from datafile and `defaultTranslations`
823
836
-`missing_datafile` / `missing_locale`: locale or datafile not available
824
837
-`missing_format`: a requested named format preset is absent
825
-
-`invalid_format`: formatter options are invalid for the runtime
838
+
-`invalid_format`: formatter options or date values are invalid for the runtime, including unknown time zones; the exception is rethrown
826
839
-`invalid_datafile`: JSON parse or shape failure
827
-
-`invalid_message`: module formatting threw
840
+
-`invalid_message`: a module format or transform hook threw; details include the hook and effective locale, and the original exception is rethrown
828
841
-`deprecated_message`: message has deprecated metadata
829
842
-`message_override_matched`: debug-level override match
830
843
-`unsupported_formatter`: runtime-native formatter limitation or unsupported option
@@ -901,6 +914,12 @@ m.removeModule("icu");
901
914
902
915
Resolver changes installed during module setup belong to that module. Setup failure or removal restores the previous resolver, and spawned instances observe later parent resolver changes dynamically.
903
916
917
+
Removal also clears that module's diagnostic subscriptions and resolver registrations in existing children. Retained module APIs cannot register new subscriptions or resolvers after removal. Closing a child clears its own registrations without closing shared modules.
918
+
919
+
Constructor modules run setup after initial locale, defaults, and datafile state are ready, and before `sdk_initialized` is reported. Setup failure reports `module_setup_error`, cleans up partial registration, and does not throw from construction.
920
+
921
+
Java completes the failed module's synchronous cleanup before delivering `module_setup_error`, so a diagnostic observer may safely close the SDK. The original setup failure remains the diagnostic's cause even if partial cleanup also fails.
922
+
904
923
### Registering at project level
905
924
906
925
It is recommended that the same modules you use with the SDK in your application are also registered in your Messagevisor project configuration.
@@ -980,6 +999,8 @@ m.close();
980
999
m.closeAsync().join();
981
1000
```
982
1001
1002
+
Concurrent and repeated `closeAsync()` calls share the same completion future, including any aggregate cleanup failure. A concurrent `close()` waits for that cleanup too. Modules are closed once, in reverse registration order.
1003
+
983
1004
## Translation lookup
984
1005
985
1006
`translate` and `getRawTranslation` resolve a source string first, then run registered modules on that string. Understanding lookup helps when debugging overrides, fallbacks, and missing-translation diagnostics.
@@ -1031,6 +1052,8 @@ After the source string is resolved, `translate` runs modules in registration or
1031
1052
1032
1053
The Java CLI reuses the JavaScript Messagevisor CLI for source-project truth. It shells out to `npx messagevisor` for built datafiles, tests, segments, and examples, then evaluates them with the Java SDK.
1033
1054
1055
+
The examples command compares every Java result with `expectedByRuntime.java` when present, otherwise with the JavaScript `evaluatedTranslation`. Mismatches make the command fail. Use `--onlyFailures` for compact output and `--normalizeSpaces` to treat only ordinary spaces, no break spaces, and narrow no break spaces as equivalent. Both reference project Make targets use only the ICU module, matching the project configuration.
1056
+
1034
1057
The SDK test suite also executes the canonical language-neutral `conformance/sdk-v1.json` contract. That contract covers conditions and segments, combined override matching, empty and fallback translations, deprecation diagnostics, locale-keyed datafile merge/replacement, module lifecycle, diagnostic envelopes, and event ordering with change sources. The bundled fixture is checked against the monorepo copy when both repositories are available.
1035
1058
1036
1059
```sh
@@ -1079,7 +1102,7 @@ make verify-artifacts
1079
1102
1080
1103
1. Update `gradle.properties`, the installation versions in this README, and `CHANGELOG.md` to the same release version.
1081
1104
2. Merge the release commit into `main`.
1082
-
3. Create and publish a GitHub release using a semantic version tag with a `v` prefix, such as `v0.2.0`.
1105
+
3. Create and publish a GitHub release using a semantic version tag with a `v` prefix, such as `v0.3.0`.
1083
1106
4. GitHub Actions validates the tag, builds and tests every artifact, checks the publication boundaries, and publishes the signed artifacts to the configured Maven repository.
1084
1107
5. Verify the published POMs, JARs, source JARs, Javadoc JARs, signatures, and checksums from a clean consumer project.
1085
1108
@@ -1101,7 +1124,7 @@ Where Messagevisor project fixtures need cross-runtime expectations, prefer `exp
1101
1124
1102
1125
Do not add Java branches for specific locales, named time zones, unit labels, or compact suffixes. Use ICU4J locale APIs such as number, measure, date/time, relative, list, and display-name formatting, then document unavoidable differences in fixtures.
1103
1126
1104
-
The ICU module uses ICU4J classic `MessageFormat`. ICU MessageFormat 2 is intentionally not used for this first Java port because it is still treated as a newer technical-preview style API in the ICU ecosystem.
1127
+
The ICU module uses ICU4J's classic message parser and native plural rules and formatters. It traverses the parsed message to evaluate only selected branches, while ICU handles apostrophe quoting, number styles, and skeletons. ICU MessageFormat 2 is not used.
0 commit comments