DEV Community

Cover image for Multilingual Ghost CMS Blog: 1. Making Posts and Pages Multilingual
Sanghun Kang
Sanghun Kang

Posted on Originally published at sanghunkang.com

Multilingual Ghost CMS Blog: 1. Making Posts and Pages Multilingual

Ghost can create a Collection of specific posts. Let's create tags for each language we want to support and make a Collection for each one to build a multilingual blog.

  1. Create internal tags for the supported languages
  2. Set up Collections in routes.yaml
  3. Modify the hbs files

I want to build a multilingual blog with English as the primary language and Korean as the secondary language.

💡 In this post series, I used Casper, Ghost's default theme. The same approach can be applied to other themes as well.

Create internal tags

In the Ghost admin screen, select Tags on the left and click New tag to add an internal tag. An internal tag must start with #.

I set the internal tag for English posts to #en and the internal tag for Korean posts to #ko. If you enter #en in Name, the Slug is automatically set to hash-en, but I deleted the hash- part to make it more concise.

Article illustration

Article illustration

When you select Internal tags, you should see a screen like the one below.

Article illustration

Publish test posts

Let's publish some posts with internal tags for later testing.

I published two posts for each internal tag.

  • en news 1: News, #en
  • en news 2: News, #en
  • ko news 1: News, #ko
  • ko news 2: News, #ko

Article illustration

I set the first tag of every post to 'News' and the second tag to the language tag (#en or #ko).

💡 Even if you apply multiple tags, the second tag must be the language tag (#en or #ko). This is a rule I defined for convenience when implementing multilingual tag pages later.

For example, if you want to apply the three tags news, latest, and #en, you should set the order as [news, #en, latest] or [latest, #en, news]. The key point is that the second tag must be the language tag.

Now if you look at the blog's main page, you can see a total of 5 published posts: the 1 default post published during installation plus the 4 additional posts I published.

Article illustration

Set up Collections in routes.yaml

  • In the admin dashboard, click the settings icon, then in Labs select Download current routes to download the routes.yaml file.

The initial state of routes.yaml is as follows.

routes:

collections:
  /:
    permalink: /{slug}/
    template: index

taxonomies:
  tag: /tag/{slug}/
  author: /author/{slug}/
Enter fullscreen mode Exit fullscreen mode

Original routes.yaml

Modify it as shown below and upload it.

routes:

collections:
  /:
    filter: "tag:en"
    permalink: /{slug}/
    template: index-en
  /ko/:
    filter: "tag:ko"
    permalink: /ko/{slug}/
    template: index-ko

taxonomies:
  tag: /tag/{slug}/
  author: /author/{slug}/

Enter fullscreen mode Exit fullscreen mode

routes.yaml (English as the main language)

This sets things up so that when you access https://sanghunkang.com/, only posts with the en tag are shown, and when you access https://sanghunkang.com/ko/, only posts with the ko tag are shown. One important point is that the primary language must be placed at the top of collections.

💡 collections are exclusive

Each collection is exclusive. In other words, there cannot be overlap. If a single post has both #en and #ko tags, it will only appear when accessed through the path of the collection placed higher up, and it will not appear when accessed through the other path.

If you want to make Korean the primary language, you can configure it like this.

routes:

collections:
  /:
    filter: "tag:ko"
    permalink: /{slug}/
    template: index-ko
  /en/:
    filter: "tag:en"
    permalink: /en/{slug}/
    template: index-en

taxonomies:
  tag: /tag/{slug}/
  author: /author/{slug}/
Enter fullscreen mode Exit fullscreen mode

routes.yaml (Korean as the main language)

In this post, I will follow the configuration where English is the primary language.

Modify the hbs files

This explanation is based on version 5.7 of the Casper theme.

For the code changes, refer to the commit below.

0.0.1 · sanghunka/ghost-multilingual-theme@0ba9bd1

  • Add two files
    • index-en.hbs
    • index-ko.hbs
  • Modify three files
    • default.hbs
    • post.hbs
    • page.hbs

index-en.hbs & index-ko.hbs

{{!< index}}
{{#contentFor "lang"}}en{{/contentFor}}
Enter fullscreen mode Exit fullscreen mode

index-en.hbs

{{!< index}}
{{#contentFor "lang"}}ko{{/contentFor}}
Enter fullscreen mode Exit fullscreen mode

index-ko.hbs

Add the two files above to the root path.

default.hbs

<html lang="{{@site.locale}}"{{#match @custom.color_scheme "Dark"}} class="dark-mode"{{else match @custom.color_scheme "Auto"}} class="auto-color"{{/match}}>
Enter fullscreen mode Exit fullscreen mode

Modify this part as follows.

<html lang="{{#if (block "lang")}}{{{block "lang"}}}{{else}}en{{/if}}"{{#match @custom.color_scheme "Dark"}} class="dark-mode"{{else match @custom.color_scheme "Auto"}} class="auto-color"{{/match}}>
Enter fullscreen mode Exit fullscreen mode

With this, pages that use the index-en.hbs template will be set to html lang="en", and pages that use the index-ko.hbs template will be set to html lang="ko".

And if there is no special lang information, the default value en is set.

post.hbs

Add these four lines under {{#post}}.

{{#post}}
  {{#has tag="#ko"}}
    {{#contentFor "lang"}}ko{{/contentFor}}
  {{else}}
    {{#contentFor "lang"}}en{{/contentFor}}
  {{/has}}
Enter fullscreen mode Exit fullscreen mode

page.hbs

Add these four lines under {{#post}}.

{{#post}}
  {{#has tag="#ko"}}
    {{#contentFor "lang"}}ko{{/contentFor}}
  {{else}}
    {{#contentFor "lang"}}en{{/contentFor}}
  {{/has}}
Enter fullscreen mode Exit fullscreen mode

One important point is that the distinction should be based on the secondary language tag. In this post, I set Korean as the secondary language, so if the #ko tag is present it is set to ko, and if not it is set to the default value en.

Result

If you access the / and /ko/ paths configured in routes.yaml, you can confirm that posts are correctly separated and displayed by language tag. This result was achieved with a single Ghost CMS, without using multiple Ghost blogs.

Article illustration

Article illustration

If you check in the developer tools, you can see that the language declaration is also properly set: <html lang="en"> for /, English posts, and English pages, and <html lang="ko"> for /ko/, Korean posts, and Korean pages.

Things to watch out for

  • From now on, every post must include either the #en or #ko tag. If it has neither of these two tags, that post cannot belong to any collection.
  • A post URL slug must not match the slug of a language tag. Since the slug of #en is en and the slug of #ko is ko, a post URL slug must not be en or ko

Article illustration

Article illustration

This must not happen

Next post

Multilingual Ghost CMS Blog: 2. Making 'More Posts' Multilingual

Originally published by Sanghun Kang on Sanghun’s Blog.

Top comments (0)