Detecter la langue - Première!

Toute cette préparation pour découper le chemin des fichier dans le premier plugin, c'était surtout pour préparer ce second. Son rôle sera de détecter la langue de chaque fichier, ainsi qu'une clé de traduction pour lier les contenu traduits entre eux.

Au final, pour le fichier posts/an/article--fr.md, la langue détectée sera le français, grâce au suffixe --fr. Tout ce qui précède ce suffixe sera la clé de traduction. Ceci permettra de l'associer à posts/an/article.md, son alter-ego anglais (et de les avoir juste à côté l'un de l'autre).

Pour le moment, par contre, la page en français est fr/index.md. On va commencer avec ça pour commencer gentillement à implémenter la détection de langue.

Structure du plugin

Dans plugins/detectLanguage.js, la structure de ce plugin sera très similaire au précédent. Il itère sur les fichiers et:

module.exports = function detectLanguage() {

  return function(files, metalsmith) {
    // Récupère un peu de configuration
    // dans les données globales du site
    const config = metalsmith.metadata();

    // Vu que toutes les infos sont dans les metadonnées
    // de chaque fichier, on peut itérer sur les valeurs
    // plutôt que les clés pour ce plugin
    Object.values(files).forEach(function(file){

      file.i18n = getLanguageInfo(file, config);
    });
  };
};

function getLanguageInfo(file, options){
  // Bientôt, très bientôt ;)
}

Vous avez peut-être remarqué que le plugin lit les metadonnées globales du site. Que ça soit au début du chemin, ou avec le suffixe comme plus targe, il ne faut pas que n'importe quelle valeur soit interprété comme langue. la/confiture.md ne parle pas de confiture en Lao, c'est juste une jolie URL.

On peut réutiliser la liste de langues ajoutée lors de la création de la navigation par langue: languages. On va lui rajouter defaultLanguage pour indiquer la langue par défaut. Oh, et n'oublions pas d'ajouter le plugin, après pathInfo, dans src/index.js.

// ...
const detectLanguage = require('./plugins/detectLanguage')
// ...
.metadata({
  i18n: {
    defaultLanguage: 'en',
    language: ['en','fr'],
    //...
  }
})
.use(pathInfo())
.use(detectLanguage())
// ...

Détecter la langue

De toutes les partie extraite par le plugin pathInfo, c'est stem qui nous importe ici. En construisant une expression régulière à partir de la liste de langues supportées, on va pouvoir capturer à la fois la langue et la clé de traduction.

function getLanguageInfo(
  file,
  { defaultLanguage, languages } = {}
) {

  const prefix = new RegExp(`^(${languages.join('|')})/(.*)`);
  const result = prefix.exec(file.pathInfo.stem);

  // `result` n'a de valeur que si l'expression régulière
  // a trouvé correspondance. Cela permet de fournir
  // une valeur par défaut dans le `else`
  if (result) {
    return {
      language: result[1],
      key: result[2]
    };
  } else {
    return {
      language: defaultLanguage,
      key: file.pathInfo.stem
    }
  }
}

Un peu de nettoyage

Une fois tout ça en place, le fichier fr/index.md se verra associé la langue fr dans i18n.language. index.md, de son côté, se verra détecté en. On peut donc utiliser cette nouvelle valeur plutôt que language (dans le front-matter):

Et surtout, plus besoin d'une valeur language dans le front-matter de chaque fichier (et pour le moment, plus besoin de front-matter du tout). C'est ça de moins à écrire à la main pour chacun d'eux.

On est pas encore au système présenté en introduction, mais ça prend forme. Dans le prochain article, on passera enfin à l'utilisatio du suffixe pour détecter la langue.