2323import com .google .gson .stream .JsonReader ;
2424import com .google .gson .stream .JsonToken ;
2525import com .google .gson .stream .JsonWriter ;
26- import org .jetbrains .annotations .NotNull ;
26+ import org .jackhuang .hmcl .util .gson .JsonSerializable ;
27+ import org .jetbrains .annotations .NotNullByDefault ;
2728import org .jetbrains .annotations .Nullable ;
2829
2930import java .io .IOException ;
3031import java .util .*;
3132
33+ /// Represents text that may either be locale-independent or stored as values keyed by language tags.
34+ ///
35+ /// The JSON representation accepts either a string or an object. A string is treated as the same text for every
36+ /// locale, while an object maps language keys, such as `en`, `zh-Hans`, or `default`, to localized text values.
37+ ///
38+ /// @author Glavo
39+ @ NotNullByDefault
3240@ JsonAdapter (LocalizedText .Adapter .class )
41+ @ JsonSerializable
3342public final class LocalizedText {
43+ /// Locale-independent text used when this instance is not backed by localized values.
3444 private final @ Nullable String value ;
45+
46+ /// Text values keyed by language keys generated by [LocaleUtils#toLanguageKey(Locale)].
3547 private final @ Nullable Map <String , String > localizedValues ;
3648
37- public LocalizedText (String value ) {
49+ /// Creates a locale-independent text value.
50+ ///
51+ /// When `value` is `null`, [#getText(List)] returns `null` for every candidate locale.
52+ ///
53+ /// @param value the text value, or `null` if the text is absent
54+ public LocalizedText (@ Nullable String value ) {
3855 this .value = value ;
3956 this .localizedValues = null ;
4057 }
4158
42- public LocalizedText (@ NotNull Map <String , String > localizedValues ) {
59+ /// Creates a localized text value backed by language-key mappings.
60+ ///
61+ /// The map is stored directly and is not copied. Later changes to `localizedValues` are visible through this
62+ /// instance.
63+ ///
64+ /// @param localizedValues text values keyed by language keys generated by [LocaleUtils#toLanguageKey(Locale)]
65+ /// @throws NullPointerException if `localizedValues` is `null`
66+ public LocalizedText (Map <String , String > localizedValues ) {
4367 this .value = null ;
4468 this .localizedValues = Objects .requireNonNull (localizedValues );
4569 }
4670
47- public String getText (@ NotNull List <Locale > candidates ) {
71+ /// Returns the best matching text for the given candidate locales.
72+ ///
73+ /// If this instance stores localized values, the candidates are checked in iteration order after conversion with
74+ /// [LocaleUtils#toLanguageKey(Locale)]. The first matching value is returned, or `null` if no candidate matches.
75+ /// If this instance stores locale-independent text, the stored value is returned without checking `candidates`.
76+ ///
77+ /// @param candidates candidate locales ordered from most preferred to least preferred
78+ /// @return the matched text, the locale-independent text, or `null` if no text is available
79+ public @ Nullable String getText (List <Locale > candidates ) {
4880 if (localizedValues != null ) {
4981 for (Locale locale : candidates ) {
5082 String value = localizedValues .get (LocaleUtils .toLanguageKey (locale ));
@@ -56,10 +88,17 @@ public String getText(@NotNull List<Locale> candidates) {
5688 return value ;
5789 }
5890
91+ /// Gson adapter for the compact localized text JSON representation.
5992 static final class Adapter extends TypeAdapter <LocalizedText > {
6093
94+ /// Reads a localized text value from `null`, a JSON string, or a JSON object.
95+ ///
96+ /// @param jsonReader the reader positioned at the next localized text value
97+ /// @return the parsed localized text, or `null` if the next JSON token is `null`
98+ /// @throws IOException if reading from `jsonReader` fails
99+ /// @throws JsonSyntaxException if the next token is neither `null`, a string, nor an object
61100 @ Override
62- public LocalizedText read (JsonReader jsonReader ) throws IOException {
101+ public @ Nullable LocalizedText read (JsonReader jsonReader ) throws IOException {
63102 JsonToken nextToken = jsonReader .peek ();
64103 if (nextToken == JsonToken .NULL ) {
65104 return null ;
@@ -83,8 +122,13 @@ public LocalizedText read(JsonReader jsonReader) throws IOException {
83122 }
84123 }
85124
125+ /// Writes a localized text value as `null`, a JSON string, or a JSON object.
126+ ///
127+ /// @param jsonWriter the writer that receives the JSON representation
128+ /// @param localizedText the localized text to write, or `null` to write a JSON `null`
129+ /// @throws IOException if writing to `jsonWriter` fails
86130 @ Override
87- public void write (JsonWriter jsonWriter , LocalizedText localizedText ) throws IOException {
131+ public void write (JsonWriter jsonWriter , @ Nullable LocalizedText localizedText ) throws IOException {
88132 if (localizedText == null ) {
89133 jsonWriter .nullValue ();
90134 } else if (localizedText .localizedValues != null ) {
0 commit comments