Bixby Developer Center

Guides

Dialog Macros

Dialog Macros

Dialog can often contain complex logic that you may want to factor out. You can use dialog macros to avoid having to duplicate dialog logic.

Take, for example, this common pattern within a capsule:

if (exists(concept)) {
template ("#{concept} and #{value(string2)}")
} else {
template ("#{value(string2)}")
}

Often, this logic can be even more complicated. If you have to repeat it across hundreds of dialog files, it would be tedious, especially if design changes call for rendering that string differently.

With a dialog macro, you can define that pattern using the template-macro-def key in this way:

template-macro-def (id1) {
content {
template (ID1 text)
}
}

Here is another example:

template-macro-def (id2) {
params {
param (x) {
type (example.testNamedDialog.TestConcept)
min (Required)
max (One)
}
param (t) {
type (Text)
}
}
content {
if (exists(t)) {
template ("#{t} : #{value(x)}")
} else {
template ("#{value(x)}")
}
}
}

You can invoke this dialog macro by calling the template-macro with the ID you specified in your template-macro-def:

dialog (Result) {
match: example.testNamedDialog.TestConcept (this)
template-macro (id2) {
param (x) {
expression (this)
}
param (t) {
literal ("some text")
}
}
}
Note

You cannot have a macro with the same ID if the macro is defined in the same resource folder. For example, if you have a macro with the ID "this-test-macro" in the bixby-mobile-en-US target, you cannot have another different macro with the same name in that target.

However, if the macro's target is in a higher level resource folder, the more specific target will override the more general target. For example, say you have a macro in bixby-mobile-en and another macro in bixby-mobile-en-US, both with the ID "this-test-macro". The macro in the bixby-mobile-en-US target will render for the bixby-mobile-en-US target, but the bixby-mobile-en macro will render for the bixby-mobile-en-GB target.

Macros with the same ID but in different targets (for example, bixby-mobile-ko-KR and bixby-mobile-en-US) are allowed and are encouraged, especially when localizing or handling development for multiple devices.

If later you need to change this complex logic, you only need to change it in the macro definition once.

You can use template macros anywhere you can use a template, including in views:

result-view {
match {
Receipt (receipt)
}

message {
template-macro (RECEIPT_RESULT) {
param (receipt) {
expression (receipt)
}
}
}

render {
...
}
}

Note that you can also use macros without any parameters, and you can declare more than one in a single dialog file:

template-macro-def (HelloWorld) {
content {
template ("Hello World!")
}
}

template-macro-def (WelcomeMessage) {
content {
template ("Welcome to the wonderful world of Bixby!")
}
}

Not only is this feature useful for composing complicated dialog, but it is also useful for localization. When a capsule is multi-locale, you can factor out strings into macros in separate files, which can then be translated by translation services. You can then place the translated versions in the appropriate resources locale folder. If you do so, ensure that the resulting composed strings work properly in the locale you are targeting.

Here is an example for a capsule in which you declare several dialog macros for contact information:

template-macro-def (ContactInformation) {
content {
template ("Contact information")
}
}

template-macro-def (Name) {
content {
template ("Name")
}
}

template-macro-def (PhoneNumber) {
content {
template ("Phone number")
}
}

template-macro-def (Email) {
content {
template ("Email")
}
}

Each dialog macro can include related parameters, which consist of a parameter name param, associated type, and cardinality rules (min and max).

There is also always corresponding content, which is where you include the text of the dialog.

And this is how you can invoke dialog macros within a layout-macro-def, which uses dialog macros to create contact information in a receipt:

layout-macro-def (receipt-contact-information) {
params {
param (receipt) {
type (Receipt)
min (Required) max (One)
}
}
content {
section {
title {template-macro (ContactInformation)}
content {
partitioned {
content {
cell-area {
slot2 {
content {
order (SecondaryPrimary)
secondary {
template-macro (Name)
}
primary {
template ("[#{value(receipt.buyer.firstName)} #{value(receipt.buyer.lastName)}]")
}
}
}
}
cell-area {
slot2 {
content {
order (SecondaryPrimary)
secondary {
template-macro (PhoneNumber)
}
primary {
template ("[#{value(receipt.buyer.phoneInfo.number)}]")
}
}
}
}
cell-area {
slot2 {
content {
order (SecondaryPrimary)
secondary {
template-macro (Email)
}
primary {
template ("[#{value(receipt.buyer.emailInfo.address)}]")
}
}
}
}
}
}
}
}
}
}

You must qualify macros that you import, but not those that are local to your capsule. Put simply, you must follow the same name-spacing rules that apply to model references.

Take, for example, a capsule called example.capsule1 that defines template macro template1. If you want to import template1 into another capsule called example.capsule2, you must fully qualify it as shown here:

template-macro(example.capsule1:template1)

However, if you want to use that same macro within example.capsule1 itself, you should use the unqualified notation:

template-macro(template1)

You can also use an alias to qualify template macros. For example, if example.capsule2 imports example.capsule1 as aliasedcapsule, you can then invoke a macro within it using the alias:

template-macro(aliasedcapsule:template1)

Why Use Macros

As mentioned before, dialog macros and macros in general are useful for reusing content in several places. It also allows you to compose complicated dialogs, as seen in previous examples.

It is also useful for localization and multiple devices. When a capsule supports multiple locales or multiple devices, you can factor out strings into macros in separate files.

For localization in particular, the strings in these separate macros can be translated by translation services. You can then place the translated versions in the appropriate resources locale folder. Similarly for multiple devices, you can tweak the dialog depending on the user experience, such as hands-free list navigation dialog versus a touch-based dialog or UI strings, and put them in the appropriate resources device folder. If you do so, ensure that the resulting composed strings work properly in the locales and devices you are targeting by testing your capsule with the Simulator.

Here is an example for a capsule in which you declare several dialog macros for contact information, which could easily be used for translation:

template-macro-def (ContactInformation) {
content {
template ("Contact information")
}
}
template-macro-def (Name) {
content {
template ("Name")
}
}
template-macro-def (PhoneNumber) {
content {
template ("Phone number")
}
}
template-macro-def (Email) {
content {
template ("Email")
}
}