Localize the Gatsby Minimal Site Sample
Introduction
This tutorial discusses how to display a localized version of the Gatsby minimal site sample. The goal of this exercise is to modify the application so that it can support multiple languages at the same time and allow users to switch between them easily. The languages are not defined in the application code; rather, they are determined by what is downloaded from the server at build time.
What This Tutorial Includes
This tutorial includes the following:
A description of how the original minimal site sample data is laid out on the server and how its assets are interconnected.
How the localized versions of the data are laid out on the Oracle Content Management server for retrieval by the application.
A discussion of how the Gatsby minimal site sample gets its data from the Oracle Content Management server and how this affects localization.
A brief overview of the code changes needed to make the client locale aware and allow it to support changing languages.
What This Tutorial Does Not Include
This is what this tutorial does not include:
Details about how the sample data should be translated on the server. There are multiple options available to complete this task, both manual and automated. This tutorial was developed using localized data with the following format: all assets have a localized version, even assets that are only used in a structural role and don’t contain translatable data. This allows the asset tree for any language to be traversed the same way without reference to the original English content.
This tutorial is not a deep dive into localizing a Gatsby application. Issues such as right-to-left locales (for example, Hebrew and Arabic) or special formatting for dates, currencies and the like are not addressed here. The goal is to take a simple Gatsby application that pulls its data from Oracle Content Management and modify it to support multiple locales in as simple a manner as possible.
The Original Gatsby Minimal Site Sample
If you’re unfamiliar with the application discussed in this tutorial, we recommend that you first have a look at the original, English-only version running on the demo site.
You can find the source code for the original application on GitHub.
For an in-depth look at the English-only application and how it was written, have a look at the tutorial.
How the Untranslated Gatsby Minimal Site Sample Works
The existing sample is a simple three-page application. It has a home page, a Contact Us page, and a People page. The first two pages are populated using data pulled by the gatsby-source-oce plugin. This plugin uses REST calls to pull data from the Oracle Content Management server and store it in its cache. The People page uses the gatsby-source-graphql plugin to retrieve the information about the individual people using Oracle Content Management’s native GraphQL support.
Structure of the Untranslated Minimal Site Sample Data
The minimal site sample uses the following Oracle Content Management asset types:
MinimalMain — This is used as the entry point to the application. It contains a list of all the pages that should be displayed.
MinimalPage — This type models a generic page consisting of a set of one or more MinimalSection type instances. The data on these pages is obtained using the Oracle Content Management REST interface via the gatsby-source-oce plugin.
PeoplePage — This defines a page consisting of a MinimalSection type containing the page header as well as a list of Person assets containing details about individual people. This page uses the source-gatsby-oce plugin to make GraphQL calls to Oracle Content Management’s GraphQL interface.
MinimalSection — This asset type contains the information used to display a portion of a page. This could be a header with a background image or simply a block of HTML data.
Person — This is a simple asset type containing an image of a person as well as some text information about them. Since it’s used exclusively in the PeoplePage context, it’s loaded via Oracle Content Management’s GraphQL interface.
The single-language minimal site sample application consists of the following assets and relationships:
A single instance of the MinimalMain asset is identified by a specific slug value. This in turn contains a list of references to all page assets (either MinimalPage or PeoplePage) in the application. In the case of the minimal site sample, there are two MinimalPage assets (home, contact-us) and one PeoplePage asset for the people page.
Each MinimalPage contains a list of MinimalSection type instances.
Each MinimalSection instance contains either an image and text used to display a page header or an arbitrary block of HTML used to render data in the page.
Each PeoplePage consists of a single MinimalSection instance that’s used for the page header and a list of person assets.
This application code uses predefined slugs as identifiers to reference pages or data sections that need special handling. For example, the home page is identified by the value of its slug (home), even though it is of the same type as the Contact Us (contact-us) page.
How the Untranslated Minimal Site Sample Loads Data from the Oracle Content Management Server
The Gatsby minimal site sample transfers asset data from the server to the Gatsby build cache using two plugins:
gatsby-source-oce — This plugin takes a server URL and a channel token and downloads all assets found on the given channel to the Gatsby cache. The application then runs GraphQL queries against this cache to pull the required data for the application.
gatsby-source-graphql — This plugin makes a GraphQL connection to the GraphQL endpoint of the Oracle Content Management server. This is used to download the person assets displayed on the People page.
Changes Needed to Create a Localized Copy of the Application
Structure of the Localized Asset Data
No changes are needed to the Oracle Content Management asset data types. All the visible translated text can be stored in assets using the existing types.
For the purpose of this exercise, an automated tool was used to create translations of the base data into Canadian French, Spanish (Spain), and Simplified Chinese. This data may have some inaccuracies due to a lack of context in the automated process, but will suffice for this exercise.
As mentioned in the introduction, each translated locale was given its own complete asset tree which can be processed independently of the source language. For example, the English asset tree looks like this:
MinimalMainGraphQL (slug: minimalmaingraphql)
Home-Page (slug: home)
Home-Announcement
Home-Section1
Home-Section2
Contact-Us-Page (slug: contact-us)
ContactUs-Announcement
ContactUs-Section1
ContactUs-Section2
People-Page (slug: people)
People-Announcement
List-of-Person-Assets
and the Spanish one looks like this (note the appended ’_es’ locale in the slugs):
MinimalMainGraphQL-ES (slug: minimalmaingraphql_es)
Home-Page-ES (slug: home_es)
Home-Announcement-ES
Home-Section1-ES
Home-Section2-ES
Contact-Us-Page-ES (slug: contact-us_es)
ContactUs-Announcement-ES
ContactUs-Section1-ES
ContactUs-Section2-ES
People-Page-ES (slug: people_es)
People-Announcement-ES
List-of-Person-Assets-ES
Note how the slugs of the MinimalMain and Page assets share a common root across languages. This is for the following reasons:
Instead of retrieving one MinimalMain asset by slug, the application can now get a list of all MinimalMain assets with a slug matching a pattern. There is one such asset for each language. Looping over this list allows the application to process the asset tree of each language in turn.
As mentioned previously, slugs are used as special identifiers that control the role of the page assets. Giving all the home pages a slug of a common pattern (home_locale ) allows the code to identify and perform special processing of any page regardless of the language used.
Note: Using slugs as special identifiers is not an optimal solution for a localized application and was done in this case to make the asset types and instances as simple as possible. Using different asset types to distinguish pages or adding an untranslatable field would be a more secure approach. Alternatively, taxonomies could be used for the same purpose at the expense of greater code complexity.
Code Modifications Needed to Display a Localized Gatsby Minimal Site Sample
Since all translations are published on the same channel token, no changes are required to the use or configuration of the gatsby-source-oce or gatsby-source-graphql plugins. The only visible change in the application is to add a locale switching control in the page header. (See the description of the Header.jsx file below).
Below are some of the source code changes required to support multiple locales.
gatsby-node.js (original)
The file gatsby-node.js performs the following functions:
It loads an asset with a slug named ‘minimalmaingraphql’ using Gatsby’s GraphQL interface. There will be only one asset of type MinimalMain returned. It will also retrieve a list of all images found in the site so it can associate the static URL of each image with any asset that will need to use it.
It collects the data needed to build the common header and footer for each page from the returned MinimalMain instance.
It then extracts the page instances from the same MinimalMain asset and calls page templates to create them. For each page it determines its type by looking at the page slug. A home page will have a slug called ‘home’ and will be created with the pageTemplate.jsx template. A person page will have a slug called ‘people’ and use the peopleTemplate.jsx template. All other pages will be assumed to be generic pages using the pageTemplate.jsx template.
gatsby-node.js (localized)
When working with localized data, gatsby-node.js needs to perform the following extra steps:
- It now loads a list of assets that have a name of the form ‘minimalmaingraphql’ rather than looking for a single one. There will be a separate asset for each language, each with the locale appended to the form name, such as minimalmaingraphql_es for Spanish or minimalgraphql_zh for Chinese. The English asset will not have a suffix. Note that the language of each asset is determined by a field inside it, not by the name of the slug. The naming of the slugs is just a convenient way to make them easier to enumerate. Here’s the GraphQL query used to pull all such assets (note the use of the ‘glob’ wildcard to select a pattern):
minimalMainList: allOceAsset(
filter: {slug: {glob: "minimalmaingraphql*"}}
) {
nodes {
id
description
oceType
language
oceFields {
pages {
fields {
sections {
name
id
type
typeCategory
}
}
name
slug
}
footerlogo {
id
name
slug
}
headerlogo {
id
name
slug
}
}
slug
}
}
Looping through the list of these assets, it then builds a list of all the locales present in the data. This will be used to build a control allowing the user to switch locales in the application. By using a query to build this list — as opposed to a static list of locales — the application can be rebuilt if locales are added or removed without requiring any code modification.
The code previously used to build a single set of pages from a single MinimalMain asset is now put in a loop to create a set of pages from each of the MinimalMain assets found in step 1. Previously, the page slug was used as the URL for each page but now the locale of the current MinimalMain asset is inserted into the page URL so that we can have:
/en/home
/en/contact-us
/fr/home
/fr/contact-usinstead of
/home
/contact-usas we did in the single-language version.
src/pages/index.jsx (new)
This file is added to the localized version to allow the site to have a default home page (/). Since all the pages created in the gatsby-node.js file now have a locale prefix to their URL, we need to have a way to give us a default page. The only thing this page does is trigger an immediate load of the ‘/en/home’ page of the site.
src/components/Header.jsx
This component must be modified to display a language (locale) switcher control for the application. It gets the required information for this control from the pageTemplate.jsx or peopleTemplate.jsx file that creates it. These two templates in turn received this information from the gatsby-node.js file when it called them to create a page.
src/templates/pageTemplate.jsx and src/templates/peopleTemplate.jsx
Original
pageTemplate.jsx
Original
peopleTemplate.jsx
These two files need to accept the list of languages from the gatsby-node.js file and pass the list into the Header component for display.
Views of the Localized Sample Site
Here are a few images showing different pages in varying locales. Note that there is text in the header and footer of each page that is untranslated. This is because the text is part of an image, not free text. It would have been possible to create localized versions of the image as well if this was intended to be a production site.
The Spanish home page:
The French People page:
The Chinese home page:
Localize the Gatsby Minimal Site Sample
F62070-01
August 2022
Copyright © 2021, 2022, Oracle and/or its affiliates.
Primary Author: Oracle Corporation