Convertir des collections de chaînes JSON en ressources binaires pour les appareils non compatibles avec l'UTF-8

illustrations illustrations illustrations illustrations illustrations illustrations illustrations

Publié le 14 avril 2022 par Andrew Owen (4 minutes)

post-thumb

La dernière fois, j’ai parlé de la localisation avec Weblate. Cette semaine, je vais montrer comment le projet SE Basic IV prend la sortie JSON de Weblate et la convertit en binaires qui peuvent être utilisés avec des pages de code 8 bits par l’interpréteur. Il s’agit d’un cas d’utilisation très particulier, mais j’espère qu’il y a des leçons générales que vous pouvez appliquer à vos adéquats projets.

Le projet utilise un dépôt Git hébergé sur GitHub. Au premier niveau se trouve un dossier locales contenant le modèle JSON anglais utilisé pour produire les autres fichiers de langue. Ces fichiers sont généralement identifiés par un code de langue ISO à deux lettres, sauf lorsqu’une désambiguïsation est nécessaire (comme pour l’espagnol d’Amérique latine).

Voici un extrait du modèle:

    {
        "NAME": "English",
        "FILENAME": "EN.LN",
        "ICONV": "IBM437",
        "SCROLL": "Scroll?____",
        "ERROR": " in ",
        "READY": "Ready_______",
        "SYNTAX": "Syntax error",
    ...
        "PATH": "Path not found"
    }

Le champ NAME est utilisé par Weblate et le script de compilation (à des fins de rapport).

Le champ FILENAME définit le nom du fichier de sortie.

Le champ ICONV définit la page de code à utiliser lors de la conversion depuis UTF-8.

Les trois premiers termes traduisibles contiennent des personnage de remplissage sous la forme de traits de soulignement. Ceci est nécessaire, car l’interpréteur s’attend à ce que ces termes soient stockés à des adresses fixes. Le script de construction convertira les underscores en null (point de code 0). Les autres termes sont terminés par des personnages nuls.

Les entrées du fichier JSON peuvent être dans n’importe quel ordre. Le script de compilation les affichera dans l’ordre requis.

Quand des changements sont faits dans le dossier locales de la branche principale, une action GitHub est déclenchée qui lance un runner hébergé par GitHub pour exécuter le script de construction. L’action est définie dans un fichier YAML:

name: build localized message bundles
on:
  push:
    paths:
    - 'locales/**'
  workflow_dispatch:
    jobs:
      locales:
        runs-on: ubuntu-latest
        permissions:
          contents: write
        steps:
          - uses: actions/checkout@v2
          - name:
            run: |
              ./scripts/locales.sh
              git config user.name github-actions
              git config user.email github-actions@github.com
              git add .
              git commit -m "locales"
              git push origin main              

Le paramètre name est utilisé à des fins de reporting.

Le paramètre on définit quand le script s’exécute. Dans ce cas, quand il y a un push de n’importe quel type de fichier (**) dans le dossier locales. Si vous ne spécifiez pas de branche, le script s’exécute par défaut sur la branche principale. Le paramètre workflow_dispatch vous permet de lancer manuellement le script depuis l’interface web GitHub Actions.

Le paramètre jobs définit ce que fait l’action. Ici, locales est un nom de travail.

Le paramètre runs-on définit le système d’exploitation utilisé par le runner hébergé, dans ce cas Ubuntu latest (x64). Vous pouvez également spécifier d’autres systèmes d’exploitation, mais si vous devez payer pour vos runners (par exemple parce que vous développez des logiciels commerciaux), Linux est l’option la moins chère.

Le paramètre steps définit le travail. Le paramètre uses vous permet d’utiliser des actions prédéfinies telles que checkout@v2. Cela place une exemplaire du référentiel sur le runner hébergé.

Le paramètre run: | vous permet de spécifier une liste d’actions en ligne de commande. Cette action effectue les tâches suivantes:

  1. Exécuter le script shell locales.sh.
  2. Définir les paramètres Git user.name et user.email. Ceux-ci montreront que des changements ont été effectués par une action.
  3. Ajoutez tous les changements.
  4. Valider les modifications.
  5. Pousser les changements.

Voici un extrait du script locales.sh:

    cd locales
    for f in *.json; do  
        export jname=${f%}
        name=$(jq -r .NAME $jname)
        echo Generating $name
        fname=$(jq -r .FILENAME $jname)
        iconv=$(jq -r .ICONV $jname)
        scroll=$(jq -r .SCROLL $jname)
        error=$(jq -r .ERROR $jname)
        ready=$(jq -r .READY $jname)
        synatx=$(jq -r .SYNTAX $jname)
    ...
        path=$(jq -r .PATH $jname)
        echo $scroll"_"$error"_"$ready"_"$ok"_"$break"_"$for"_"$synatx"_"$gosub"_"$data"_"$call"_"$overflow"_"$memory"_"$line"_"$subscript"_"$variable"_"$address"_"$statement"_"$type"_"$screen"_"$device"_"$stream"_"$channel"_"$function"_"$buffer"_"$next"_"$wend"_"$while"_"$file"_"$input"_"$path"____________________________________________________________________________________________________________________________________________________________________________________________________________________" > TEMP.LN
        iconv -f UTF8 -t $iconv TEMP.LN > $fname
        head -c 608 $fname > TEMP.LN
        mv TEMP.LN $fname
        perl -pi -e 's/_/\0/g' $fname
        mv $fname ../ChloeVM.app/Contents/Resources/chloehd/SYSTEM/LANGUAGE.S/$fname
    done

Le script utilise une boucle FOR pour itérer à travers chaque fichier JSON dans le dossier locales. La plupart du travail est effectué par deux outils:

  • jq - un processeur JSON en ligne de commande.
  • iconv - un outil d’encodage de personnage en ligne de commande.

Pour chaque paramètre du fichier JSON, le script utilise jq pour créer une variable équivalente. Le processus pour chaque fichier se déroule comme suit:

  1. Lorsque toutes les variables sont assignées, un fichier temporaire appelé TEMP.LN est créé avec un peu de remplissage supplémentaire.
  2. Ensuite, iconv est utilisé pour convertir le fichier temporaire en un nom de fichier correct, encodé pour la page de code appropriée.
  3. La commande head est utilisée pour couper le binaire à une longueur fixe.
  4. Le fichier temporaire est supprimé.
  5. Perl est utilisé pour remplacer les underscores (_) par le personnage nul (point de code 0).
  6. Le fichier binaire est déplacé au bon endroit dans le système de fichiers par défaut.

Image: Original par Pineapple Supply Co..