Add a Language Switcher to a Cascade Story

A recent post on the ArcGIS blog describes how to publish a story map in multiple languages.

That post mentioned how it’s possible to customize one of Esri’s open source story map apps to add a button to let readers easily switch languages. The following article shows you one way to implement a custom language switcher button for Story Map Cascade and provides sample code so you can implement this for your own stories.


Examples

Here are a few examples of stories published in English plus a second language that implement a custom language switcher: Embattled Borderlands, Restoring Old Havana, and The Two Koreas.

The method of switching languages used by both of these stories is simply a button on the cover page (and custom link in the header that can be used anywhere in the story). Below are images of how the button and header link look on a desktop browser and when viewed on a mobile device.

Open the Restoring Old Havana story in a new tab to see its language switcher in action.
The custom language switcher and header link as seen in the mobile view of Cascade.

How to implement the language switcher

The basic steps for creating a story with a language switcher are:

  1. Build two versions of your story map, one in each language.
  2. Download the compiled code for the latest version of the Story Map Cascade app here via the Download the ready-to-deploy app link at the bottom of the page.
  3. Modify the code to include the language switcher (as described in the next section).
  4. Host your modified version of the app on your own web server.
If you’ve never customized or hosted a story map before, this article covers the basics…

The Code

Below are the code snippets you’ll need to add the language switcher. Essentially, this code adds a button to the story cover and a link to the header, both of which can be used to switch languages.

A URL parameter is used to show the alternate language. In the sample code, the default language is English and the alternate language is Spanish.

Remember, you’ll need to have already created two versions of your story map, one for each language. You’ll also need the appid of each story.

Make the following modifications to index.html, as shown in the code below (marked in bold).

  • Add a variable for the URL parameter value. In the example below this is _spanish, but you should name this based on the alternate language used in your story.
  • Modify the appid definition in configOptions as shown below using the URL parameter variable and the ids of your stories. The second appid should be the language specified in your URL parameter variable.
  • Add the getURLParameter function after configOptions.
You may want to first copy and paste the code exactly as it is below into your locally hosted story. That way, you can test your code and know if you have everything in the right place before you make modifications to reflect the languages or appids for your stories.
var _spanish = getUrlParameter("language") === "spanish";

var configOptions = {
// Enter application IDs for stories created through the Cascade builder
        appid: _spanish ? "c9a1396a0b4f4f2eade8b807f8235a6c" : "7d368289bba9419f93934cb530c74822",
// Optionally, to secure Cascade's access if the story item is private or to use the builder, configure an ArcGIS OAuth application ID (example: 6gyOg377fLUhUk6f)
// When specified, sign-in is mandatory even if your story is public
oAuthAppId: "",
// Optionally, to use the appid URL parameter, configure authorizedOwners to reference members whose stories can be viewed by this storytelling app.
// To authorize stories owned by...
// specific members: use ["member"] or ["member1", "member2", ...]
// any ArcGIS member: use ["*"]
// any member of one or more organizations: use ["[orgID]"] or ["[orgID1]", "[orgID2]", ...] (Note the use of brackets in this case, e.g., ["[nzS0F0zdNLvs7nc8]"])
// You can get your orgID by going to My Organization and clicking Find...The most viewed items in the organization.
// Your orgID will be shown in the search box.
authorizedOwners: [""]
};

function getUrlParameter(name) {
name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
var regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
var results = regex.exec(location.search.toLowerCase());
return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
}

Add this CSS to the index.html file just under where it says /* CUSTOM CSS RULES */. Change the language names and their abbreviations, which are used in the mobile view of the story, as needed (marked in bold).

a#languageButtonHeader {
margin-right: 10px;
cursor: pointer;
color: inherit;
}

.mobile-view a#languageButtonHeader {
margin-right: 15px;
}

a#languageButtonHeader:before {
content: "Español";
}

.storymap-spanish a#languageButtonHeader:before {
content: "English";
}

.mobile-view a#languageButtonHeader:before {
content: "ES";
}

.mobile-view.storymap-spanish a#languageButtonHeader:before {
content: "EN";
}

a#languageButtonCover {
background-color: #864726;
cursor: pointer;
color: inherit;
margin-top: 20px;
font-family: 'open_sans','Helvetica Neue','Helvetica','Arial', sans-serif;
font-size: 27px;
padding: 15px;
padding-right: 25px;
padding-left: 25px;
border-radius: 25px;
}

a#languageButtonCover:hover {
text-decoration: none;
}

.mobile-view a#languageButtonCover {
font-size: 1.2em;
padding: 5px;
padding-right: 15px;
padding-left: 15px;
border-radius: 15px;
}

a#languageButtonCover:before {
content: "En Español";
}

.storymap-spanish a#languageButtonCover:before {
content: "In English";
}

Finally, add the JavaScript below to custom-scripts.js. This goes after the note that says Custom Javascript to be executed when the application is ready goes here. Change the language names as needed (marked in bold).

/*
* Custom Javascript to be executed when the application is ready goes here
*/
if (_spanish) {
$("html body").addClass("storymap-spanish");
}
    var languageButtonHeader = $("<a>")
.attr("id", "languageButtonHeader")
.addClass("link")
.attr("href", _spanish ? "?language=english" : "?language=spanish");
$("div.share").prepend(languageButtonHeader);
    var languageButtonCover = $("<a>")
.attr("id", "languageButtonCover")
.attr("href", _spanish ? "?language=english" : "?language=spanish");
$("div.section.section-layout-cover div.foo").append(languageButtonCover);

Code Challenge

Here are some other ideas you could try by modifying/extending the sample code:

  • Style the language switcher button differently: change it’s color, shape, or hover effect, or modify how it looks on mobile devices.
  • Add additional buttons on the cover if you have a story that’s available in three or more languages.
  • Use the locale parameter to also translate the app user interface into another language. For example:

https://www.example.com/Cascade/index.html&language=spanish&locale=es

Cascade’s Share panel and other user interface components can be translated using the locale URL parameter.

What we’ve been calling a “language switcher” in this article is really just some code that adds a button that loads a different story map (using a different appid). You could think of this code as a generic “story switcher.”

What other creative ideas can you come up with to use this code?