Tag: polylang

Migrating this blog from WordPress to Hugo

So, the blog is live with Hugo and I’m writing the first post in markdown.

The road has been long, but because I geeked in a new way … well we are in 2026, you already guessed it: yes, AI is behind all of that !

It all started with a question to Gemini: port the blog from WordPress to a static site using a generator in Go… then we started to code with a lot of copy-paste: the Hugo conf and templates, a first docker-compose with a dump of the WordPress db to recover the content. The idea was to code a tool in Go that would do the conversion, so that as long as the rendering wasn’t satisfying I could erase everything and relaunch the import of the posts.

After a lot of reluctance I installed opencode but not without locking it in a Docker. Then I discovered greywall, pi.dev and developed AI-Cabin but my dive into AI is another story, back to the blog.

So I was saying, this port was made with the help of more and more performant AI, but still limited because to keep control over my data I didn’t open accounts at the big actors. I used Gemini because I already have a Google account and this blog is already public, then I moved to the models of Scaleway.

The 3 big elements of this port:

  • an importer: code in Go that uses sqlc to read the db and html-to-markdown/v2 to transform the (pseudo) html of WordPress into markdown files.
  • a multilingual Hugo conf
    • and there, the feature I never finished: the thing that was limping with gengo and that I didn’t finish on polylang: the multilingual aggregate view was finally possible ! a virtual language all in the Hugo config and a virtual duplication of the french or english content into this ‘dimension’ as defined since Hugo v0.156.
  • finally, a tool to compare the Hugo rendering against a wget capture of the WordPress (with plenty of tolerance rules for the things I chose to change)

The big features:

  • reproducible and quite faithful import despite a conversion to markdown
    • thanks to a plugin on html-to-md that I have to publish quickly: because the WordPress html has quite a lot of weirdness:
      • you think already about the line jumps that make paragraphs (wpautop)
      • the smileys
      • the typographic conversions (ex the pretty quotes)
  • comments import (in static because well it was disabled since a long time … thanks spammers)
  • URI preservation because « Cool URIs don’t change » — I already talked about it in 2010 — by configuring Hugo to reproduce in part the WordPress structure, the rest with generated redirects.

There it is, it’s live, I’ll be able to remove PHP from the server, a bit less stress regarding the flaws 😅

From gengo to polylang: updating the theme

So I postponed hacking a mode with multiple languages on the same page and decided to set polylang on my production site (hem) my blog.

But Gengo was using some customized template tags so the theme was adapted to it and this needed to be changed.

With polylang it’s a lot simpler, all navigation is handled by filters, so only thing really custom had to be written:

Basically my hacked version of the_translations had to be ported. And to keep it simple it can even be part of the functions.php file in the theme and use the pll_the_languages function.
I want to display the other language title prefixed by “Language version” written in this language. As the gettext like functions would only return strings in the current language, I hardcoded those strings, but adding them in Polylang admin “strings translation” would have been nice…
So here is the code:

 $translation_title=array(
    'en' => "English version:", 
    'fr' => "Version française : ");
function my_translations() {
    global $post;
    global $translation_title;
    $post_id=$post->ID;
    if ( function_exists('pll_the_languages') ) {
        $translations = pll_the_languages(array('post_id' => $post_id, 'hide_if_no_translation'=>1, 'hide_current'=>1, 'raw'=>1));
        if(!empty($translations)) {
            foreach($translations as $tr) {
                $trid=pll_get_post($post_id, $tr['slug']);
                ?><li lang="<?php echo esc_attr($tr['slug']);?>"><?php echo $translation_title[$tr['slug']]; ?><a hreflang="<?php echo esc_attr($tr['slug']);?>" href="<?php echo esc_url($tr['url']);?>" rel="alternate"><?php echo get_the_title($trid); ?></a></li><?php
            }
        }
    }
}

Instead of porting the old theme, I did build a new one based on WordPress’ Twenty Twelve updated with my previous header and dark color scheme.
I also played with a few css3 features for more neon light effects 🙂

And here it is !

From gengo to polylang: importing data

As you might know, my blog is using gengo to enable translations.

But gengo is an old unmaintained plugin (I’m even running a custom version that I recently needed to fix again) so I’d like to migrate away.

Recently, I studied the available options (thanks to Multilingual WordPress page) and selected Polylang. This one seams to be what Gengo could have been with a rewrite: no extra database tables but using WP3 custom taxonomies. (I can’t find the message but I remember Pixline telling this would be the way to go, so…).

Anyway, I started to test Polylang, what it misses compared to Gengo, is the ability to really mix languages on the same page, so it will need some customizations before replacing Gengo here, but it will come.

It’s only a few days layer that I found the WPML to Polylang plugin.
This basically triggered the development of Gengo to Polylang a plugin to import translations informations from Gengo to Polylang.

It seams to work… I missed the Site Title and Tagline (but they are no longer translated on my blog so I don’t need it 😕 ) and I did take some shortcut for terms (tags & categories) that are the same in both languages.
UPDATE 2014-02-04: I fixed that as it caused the tag archive to contain both english and french posts so… also fixed the Title and Tagline part.

So if you still have a Gengo powered blog and want to migrate, the code could help you, but don’t just run it blindly, make a backup, setup a test instance and be prepared to hack the code ! You have been warned !