Repository: theopenconversationkit/tock
Issue: Suggestions in story builder are not translated

Suggestions in story builder are not translated when modified in i18n

Changed files:
bot/engine/src/test/kotlin/engine/config/ConfiguredStoryHandlerTest.kt, bot/engine/src/main/kotlin/engine/config/ConfiguredStoryHandler.kt

diff --git a/bot/engine/src/main/kotlin/engine/config/ConfiguredStoryHandler.kt b/bot/engine/src/main/kotlin/engine/config/ConfiguredStoryHandler.kt
index a0369cfae..2c6ff3bb6 100644
--- a/bot/engine/src/main/kotlin/engine/config/ConfiguredStoryHandler.kt
+++ b/bot/engine/src/main/kotlin/engine/config/ConfiguredStoryHandler.kt
@@ -143,7 +143,7 @@ internal class ConfiguredStoryHandler(private val configuration: StoryDefinition
 
     private fun BotBus.send(container: StoryDefinitionAnswersContainer, answer: SimpleAnswer, end: Boolean = false) {
         val label = translate(answer.key)
-        val suggestions = container.findNextSteps(this, configuration)
+        val suggestions = container.findNextSteps(this, configuration).map { this.translate(it) }
         val connectorMessages =
             answer.mediaMessage
                 ?.takeIf { it.checkValidity() }
diff --git a/bot/engine/src/test/kotlin/engine/config/ConfiguredStoryHandlerTest.kt b/bot/engine/src/test/kotlin/engine/config/ConfiguredStoryHandlerTest.kt
index c8df0ecf0..9ead92c86 100644
--- a/bot/engine/src/test/kotlin/engine/config/ConfiguredStoryHandlerTest.kt
+++ b/bot/engine/src/test/kotlin/engine/config/ConfiguredStoryHandlerTest.kt
@@ -16,21 +16,41 @@
 
 package ai.tock.bot.engine.config
 
+import ai.tock.bot.admin.answer.SimpleAnswer
+import ai.tock.bot.admin.answer.SimpleAnswerConfiguration
 import ai.tock.bot.admin.story.StoryDefinitionConfiguration
 import ai.tock.bot.admin.story.StoryDefinitionConfigurationFeature
+import ai.tock.bot.connector.ConnectorMessage
+import ai.tock.bot.connector.ConnectorType
 import ai.tock.bot.engine.BotBus
 import ai.tock.bot.engine.BotDefinitionTest
 import ai.tock.bot.engine.StepTest
 import ai.tock.bot.engine.TestStoryDefinition
 import ai.tock.bot.engine.TestStoryDefinition.test
+import ai.tock.bot.engine.action.SendSentence
 import ai.tock.bot.engine.dialog.Story
+import ai.tock.bot.engine.message.ActionWrappedMessage
+import ai.tock.bot.engine.message.MessagesList
+import ai.tock.bot.engine.user.PlayerId
+import ai.tock.translator.I18nLabel
+import ai.tock.translator.I18nLabelValue
+import ai.tock.translator.RawString
 import io.mockk.every
 import io.mockk.mockk
+import io.mockk.slot
 import io.mockk.verify
 import org.junit.jupiter.api.Test
+import org.litote.kmongo.toId
+import kotlin.test.assertEquals
+import kotlin.test.assertTrue
 
 class ConfiguredStoryHandlerTest {
 
+    data class TestConnectorMessage(
+        val suggestions: List<CharSequence>,
+        override val connectorType: ConnectorType = ConnectorType.none
+    ) : ConnectorMessage
+
     @Test
     fun `switchStory switch story and reset step if same story def`() {
         val feature: StoryDefinitionConfigurationFeature = mockk {
@@ -58,4 +78,73 @@ class ConfiguredStoryHandlerTest {
         verify { bus.step = null }
         verify { bus.handleAndSwitchStory(test, test.mainIntent()) }
     }
+
+    @Test
+    fun `GIVEN simple answer configuration WHEN sending answer THEN translate suggestions`() {
+
+        // Given
+        val originalLabel = I18nLabel(
+            _id = "id".toId(),
+            namespace = "namespace",
+            category = "category",
+            defaultLabel = "Not translated label",
+            i18n = LinkedHashSet()
+        )
+        val simpleAnswerConfiguration = SimpleAnswerConfiguration(
+            answers = listOf(
+                SimpleAnswer(
+                    key = I18nLabelValue(originalLabel),
+                    delay = -1
+                )
+            )
+        )
+
+        val messagesSlot = slot<MessagesList>()
+        val suggestionsSlot = slot<List<CharSequence>>()
+        val connectorMessageRetriever: BotBus.() -> ConnectorMessage? = {
+            TestConnectorMessage(suggestionsSlot.captured)
+        }
+
+        val bus: BotBus = mockk {
+            every { botId } returns PlayerId("botId")
+            every { userId } returns PlayerId("userId")
+            every { applicationId } returns "appId"
+            every { currentAnswerIndex } returns 1
+            every { botDefinition } returns BotDefinitionTest()
+            every { step } returns mockk()
+            every { translate(I18nLabelValue(originalLabel)) } returns RawString("translated label")
+            every { translate(RawString("Step 1 not translated")) } returns RawString("Step 1 translated")
+            every {
+                underlyingConnector.addSuggestions(
+                    RawString("translated label"),
+                    capture(suggestionsSlot)
+                )
+            } returns connectorMessageRetriever
+            every { end(messages = capture(messagesSlot), initialDelay = any()) } returns mockk()
+        }
+
+        val configuration: StoryDefinitionConfiguration = mockk {
+            every { findEnabledFeature("appId") } returns null
+            every { mandatoryEntities } returns emptyList()
+            every { findCurrentAnswer() } returns simpleAnswerConfiguration
+
+        }
+
+        val nextStepTranslated = listOf(RawString("Step 1 not translated"))
+        every { configuration.findNextSteps(bus, configuration) } returns nextStepTranslated
+
+        // When
+        val handler = ConfiguredStoryHandler(configuration)
+        handler.handle(bus)
+
+        // Then
+        val capturedMessage = messagesSlot.captured.messages.first()
+        assertTrue(capturedMessage is ActionWrappedMessage)
+        val messageAction = capturedMessage.action
+        assertTrue(messageAction is SendSentence)
+        val connectorMessage = messageAction.messages.first()
+        assertTrue(connectorMessage is TestConnectorMessage)
+
+        assertEquals("Step 1 translated", connectorMessage.suggestions.first().toString())
+    }
 }
\\ No newline at end of file