Introduction

If your church has multiple languages, it can be a pain to collect user data using workflows. Often, the best solution is creating multiple workflows in different languages that all do the same thing and then making the user click the link that corresponds to their preferred language. But what happens when you need to make a change to the logic of the workflow? Now you have to change it and test it in multiple places.

What if you could create a single workflow that automatically uses the preferred language of its user? That would mean less friction for users, and since the logic is all in one workflow, less work for developers.

The following is a guide on how to create a bilingual workflow. Once you do the initial setup, creating bilingual workflows can actually be less work than creating two workflows and modifying the text on one of them.

Preferred Language Person Attribute

The first step in this process is to add a person attribute for their preferred language. The benefit of using a person attribute is that we can look at the attribute whenever we display a form or other content to them to make sure that they see it in their preferred language without having to click a button every time to switch the language they are viewing the form/content in.

To add a person attribute, go to Admin Tools (the toolbox on the left sidebar) and then to General Settings. Then, click on the Person Attributes button and you will see a grid that shows all of the person attributes currently in your Rock. Click on the plus button at the top right or bottom right of the grid to add a new person attribute.

For this attribute, I will name it 'Preferred Language' and give it a Key of 'PreferredLanguage'. The key is how the lava will reference this attribute, so if you give it a different key, make sure to make a note so that you can change the lava later.

For the Field Type, I will use a Defined Value and assign the Defined Type to the built-in 'Languages' type. Then, I will select English and Spanish in the Selectable Values area since those are the only languages that Lakepointe currently supports. This will make it so that people can't select other values besides English and Spanish. Leave the default value blank.

PreferredLanguagePersonAttribute.png

Language Campus Attribute

The next step is to add a campus attribute for the campus's language. This is useful for guessing what language a person would prefer if they do not have their Preferred Language attribute set. We can look at their primary campus and see what the language of that campus is.

The process of adding a campus attribute is very similar to adding a person attribute.

To add a campus attribute, go to Admin Tools (the toolbox on the left sidebar) and then to System Settings. Then, click on the Entity Attributes button and you will see a panel with the heading 'Attribute List'. On the top right corner of that panel, there is an Entity Type dropdown. Select campus from this dropdown and the panel will show a grid that shows all of the campus attributes currently in your Rock (if there are any campus attributes). Click on the plus button at the top right or bottom right of the grid to add a new campus attribute.

For this attribute, I will name it 'Language' and give it a Key of 'Language'. Again, if you use a different key, remember what key you gave it and make sure to modify the lava later.

Just like with the person attribute, I will make this attribute a Defined Value that uses the 'Languages' Defined Type. I will also select English and Spanish in the Selectable values section so that those are the only languages that can be selected.

Here, I will use a Default Value of 'English', which will automatically set the value to English for every campus once I hit save for the first time. Plus, for each new campus I add, this attribute will default to English. Now I will only need to change this language attribute for Spanish campuses instead of for all campuses.

Tip: To edit campus attributes go to Admin Tools > General Settings > Campuses. Then, click on the campus you want to edit the attributes of and click the edit button.

LanguageCampusAttribute.png

Lava File

This step is where we add the lava file that does all the logic to determine which language should be used. Since I already wrote all the lava, the most complicated part of this step will be adding the file to your Rock server. Depending on how your server is hosted, the way to add files to your Rock server will be different. For that reason, I will assume you know how to access your Rock's file system.

Once you have downloaded the lava file from the link at the bottom of the page, you can move it somewhere on your server in the RockWeb folder. I suggest putting it in 'RockWeb/Plugins/org_lakepointe/Assets/Lava/' since the Plugins folder is ignored by Git and you won't have to work around this file if you choose to contribute code back to Rock.

Once the file is on your server you are done with this step. The following is an explanation of how the lava works so that you will understand why it is returning what is returning and to make it easier for you to edit the logic of the lava, should you need to at some point.

The lava will always return a value (unless there is an unexpected error). It will either return 'en' or 'es' (the ISO 639-1 codes for English and Spanish).

The lava will look at the 'lang' page parameter first. The page parameter will override all other checks. This is so that you can link to a page and force the language to a specific value. Page parameters (aka Query Strings or Query Parameters) are the things after the '?' in URLs. For example, a URL with the page parameters of lang equal to es and PersonId equal to 10023 would look like this: https://rock.example.com/page/3?lang=es&PersonId=10023.

Next, if there is no lang page parameter, the lava will look at the person's preferred language attribute.

Next, if the preferred language person attribute is blank, the lava will look at the person's primary campus's language attribute.

Next, if the campus's language attribute is blank or if the person doesn't have a primary campus, the lava will default to English and will return 'en'.

Lava Shortcode

Now that the lava file is on your server, you can run it with the following lava:

{% include '~/Plugins/org_lakepointe/Assets/Lava/GetLanguage.lava' %}

But that is super long and hard to remember. So, what I did is I put this include statement inside of a lava shortcode so that I can just say '{[ GetLanguage ]}'. This is a lot shorter and easier to remember.

You may be wondering why I didn't just put the lava from the lava file into a shortcode. The reason is that shortcodes don't run in the context of where they are called. They don't have access to the Current Person or Page Parameters.

To create your own lava shortcode, go to go to Admin Tools (the toolbox on the left sidebar) and then to CMS Configuration. Then, click on the Lava Shortcodes button and you will see a list of all the shortcodes on your Rock. To create a new one, click the plus button in the top right of the panel.

The Name is whatever you want to call the shortcode. I named mine 'Get Language'.

The Tag Name is the word you will use in the lava to call this shortcode. I gave mine the tag name of 'GetLanguage'. Then, to use my shortcode in lava I will say '{[ GetLanguage ]}'.

The Tag Type will be inline. Block shortcodes have a start and an end tag (think 'capture' and 'endcapture'). Inline shortcodes just have one tag.

The Description can be whatever you want, but it should briefly describe what the shortcode is used for. I like to preface all my shortcodes with my church's acronym so that I know that we created it and are responsible for maintaining it (it wasn't built-in and it wasn't from a plugin). I will give mine the description of 'LPC - Gets a person's preferred language. Always returns a value.'

The Documentation is a longer-form description of exactly what the shortcode does and how it does it. Here is the description I used:

Includes the GetLanguage.lava file.
The lava from the file will always return a value (unless there is an unexpected error). It will either return 'en' or 'es' (the ISO 639-1 codes for English and Spanish).
The lava will look at the 'lang' page parameter (aka query string) first. The page parameter will override all other checks. This is so that you can link to a page and force the language to a specific value.
Next, if there is no lang page parameter, the lava will look at the person's preferred language attribute.
Next, if the preferred language person attribute is blank, the lava will look at the person's primary campus's language attribute.
Next, if the campus's language attribute is blank or if the person doesn't have a primary campus, the lava will default to English and will return 'en'.

The Shortcode Markup is the actual lava that this shortcode will run. In this case, it is as simple as just putting in the include statement for our lava file: '{% include '~/Plugins/org_lakepointe/Assets/Lava/GetLanguage.lava' %}'. If you put your lava file in a different place, don't forget to change the path in this include statement.

Now, you can run the lava in the file just using '{[ GetLanguage ]}'

GetLanguageLavaShortcode.png

Workflow

Intro and initial setup

As a bilingual form is just an aspect of a workflow, I will show you how to do the parts related to making a bilingual form and leave it up to you to do the rest of the data processing for your use cases.

To start out, go ahead and create a workflow and add any attributes you would like to show on the form.

How to get the person's language

To get the person's language, create a text Workflow attribute called Language. Then, create a Lava Run action (which is under Utility). Put the shortcode we created in the Lava field ('{[ GetLanguage ]}'). Then, put the Language workflow attribute in the Attribute field to capture what the shortcode returns. We put it in a workflow attribute so that it can be accessed from all of the activities.

Now, if you need to check the person's language anywhere in the workflow, you can check the contents of the Language workflow attribute.

How to create the forms

The next piece is to add the forms themselves. We use two separate forms, one in English and one in Spanish to get the desired result. We then just use a filter on the form actions to only show the relevant form.

The setup for the English form is pretty straightforward. Simply set it up as you normally would and then add a filter to the form action to only run this action if Language is Not Equal To 'es' (that way, if for some reason Language is something besides 'en' or 'es', the user will still get a form).

The setup for the Spanish form is a bit more complicated. Create another form and set it up just like you did for the English form. Then, change the filter to only run this action if Language is Equal To 'es'. Also, you can go ahead and translate the button(s) at the bottom of the form now by simply replacing the text.

The next step for the Spanish form is to select the Hide Label, Pre-HTML, and Post-HTML options for each of the labels that you need to translate. Then, to write your own label, put this in the Pre-HTML and replace the 'Your Text Here' with the translation for the attribute:

<div class="form-group">
<label class="control-label">Your Text Here</label>

And put a '</div>' in the Post-HTML.

If the field is a required field and should have a required bubble, add the 'required' class to the form-group div like this:

<div class="form-group required">

Now that that is all done, we have an English form and a Spanish form. The Spanish form is only displayed if the language is set to 'es' and the English form is displayed every other time.

How to add a button to switch back and forth

Now that we have the two forms, we need a way for users to switch to another language. This is as simple as adding a button to the top of the form that changes the 'lang' page parameter to the other language. Since the 'lang' page parameter overrides everything else, it will allow us to easily switch the language.

To add a button to switch the language, put the following into the form's Form Header

{%- assign WorkflowTypeId = 'Global' | PageParameter:'WorkflowTypeId' -%}
{%- if WorkflowTypeId != empty -%}
 {%- capture link -%}?WorkflowTypeId={{ WorkflowTypeId }}&lang=es{%- endcapture -%}
{%- else -%}
 {%- assign link = '?lang=es' -%}
{%- endif -%}
<a class="btn btn-primary" href="{{ link }}" style="float: right;">En Español</a><br><br>

And on the Spanish form, change out the two places where 'es' is for 'en' and change out the 'En Español' for 'English'.

All the lava above the HTML does is preserve the WorkflowTypeId Page Parameter if it exists. That way, switching the language doesn’t cause the Workflow Entry block to forget which workflow type you are entering. The HTML is just a link that is styled to look like a button.

When the button is clicked, the current workflow redirects the user to the same page, but with the lang page parameter set. A new workflow is created that sees that page parameter and uses it as its language. Since a new workflow is created each time the language is switched from this button, you will have to be careful about doing any processing before the form as it could potentially run multiple times if the user uses the button to switch their language.

How to set the person's preferred language to whatever they submitted the form in

Once a user submits the form, it would be a good idea to set their Preferred Language attribute so that the next time they fill out a bilingual form, the form will automatically be in their preferred language without them having to switch it.

To do this, first, we need to create two Defined Value attributes on either the activity that sets the Preferred Language person attribute or on the workflow. Their type needs to be Languages. One of them needs to have a default value of 'English' and the other needs to have a default value of 'Spanish'.

Then we need to create two Person Attribute Set workflow actions.

The English one should be filtered to only run if Language is Not Equal To 'es'. It should set the Preferred Language attribute on the person to the English attribute we just created.

The Spanish one should be filtered to only run if Language is Equal To 'es'. It should set the Preferred Language attribute on the person to the Spanish attribute we just created.

Suggestions on how to handle single-selects, multi-selects, and defined values

You may have noticed that only the labels on the controls have been translated on the Spanish form. The selectable values on things like Single-Selects, Multi-Selects, and Defined Values are all still in English. For single-selects and multi-selects, you can actually use lava in the Values field of the attribute. This means that if you do something like the following, the values will switch with the language:

{% capture lang %}{[ GetLanguage ]}{% endcapture %}
{% if lang == 'es' %}
1^Rojo,
2^Azul,
3^Verde,
4^Amarillo
{% else %}
1^Red,
2^Blue,
3^Green,
4^Yellow
{% endif %}

Just make sure to include the Value section for each of those values (the part before the '^'). This allows you to use the Value in lava instead of having to check if the selected value was the English value or the Spanish value.

If you edited the lava file and the values are not updating properly, check for any empty lines or tags without dashes (tags should have dashes like this: '{%- example -%}' not this: '{% example %}'). The if statement is very sensitive to extra whitespace.

Defined values are a bit more tricky. My suggestion would be to have the Spanish form use a single-select or multi-select with the same values as the defined value and then have some lava after the form that runs when the language is Spanish. Use the lava to check the value of the single-select/multi-select and assign the corresponding value on the defined value attribute before continuing with processing the data.

Here is the example lava that I put together for this demo workflow. You can see it in action by downloading the workflow below and importing it into your Rock.

{% comment %}
 Get the raw value from the Spanish single-select.
 The raw value is whatever is before the '^' for each option in the single select.
 I'm using numbers because it is a lot harder to put a typo in a short number than it is to compare it directly to the text.
{% endcomment %}
{%- assign status = Activity | Attribute:'MaritalStatus-es','RawValue' -%}
{% comment %}
 The following spits out the Guid for the defined value that corresponds to the selected value on the single-select.
 Defined Values' Guids can be found in the SQL database.
{% endcomment %}
{%- if status == 1 -%}
 5FE5A540-7D9F-433E-B47E-4229D1472248
{%- elseif status == 2 -%}
 DB239675-259B-454A-8A40-2A712EDF24C9
{%- elseif status == 3 -%}
 F19FC180-FE8F-4B72-A59C-8013E3B0EB0D
{%- elseif status == 4 -%}
 3B689240-24C2-434B-A7B9-A4A6CBA7928C
{%- endif -%}

Screenshot of workflow

DemoBilingualWorkflow.png

Final Notes

Both the lava file and the demo workflow are available to be downloaded here:

GetLanguage.lava

Bilingual-Workflow-Demo.json

To import a workflow into your Rock, go to Admin Tools (the toolbox on the left sidebar) and then to Power Tools. Then, click on the Workflow Import/Export button and you will see a file upload area on the right. Upload the .json file there, select a category to put it in, and click 'Import'.

I hope this recipe helps you to reach more people for Christ! If you have any questions, feel free to put them in the comments below or message me on Rocket.Chat.