Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion docs/features/translation.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,26 @@ Channel.update("channeltype", "channelid")
.data(ChannelRequestObject
.builder()
.autoTranslationEnabled(true)
.autoTranslationLanguage(Language.EN)
.autoTranslationLanguages(List.of(Language.EN))
.build())
.request();

// translate messages into up to five languages
Channel.update("channeltype", "channelid")
.data(ChannelRequestObject
.builder()
.autoTranslationEnabled(true)
.autoTranslationLanguages(List.of(Language.EN, Language.FR, Language.IT))
.build())
.request();

// auto translate messages for all channels
App.update().autoTranslationEnabled(true).request();
```

> [!NOTE]
> `autoTranslationLanguages` accepts up to five languages and can only be set on channel create or full update. Partial update rejects `auto_translation_language` as a reserved field. The single language `autoTranslationLanguage(Language)` setter is deprecated: calling it more than once keeps only the last language.

### Set user language

In order for auto translation to work, you must set the user language or specify a destination language for the channel using the `auto_translation_language` field (see previous code example).
Expand Down
29 changes: 28 additions & 1 deletion src/main/java/io/getstream/chat/java/models/Channel.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@
import io.getstream.chat.java.models.framework.StreamResponseObject;
import io.getstream.chat.java.services.ChannelService;
import io.getstream.chat.java.services.framework.Client;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import lombok.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
Expand Down Expand Up @@ -272,9 +274,32 @@ public static class ChannelRequestObject {
@JsonProperty("auto_translation_enabled")
private Boolean autoTranslationEnabled;

/**
* @deprecated the backend accepts up to five languages, use {@code
* autoTranslationLanguages(List)} instead.
*/
@Nullable @Deprecated @JsonIgnore private Language autoTranslationLanguage;

/** Up to five languages. Can only be set on channel create or full update. */
@Nullable @JsonIgnore private List<Language> autoTranslationLanguages;

@Nullable
@JsonProperty("auto_translation_language")
private Language autoTranslationLanguage;
public String getAutoTranslationLanguageValue() {
List<Language> languages = autoTranslationLanguages;
if (languages == null && autoTranslationLanguage != null) {
languages = Collections.singletonList(autoTranslationLanguage);
}
if (languages == null) {
return null;
}
String value =
languages.stream()
.filter(language -> language != null && language != Language.UNKNOWN)
.map(Language::getValue)
.collect(Collectors.joining(","));
return value.isEmpty() ? null : value;
}

@Nullable
@JsonProperty("frozen")
Expand Down Expand Up @@ -321,6 +346,7 @@ private ChannelRequestObject(
@Nullable String team,
@Nullable Boolean autoTranslationEnabled,
@Nullable Language autoTranslationLanguage,
@Nullable List<Language> autoTranslationLanguages,
@Nullable Boolean frozen,
@Nullable List<ChannelMemberRequestObject> members,
@Nullable List<ChannelMemberRequestObject> invites,
Expand All @@ -331,6 +357,7 @@ private ChannelRequestObject(
this.team = team;
this.autoTranslationEnabled = autoTranslationEnabled;
this.autoTranslationLanguage = autoTranslationLanguage;
this.autoTranslationLanguages = autoTranslationLanguages;
this.frozen = frozen;
this.members = members;
this.invites = invites;
Expand Down
14 changes: 13 additions & 1 deletion src/main/java/io/getstream/chat/java/models/Language.java
Original file line number Diff line number Diff line change
Expand Up @@ -117,5 +117,17 @@ public enum Language {
@JsonProperty("zh-TW")
ZH_TW,
@JsonEnumDefaultValue
UNKNOWN
UNKNOWN;

/**
* @return the value sent over the wire, e.g. {@code "es-MX"} for {@link Language#ES_MX}
*/
public String getValue() {
try {
JsonProperty jsonProperty = Language.class.getField(name()).getAnnotation(JsonProperty.class);
return jsonProperty == null ? name() : jsonProperty.value();
} catch (NoSuchFieldException e) {
throw new IllegalStateException("Unknown language constant " + name(), e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package io.getstream.chat.java;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.getstream.chat.java.models.Channel.ChannelRequestObject;
import io.getstream.chat.java.models.Language;
import java.util.Arrays;
import java.util.Collections;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

public class ChannelAutoTranslationLanguageTest {

// Mirrors the visibility configuration of DefaultClient's mapper.
private static final ObjectMapper MAPPER =
new ObjectMapper()
.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE)
.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);

@DisplayName("Multiple languages serialize as a comma separated list")
@Test
void whenSettingLanguages_thenSerializedAsCommaSeparatedList() throws Exception {
ChannelRequestObject channel =
ChannelRequestObject.builder()
.autoTranslationEnabled(true)
.autoTranslationLanguages(Arrays.asList(Language.IT, Language.FR, Language.ES_MX))
.build();

Assertions.assertEquals("it,fr,es-MX", channel.getAutoTranslationLanguageValue());
Assertions.assertTrue(
MAPPER
.writeValueAsString(channel)
.contains("\"auto_translation_language\":\"it,fr,es-MX\""));
}

@DisplayName("Single language setter keeps working")
@Test
void whenSettingSingleLanguage_thenSerializedAsSingleValue() throws Exception {
@SuppressWarnings("deprecation")
ChannelRequestObject channel =
ChannelRequestObject.builder().autoTranslationLanguage(Language.IT).build();

Assertions.assertTrue(
MAPPER.writeValueAsString(channel).contains("\"auto_translation_language\":\"it\""));
}

@DisplayName("The language list wins over the single language")
@Test
void whenSettingBoth_thenListWins() {
@SuppressWarnings("deprecation")
ChannelRequestObject channel =
ChannelRequestObject.builder()
.autoTranslationLanguage(Language.IT)
.autoTranslationLanguages(Collections.singletonList(Language.FR))
.build();

Assertions.assertEquals("fr", channel.getAutoTranslationLanguageValue());
}

@DisplayName("An empty list serializes as null")
@Test
void whenSettingEmptyList_thenSerializedAsNull() throws Exception {
ChannelRequestObject channel =
ChannelRequestObject.builder().autoTranslationLanguages(Collections.emptyList()).build();

Assertions.assertNull(channel.getAutoTranslationLanguageValue());
Assertions.assertTrue(
MAPPER.writeValueAsString(channel).contains("\"auto_translation_language\":null"));
}

@DisplayName("Null and unknown languages are dropped")
@Test
void whenListHoldsNullOrUnknown_thenTheyAreDropped() {
ChannelRequestObject channel =
ChannelRequestObject.builder()
.autoTranslationLanguages(Arrays.asList(Language.EN, null, Language.UNKNOWN))
.build();

Assertions.assertEquals("en", channel.getAutoTranslationLanguageValue());
Assertions.assertNull(
ChannelRequestObject.builder()
.autoTranslationLanguages(Arrays.asList(null, Language.UNKNOWN))
.build()
.getAutoTranslationLanguageValue());
}

@DisplayName("No language set serializes as null")
@Test
void whenSettingNoLanguage_thenSerializedAsNull() throws Exception {
Comment thread
mogita marked this conversation as resolved.
ChannelRequestObject channel = ChannelRequestObject.builder().build();

Assertions.assertNull(channel.getAutoTranslationLanguageValue());
Assertions.assertTrue(
MAPPER.writeValueAsString(channel).contains("\"auto_translation_language\":null"));
}
}
25 changes: 25 additions & 0 deletions src/test/java/io/getstream/chat/java/LanguageTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package io.getstream.chat.java;

import com.fasterxml.jackson.annotation.JsonProperty;
import io.getstream.chat.java.models.Language;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

public class LanguageTest {

@DisplayName("Every language returns its declared wire value")
@Test
void whenReadingValue_thenItMatchesTheDeclaredJsonProperty() throws Exception {
for (Language language : Language.values()) {
JsonProperty jsonProperty =
Language.class.getField(language.name()).getAnnotation(JsonProperty.class);
if (language == Language.UNKNOWN) {
Assertions.assertNull(jsonProperty);
continue;
}
Assertions.assertNotNull(jsonProperty, language.name() + " is missing @JsonProperty");
Assertions.assertEquals(jsonProperty.value(), language.getValue());
}
}
}
Loading