PROJET AUTOBLOG


Planet-Libre

source: Planet-Libre

⇐ retour index

Jean-Baptiste Holcroft : Traduction des langues, pays et autres - merci Unicode

vendredi 20 janvier 2017 à 00:00

Il arrive parfois d’avoir à traduire le nom de langues dans les logiciels. Et quand vous tombez sur « Fulani », vous êtes un peu perplexe !

Heureusement, des experts sont déjà passés par là et ont déjà fait le travail de traduction !

La débrouille

Les contributeurs wikipédia qui tracent presque tout par des publications sont assez utiles pour les mots spécifiques déjà traduits de façon standardisée. Le Fulani existe sous le nom Fula language qui nous mène à la page française Peul. Merci les contributeurs wikipédia 😏.

Vérifier/automatiser/accélérer avec l’Unicode Common Locale Data Repository

Le consortium Unicode maintien à jour une liste immense, qu’on trouve traduit Wikipédia ont traduit en « Répertoire de données de paramètres régionaux classiques ».

On y trouve toute sorte de traduction de langue, de pays, de mesures, des jours de la semaine, etc. En se rendant sur le site du CLDR on télécharge la dernière version publique 30.0.3 puis on récupère cldr-common-30.0.3.zip.

Dans l’arborescence, on va dans le sous-dossier common/main puis on ouvre le fichier xml fr.xml qui contient ce qu’on cherche. Sans surprise, on trouve dans « languages » les traductions des langues, dans « scripts » la traduction des écritures, etc.

Bon, le Peul tout come le Fulani ont comme code “ff” ou “ful”, donc la traduction est cohérente.

Ami développeurs, si vous avez ce type de vocabulaire à traduire, n’hésitez pas à capitaliser sur l’Unicode !

Le risque de ne pas utiliser Unicode : Roumanie = Romanche

Dans l’application Dictionary qui récupère du contenu du Wiktionnaire, on a des listes de langues traduites. Ayant moi-même besoin de traduire en roumain, j’ai détecté deux problèmes : le nom du dictionnaire est traduit en “Romanche” à la place de “Roumain”, on traduit des listes de valeurs déjà traduites dans android (voir le tableau de support).

Tout est dans le rapport d’anomalie.

Bonne traduction !

Gravatar de Jean-Baptiste Holcroft
Original post of Jean-Baptiste Holcroft.Votez pour ce billet sur Planet Libre.

Dimitri Robert : Scribus – table des matières avec un script

jeudi 19 janvier 2017 à 19:43

Scribus est un fabuleux logiciel libre de mise en page (oui, fabuleux, j’assume !) même s’il souffre encore de manques (en passe de disparaître, la prochaine version est encore plus fabuleuse). Par exemple, la création d’une table des matières est lourde et peu pratique. Voir l’article Réaliser une table des matières que j’avais écrit il y a presque quatre ans (et que je remets sur ce blog) et qui n’a, malheureusement, pas pris une ride.

Ayant quelques compétences en programmation et connaissant un peu le format SLA (Scribus Layout), le format de travail de Scribus, je me suis dit qu’on pouvait automatiser la recherche de titres. J’ai donc écrit un script Perl qui extrait tous les titres ayant un style clairement identifié.

Pourquoi Perl et pas Python, le langage de prédilection des extensions de Scribus ? Déjà, je connais mieux Perl que Python et j’avais une contrainte de temps. D’autre part, le format SLA est amené à évoluer d’ici la sortie de Scribus 1.6 de même que le moteur interne de scripts. Enfin, le script que je vous présente là est indépendant de Scribus, vu qu’il lit directement le SLA (qui n’est autre que du XML). Ce script est donc une solution intermédiaire, temporaire. À la sortie quelqu’un (moi peut-être) sera toujours à temps de s’atteler à la tâche (si le mécanisme de table des matières n’a pas été amélioré d’ici-là).

Conditions de base

Lorsque vous réalisez votre maquette, vous devez insérer vos titres dans des cadres de textes séparés du reste et surtout, non liés. Vous devez appliquer un style de paragraphe directement sur le cadre de texte.

Vous pouvez insérer des retours à la ligne (Maj + Entrée), c’est-à-dire, sans changement de paragraphe. Cela peut servir à mieux présenter un titre sur plusieurs lignes. Le script concatène les différentes lignes.

Enfin, vous pouvez utiliser plusieurs styles différents pourvu qu’ils aient une partie du nom commune (c’est le cas dans l’exemple ci-dessous).

Enfin, pour la bonne exécution du script, vous devez avoir installé l’interpréteur Perl (c’est le cas par défaut sous Linux), ainsi que le module XML::DOM.

Le script

#!/usr/bin/perl -w
use strict;
use Data::Dumper;
use utf8;

# Chargement du module XML::DOM pour parser du XML
use XML::DOM;

# Création de l'objet parser et chargement du fichier XML passé en paramètre
my $parser = new XML::DOM::Parser;
my $doc = $parser->parsefile(shift);

# Sélection des éléments de type PAGEOBJECT et calcul de leur nombre
my $frameobject = $doc->getElementsByTagName("PAGEOBJECT");
my $n = $frameobject->getLength;

# Une table de hachage pour accueillir la table des matières
my %tdm = ();

# Tri des PAGEOBJECT
for (my $i = 0; $i getAttribute ("PSTYLE");

	# S'il ne contient pas -TF- on passe au suivant
	next unless ($style =~ m/-TF-/);

	# Sinon on récupère le numéro de la page (OwnPage)
	my $pageNum = $node->getAttribute ("OwnPage") + 1; # Attention OwnPage commence à 0

	# Ainsi que les sous-éléments de type ITEXT.
	# S'il y a des retours à la ligne (Maj + Entrée) il y a plusieurs ITEXT
	# qu'il nous faut concaténer
	my $itext = $node->getElementsByTagName("ITEXT");
	my $nt = $itext->getLength;
	my $title = "";
	for (my $j = 0; $j item($j);

		# Pour une obscure raison, le texte est stocké dans un paramètre CH
		$title .= $t->getAttribute("CH")." ";
	}

	# Encodage du texte en UTF-8
	utf8::encode($title);

	# Les titres seront automatiquement classés par leur numéro de page
	# Pour cela il faut que ces numéros soient classés dans le bon ordre.
	# On rajoute un zéro pour les numéros inférieurs à 10.
	$pageNum = sprintf("%.2u", $pageNum);

	# L'affectation du titre dans la table de hachage trie automatiquement
	# par numéro de page
	$tdm{$pageNum} = $title;
}

# Réécriture propre de la table des matières
foreach my $k (sort(keys(%tdm)))
{
	printf("%s\\t%u\\n", $tdm{$k}, $k);
}

Quelques explications de codage :

Créer la table des matières

Passons à l’action. Enregistrez ce script dans un fichier nommé, par exemple, tdm-sla.pl. Ajoutez-lui les droits d’exécution :

chmod +x tdm-sla.pl

Puis exécutez-le en passant en argument votre document Scribus. L’affichage de la table des matières se fait sur la sortie standard, donc, redirigez-la vers un fichier texte.

./tdm-sla.pl document.sla > tdm.txt

Dans Scribus il ne vous reste plus qu’à créer un cadre de texte et insérer ce texte.

Un style pour les entrées de la table

Dernière étape : créer un style de paragraphe pour les entrées de la table des matières. Dans Scribus allez dans le gestionnaire de styles (Édition → Styles) et créez un style nommé TDM (par exemple).

Il faut gérer la tabulation que le script insère entre le titre et le numéro de page. Cliquez sur la ligne graduée en bas pour créer une tabulation. Vous pouvez en saisir une valeur précise dans le champ prévu à cet effet (dans le rectangle vert sur la capture ci-dessous). Vous pouvez également choisir l’alignement du numéro de page (liste déroulante à gauche de la position de la tabulation). Ici, les numéros de page seront centrés.

Gestionnaire de styles Scribus

En personnalisant un peu le script ci-dessus j’ai donc pu extraire plusieurs niveaux de titres et générer automatiquement la table des matières donc voici un extrait ci-dessous. Il s’agit du catalogue de formations d’Artefacts, encore en cours d’élaboration (mais la sortie est imminente).

Table des matières dans le catalogue de formations d'Artefacts

Astuce : si vous souhaitez extraire plusieurs niveaux de titre (donc à partir de cadres de textes de styles différents) il faut d’abord les gérer dans le script. Vous pouvez ajouter un symbole en début de ligne pour distinguer ces différents niveaux. Par exemple, vous ajoutez un dièse devant les titres de rubrique.

Ensuite, dans Scribus, vous pouvez importer votre table des matières comme texte avec filtrage (plutôt que texte simple). Définissez ensuite des filtres comme ceci.

Importer un texte avec filtrage

Cet article Scribus – table des matières avec un script est publié sous licence CC By-SA 4.0 par Dimitri Robert sur Formation logiciel libre - Reprenez le contrôle de votre informatique !.

Gravatar de Dimitri Robert
Original post of Dimitri Robert.Votez pour ce billet sur Planet Libre.

Articles similaires

Thuban : Un GUI en python : TP 2, des dialogues

mercredi 18 janvier 2017 à 16:16

Nous sommes aujourd'hui réunis suite à un terrible constat : notre visionneuse tkv craint un max.
C'est pourquoi nous allons ajouter une toute petite option nous permettant de choisir l'image que l'on souhaite visualiser sur notre ordinateur. Cela nous permettra par la même occasion de nous débarasser de certains morceaux qui ne sont plus utiles.

Profitons des dialogues déjà prêts dans la bibliothèque de tkinter en important celle qui nous intéresse :

from tkinter import filedialog

Nous pouvons à la place du téléchargement de l'image appeler une fenêtre de dialogue pour demander l'image à ouvrir :

# Ouverture de l'image
img_path = filedialog.askopenfilename(\\
        initialdir=(os.path.expanduser("~")),\\
        title="Image à ouvrir",\\
        parent=w)

Notez ici plusieurs options :

Cela ne sufit pas, il faudrait proposer seulement les fichiers qui sont des images. On va donc indiquer les motifs qui nous intéressent (pattern). En gros, ce sont juste les extensions :

# Ouverture de l'image
img_path = filedialog.askopenfilename(\\
        initialdir=(os.path.expanduser("~")),\\
        filetypes=[('Images', ('.png', '.PNG', '.jpg', '.JPG', '.gif', '.GIF')), ('Tout', '.*')],\\
        title="Image à ouvrir",\\
        parent=w)

On ajoute quand même un petit test pour vérifier que on a bien sélectionné un fichier valide. On utilise la bibliothque "mimetypes" qui est livrée par défaut avec python, et on regarde si le mot "image" apparait dans le type du fichier.
Pour afficher l'erreur, on utilise une fenêtre de dialogue livré avec tkinter après avoir importé la partie qui nous intéresse :

mimtyp = mimetypes.guess_type(img_path)[0] # i.e 'image/jpeg'
if not mimtyp or "image" not in mimtyp :
    # Il n'y a pas le mot "image" dans le mimetype
    from tkinter import messagebox
    messagebox.showerror("Fichier invalide", "Le fichier demandé n'est pas une image.")

Et voilà !

Remarquez qu'il existe un tas de fenêtres de dialogue déjà toutes prêtes pour afficher des avertissements (showwarning) ou des informations (showinfo) ou de poser une simple question (askquestion). Regardez par ici pour plus de détails : http://effbot.org/tkinterbook/tkinter-standard-dialogs.htm.

Je vais rajouter quelques lignes pour afficher une image si elle est passée en argument (par exemple en faisant tkv /home/bibi/image.jpg) :


# Ouverture de l'image
if len(sys.argv) == 2:
    # On a une image en agument
    img_path = sys.argv[1]
else:
    # On va chercher une image sur le disque
    img_path = filedialog.askopenfilename(\\
    # ...
    # ...

Il reste encore quelques points à améliorer, mais ça reste déjà plus pratique. ^^
Ça sera tout pour aujourd'hui.
La prochaine fois, nous ajouterons quelques boutons à notre visionneuse d'images :)

Voici le code final :


#!/usr/bin/env python
# -*- coding:Utf-8 -*- 

import os
import sys
import mimetypes
from tkinter import *
from tkinter import filedialog
from PIL import Image, ImageTk


# Notre fenêtre principale
w = Tk()
w.title("tkv : visionneuse d'images") # Un titre
w.configure(background='#000000')     # Fond noir

# Un conteneur dans la fenêtre
mainframe = Frame(w)
mainframe.pack(fill=BOTH,expand=True, padx=15, pady=15)

# Ouverture de l'image
img_path=""
if len(sys.argv) == 2:
    # On a une image en agument
    img_path = sys.argv[1]

if not os.path.isfile(img_path):
    # On va chercher une image sur le disque
    img_path = filedialog.askopenfilename(\\
            initialdir=(os.path.expanduser("~")),\\
            filetypes=[('Images', ('.png', '.PNG', '.jpg', '.JPG', '.gif', '.GIF')), ('Tout', '.*')],\\
            title="Image à ouvrir",\\
            parent=w)

# Est-ce un fichier valide ?
mimtyp = mimetypes.guess_type(img_path)[0] # i.e 'image/jpeg'
if not mimtyp or "image" not in mimtyp :
    # Il n'y a pas le mot "image" dans le mimetype
    from tkinter import messagebox
    messagebox.showerror("Fichier invalide", "Le fichier demandé n'est pas une image.")
    sys.exit(1)

# Ouverture de l'image
image = Image.open(img_path)
# Dimensions de l'écran : 
gap = 100 # marge par rapport aux bordes de l'écran
screen_width = w.winfo_screenwidth() - gap
screen_height = w.winfo_screenheight() - gap

if image.width > screen_width : 
    image = image.resize((screen_width, int(image.height * screen_width / image.width)), Image.ANTIALIAS)
if image.height > screen_height :   
    image = image.resize((int(image.width * screen_height / image.height), screen_height), Image.ANTIALIAS)

# Chargement de l'image en mémoire
img = ImageTk.PhotoImage(image)

# Insertion de l'image dans le conteneur.
img_widget = Label(mainframe, image=img)
img_widget.pack()

# Démarrage du programme
w.mainloop()

sys.exit(0)

Gravatar de Thuban
Original post of Thuban.Votez pour ce billet sur Planet Libre.

Thuban : Un GUI en python : TP 2, des dialogues

mercredi 18 janvier 2017 à 16:16

Nous sommes aujourd'hui réunis suite à un terrible constat : notre visionneuse tkv craint un max.
C'est pourquoi nous allons ajouter une toute petite option nous permettant de choisir l'image que l'on souhaite visualiser sur notre ordinateur. Cela nous permettra par la même occasion de nous débarasser de certains morceaux qui ne sont plus utiles.

Profitons des dialogues déjà prêts dans la bibliothèque de tkinter en important celle qui nous intéresse :

from tkinter import filedialog

Nous pouvons à la place du téléchargement de l'image appeler une fenêtre de dialogue pour demander l'image à ouvrir :

# Ouverture de l'image
img_path = filedialog.askopenfilename(\\
        initialdir=(os.path.expanduser("~")),\\
        title="Image à ouvrir",\\
        parent=w)

Notez ici plusieurs options :

Cela ne sufit pas, il faudrait proposer seulement les fichiers qui sont des images. On va donc indiquer les motifs qui nous intéressent (pattern). En gros, ce sont juste les extensions :

# Ouverture de l'image
img_path = filedialog.askopenfilename(\\
        initialdir=(os.path.expanduser("~")),\\
        filetypes=[('Images', ('.png', '.PNG', '.jpg', '.JPG', '.gif', '.GIF')), ('Tout', '.*')],\\
        title="Image à ouvrir",\\
        parent=w)

On ajoute quand même un petit test pour vérifier que on a bien sélectionné un fichier valide. On utilise la bibliothque "mimetypes" qui est livrée par défaut avec python, et on regarde si le mot "image" apparait dans le type du fichier.
Pour afficher l'erreur, on utilise une fenêtre de dialogue livré avec tkinter après avoir importé la partie qui nous intéresse :

mimtyp = mimetypes.guess_type(img_path)[0] # i.e 'image/jpeg'
if not mimtyp or "image" not in mimtyp :
    # Il n'y a pas le mot "image" dans le mimetype
    from tkinter import messagebox
    messagebox.showerror("Fichier invalide", "Le fichier demandé n'est pas une image.")

Et voilà !

Remarquez qu'il existe un tas de fenêtres de dialogue déjà toutes prêtes pour afficher des avertissements (showwarning) ou des informations (showinfo) ou de poser une simple question (askquestion). Regardez par ici pour plus de détails : http://effbot.org/tkinterbook/tkinter-standard-dialogs.htm.

Je vais rajouter quelques lignes pour afficher une image si elle est passée en argument (par exemple en faisant tkv /home/bibi/image.jpg) :


# Ouverture de l'image
if len(sys.argv) == 2:
    # On a une image en agument
    img_path = sys.argv[1]
else:
    # On va chercher une image sur le disque
    img_path = filedialog.askopenfilename(\\
    # ...
    # ...

Il reste encore quelques points à améliorer, mais ça reste déjà plus pratique. ^^
Ça sera tout pour aujourd'hui.
La prochaine fois, nous ajouterons quelques boutons à notre visionneuse d'images :)

Voici le code final :


#!/usr/bin/env python
# -*- coding:Utf-8 -*- 

import os
import sys
import mimetypes
from tkinter import *
from tkinter import filedialog
from PIL import Image, ImageTk


# Notre fenêtre principale
w = Tk()
w.title("tkv : visionneuse d'images") # Un titre
w.configure(background='#000000')     # Fond noir

# Un conteneur dans la fenêtre
mainframe = Frame(w)
mainframe.pack(fill=BOTH,expand=True, padx=15, pady=15)

# Ouverture de l'image
img_path=""
if len(sys.argv) == 2:
    # On a une image en agument
    img_path = sys.argv[1]

if not os.path.isfile(img_path):
    # On va chercher une image sur le disque
    img_path = filedialog.askopenfilename(\\
            initialdir=(os.path.expanduser("~")),\\
            filetypes=[('Images', ('.png', '.PNG', '.jpg', '.JPG', '.gif', '.GIF')), ('Tout', '.*')],\\
            title="Image à ouvrir",\\
            parent=w)

# Est-ce un fichier valide ?
mimtyp = mimetypes.guess_type(img_path)[0] # i.e 'image/jpeg'
if not mimtyp or "image" not in mimtyp :
    # Il n'y a pas le mot "image" dans le mimetype
    from tkinter import messagebox
    messagebox.showerror("Fichier invalide", "Le fichier demandé n'est pas une image.")
    sys.exit(1)

# Ouverture de l'image
image = Image.open(img_path)
# Dimensions de l'écran : 
gap = 100 # marge par rapport aux bordes de l'écran
screen_width = w.winfo_screenwidth() - gap
screen_height = w.winfo_screenheight() - gap

if image.width > screen_width : 
    image = image.resize((screen_width, int(image.height * screen_width / image.width)), Image.ANTIALIAS)
if image.height > screen_height :   
    image = image.resize((int(image.width * screen_height / image.height), screen_height), Image.ANTIALIAS)

# Chargement de l'image en mémoire
img = ImageTk.PhotoImage(image)

# Insertion de l'image dans le conteneur.
img_widget = Label(mainframe, image=img)
img_widget.pack()

# Démarrage du programme
w.mainloop()

sys.exit(0)

Gravatar de Thuban
Original post of Thuban.Votez pour ce billet sur Planet Libre.

nIQnutn : Gestionnaire de liens: adieu Shaarli, bonjour PluXml

mercredi 18 janvier 2017 à 13:31

Après avoir utilisé Shaarli comme gestionnaire de liens depuis 2015, j'ai décidé de passer à autre chose. En fait c'est Bronco qui m'a un peu inspiré.
C'est sympa de partager des liens, mais ça devient vite pénible et on ne sait pas par où commencer: réseaux sociaux, site web, shaarli,...
Je n'utilise que la gestion des liens avec Shaarli et je n'ai pas eu de problème avec. C'est juste que ça ne correspond plus à mes besoins et j'ai envie de me simplifier la vie.

Comme je suis plus attaché à ce blog, j'ai décidé de gérer les liens directement depuis PluXml.

Dans son article, Bronco explique l'abandon de Shaarli:

Dans un souci de simplicité et de compacité, je vais désormais réunir le maximum de choses sous PluXml, à commencer par mes liens...

Dans mon cas, c'est la même chose. J'ai envie de faire simple et gérer le maximum de chose possible depuis un seul outil. Comme je ne compte pas me séparer pour le moment de PluXml, c'est Shaarli qui prend le départ.
Dans le même esprit, blogotext permet de gérer des liens. Dommage que le projet soit abandonné.

Au final, je ne perds pas beaucoup au change, éventuellement l'absence de tags et des vignettes.
Je n'utilise évidemment pas toutes les fonctionnalités de Shaarli.

Le passage vers PluXml

Coté PluXml, j'ai décidé d'utiliser les commentaires d'un article comme gestionnaire de liens.
Il n'y a pas de gros changement à effectuer et ça peut fonctionner sans modifications de PluXml.

On commence par créer un article qui recensera tous les liens.
Ensuite, il suffit d'ajouter de nouveaux commentaires qui seront en fait nos liens.

Pour créer un lien, il nous faut:

On aura aussi un flux RSS pour ceux qui veulent suivre les derniers liens.

Création d'un template

Pour faciliter la lecture des liens j'ai créé un nouveau template d'article et ajouter un champ de recherche.
J'ai aussi modifié le formulaire pour ajouter un lien. En l'état, il faut faire correspondre les champs et c'est pas très pratique. C'est pas indispensable mais plus agréable à l'usage.

La discussion et les détails sur le forum PluXml: http://forum.pluxml.org/viewtopic.php?id=5751

Les éventuels problèmes

J'ai eu un petit doutes concernant les performances pour afficher un nombre important de liens. Pour le moment ça semble tenir le choc et j'ai décidé de limiter les liens en créant un article par année. De toute façon, je n'ai pas l'intention de faire une collection de liens, seulement partager ceux qui me semblent intéressant de partager.

Si je dois faire un retour en arrière, je sais que je pourrais facilement récupérer mes liens.
Ils sont faciles à récupérer et l'utilisation de fichiers XML me permettra d'extraire facilement les données si besoin.

Il est possible d'exporter ses liens depuis Shaarli vers un fichier Nestcape html bookmark pour ne rien perdre.
Depuis le menu: Tools > Export


2016 nIQnutn CC-BY

Gravatar de nIQnutn
Original post of nIQnutn.Votez pour ce billet sur Planet Libre.

I'm richer than you! infinity loop