Localize the Vue Minimal Site Sample
Introduction
This tutorial discusses how to display a localized version of the Vue 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 Vue 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 Vue 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 Vue 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 Vue 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 Vue 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.
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 Oracle Content SDK.
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 fetch API 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.
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. The people page is built using a different asset type than the home and contact-us pages, but the code uses its slug as a way to distinguish it.
How the Untranslated Minimal Site Sample Loads Data from the Oracle Content Management Server
The Vue minimal site sample uses two methods to load data: REST calls to Oracle Content Management via the Content SDK and POST calls to the GraphQL endpoint of Oracle Content Management using the cross-fetch library. One quirk in the application is that all pages loaded by entering an explicit URL are rendered on the server side, while all pages loaded by clicking a link will be loaded and rendered by code running in the client web browser.
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.
Code Modifications Needed to Display a Localized Vue Minimal Site Sample
The only visible change in the application is to add a locale switching control in the page header. (See the description of the Header.vue file below). Since all translations are published on the same channel token, there’s no need to support multiple channels for data acquisition.
Below are some of the source code changes required to support multiple locales.
/src/router/index.js
The routes used for the Home, Contact-Us, and People pages now optionally contain the locale of the pages as well as the slug of the default English pages. The slugs for pages in other languages is now constructed based on the language passed in and the default language page slug.
path: '/page/:lang?/:slug'
/src/scripts/services.js
This set of utility functions performs the calls to the Content SDK to retrieve server data for the application. Originally, it was built on the idea that there would be one MinimalMain asset that would contain the references to all the pages that the application should know about. This is no longer the case with localization, as each language has its own MinimalMain asset that contains a list of localized pages. Rather than rework the application to support multiple lists of pages, it was decided to have the application get the list of all MinimalMain assets that have a slug starting with “minimalmaingraphql” and then load each one in turn. The list of all pages defined in each MinimalMain instance is then merged into one list and passed into the application for processing.
New functions
getAllMains — Gets a list of all the MinimalMain assets on the server that have a slug starting with “minimalmaingraphql.” Each localized copy of the data has its own MinimalMain asset that matches this pattern. Since the list of these assets is not hard-coded in the client, it’s not necessary to maintain a list of predefined locales to display. Instead, the application can determine this information based on the list of MinimalMain assets that the server returns to it.
const data = await client.getItems({
q: '(type eq "MinimalMain" AND slug sw "minimalmaingraphql")',
});
Modified functions
fetchOceMinimalMain — It now calls getAllMains and loads each one of the returned slugs in turn. It then merges the page lists from all the returned assets into one asset and returns it. Previously it would load one asset only by slug name and return that. The footer logo and header logo are still derived from the first MinimalMain asset loaded so if these were localized, the code would not currently handle them being displayed differently for each language. Instead, the application would have to be modified to manage the set of all MinimalMain assets.
/src/components/Header.vue
The only UI change made in this component is to add a selection box to choose which language should be displayed. This serves two purposes: when a new language is selected, it will change the menu to display only the links for the pages in the new locale, and then it will reload the current page in the new locale. For example, if the user is viewing the French home page and then selects Chinese, it will remove the French page links, display the Chinese page links, and then navigate to the Chinese home page. The data now keeps track of the current language and all the available languages.
Modified functions
created — This function now initializes the default language from the route parameter set in the url. It used to select the first language defined in the list. It also creates an array of available languages. The page slug is now constructed based on the language and the slug passed in the url.
onLanguageChange — This is the callback for the language dropdown selector. It causes the page menu to update to display the pages for the newly selected language. It also checks the current page and loads its equivalent in the new language.
template — The template now includes the UI for rendering the languages dropdown.
<div id="language">
Language
<select v-model="language" @change="onLanguageChange($event)">
<option :key="lang" :value="lang" v-for="(lang) in languages">
{{lang}}
</option>
</select>
</div>
/src/pages/Page.vue
Modified functions
created and beforeRouteUpdate — These functions now also consider the language parameter that’s passed in and creates the page slug to be fetched accordingly.
created() {
// get data passed in on the URL
this.lang = this.$route.params.lang;
const { slug } = this.$route.params;
this.slug = this.lang === 'en' || this.lang === '' || !this.lang ? slug : `${slug}_${this.lang.split('-')[0]}`;
...
}
/src/styles/styles.css
Add a style used to hide languages that are not in use.
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 Vue Minimal Site Sample
F75072-01
December 2022
Copyright © 2021, 2022, Oracle and/or its affiliates.
Primary Author: Oracle Corporation