Skip to content

Commit

Permalink
Map legacy translations of "base" to the actual base language
Browse files Browse the repository at this point in the history
  • Loading branch information
rowanseymour committed May 25, 2018
1 parent e617ef4 commit 16d7f54
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 83 deletions.
53 changes: 7 additions & 46 deletions legacy/definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,6 @@ import (
"github.com/shopspring/decimal"
)

// represents a decimal value which may be provided as a string or floating point value
type decimalString string

// UnmarshalJSON unmarshals a decimal string from the given JSON
func (s *decimalString) UnmarshalJSON(data []byte) error {
if data[0] == '"' {
// data is a quoted string
*s = decimalString(data[1 : len(data)-1])
} else {
// data is JSON float
*s = decimalString(data)
}
return nil
}

var legacyWebhookBody = `{
"contact": {"uuid": "@contact.uuid", "name": "@contact.name", "urn": @(json(if(default(run.input.urn, default(contact.urns.0, null)), text(default(run.input.urn, default(contact.urns.0, null))), null)))},
"flow": @(json(run.flow)),
Expand All @@ -51,30 +36,6 @@ type Flow struct {
Entry flows.NodeUUID `json:"entry" validate:"required,uuid4"`
}

// Translations is an inline translation map used for localization
type Translations map[utils.Language]string

// UnmarshalJSON unmarshals legacy translations from the given JSON
func (t *Translations) UnmarshalJSON(data []byte) error {
// sometimes legacy flows have a single string instead of a map
if data[0] == '"' {
var asString string
if err := json.Unmarshal(data, &asString); err != nil {
return err
}
*t = Translations{"base": asString}
return nil
}

asMap := make(map[utils.Language]string)
if err := json.Unmarshal(data, &asMap); err != nil {
return err
}

*t = asMap
return nil
}

// Note is a legacy sticky note
type Note struct {
X decimal.Decimal `json:"x"`
Expand Down Expand Up @@ -308,7 +269,7 @@ type stringTest struct {
}

type numericTest struct {
Test decimalString `json:"test"`
Test DecimalString `json:"test"`
}

type betweenTest struct {
Expand All @@ -333,7 +294,7 @@ func addTranslationMap(baseLanguage utils.Language, localization flows.Localizat
var inBaseLanguage string
for language, item := range mapped {
expression, _ := expressions.MigrateTemplate(item, expressions.ExtraAsFunction)
if language != baseLanguage {
if language != baseLanguage && language != "base" {
localization.AddItemTranslation(language, uuid, property, []string{expression})
} else {
inBaseLanguage = expression
Expand Down Expand Up @@ -644,7 +605,7 @@ func migrateAction(baseLanguage utils.Language, a Action, localization flows.Loc

// migrates the given legacy rule to a router case
func migrateRule(baseLanguage utils.Language, exitMap map[string]flows.Exit, r Rule, localization flows.Localization) (routers.Case, error) {
category := r.Category[baseLanguage]
category := r.Category.Base(baseLanguage)

newType, _ := testTypeMappings[r.Test.Type]
var omitOperand bool
Expand Down Expand Up @@ -686,7 +647,7 @@ func migrateRule(baseLanguage utils.Language, exitMap map[string]flows.Exit, r R
case "contains", "contains_any", "contains_phrase", "contains_only_phrase", "regex", "starts":
test := localizedStringTest{}
err = json.Unmarshal(r.Test.Data, &test)
arguments = []string{test.Test[baseLanguage]}
arguments = []string{test.Test.Base(baseLanguage)}

addTranslationMap(baseLanguage, localization, test.Test, caseUUID, "arguments")

Expand Down Expand Up @@ -775,7 +736,7 @@ func parseRules(baseLanguage utils.Language, r RuleSet, localization flows.Local
categoryMap := make(map[string]categoryName)
order := 0
for i := range r.Rules {
category := r.Rules[i].Category[baseLanguage]
category := r.Rules[i].Category.Base(baseLanguage)
_, ok := categoryMap[category]
if !ok {
categoryMap[category] = categoryName{
Expand Down Expand Up @@ -806,7 +767,7 @@ func parseRules(baseLanguage utils.Language, r RuleSet, localization flows.Local
if r.Rules[i].Test.Type == "true" {
// take the first true rule as our default exit
if defaultExit == "" {
defaultExit = exitMap[r.Rules[i].Category[baseLanguage]].UUID()
defaultExit = exitMap[r.Rules[i].Category.Base(baseLanguage)].UUID()
}
continue
}
Expand All @@ -820,7 +781,7 @@ func parseRules(baseLanguage utils.Language, r RuleSet, localization flows.Local

if r.Rules[i].Test.Type == "webhook_status" {
// webhook failures don't have a case, instead they are the default
defaultExit = exitMap[r.Rules[i].Category[baseLanguage]].UUID()
defaultExit = exitMap[r.Rules[i].Category.Base(baseLanguage)].UUID()
}
}

Expand Down
28 changes: 0 additions & 28 deletions legacy/definition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,31 +269,3 @@ func checkFlowLocalization(t *testing.T, flow flows.Flow, expectedLocalizationRa

assert.Equal(t, string(expectedLocalizationJSON), string(actualLocalizationJSON))
}

func TestTranslations(t *testing.T) {
// can unmarshall from a single string
translations := make(legacy.Translations)
json.Unmarshal([]byte(`"hello"`), &translations)
assert.Equal(t, legacy.Translations{"base": "hello"}, translations)

// or a map
translations = make(legacy.Translations)
json.Unmarshal([]byte(`{"eng": "hello", "fra": "bonjour"}`), &translations)
assert.Equal(t, legacy.Translations{"eng": "hello", "fra": "bonjour"}, translations)

// and back to JSON
data, err := json.Marshal(translations)
require.NoError(t, err)
assert.Equal(t, []byte(`{"eng":"hello","fra":"bonjour"}`), data)

translationSet := []legacy.Translations{
{"eng": "Yes", "fra": "Oui"},
{"eng": "No", "fra": "Non"},
{"eng": "Maybe"},
{"eng": "Never", "fra": "Jamas"},
}
assert.Equal(t, map[utils.Language][]string{
"eng": {"Yes", "No", "Maybe", "Never"},
"fra": {"Oui", "Non", "", "Jamas"},
}, legacy.TransformTranslations(translationSet))
}
11 changes: 2 additions & 9 deletions legacy/testdata/flows.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"actions": [
{
"msg": {
"base": "Hello",
"eng": "Hello",
"fre": "Bonjour"
},
"media": {},
Expand All @@ -46,13 +46,6 @@
"language": "eng",
"expire_after_minutes": 0,
"localization": {
"base": {
"98388930-7a0f-4eb8-9a0a-09be2f006420": {
"text": [
"Hello"
]
}
},
"fre": {
"98388930-7a0f-4eb8-9a0a-09be2f006420": {
"text": [
Expand All @@ -68,7 +61,7 @@
{
"type": "send_msg",
"uuid": "98388930-7a0f-4eb8-9a0a-09be2f006420",
"text": "",
"text": "Hello",
"attachments": []
}
],
Expand Down
13 changes: 13 additions & 0 deletions legacy/testdata/tests.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,19 @@
}
}
},
{
"legacy_test": {
"type": "contains_any",
"test": "oops not a dict"
},
"expected_case": {
"uuid": "d2f852ec-7b4e-457f-ae7f-f8b243c49ff5",
"type": "has_any_word",
"arguments": ["oops not a dict"],
"exit_uuid": "c072ecb5-0686-40ea-8ed3-898dc1349783"
},
"expected_localization": {}
},
{
"legacy_test": {
"type": "contains_only_phrase",
Expand Down
55 changes: 55 additions & 0 deletions legacy/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package legacy

import (
"encoding/json"

"github.com/nyaruka/goflow/utils"
)

// Translations is an inline translation map used for localization
type Translations map[utils.Language]string

// Base looks up the translation in the given base language, or "base"
func (t Translations) Base(baseLanguage utils.Language) string {
val, exists := t[baseLanguage]
if exists {
return val
}
return t["base"]
}

// UnmarshalJSON unmarshals legacy translations from the given JSON
func (t *Translations) UnmarshalJSON(data []byte) error {
// sometimes legacy flows have a single string instead of a map
if data[0] == '"' {
var asString string
if err := json.Unmarshal(data, &asString); err != nil {
return err
}
*t = Translations{"base": asString}
return nil
}

asMap := make(map[utils.Language]string)
if err := json.Unmarshal(data, &asMap); err != nil {
return err
}

*t = asMap
return nil
}

// DecimalString represents a decimal value which may be provided as a string or floating point value
type DecimalString string

// UnmarshalJSON unmarshals a decimal string from the given JSON
func (s *DecimalString) UnmarshalJSON(data []byte) error {
if data[0] == '"' {
// data is a quoted string
*s = DecimalString(data[1 : len(data)-1])
} else {
// data is JSON float
*s = DecimalString(data)
}
return nil
}
50 changes: 50 additions & 0 deletions legacy/utils_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package legacy_test

import (
"encoding/json"
"testing"

"github.com/nyaruka/goflow/legacy"
"github.com/nyaruka/goflow/utils"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestTranslations(t *testing.T) {
// can unmarshall from a single string
translations := make(legacy.Translations)
json.Unmarshal([]byte(`"hello"`), &translations)
assert.Equal(t, legacy.Translations{"base": "hello"}, translations)

// or a map
translations = make(legacy.Translations)
json.Unmarshal([]byte(`{"eng": "hello", "fra": "bonjour"}`), &translations)
assert.Equal(t, legacy.Translations{"eng": "hello", "fra": "bonjour"}, translations)

// and back to JSON
data, err := json.Marshal(translations)
require.NoError(t, err)
assert.Equal(t, []byte(`{"eng":"hello","fra":"bonjour"}`), data)

translationSet := []legacy.Translations{
{"eng": "Yes", "fra": "Oui"},
{"eng": "No", "fra": "Non"},
{"eng": "Maybe"},
{"eng": "Never", "fra": "Jamas"},
}
assert.Equal(t, map[utils.Language][]string{
"eng": {"Yes", "No", "Maybe", "Never"},
"fra": {"Oui", "Non", "", "Jamas"},
}, legacy.TransformTranslations(translationSet))
}

func TestDecimalString(t *testing.T) {
// can unmarshall from a string
var decimal legacy.DecimalString
json.Unmarshal([]byte(`"123.45"`), &decimal)
assert.Equal(t, legacy.DecimalString("123.45"), decimal)

// or a floating point (JSON number type)
json.Unmarshal([]byte(`567.89`), &decimal)
assert.Equal(t, legacy.DecimalString("567.89"), decimal)
}

0 comments on commit 16d7f54

Please sign in to comment.