Localizing a Ghost Theme
Lately I've spent some time setting up a blog for a friend. Ghost is where it's at these days when it comes to blogging — unless you're a nerd like me who loves to mess around with static site generators every now and then. 😅
Ghost provides many beautiful themes out of the box but most of them don't seem to support localization, which would be a nice thing to have for my friends blog. So I did some digging and essentially it comes down to:
-
Using the
{{t}}
helper for any strings that should be localized (docs) -
Providing a
locales/de.json
file with mappings to localized strings
The
Dawn theme that
we were using was pretty light on strings that needed
localization so with a little bit of
vim-sandwich
magic and a custom mapping I was able to update it to use the
{{t}}
helper in maybe half an hour.
xmap <Leader>t sai{{t "<CR>"}}<CR>
With the visual mapping above all I needed to do is select the
text that I want to localize and hit
<space>t
.
Now the last step was to create the initial
locales/en.json
file. Later on I will use the
English one as a template to create a German localization.
Since typing out the more than a dozen strings manually would have been boring I instead wrote a babashka script to generate the English locales file for me.
#!/usr/bin/env bb
(require '[clojure.java.io :as io]
'[cheshire.core :as json]
'[babashka.fs :as fs])
(def entries
(->> (fs/glob "." "**/*.hbs")
(map (fn [p] (slurp (io/file (str p)))))
(mapcat (fn [file-contents]
(map second (re-seq #"\{\{t \"(.*)\"\}\}" file-contents))))
(set)
(map (fn [s] [s s]))
(into {})))
(println (json/generate-string entries {:pretty true}))
This script essentially finds all usages of the
{{t}}
helper and spits out a JSON object where the
keys are identical to the values (i.e. if the theme was English,
that would be the locales/en.json
file).
Babashka makes figuring this stuff out such a breeze because I can just incrementally build this out in a connected babashka nREPL session instead of changing the file and running the script as a whole on every change. REPLs for the win!
In the end I created this little PR to the theme.