How to translate a site developed with Grav

using 2 more open source tools

Ragazza impazzita logo grav

To create multilingual sites you can combine 3 free and open source tools, a CMS, a version control system, and computer-aided translation software:

  • Grav
  • Git
  • OmegaT

What is Grav?

Grav is an open-source flat-file CMS. CMS means Content Management System. A CMS is a programme installed on a web server that lets you create and manage sites. It normally uses a graphic administration interface, a back-end, where the visible elements of the site, the front-end, can be controlled from without necessarily having to write code.

However, the site’s appearance is controlled by themes or templates, collections of files that can be installed separately to change the layout, colours, how content is displayed across the page, etc.

The best-known CMSs are WordPress, Joomla, and Drupal, but there are hundreds more out there. About half of all existing sites are estimated to be CMS-based. Most of these systems, such as WordPress or Joomla, save user-generated content in a database (usually MySQL), while site pages are generated via PHP files. These systems are referred to as database CMS.

Screenshot of Grav CMS

Advantages of Grav

Unlike WordPress, Grav does not save content in a database. It falls within the flat-file CMS category, meaning it is file-based instead. User-generated content is saved in text files in Markdown format (*.md). Markdown is a markup language that supports file scripts that are to be converted to HTML or other formats. We discuss this extensively in another article on this blog, "What is Markdown and how to use it." Markdown files are plain text files that use a special syntax.

This feature makes a huge difference to streamlining admin and management work. For instance, all that is needed to create a backup copy of a site developed with Grav (or another flat-file CMS) is to download the web folder where the site is located. Unlike with database CMS, you won’t need to download files with the one hand and dump the database with the other.

One other really important advantage for what we are trying to achieve is that a site can be localised by simply creating the text files in each language and changing just a few settings in the system configuration file. With database CMS we should instead intervene on the database structure or install appropriate add-ons (plugins).

Lastly, Grav is an open source project, meaning its code is public, so it can be freely viewed and edited. It was voted “Best Open-Source CMS” in 2016 and “Best Flat-File CMS” in 2017 by CMS Critic. Not having to dredge up content from a database not only makes it much faster, but it is also versatile and powerful enough to be used to create almost any kind of site.

Even though there is an administration interface, all the management can also be run directly from the command line, giving admins an additional advantage in terms of flexibility. Regarding multilingual functionality, Grav was born already internationalized, that is, it is already set up to be able to publish sites in various languages. This is a crucial aspect for us and one of the reasons why we have analysed and studied it.

What is Git?

Git is a distributed version control programme.

Version control is a system used by programmers that keeps track of changes made to a file or series of files. These files usually belong to the source code of a programme, but the system can track changes to any file. In this case, we will use the version control tool to track changes to the files that make up the site, as we will see below.

Without going into too much detail, version control systems may be:

  • local
  • centralised
  • distributed

Centralised version control systems, like CVS or Subversion, use a single server which contains every file version. Users download (“checkout”) files from the central server before re-uploading them once changes have been made (“commit”).

However, in distributed version control systems like Git, every user has a complete copy of what is called the “repository” (of the complete project) on their own device.

This way, if the server becomes inaccessible, it can still be restored from a user copy. For further details, we recommend the official Git documentation. For our purposes here, it is enough to know that Git users can each work on their own “branch” of development, introduce and record changes, and finally share these changes, or combine them with those made by other users.

To use Git, the programme must first be installed on your device, and it is also recommended to install a graphic interface along with it for convenience. It is installed by default on almost all Linux distributions, but for Mac and Windows it must be installed manually. There are also online services that allow you to have a Git repository on a remote server without having to install Git on your computer. Let’s use one of these: GitLab.

What is GitLab?

GitLab is a web platform, also open-source, for managing Git repositories. There are various features available, depending on the subscription. The free version offers unlimited private projects and collaborators, but limits the number of operations to 2000 (expressed as CI pipeline minutes per group per month).

To use GitLab you need to register on the site and create one or more projects using the online interface.

New project screen in GitLab

What is OmegaT?

OmegaT is an open-source assisted translation tool. An assisted translation tool, or CAT tool, is a piece of software made up of various modules that save the original texts and their respective translations on a database (called a “translation memory”) and also provide the translator-user with a range of integrated tools to facilitate the translation process (glossaries, dictionaries, spellcheckers, etc.)

We have discussed OmegaT many times on this site, and we provide a range of demonstrations on our YouTube channel.

One of OmegaT’s best attributes is that it can read a wide range of formats, including markdown (*.md) and plain text files (*.txt).

Another distinctive feature is its ability to retrieve projects saved on a Git repository, allowing them to be edited by multiple translators. This feature, called “team project”, basically replaces a centralised translation memory system. We have already explained how to create a shared project using OmegaT and Subversion in another tutorial. The procedure is pretty much the same with Git.

Screenshot of a team project in OmegaT

How to combine these systems

Grav, Git and OmegaT can be used in conjunction with each other. Where the procedure is not specified in detail, please refer to the official documentation for each tool.

Here, we will assume that you are already using Grav to create and manage your site. If that is not the case, system documentation demonstrates how to download, install, and configure it.

Grav requires installing a plugin that allows you to synchronise the entire website bidirectionally with a Git repository. This plugin is called Git Sync.

“Bidirectionally” means that changes made to the Git repository by a user will appear on the site and, vice versa, all changes made from within Grav will also be saved to the repository.

Screenshot of the Grav Git Sync plugin

In this way, multiple authors will be able to collaborate on the website texts, both in the usual way (from the Grav back-end) and by editing the text files directly and synchronizing them through Git.

For convenience, let’s create the main Git repository on GitLab, to execute the whole procedure without even having to worry about installing Git locally. Exact instructions on how to create a repository can be found here: https://docs.gitlab.com/ee/user/project/repository/.

Take note: if the site is to be translated into more than one language, there are two options: either a separate repository can be created for each target language - one for every OmegaT project, or a single repository can be created with sub-folders, into which the different OmegaT projects are inserted, with a sub-folder for each language. Creating a repository for each language is recommended.

Let’s imagine we want to create a site in three languages: English (source language or L1), Spanish (target language, L2) and Italian (target language, L3). We decide to use the first option from above: creating three separate repositories:

  1. a Git repository that will contain the site structure in the source language (L1);
  2. a Git repository for the OmegaT translation project from L1 to L2
  3. a Git repository for the OmegaT translation project from L1 to L3.

Repository 1 synchronises with the site via the Git Sync plugin every time you click the synchronisation icon.

Repository 2 will be synchronised with the relevant local OmegaT projects both when the programme connects to the repository for the first time, and whenever the translation project is saved (even automatically) by one of the translators involved (if there is more than one). The same goes for repository 3. 

Diagram of the interaction between Grav, Gitlab and OmegaT

There are two ways to save the files translated in OmegaT within repository 1:

  1. when you select the “Commit target files” command in OmegaT, which generates the target files and sends them to the repository
  2. copying the target files from the local project to the web server via an FTP connection.

How to configure OmegaT

OmegaT manages translation workflow.

A default OmegaT project consists of a series of folders:

  • dictionary
  • glossary
  • omegat
  • source
  • target
  • tm

and contains a file called omegat.project, which contains the project details.

To get started, create a new project locally, on your own computer, by clicking on Project > New, and choosing the language pair you need (in our example, from Italian to Spanish). Remember to check the box that sets segmentation rules as project-specific, so as to avoid segmentation differences between the various translators involved in the project. Similarly, also check the box that makes the file filter options project-specific.

The usual procedure is to copy the files to be translated into the project’s /source/ folder. Once they are translated, the target files will be created in the /target/ folder.

However, in our case, the files to be translated correspond to the *.md files contained in the user/pages/ folder of the site made with Grav. To avoid the in-between step of copying these files and then having to reload the files translated online again, use the project folder “mapping” function. Thanks to this feature, not all folders need to be present in the project’s root folder. You can configure OmegaT so that each folder in the project is redirected to a folder in another repository, as long as it is just as accessible.

Then, tell OmegaT to use the user/pages/ folder as the origin folder of the files to be translated. Even the translated files, which will be created locally in the /target/ folder, will be copied/synchronised into that folder. This is needed to make Grav’s multilingual mechanism work, which requires the content in each language (the *.md files) to all be stored in the same folder.

For example, to have a home page in each of the 3 languages mentioned above, home.it.md, home.es.md, and home.en.md all need to be saved in the 01.home folder.

While on the subject of file filters, OmegaT can translate files in Markdown format. However, this filter, which is part of the Okapi plugin for OmegaT, is still in the beta phase of development. One of the current shortfalls is that white spaces at the beginning of lines are deleted when generating translated files, which makes them unusable in Grav. While we wait for this problem to be solved by the Okapi plugin developers, we recommend using the plain text file filter.

Most of the options contained in the header should be left unchanged, but - depending on the theme and selected options - sometimes localisable strings are found in the header as well. The Markdown file filter detects some of them, but may not detect all of them.

But be careful! If you’re using the text file filter:

  • both the file header and the text body of the Markdown files will appear as translatable
  • particular attention should be paid to syntax, e.g. single quotes that enclose string values. A missing single quote can prevent the entire file from being rendered.

In the Project Specific File Filters window, click Text and then Options... Select the option that segments the source text at the line breaks.

Next you need to tell OmegaT to save the translated files with a different name from the original, by adding the target-language suffix to the syntax. As previously discussed, since the translated files must be saved in the same folder as the source files, they must be renamed for two reasons:

  • you don’t want the original files to be overwritten
  • as we saw earlier, all the language files need to be in the same folder for the multilingual site to work properly.

To do this, open project properties, click File Filters, choose the Text filter and then press the Edit button. Enter the *.it.md pattern into the dialogue box that opens, and enter ${nameOnly-0}.es.md into the Translated Filename Pattern field. nameOnly-0 is the code that tells OmegaT to only take the name part of the file, and exclude suffixes and extensions. When translating into another language, you must change the language ISO code.

By adding the *.it.md pattern, OmegaT will ignore the files contained in the designated source folder, which are in a different language to the one set as original (Italian in our case).

Screenshot of file filters for txt format in OmegaT

In “project properties” you must also click “Repository Mapping...” and add the address of all the repositories you will use into the first table, i.e. the URL of project/repository 1 created on GitLab and then that of all the repositories that will contain OmegaT projects.

At the bottom of the same window, enter the folder mapping:

  • the source folder = the user/pages folder in repository 1
  • the target folder = the user/pages folder in repository 1.

Grav’s user/pages folder is the one that contains the files and folders that correspond to a website.

Screenshot of Mapping in OmegaT

In order to prevent OmegaT from making any images and PDFs on the site available for translation, a filter must also be created in the shared project properties, excluding all files with .jpg, .gif, .png and .pdf extensions. It is also possible to write a regex telling OmegaT to ignore anything that is not .md, but we have decided to specify the files to be excluded one by one for the sake of clarity.

Screenshot of exclusions in OmegaT

Try to reload the project and make sure it synchronises with the set repositories.

At this point, you need to “commit” the local project to a shared project through Git, using the corresponding Git command.

For GitLab, this can be done from the computer terminal if you are using an operating system with Git installed, or you can use the GitLab web interface, which, however, only allows you to upload files and not folders.

The easiest way is to create the minimum folders of an OmegaT project manually, namely: 

  • glossary
  • omegat
  • source
  • tm

and upload the omegat.project to the root level of the project (the project’s locally created omegat.project file must be uploaded).

With this configured, all translators working on the project will be able to download the translation project corresponding to their language locally, translate the files and eventually generate the target files, which will be saved in the same folder labelled “source", but with the target language suffix.

As mentioned, at that point all the translated files must be saved on the web server so that they go online together along with the rest of the site. This is done with “Commit target files” or via FTP.

On top of this, there are a few necessary measures to be implemented within Grav. These are all explained in the Multi-language chapter of the official documentation, so we won’t get into that here.

It is especially important to add a “slug” option to every page. This option tells Grav how the URL of a page should be translated. Using the same example as in the official documentation, let’s imagine the site had the following structure:

- 01.Animals
  - 01.Mammals
    - 01.Bats
    - 02.Bears
    - 03.Foxes
    - 04.Cats
  - 02.Reptiles
  - 03.Birds
  - 04.Insects

Our URL might be something like http://domain.com/animals/mammals/bears for example. When translating the site into Spanish, it would be useful if the URL also appeared in Spanish. To do this, simply add the “slug:” option, followed by the translation (without special characters). For example:

---
title: Mamíferos
slug: mamíferos
---

By following this criterion, the Spanish URL will look similar to this one: http://dominio.com/animales/mamiferos/osos.

Thanks to the process briefly summarised in this article, you not only will be able to translate a new site, but also all its updates. It will be as simple as setting notifications (automatic or otherwise) to be sent every time the authors add or modify the content in the source language and, at that point, translate the new texts.

As complex as it may seem, the process is much easier to implement than to explain. Once set up on one site, the steps are the same for all others. For a project manager, a small business owner, and even someone with a translation agency like us, the combination of Grav, GitLab, and OmegaT really opens up a range of opportunities to more flexibly and efficiently handle the growing demand for multilingual site development.

The site you are surfing right now is the perfect example of the strategy discussed in this article: it was made entirely with Grav, and was translated into 3 languages using OmegaT and Git.

If you have any questions or concerns, the Comments section below is open to all. If you are looking to internationalise your website or translate it into another language, book a free, non-binding consultation.

Technical translator, project manager, entrepreneur. Languages graduate with an MA in Design and Multimedia Production. He founded Qabiria in 2008.

Further Reading

Chat to one of us

Let us know what you need by sending an email to hola@qabiria.com or by filling in the contact form. We guarantee a response within 24 hours, but usually we’re much faster.

Contact us