Help with multi-language content


I have some troubles finishing the set-up of my multi-language architecture.
Basically the main page will be in English, and a few selected articles will be translated into French.

I have Ghost 3.12.0. My theme is a fork of Casper-XYZ, itself a fork of Casper.
Bascially it is a few tweaks here and there, a custom CSS. The original fork was up-to-date with Casper 3.0.6, I merged the latest changes until 3.10.0.

Besides that, I would say the core of my theme is 98% Casper, no breaking changes were made to its core.

So I followed the famous tutorial.

I created the #fr tag.

My routes look like that:

    permalink: /{year}/{month}/{slug}/
    template: index
    filter: 'tag:-hash-fr'
    permalink: /{year}/{month}/{slug}/
    template: index-fr
    filter: 'tag:hash-fr'

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

Then I duplicated the index.hbs and named it index-fr.hbs.

Since I am still on a development phase, I moved 3 default Ghost articles from getting-started to #fr and I see that the routing is working great.

4 articles on the main page and 3 articles when I go to /fr

Now here are 2 issues.

First issue:
In Casper, the <html lang="{{@site.lang}}"> attribute is hard-coded in default.hbs and applies to all templates.

The point 2 of the tutorial is not really working. In posts, it passes a second html lang attribute in the middle of the post code, and this tweak has no effects on other templates than posts.

I am no HBS expert so my solution may be dirty, here is what I did:

in default.hbs:
I changed <html lang="{{@site.lang}}"> to <html lang="{{block "lang"}}">

in post.hbs:
at the very bottom, I added:

  {{#has tag="#fr"}}
    {{#contentFor "lang"}}fr{{/contentFor}}
    {{#contentFor "lang"}}{{@site.lang}}{{/contentFor}}

And all the other templates: index.hbs, author.hbs, tag.hbs I added at the very bottom:

{{#contentFor "lang"}}{{@site.lang}}{{/contentFor}}

except of course index-f.hbs which is:

{{#contentFor "lang"}}fr{{/contentFor}}

It works fine, the html lang is ‘en’ everywhere, except the index-fr and the #fr posts, which is ‘fr’.

The problem with that solution is that I hade to made many changes, and in the future it may be a pain to maintain with the merges with the Casper upstream. I would like to keep my core files as unchanged as possible.

Is there a more elegant solution than the one I described above? To pass the right html lang attribute to the default.hbs template?

Second issue:

The index.hbs I duplicated into index-fr.hbs has no context. When I check the source code on Chrome, I see

<body class="">

I tried all {{#is “contexts”}} nothing is returned.

What can I do to pass the right {{body_class}}?

I would like the index-fr.hbs template to be recognized just like index.hbs, as a home-template:

<body class="home-template">

Thank you a lot for your help!

Hey @frenchvandal,

First of all, nice job on this! Glad the tutorial has been working for you. That block technique you’re using is actually pretty elegant. I understand why you might want to maintain the upstream of changes from Casper, but to be honest when you’re making customisations like this you’re already “off track”. Best thing to do is to keep an eye on Casper, by subscribing to the repo on GitHub, and watch out for any major fixes and improvements.

As for the context, I believe this is due to it being a collection page and not an actual home page template. The home-template class only gets applied if the template is actually being used on the root page. You can add the class yourself though and it should behave in the same manner :slight_smile:

Here’s a bit more context on how the body_class behaves:

Well this is nice to read that my solution is not bad! Really this is new to me it was a wild guess.

Yes this is what I already do :slight_smile:

Is there a way to force/assign a home-template value to body_class within index-fr.hbs code? The page you attached does not give me hints.

If I add an embed <body class="home-template"></body> in index-fr.hbs, I will end up with 2 bodies (because of default.hbs) inside the <html> tag which is not clean (and does not change the behaviour after a try). Otherwise I will just keep the French page as is, a collection page.

You could do an #if statement or use the block method again like you did before?

Before I try the block method, can we check if I can figure something out in default.hbs with a #if statement?

I tried several methods, none worked :confused:

<body class="{{#if index-fr}}home-template{{else}}{{body_class}}{{/if}}">
<body class="{{#if "index-fr.hbs"}}home-template{{else}}{{body_class}}{{/if}}">
<body class="{{#if index-fr.hbs}}home-template{{else}}{{body_class}}{{/if}}">
<body class="{{#if undefined}}home-template{{else}}{{body_class}}{{/if}}">
<body class="{{#if template="index-fr"}}home-template{{else}}{{body_class}}{{/if}}">
<body class="{{#has template="index-fr"}}home-template{{else}}{{body_class}}{{/has}}">
<body class="{{#has {{body_class}}=null}}home-template{{else}}{{body_class}}{{/has}}">
<body class="{{#has template=index-fr}}home-template{{else}}{{body_class}}{{/has}}

Thank you!

@DavidDarnes I have thinking a little bit out loud, posting here made me think differently.

Instead of doing these tweaks in the different templates, is this a viable solution not to insert index-fr.hbs in the body of default.hbs, and just hard code everything directly into index-fr.hbs. Will the route still work? :slight_smile:

That is certainly possible. The method of using a default.hbs template is merely to prevent the repeated use of the same code. Making completely custom index pages might be more beneficial to you and you’re kind of already doing it. In your index files you can remove the {{!< default}} line at the top of the template file, then you’ll need to insert your own code to replace it :+1:

Hey @frenchvandal, just thought I’d let you know we’ve updated our docs to include the block and contentFor helpers which were the helpers chatted about for your query. Hope this helps in future: