From 1a6e27b0c0db28ddcc6614be1bf6a6b0660d9f3a Mon Sep 17 00:00:00 2001 From: Rowan Seymour Date: Wed, 17 Apr 2024 15:48:04 -0500 Subject: [PATCH 1/2] Rework send_msg to use single list of variables --- flows/actions/base_test.go | 6 +- flows/actions/send_msg.go | 66 +++-------- flows/actions/testdata/send_msg.json | 159 +++++++++------------------ 3 files changed, 70 insertions(+), 161 deletions(-) diff --git a/flows/actions/base_test.go b/flows/actions/base_test.go index 8dd80632c..33b1c73bd 100644 --- a/flows/actions/base_test.go +++ b/flows/actions/base_test.go @@ -140,16 +140,16 @@ func testActionType(t *testing.T, assetsJSON json.RawMessage, typeName string) { // inject the action into a suitable node's actions in that flow actionsPath := []string{"flows", fmt.Sprintf("[%d]", flowIndex), "nodes", "[0]", "actions"} actionsJson := []byte(fmt.Sprintf("[%s]", string(tc.Action))) - assetsJSON = test.JSONReplace(assetsJSON, actionsPath, actionsJson) + testAssetsJSON := test.JSONReplace(assetsJSON, actionsPath, actionsJson) // if we have a localization section, inject that too if tc.Localization != nil { localizationPath := []string{"flows", fmt.Sprintf("[%d]", flowIndex), "localization"} - assetsJSON = test.JSONReplace(assetsJSON, localizationPath, tc.Localization) + testAssetsJSON = test.JSONReplace(testAssetsJSON, localizationPath, tc.Localization) } // create session assets - sa, err := test.CreateSessionAssets(assetsJSON, "") + sa, err := test.CreateSessionAssets(testAssetsJSON, "") require.NoError(t, err, "unable to create session assets in %s", testName) // now try to read the flow, and if we expect a read error, check that diff --git a/flows/actions/send_msg.go b/flows/actions/send_msg.go index 191fb6df5..b16c983e9 100644 --- a/flows/actions/send_msg.go +++ b/flows/actions/send_msg.go @@ -32,19 +32,11 @@ const TypeSendMsg string = "send_msg" // "text": "Hi @contact.name, are you ready to complete today's survey?", // "attachments": [], // "all_urns": false, -// "templating": { -// "template": { -// "uuid": "3ce100b7-a734-4b4e-891b-350b1279ade2", -// "name": "revive_issue" -// }, -// "components": [ -// { -// "uuid": "2131d674-9afb-41e8-bcb8-5910c2faec2f", -// "name": "body", -// "params": ["@contact.name"] -// } -// ] +// "template": { +// "uuid": "3ce100b7-a734-4b4e-891b-350b1279ade2", +// "name": "revive_issue" // }, +// "template_variables": ["@contact.name"], // "topic": "event" // } // @@ -54,24 +46,10 @@ type SendMsgAction struct { universalAction createMsgAction - AllURNs bool `json:"all_urns,omitempty"` - Templating *Templating `json:"templating,omitempty" validate:"omitempty"` - Topic flows.MsgTopic `json:"topic,omitempty" validate:"omitempty,msg_topic"` -} - -type TemplatingComponent struct { - UUID uuids.UUID `json:"uuid" validate:"required,uuid4"` - Name string `json:"name" validate:"required"` - Params []string `json:"params" engine:"localized,evaluated"` -} - -// LocalizationUUID gets the UUID which identifies this object for localization -func (c *TemplatingComponent) LocalizationUUID() uuids.UUID { return c.UUID } - -// Templating represents the templating that should be used if possible -type Templating struct { - Template *assets.TemplateReference `json:"template" validate:"required"` - Components []*TemplatingComponent `json:"components,omitempty"` + AllURNs bool `json:"all_urns,omitempty"` + Template *assets.TemplateReference `json:"template,omitempty"` + TemplateVariables []string `json:"template_variables,omitempty" engine:"localized,evaluated"` + Topic flows.MsgTopic `json:"topic,omitempty" validate:"omitempty,msg_topic"` } // NewSendMsg creates a new send msg action @@ -103,8 +81,8 @@ func (a *SendMsgAction) Execute(run flows.Run, step flows.Step, logModifier flow sa := run.Session().Assets() var template *flows.Template - if a.Templating != nil { - template = sa.Templates().Get(a.Templating.Template.UUID) + if a.Template != nil { + template = sa.Templates().Get(a.Template.UUID) } // create a new message for each URN+channel destination @@ -141,12 +119,10 @@ func (a *SendMsgAction) Execute(run flows.Run, step flows.Step, logModifier flow // for message actions that specify a template, this generates a mesage with templating information and content that can // be used as a preview func (a *SendMsgAction) getTemplateMsg(run flows.Run, urn urns.URN, channelRef *assets.ChannelReference, translation *flows.TemplateTranslation, unsendableReason flows.UnsendableReason, logEvent flows.EventCallback) *flows.MsgOut { - // start by localizing and transforming the current per-component lists into a single list - variableExpressions := getTemplateVariables(run, a.Templating) - - // evaluate the variables - evaluatedVariables := make([]string, len(variableExpressions)) - for i, varExp := range variableExpressions { + // localize and evaluate the variables + localizedVariables, _ := run.GetTextArray(uuids.UUID(a.UUID()), "template_variables", a.TemplateVariables, nil) + evaluatedVariables := make([]string, len(localizedVariables)) + for i, varExp := range localizedVariables { v, _ := run.EvaluateTemplate(varExp, logEvent) evaluatedVariables[i] = v } @@ -194,19 +170,7 @@ func (a *SendMsgAction) getTemplateMsg(run flows.Run, urn urns.URN, channelRef * previewText := strings.Join(previewParts, "\n\n") locale := translation.Locale() - templating := flows.NewMsgTemplating(a.Templating.Template, translation.Namespace(), components, variables) + templating := flows.NewMsgTemplating(a.Template, translation.Namespace(), components, variables) return flows.NewMsgOut(urn, channelRef, previewText, nil, previewQRs, templating, flows.NilMsgTopic, locale, unsendableReason) } - -func getTemplateVariables(run flows.Run, t *Templating) []string { - variables := make([]string, 0, 5) - - for _, comp := range t.Components { - localized, _ := run.GetTextArray(comp.UUID, "params", comp.Params, nil) - - variables = append(variables, localized...) - } - - return variables -} diff --git a/flows/actions/testdata/send_msg.json b/flows/actions/testdata/send_msg.json index 74f979fa0..38cc235c2 100644 --- a/flows/actions/testdata/send_msg.json +++ b/flows/actions/testdata/send_msg.json @@ -345,22 +345,14 @@ "type": "send_msg", "uuid": "ad154980-7bf7-4ab8-8728-545fd6378912", "text": "Hi @contact.name, who's a good boy?", - "templating": { - "template": { - "uuid": "b620b463-8d15-427f-b2e3-4f44f9f071ec", - "name": "missing" - }, - "components": [ - { - "uuid": "aa304c85-c14f-4f94-b97c-ec59c07a3f39", - "name": "body", - "params": [ - "@contact.name", - "boy" - ] - } - ] - } + "template": { + "uuid": "b620b463-8d15-427f-b2e3-4f44f9f071ec", + "name": "missing" + }, + "template_variables": [ + "@contact.name", + "boy" + ] }, "events": [ { @@ -422,22 +414,14 @@ "type": "send_msg", "uuid": "ad154980-7bf7-4ab8-8728-545fd6378912", "text": "Hi Ryan Lewis, who's a good boy?", - "templating": { - "template": { - "uuid": "5722e1fd-fe32-4e74-ac78-3cf41a6adb7e", - "name": "affirmation" - }, - "components": [ - { - "uuid": "1067f8e2-82f0-4378-9214-0f019365ddb7", - "name": "body", - "params": [ - "@contact.name", - "boy" - ] - } - ] + "template": { + "uuid": "5722e1fd-fe32-4e74-ac78-3cf41a6adb7e", + "name": "affirmation" }, + "template_variables": [ + "@contact.name", + "boy" + ], "topic": "account" }, "events": [ @@ -509,32 +493,24 @@ } }, { - "description": "Msg with a matching template with localized component params", + "description": "Msg with a matching template with localized variables", "action": { "type": "send_msg", "uuid": "ad154980-7bf7-4ab8-8728-545fd6378912", "text": "Hi Ryan Lewis, who's a good boy?", - "templating": { - "template": { - "uuid": "5722e1fd-fe32-4e74-ac78-3cf41a6adb7e", - "name": "affirmation" - }, - "components": [ - { - "uuid": "1067f8e2-82f0-4378-9214-0f019365ddb7", - "name": "body", - "params": [ - "@contact.name", - "boy" - ] - } - ] - } + "template": { + "uuid": "5722e1fd-fe32-4e74-ac78-3cf41a6adb7e", + "name": "affirmation" + }, + "template_variables": [ + "@contact.name", + "boy" + ] }, "localization": { "spa": { - "1067f8e2-82f0-4378-9214-0f019365ddb7": { - "params": [ + "ad154980-7bf7-4ab8-8728-545fd6378912": { + "template_variables": [ "@contact.name", "niño" ] @@ -612,16 +588,14 @@ } }, { - "description": "Msg with template but no params or variables", + "description": "Msg with template but no variables", "action": { "type": "send_msg", "uuid": "ad154980-7bf7-4ab8-8728-545fd6378912", "text": "Hi there, it's time to get up!", - "templating": { - "template": { - "uuid": "2edc8dfd-aef0-41cf-a900-8a71bdb00900", - "name": "wakeup" - } + "template": { + "uuid": "2edc8dfd-aef0-41cf-a900-8a71bdb00900", + "name": "wakeup" } }, "events": [ @@ -674,11 +648,9 @@ "type": "send_msg", "uuid": "4f0510e9-7e41-4f83-aaa3-59b6e9a17e70", "text": "Hi Ryan, wakeup!", - "templating": { - "template": { - "uuid": "2edc8dfd-aef0-41cf-a900-8a71bdb00900", - "name": "wakeup" - } + "template": { + "uuid": "2edc8dfd-aef0-41cf-a900-8a71bdb00900", + "name": "wakeup" } }, "localization": { @@ -814,7 +786,7 @@ } }, { - "description": "Use template translation with non body component params", + "description": "Use template translation with non body component params and too many variables", "action": { "type": "send_msg", "uuid": "ad154980-7bf7-4ab8-8728-545fd6378912", @@ -826,53 +798,25 @@ "Yes", "No" ], - "templating": { - "template": { - "uuid": "ce00c80e-991a-4c03-b373-3273c23ee042", - "name": "gender_update" - }, - "components": [ - { - "uuid": "1067f8e2-82f0-4378-9214-0f019365ddb7", - "name": "body", - "params": [ - "@contact.name", - "boy" - ] - }, - { - "uuid": "5fb16175-4aef-4ee3-ae59-53cd55452bd8", - "name": "button.0", - "params": [ - "Yeah" - ] - }, - { - "uuid": "1be525d9-7bbd-478e-8922-38a75ad95c36", - "name": "button.1", - "params": [ - "Nope" - ] - } - ] - } + "template": { + "uuid": "ce00c80e-991a-4c03-b373-3273c23ee042", + "name": "gender_update" + }, + "template_variables": [ + "@contact.name", + "boy", + "Yeah", + "Nope" + ] }, "localization": { "spa": { - "128b97ff-a530-4ec8-87dd-04a9a778c3e0": { - "params": [ - "http://templates.com/rojo.jpg" - ] - }, - "1067f8e2-82f0-4378-9214-0f019365ddb7": { - "params": [ + "ad154980-7bf7-4ab8-8728-545fd6378912": { + "template_variables": [ "@contact.name", - "niño" - ] - }, - "5fb16175-4aef-4ee3-ae59-53cd55452bd8": { - "params": [ - "Sip" + "niño", + "Sip", + "Nop" ] } } @@ -943,11 +887,12 @@ "No", "@contact.name", "boy", + "Yeah", + "Nope", "@contact.name", "niño", - "Yeah", "Sip", - "Nope" + "Nop" ], "localizables": [ "Hey Ryan Lewis, your gender is saved as boy.", From 8e6abe04b8c5b81cf335a0dfab408518009afc4a Mon Sep 17 00:00:00 2001 From: Rowan Seymour Date: Wed, 17 Apr 2024 16:47:37 -0500 Subject: [PATCH 2/2] Add new 13.5 flow spec --- flows/actions/testdata/_assets.json | 6 +- flows/definition/flow.go | 2 +- flows/definition/migrations/13_x.go | 69 ++++++ flows/definition/migrations/primitives.go | 6 + .../migrations/specdata/templates.json | 89 +++++++ .../testdata/migrations/13.5.0.json | 225 ++++++++++++++++++ ...ChangeLanguage_change_language_to_ara.snap | 2 +- ...ChangeLanguage_change_language_to_kin.snap | 2 +- ...ChangeLanguage_change_language_to_spa.snap | 2 +- .../definition/testdata/change_language.json | 2 +- flows/inspect/gettext_test.go | 11 +- 11 files changed, 405 insertions(+), 11 deletions(-) create mode 100644 flows/definition/migrations/testdata/migrations/13.5.0.json diff --git a/flows/actions/testdata/_assets.json b/flows/actions/testdata/_assets.json index 78fe1a70b..5383a7cc9 100644 --- a/flows/actions/testdata/_assets.json +++ b/flows/actions/testdata/_assets.json @@ -3,7 +3,7 @@ { "uuid": "bead76f5-dac4-4c9d-996c-c62b326e8c0a", "name": "Action Tester", - "spec_version": "13.4.0", + "spec_version": "13.5.0", "language": "eng", "type": "messaging", "revision": 123, @@ -23,7 +23,7 @@ { "uuid": "7a84463d-d209-4d3e-a0ff-79f977cd7bd0", "name": "Voice Action Tester", - "spec_version": "13.4.0", + "spec_version": "13.5.0", "language": "eng", "type": "voice", "revision": 123, @@ -43,7 +43,7 @@ { "uuid": "b7cf0d83-f1c9-411c-96fd-c511a4cfa86d", "name": "Collect Age", - "spec_version": "13.4.0", + "spec_version": "13.5.0", "revision": 123, "language": "eng", "type": "messaging", diff --git a/flows/definition/flow.go b/flows/definition/flow.go index c9bd5d26b..7814c81c5 100644 --- a/flows/definition/flow.go +++ b/flows/definition/flow.go @@ -19,7 +19,7 @@ import ( ) // CurrentSpecVersion is the flow spec version supported by this library -var CurrentSpecVersion = semver.MustParse("13.4.0") +var CurrentSpecVersion = semver.MustParse("13.5.0") // IsVersionSupported checks the given version is supported func IsVersionSupported(v *semver.Version) bool { diff --git a/flows/definition/migrations/13_x.go b/flows/definition/migrations/13_x.go index 5d34d4a46..289252d67 100644 --- a/flows/definition/migrations/13_x.go +++ b/flows/definition/migrations/13_x.go @@ -2,17 +2,86 @@ package migrations import ( "github.com/Masterminds/semver" + "github.com/nyaruka/gocommon/i18n" "github.com/nyaruka/gocommon/uuids" "github.com/nyaruka/goflow/excellent/refactor" ) func init() { + registerMigration(semver.MustParse("13.5.0"), Migrate13_5) registerMigration(semver.MustParse("13.4.0"), Migrate13_4) registerMigration(semver.MustParse("13.3.0"), Migrate13_3) registerMigration(semver.MustParse("13.2.0"), Migrate13_2) registerMigration(semver.MustParse("13.1.0"), Migrate13_1) } +// Migrate13_5 converts the `templating` object in [action:send_msg] actions to use a merged list of variables. +// +// @version 13_5 "13.5" +func Migrate13_5(f Flow, cfg *Config) (Flow, error) { + localization := f.Localization() + + for _, node := range f.Nodes() { + for _, action := range node.Actions() { + if action.Type() == "send_msg" { + templating, _ := action["templating"].(map[string]any) + + if templating != nil { + variables := make([]string, 0, 5) + localizedVariables := make(map[i18n.Language][]string) + + // the languages for which any component has param translations + localizedLangs := make(map[i18n.Language]bool) + + components, _ := templating["components"].([]any) + for i := range components { + comp, _ := components[i].(map[string]any) + compUUID := GetObjectUUID(comp) + compParams, _ := comp["params"].([]any) + compParamsAsStrings := make([]string, len(compParams)) + for j := range compParams { + p, _ := compParams[j].(string) + variables = append(variables, p) + compParamsAsStrings[j] = p + } + + if localization != nil { + for _, lang := range localization.Languages() { + langTrans := localization.GetLanguageTranslation(lang) + if langTrans != nil { + params := langTrans.GetTranslation(compUUID, "params") + if params != nil { + localizedVariables[lang] = append(localizedVariables[lang], params...) + langTrans.DeleteTranslation(compUUID, "params") + localizedLangs[lang] = true + } else { + // maybe this component's params aren't translated but others are + localizedVariables[lang] = append(localizedVariables[lang], compParamsAsStrings...) + } + } + } + } + } + + action["template"] = templating["template"] + action["template_variables"] = variables + delete(action, "templating") + + if localization != nil { + for lang, langVariables := range localizedVariables { + if localizedLangs[lang] { + langTrans := localization.GetLanguageTranslation(lang) + langTrans.SetTranslation(action.UUID(), "template_variables", langVariables) + } + } + } + } + } + } + } + return f, nil +} + // Migrate13_4 converts the `templating` object in [action:send_msg] actions to use a list of components. // // @version 13_4 "13.4" diff --git a/flows/definition/migrations/primitives.go b/flows/definition/migrations/primitives.go index 6eca744ea..d6cd32d63 100644 --- a/flows/definition/migrations/primitives.go +++ b/flows/definition/migrations/primitives.go @@ -136,6 +136,12 @@ func (n Node) Router() Router { // Action holds an action definition type Action map[string]any +// UUID returns the uuid of this action +func (a Action) UUID() uuids.UUID { + d, _ := a["uuid"].(string) + return uuids.UUID(d) +} + // Type returns the type of this action func (a Action) Type() string { d, _ := a["type"].(string) diff --git a/flows/definition/migrations/specdata/templates.json b/flows/definition/migrations/specdata/templates.json index f52834cb4..0a1ba083b 100644 --- a/flows/definition/migrations/specdata/templates.json +++ b/flows/definition/migrations/specdata/templates.json @@ -1,4 +1,93 @@ { + "13.5.0": { + "actions": { + "add_contact_groups": [ + ".groups[*].name_match" + ], + "add_contact_urn": [ + ".path" + ], + "add_input_labels": [ + ".labels[*].name_match" + ], + "call_classifier": [ + ".input" + ], + "call_resthook": [], + "call_webhook": [ + ".body", + ".headers.*", + ".url" + ], + "enter_flow": [], + "open_ticket": [ + ".assignee.email_match", + ".body" + ], + "play_audio": [ + ".audio_url" + ], + "remove_contact_groups": [ + ".groups[*].name_match" + ], + "request_optin": [], + "say_msg": [ + ".text" + ], + "send_broadcast": [ + ".attachments[*]", + ".contact_query", + ".groups[*].name_match", + ".legacy_vars[*]", + ".quick_replies[*]", + ".text" + ], + "send_email": [ + ".addresses[*]", + ".body", + ".subject" + ], + "send_msg": [ + ".attachments[*]", + ".quick_replies[*]", + ".template_variables[*]", + ".text" + ], + "set_contact_channel": [], + "set_contact_field": [ + ".value" + ], + "set_contact_language": [ + ".language" + ], + "set_contact_name": [ + ".name" + ], + "set_contact_status": [], + "set_contact_timezone": [ + ".timezone" + ], + "set_run_result": [ + ".value" + ], + "start_session": [ + ".contact_query", + ".groups[*].name_match", + ".legacy_vars[*]" + ], + "transfer_airtime": [] + }, + "routers": { + "random": [ + ".operand", + ".cases[*].arguments[*]" + ], + "switch": [ + ".operand", + ".cases[*].arguments[*]" + ] + } + }, "13.4.0": { "actions": { "add_contact_groups": [ diff --git a/flows/definition/migrations/testdata/migrations/13.5.0.json b/flows/definition/migrations/testdata/migrations/13.5.0.json new file mode 100644 index 000000000..9a4dc10be --- /dev/null +++ b/flows/definition/migrations/testdata/migrations/13.5.0.json @@ -0,0 +1,225 @@ +[ + { + "description": "flow without localization", + "original": { + "uuid": "76f0a02f-3b75-4b86-9064-e9195e1b3a02", + "name": "Testing", + "spec_version": "13.4.0", + "language": "eng", + "type": "messaging", + "nodes": [ + { + "uuid": "365293c7-633c-45bd-96b7-0b059766588d", + "actions": [ + { + "uuid": "8eebd020-1af5-431c-b943-aa670fc74da9", + "type": "send_msg", + "text": "Hello", + "templating": { + "template": { + "uuid": "ce00c80e-991a-4c03-b373-3273c23ee042", + "name": "welcome" + }, + "components": [ + { + "uuid": "d2f852ec-7b4e-457f-ae7f-f8b243c49ff5", + "name": "body", + "params": [ + "@contact.name" + ] + }, + { + "uuid": "5a5ccef6-8daa-4cb8-8e52-6b486361710f", + "name": "button.0", + "params": [ + "@contact.language" + ] + } + ] + } + } + ], + "exits": [ + { + "uuid": "3bd19c40-1114-4b83-b12e-f0c38054ba3f" + } + ] + } + ] + }, + "migrated": { + "uuid": "76f0a02f-3b75-4b86-9064-e9195e1b3a02", + "name": "Testing", + "spec_version": "13.5.0", + "language": "eng", + "type": "messaging", + "nodes": [ + { + "uuid": "365293c7-633c-45bd-96b7-0b059766588d", + "actions": [ + { + "uuid": "8eebd020-1af5-431c-b943-aa670fc74da9", + "type": "send_msg", + "text": "Hello", + "template": { + "uuid": "ce00c80e-991a-4c03-b373-3273c23ee042", + "name": "welcome" + }, + "template_variables": [ + "@contact.name", + "@contact.language" + ] + } + ], + "exits": [ + { + "uuid": "3bd19c40-1114-4b83-b12e-f0c38054ba3f" + } + ] + } + ] + } + }, + { + "description": "flow with localization", + "original": { + "uuid": "76f0a02f-3b75-4b86-9064-e9195e1b3a02", + "name": "Testing", + "spec_version": "13.4.0", + "language": "eng", + "type": "messaging", + "localization": { + "spa": { + "8eebd020-1af5-431c-b943-aa670fc74da9": { + "text": [ + "Hola" + ] + }, + "d2f852ec-7b4e-457f-ae7f-f8b243c49ff5": { + "params": [ + "Nombre" + ] + }, + "5a5ccef6-8daa-4cb8-8e52-6b486361710f": { + "params": [ + "Si" + ] + } + }, + "kin": { + "5a5ccef6-8daa-4cb8-8e52-6b486361710f": { + "params": [ + "Yego" + ] + } + }, + "fra": { + "8eebd020-1af5-431c-b943-aa670fc74da9": { + "text": [ + "Bonjour" + ] + } + } + }, + "nodes": [ + { + "uuid": "365293c7-633c-45bd-96b7-0b059766588d", + "actions": [ + { + "uuid": "8eebd020-1af5-431c-b943-aa670fc74da9", + "type": "send_msg", + "text": "Hello", + "templating": { + "template": { + "uuid": "ce00c80e-991a-4c03-b373-3273c23ee042", + "name": "welcome" + }, + "components": [ + { + "uuid": "d2f852ec-7b4e-457f-ae7f-f8b243c49ff5", + "name": "body", + "params": [ + "@contact.name" + ] + }, + { + "uuid": "5a5ccef6-8daa-4cb8-8e52-6b486361710f", + "name": "button.0", + "params": [ + "@contact.language" + ] + } + ] + } + } + ], + "exits": [ + { + "uuid": "3bd19c40-1114-4b83-b12e-f0c38054ba3f" + } + ] + } + ] + }, + "migrated": { + "uuid": "76f0a02f-3b75-4b86-9064-e9195e1b3a02", + "name": "Testing", + "spec_version": "13.5.0", + "language": "eng", + "type": "messaging", + "localization": { + "spa": { + "8eebd020-1af5-431c-b943-aa670fc74da9": { + "text": [ + "Hola" + ], + "template_variables": [ + "Nombre", + "Si" + ] + } + }, + "kin": { + "8eebd020-1af5-431c-b943-aa670fc74da9": { + "template_variables": [ + "@contact.name", + "Yego" + ] + } + }, + "fra": { + "8eebd020-1af5-431c-b943-aa670fc74da9": { + "text": [ + "Bonjour" + ] + } + } + }, + "nodes": [ + { + "uuid": "365293c7-633c-45bd-96b7-0b059766588d", + "actions": [ + { + "uuid": "8eebd020-1af5-431c-b943-aa670fc74da9", + "type": "send_msg", + "text": "Hello", + "template": { + "uuid": "ce00c80e-991a-4c03-b373-3273c23ee042", + "name": "welcome" + }, + "template_variables": [ + "@contact.name", + "@contact.language" + ] + } + ], + "exits": [ + { + "uuid": "3bd19c40-1114-4b83-b12e-f0c38054ba3f" + } + ] + } + ] + } + } +] \ No newline at end of file diff --git a/flows/definition/testdata/TestChangeLanguage_change_language_to_ara.snap b/flows/definition/testdata/TestChangeLanguage_change_language_to_ara.snap index 1525c9c5d..a6babf773 100644 --- a/flows/definition/testdata/TestChangeLanguage_change_language_to_ara.snap +++ b/flows/definition/testdata/TestChangeLanguage_change_language_to_ara.snap @@ -1,7 +1,7 @@ { "uuid": "19cad1f2-9110-4271-98d4-1b968bf19410", "name": "Change Language", - "spec_version": "13.4.0", + "spec_version": "13.5.0", "language": "ara", "type": "messaging", "revision": 16, diff --git a/flows/definition/testdata/TestChangeLanguage_change_language_to_kin.snap b/flows/definition/testdata/TestChangeLanguage_change_language_to_kin.snap index 2efb24214..274cab364 100644 --- a/flows/definition/testdata/TestChangeLanguage_change_language_to_kin.snap +++ b/flows/definition/testdata/TestChangeLanguage_change_language_to_kin.snap @@ -1,7 +1,7 @@ { "uuid": "19cad1f2-9110-4271-98d4-1b968bf19410", "name": "Change Language", - "spec_version": "13.4.0", + "spec_version": "13.5.0", "language": "kin", "type": "messaging", "revision": 16, diff --git a/flows/definition/testdata/TestChangeLanguage_change_language_to_spa.snap b/flows/definition/testdata/TestChangeLanguage_change_language_to_spa.snap index 5e5e28c93..8dcb0de46 100644 --- a/flows/definition/testdata/TestChangeLanguage_change_language_to_spa.snap +++ b/flows/definition/testdata/TestChangeLanguage_change_language_to_spa.snap @@ -1,7 +1,7 @@ { "uuid": "19cad1f2-9110-4271-98d4-1b968bf19410", "name": "Change Language", - "spec_version": "13.4.0", + "spec_version": "13.5.0", "language": "spa", "type": "messaging", "revision": 16, diff --git a/flows/definition/testdata/change_language.json b/flows/definition/testdata/change_language.json index d2a8c476c..3e36c766e 100644 --- a/flows/definition/testdata/change_language.json +++ b/flows/definition/testdata/change_language.json @@ -3,7 +3,7 @@ { "uuid": "19cad1f2-9110-4271-98d4-1b968bf19410", "name": "Change Language", - "spec_version": "13.4.0", + "spec_version": "13.5.0", "language": "eng", "type": "messaging", "revision": 16, diff --git a/flows/inspect/gettext_test.go b/flows/inspect/gettext_test.go index dc6c878a2..06b6e4112 100644 --- a/flows/inspect/gettext_test.go +++ b/flows/inspect/gettext_test.go @@ -31,9 +31,10 @@ func TestLocalizableText(t *testing.T) { }) assert.Equal(t, map[string][]string{ - "attachments": {"image:https://example.com/test.jpg", "audio:https://example.com/test.mp3"}, - "quick_replies": {"Yes", "No"}, - "text": {"Hi there"}, + "attachments": {"image:https://example.com/test.jpg", "audio:https://example.com/test.mp3"}, + "quick_replies": {"Yes", "No"}, + "text": {"Hi there"}, + "template_variables": nil, }, extracted) data := jsonx.MustMarshal(sendMsg) @@ -48,6 +49,10 @@ func TestLocalizableText(t *testing.T) { "quick_replies": [ "foo", "bar" + ], + "template_variables": [ + "foo", + "bar" ] }`), data, "JSON mismatch") }