up wiki compare

This commit is contained in:
Tykayn 2025-08-22 17:58:04 +02:00 committed by tykayn
parent ce508974c9
commit 2f49ef6479
23 changed files with 567403 additions and 5132 deletions

View file

@ -9,6 +9,175 @@ use Symfony\Component\HttpFoundation\Request;
class WikiController extends AbstractController
{
#[Route('/admin/wiki/missing-translations', name: 'app_admin_wiki_missing_translations')]
public function missingTranslations(): Response
{
$csvFile = $this->getParameter('kernel.project_dir') . '/wiki_compare/wiki_pages.csv';
if (!file_exists($csvFile)) {
$this->addFlash('error', 'Le fichier wiki_pages.csv n\'existe pas.');
return $this->redirectToRoute('app_admin_wiki');
}
$csvData = array_map('str_getcsv', file($csvFile));
$headers = array_shift($csvData);
$wikiPages = [];
// Process CSV data
foreach ($csvData as $row) {
$page = array_combine($headers, $row);
$wikiPages[$page['key']][$page['language']] = $page;
}
// Find French pages without English translations
$frenchOnlyPages = [];
foreach ($wikiPages as $key => $languages) {
if (isset($languages['fr']) && !isset($languages['en'])) {
$frenchOnlyPages[$key] = $languages['fr'];
}
}
// Sort by key
ksort($frenchOnlyPages);
return $this->render('admin/wiki_missing_translations.html.twig', [
'french_only_pages' => $frenchOnlyPages
]);
}
#[Route('/admin/wiki/suspicious-deletions', name: 'app_admin_wiki_suspicious_deletions')]
public function suspiciousDeletions(): Response
{
$csvFile = $this->getParameter('kernel.project_dir') . '/wiki_compare/wiki_pages.csv';
$jsonFile = $this->getParameter('kernel.project_dir') . '/wiki_compare/outdated_pages.json';
if (!file_exists($csvFile) || !file_exists($jsonFile)) {
$this->addFlash('error', 'Les fichiers nécessaires n\'existent pas.');
return $this->redirectToRoute('app_admin_wiki');
}
// Load CSV data
$csvData = array_map('str_getcsv', file($csvFile));
$headers = array_shift($csvData);
// Process CSV data to find French pages
$frenchPages = [];
foreach ($csvData as $row) {
$page = array_combine($headers, $row);
if ($page['language'] === 'fr') {
$frenchPages[$page['key']] = $page;
}
}
// Load JSON data
$jsonData = json_decode(file_get_contents($jsonFile), true);
// Find pages with suspicious deletions
$suspiciousPages = [];
foreach ($jsonData as $page) {
if (isset($page['fr_page']) && isset($page['en_page'])) {
// Calculate deletion percentage
$enWordCount = (int)$page['en_page']['word_count'];
$frWordCount = (int)$page['fr_page']['word_count'];
$wordDiff = $enWordCount - $frWordCount;
// If English has more words and the difference is significant (>30%)
if ($wordDiff > 0 && $frWordCount > 0 && ($wordDiff / $enWordCount) > 0.3) {
$page['deletion_percentage'] = round(($wordDiff / $enWordCount) * 100, 2);
$suspiciousPages[] = $page;
}
}
}
// Sort by deletion percentage (highest first)
usort($suspiciousPages, function($a, $b) {
return $b['deletion_percentage'] <=> $a['deletion_percentage'];
});
return $this->render('admin/wiki_suspicious_deletions.html.twig', [
'suspicious_pages' => $suspiciousPages
]);
}
#[Route('/admin/wiki/tag-proposals', name: 'app_admin_wiki_tag_proposals')]
public function tagProposals(): Response
{
// URL of the OSM wiki page that lists tag proposals
$url = 'https://wiki.openstreetmap.org/wiki/Proposed_features';
try {
$html = file_get_contents($url);
if ($html === false) {
throw new \Exception('Failed to fetch the tag proposals page');
}
// Create a DOM parser
$dom = new \DOMDocument();
@$dom->loadHTML($html);
$xpath = new \DOMXPath($dom);
// Find the table with proposals
$tables = $xpath->query("//table[contains(@class, 'wikitable')]");
$proposals = [];
if ($tables->length > 0) {
// Get the first table which contains the active proposals
$table = $tables->item(0);
$rows = $xpath->query(".//tr", $table);
// Skip the header row
for ($i = 1; $i < $rows->length; $i++) {
$row = $rows->item($i);
$cells = $xpath->query(".//td", $row);
if ($cells->length >= 4) {
$proposal = [
'feature' => $xpath->query(".//a", $cells->item(0))->item(0)->textContent,
'url' => 'https://wiki.openstreetmap.org' . $xpath->query(".//a", $cells->item(0))->item(0)->getAttribute('href'),
'description' => $cells->item(1)->textContent,
'proposer' => $cells->item(2)->textContent,
'status' => $cells->item(3)->textContent,
];
$proposals[] = $proposal;
}
}
}
return $this->render('admin/wiki_tag_proposals.html.twig', [
'proposals' => $proposals
]);
} catch (\Exception $e) {
$this->addFlash('error', 'Erreur lors de la récupération des propositions de tags : ' . $e->getMessage());
return $this->redirectToRoute('app_admin_wiki');
}
}
#[Route('/admin/wiki/random-suggestion', name: 'app_admin_wiki_random_suggestion')]
public function randomSuggestion(): Response
{
$jsonFile = $this->getParameter('kernel.project_dir') . '/wiki_compare/outdated_pages.json';
if (!file_exists($jsonFile)) {
$this->addFlash('error', 'Le fichier outdated_pages.json n\'existe pas.');
return $this->redirectToRoute('app_admin_wiki');
}
$jsonData = json_decode(file_get_contents($jsonFile), true);
if (empty($jsonData)) {
$this->addFlash('error', 'Aucune page à améliorer n\'a été trouvée.');
return $this->redirectToRoute('app_admin_wiki');
}
// Select a random page from the outdated pages
$randomPage = $jsonData[array_rand($jsonData)];
return $this->render('admin/wiki_random_suggestion.html.twig', [
'page' => $randomPage
]);
}
#[Route('/admin/wiki', name: 'app_admin_wiki')]
public function index(): Response

View file

@ -0,0 +1,37 @@
<nav class="navbar navbar-expand-lg navbar-light bg-light mb-4">
<div class="container-fluid">
<a class="navbar-brand" href="{{ path('app_admin_wiki') }}">Wiki OSM</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#wikiNavbar" aria-controls="wikiNavbar" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="wikiNavbar">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link {% if app.request.get('_route') == 'app_admin_wiki' %}active{% endif %}" href="{{ path('app_admin_wiki') }}">
<i class="bi bi-list-ul"></i> Liste des pages
</a>
</li>
<li class="nav-item">
<a class="nav-link {% if app.request.get('_route') == 'app_admin_wiki_random_suggestion' %}active{% endif %}" href="{{ path('app_admin_wiki_random_suggestion') }}">
<i class="bi bi-shuffle"></i> Suggestion aléatoire
</a>
</li>
<li class="nav-item">
<a class="nav-link {% if app.request.get('_route') == 'app_admin_wiki_tag_proposals' %}active{% endif %}" href="{{ path('app_admin_wiki_tag_proposals') }}">
<i class="bi bi-tag"></i> Propositions de tags
</a>
</li>
<li class="nav-item">
<a class="nav-link {% if app.request.get('_route') == 'app_admin_wiki_suspicious_deletions' %}active{% endif %}" href="{{ path('app_admin_wiki_suspicious_deletions') }}">
<i class="bi bi-exclamation-triangle"></i> Suppressions suspectes
</a>
</li>
<li class="nav-item">
<a class="nav-link {% if app.request.get('_route') == 'app_admin_wiki_missing_translations' %}active{% endif %}" href="{{ path('app_admin_wiki_missing_translations') }}">
<i class="bi bi-translate"></i> Pages sans traduction
</a>
</li>
</ul>
</div>
</div>
</nav>

View file

@ -4,6 +4,8 @@
{% block body %}
<div class="container mt-4">
{% include 'admin/_wiki_navigation.html.twig' %}
<h1>Pages Wiki OpenStreetMap</h1>
<p class="lead">Comparaison des pages wiki en français et en anglais pour les clés OSM les plus utilisées.</p>

View file

@ -8,14 +8,29 @@
transform: none !important;
box-shadow: none !important;
}
.title-level-1 {
font-weight: bold;
}
.title-level-2 {
padding-left: 1.5rem;
}
.title-level-3 {
padding-left: 2.8rem;
}
.title-level-4 {
padding-left: 4rem;
}
.title-level-5 {
padding-left: 5.2rem;
}
.title-level-6 {
padding-left: 6.4rem;
font-size: 0.9rem;
}
</style>
<div class="container mt-4">
{% include 'admin/_wiki_navigation.html.twig' %}
<h1>Comparaison Wiki OpenStreetMap - {{ key }}</h1>
<p class="lead">Comparaison détaillée des pages wiki en français et en anglais pour la clé OSM "{{ key }}".</p>
@ -118,22 +133,20 @@
<span class="badge bg-light text-dark">{{ en_page.sections }} sections</span>
</div>
<div class="card-body">
{# <h4>Sections communes ({{ detailed_comparison.section_comparison.common|length }})</h4>#}
{# <ul class="list-group mb-3">#}
{# {% for section in detailed_comparison.section_comparison.common %}#}
{# <li class="list-group-item">#}
{# <span class="badge bg-secondary">h{{ section.en.level }}</span>#}
{# {{ section.en.title }}#}
{# </li>#}
{# {% endfor %}#}
{# </ul>#}
<h4>Sections uniquement en anglais ({{ detailed_comparison.section_comparison.en_only|length }})</h4>
<ul class="list-group">
<h4>Sections alignées par hiérarchie</h4>
<ul class="list-group mb-3">
{% for section in detailed_comparison.section_comparison.common %}
<li class="list-group-item title-level-{{ section.en.level }}">
<span class="badge bg-secondary">h{{ section.en.level }}</span>
{{ section.en.title }}
</li>
{% endfor %}
{% for section in detailed_comparison.section_comparison.en_only %}
<li class="list-group-item list-group-item-warning title-level-{{ section.level }}">
<li class="list-group-item list-group-item-warning title-level-{{ section.level }}">
<span class="badge bg-secondary">h{{ section.level }}</span>
{{ section.title }}
<span class="badge bg-warning text-dark float-end">EN uniquement</span>
</li>
{% endfor %}
</ul>
@ -147,22 +160,20 @@
<span class="badge bg-light text-dark">{{ fr_page.sections }} sections</span>
</div>
<div class="card-body">
{# <h4>Sections communes ({{ detailed_comparison.section_comparison.common|length }})</h4>#}
{# <ul class="list-group mb-3">#}
{# {% for section in detailed_comparison.section_comparison.common %}#}
{# <li class="list-group-item">#}
{# <span class="badge bg-secondary">h{{ section.fr.level }}</span>#}
{# {{ section.fr.title }}#}
{# </li>#}
{# {% endfor %}#}
{# </ul>#}
<h4>Sections uniquement en français ({{ detailed_comparison.section_comparison.fr_only|length }})</h4>
<ul class="list-group">
<h4>Sections alignées par hiérarchie</h4>
<ul class="list-group mb-3">
{% for section in detailed_comparison.section_comparison.common %}
<li class="list-group-item title-level-{{ section.fr.level }}">
<span class="badge bg-secondary">h{{ section.fr.level }}</span>
{{ section.fr.title }}
</li>
{% endfor %}
{% for section in detailed_comparison.section_comparison.fr_only %}
<li class="list-group-item list-group-item-info title-level-{{ section.level }}">
<li class="list-group-item list-group-item-info title-level-{{ section.level }}">
<span class="badge bg-secondary">h{{ section.level }}</span>
{{ section.title }}
<span class="badge bg-info float-end">FR uniquement</span>
</li>
{% endfor %}
</ul>

View file

@ -0,0 +1,83 @@
{% extends 'base.html.twig' %}
{% block title %}Pages Wiki françaises sans traduction anglaise{% endblock %}
{% block body %}
<div class="container mt-4">
{% include 'admin/_wiki_navigation.html.twig' %}
<h1>Pages Wiki françaises sans traduction anglaise</h1>
<p class="lead">Liste des pages françaises du wiki OSM qui n'ont pas de traduction en anglais.</p>
<div class="card mb-4">
<div class="card-header">
<h2>Pages françaises uniquement</h2>
</div>
<div class="card-body">
{% if french_only_pages|length > 0 %}
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead class="thead-dark">
<tr>
<th>Clé</th>
<th>Sections</th>
<th>Mots</th>
<th>Liens</th>
<th>Dernière modification</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for key, page in french_only_pages %}
<tr>
<td><strong>{{ key }}</strong></td>
<td>{{ page.sections }}</td>
<td>{{ page.word_count }}</td>
<td>{{ page.link_count }}</td>
<td>{{ page.last_modified }}</td>
<td>
<div class="btn-group" role="group">
<a href="{{ page.url }}" target="_blank" class="btn btn-sm btn-outline-info" title="Version française">
<i class="bi bi-translate"></i> FR
</a>
<a href="https://wiki.openstreetmap.org/wiki/Key:{{ key }}" target="_blank" class="btn btn-sm btn-success" title="Créer la version anglaise">
<i class="bi bi-plus-circle"></i> Créer EN
</a>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="alert alert-info">
<p><i class="bi bi-info-circle"></i> Aucune page française sans traduction anglaise n'a été trouvée.</p>
</div>
{% endif %}
</div>
</div>
<div class="card mb-4">
<div class="card-header">
<h2>À propos des pages sans traduction anglaise</h2>
</div>
<div class="card-body">
<p>Ces pages sont des contenus originaux créés en français qui n'ont pas encore été traduits en anglais.</p>
<p>Bien que la langue principale du wiki OSM soit l'anglais, il est parfois utile de créer d'abord du contenu dans sa langue maternelle, puis de le traduire.</p>
<p>Contribuer à la traduction de ces pages en anglais permet de :</p>
<ul>
<li>Partager les connaissances avec la communauté internationale</li>
<li>Améliorer la visibilité des contributions françaises</li>
<li>Faciliter la collaboration entre contributeurs de différentes langues</li>
</ul>
</div>
</div>
<div class="mt-3">
<a href="{{ path('app_admin_wiki') }}" class="btn btn-secondary">
<i class="bi bi-arrow-left"></i> Retour à la liste des pages wiki
</a>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,122 @@
{% extends 'base.html.twig' %}
{% block title %}Suggestion de page Wiki à améliorer{% endblock %}
{% block body %}
<div class="container mt-4">
{% include 'admin/_wiki_navigation.html.twig' %}
<h1>Suggestion de page Wiki à améliorer</h1>
<p class="lead">Voici une page wiki qui a besoin d'être améliorée.</p>
<div class="card mb-4">
<div class="card-header bg-primary text-white">
<h2>{{ page.key }}</h2>
</div>
<div class="card-body">
<div class="alert alert-info">
<h3>Raisons d'amélioration</h3>
<p>{{ page.reason }}</p>
</div>
<div class="row">
<div class="col-md-6">
<div class="card h-100">
<div class="card-header bg-primary text-white">
<h3>Version anglaise</h3>
<p class="mb-0">
<small>Dernière modification: {{ page.en_page.last_modified }}</small>
</p>
</div>
<div class="card-body">
<ul class="list-group mb-3">
<li class="list-group-item d-flex justify-content-between align-items-center">
Sections
<span class="badge bg-primary rounded-pill">{{ page.en_page.sections }}</span>
</li>
<li class="list-group-item d-flex justify-content-between align-items-center">
Mots
<span class="badge bg-primary rounded-pill">{{ page.en_page.word_count|default(0) }}</span>
</li>
<li class="list-group-item d-flex justify-content-between align-items-center">
Liens
<span class="badge bg-primary rounded-pill">{{ page.en_page.link_count|default(0) }}</span>
</li>
</ul>
<div class="d-grid gap-2">
<a href="{{ page.en_page.url }}" target="_blank" class="btn btn-outline-primary">
<i class="bi bi-box-arrow-up-right"></i> Voir la page anglaise
</a>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card h-100">
<div class="card-header bg-info text-white">
<h3>Version française</h3>
{% if page.fr_page %}
<p class="mb-0">
<small>Dernière modification: {{ page.fr_page.last_modified }}</small>
</p>
{% else %}
<p class="mb-0">
<small>Page non existante</small>
</p>
{% endif %}
</div>
<div class="card-body">
{% if page.fr_page %}
<ul class="list-group mb-3">
<li class="list-group-item d-flex justify-content-between align-items-center">
Sections
<span class="badge bg-info rounded-pill">{{ page.fr_page.sections }}</span>
</li>
<li class="list-group-item d-flex justify-content-between align-items-center">
Mots
<span class="badge bg-info rounded-pill">{{ page.fr_page.word_count|default(0) }}</span>
</li>
<li class="list-group-item d-flex justify-content-between align-items-center">
Liens
<span class="badge bg-info rounded-pill">{{ page.fr_page.link_count|default(0) }}</span>
</li>
</ul>
<div class="d-grid gap-2">
<a href="{{ page.fr_page.url }}" target="_blank" class="btn btn-outline-info">
<i class="bi bi-box-arrow-up-right"></i> Voir la page française
</a>
</div>
{% else %}
<div class="alert alert-warning">
<p><i class="bi bi-exclamation-triangle"></i> <strong>La page wiki pour la clé "{{ page.key }}" n'existe pas en français.</strong></p>
<p>Vous pouvez contribuer en créant cette page sur le wiki OpenStreetMap.</p>
</div>
<div class="d-grid gap-2">
<a href="https://wiki.openstreetmap.org/wiki/FR:Key:{{ page.key }}" target="_blank" class="btn btn-success">
<i class="bi bi-plus-circle"></i> Créer la page française
</a>
</div>
{% endif %}
</div>
</div>
</div>
</div>
<div class="mt-4 d-grid gap-2">
<a href="{{ path('app_admin_wiki_compare', {'key': page.key}) }}" class="btn btn-primary">
<i class="bi bi-arrows-angle-expand"></i> Voir la comparaison détaillée
</a>
<a href="{{ path('app_admin_wiki_random_suggestion') }}" class="btn btn-secondary">
<i class="bi bi-shuffle"></i> Autre suggestion aléatoire
</a>
</div>
</div>
</div>
<div class="mt-3">
<a href="{{ path('app_admin_wiki') }}" class="btn btn-secondary">
<i class="bi bi-arrow-left"></i> Retour à la liste des pages wiki
</a>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,94 @@
{% extends 'base.html.twig' %}
{% block title %}Pages Wiki avec suppressions suspectes{% endblock %}
{% block body %}
<div class="container mt-4">
{% include 'admin/_wiki_navigation.html.twig' %}
<h1>Pages Wiki avec suppressions suspectes</h1>
<p class="lead">Pages françaises du wiki OSM qui ont des suppressions suspectes, avec un grand pourcentage de suppression par rapport à la version anglaise.</p>
<div class="card mb-4">
<div class="card-header">
<h2>Pages avec suppressions suspectes</h2>
</div>
<div class="card-body">
{% if suspicious_pages|length > 0 %}
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead class="thead-dark">
<tr>
<th>Clé</th>
<th>Mots (EN)</th>
<th>Mots (FR)</th>
<th>Différence</th>
<th>% Suppression</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for page in suspicious_pages %}
<tr>
<td><strong>{{ page.key }}</strong></td>
<td>{{ page.en_page.word_count }}</td>
<td>{{ page.fr_page.word_count }}</td>
<td>{{ page.en_page.word_count - page.fr_page.word_count }}</td>
<td>
{% if page.deletion_percentage > 70 %}
<span class="badge bg-danger">{{ page.deletion_percentage }}%</span>
{% elseif page.deletion_percentage > 50 %}
<span class="badge bg-warning text-dark">{{ page.deletion_percentage }}%</span>
{% else %}
<span class="badge bg-info">{{ page.deletion_percentage }}%</span>
{% endif %}
</td>
<td>
<div class="btn-group" role="group">
<a href="{{ page.en_page.url }}" target="_blank" class="btn btn-sm btn-outline-primary" title="Version anglaise">
<i class="bi bi-translate"></i> EN
</a>
<a href="{{ page.fr_page.url }}" target="_blank" class="btn btn-sm btn-outline-info" title="Version française">
<i class="bi bi-translate"></i> FR
</a>
<a href="{{ path('app_admin_wiki_compare', {'key': page.key}) }}" class="btn btn-sm btn-outline-secondary" title="Comparer les versions">
<i class="bi bi-arrows-angle-expand"></i> Comparer
</a>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="alert alert-info">
<p><i class="bi bi-info-circle"></i> Aucune page avec suppressions suspectes n'a été trouvée.</p>
</div>
{% endif %}
</div>
</div>
<div class="card mb-4">
<div class="card-header">
<h2>À propos des suppressions suspectes</h2>
</div>
<div class="card-body">
<p>Les suppressions suspectes sont identifiées lorsque la version française d'une page wiki contient significativement moins de mots que la version anglaise (plus de 30% de différence).</p>
<p>Cela peut indiquer :</p>
<ul>
<li>Une traduction incomplète</li>
<li>Des sections manquantes dans la version française</li>
<li>Des mises à jour importantes dans la version anglaise qui n'ont pas été reportées en français</li>
</ul>
<p>Ces pages sont des candidates prioritaires pour une mise à jour de la traduction française.</p>
</div>
</div>
<div class="mt-3">
<a href="{{ path('app_admin_wiki') }}" class="btn btn-secondary">
<i class="bi bi-arrow-left"></i> Retour à la liste des pages wiki
</a>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,92 @@
{% extends 'base.html.twig' %}
{% block title %}Propositions de tags OSM{% endblock %}
{% block body %}
<div class="container mt-4">
{% include 'admin/_wiki_navigation.html.twig' %}
<h1>Propositions de tags OSM en cours de vote</h1>
<p class="lead">Liste des propositions de tags OpenStreetMap actuellement en cours de vote ou de discussion.</p>
<div class="card mb-4">
<div class="card-header">
<h2>Propositions actives</h2>
</div>
<div class="card-body">
{% if proposals|length > 0 %}
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead class="thead-dark">
<tr>
<th>Fonctionnalité</th>
<th>Description</th>
<th>Proposé par</th>
<th>Statut</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for proposal in proposals %}
<tr>
<td>{{ proposal.feature }}</td>
<td>{{ proposal.description }}</td>
<td>{{ proposal.proposer }}</td>
<td>
{% if 'voting' in proposal.status|lower %}
<span class="badge bg-primary">En vote</span>
{% elseif 'draft' in proposal.status|lower %}
<span class="badge bg-warning text-dark">Brouillon</span>
{% elseif 'rfc' in proposal.status|lower %}
<span class="badge bg-info">RFC</span>
{% else %}
<span class="badge bg-secondary">{{ proposal.status }}</span>
{% endif %}
</td>
<td>
<a href="{{ proposal.url }}" target="_blank" class="btn btn-sm btn-outline-primary">
<i class="bi bi-box-arrow-up-right"></i> Voir
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="alert alert-info">
<p><i class="bi bi-info-circle"></i> Aucune proposition de tag n'a été trouvée.</p>
</div>
{% endif %}
</div>
</div>
<div class="card mb-4">
<div class="card-header">
<h2>À propos des propositions de tags</h2>
</div>
<div class="card-body">
<p>Les propositions de tags sont un processus communautaire pour introduire de nouveaux tags ou modifier des tags existants dans OpenStreetMap.</p>
<p>Le processus typique comprend les étapes suivantes :</p>
<ol>
<li><strong>Brouillon</strong> : La proposition initiale est rédigée et discutée.</li>
<li><strong>RFC (Request for Comments)</strong> : La proposition est ouverte aux commentaires de la communauté.</li>
<li><strong>Vote</strong> : La proposition est soumise au vote de la communauté.</li>
<li><strong>Approbation ou rejet</strong> : Selon les résultats du vote, la proposition est approuvée ou rejetée.</li>
</ol>
<p>Vous pouvez participer à ce processus en commentant les propositions ou en votant lorsqu'elles sont en phase de vote.</p>
<div class="d-grid gap-2 col-md-6 mx-auto mt-3">
<a href="https://wiki.openstreetmap.org/wiki/Proposed_features" target="_blank" class="btn btn-outline-primary">
<i class="bi bi-box-arrow-up-right"></i> Voir toutes les propositions sur le wiki OSM
</a>
</div>
</div>
</div>
<div class="mt-3">
<a href="{{ path('app_admin_wiki') }}" class="btn btn-secondary">
<i class="bi bi-arrow-left"></i> Retour à la liste des pages wiki
</a>
</div>
</div>
{% endblock %}

View file

@ -1,14 +1,31 @@
# OSM Wiki Compare
Ce projet contient des scripts pour analyser les pages wiki d'OpenStreetMap, identifier celles qui ont besoin de mises à jour ou de traductions, et publier des suggestions sur Mastodon pour encourager la communauté à contribuer.
Ce projet contient des scripts pour analyser les pages wiki d'OpenStreetMap, identifier celles qui ont besoin de mises à
jour ou de traductions, et publier des suggestions sur Mastodon pour encourager la communauté à contribuer.
## Vue d'ensemble
Le projet comprend trois scripts principaux :
Le projet comprend huit scripts principaux :
1. **wiki_compare.py** : Récupère les 10 clés OSM les plus utilisées, compare leurs pages wiki en anglais et en français, et identifie celles qui ont besoin de mises à jour.
2. **post_outdated_page.py** : Sélectionne aléatoirement une page wiki française qui n'est pas à jour et publie un message sur Mastodon pour suggérer sa mise à jour.
3. **suggest_translation.py** : Identifie les pages wiki anglaises qui n'ont pas de traduction française et publie une suggestion de traduction sur Mastodon.
1. **wiki_compare.py** : Récupère les 10 clés OSM les plus utilisées, compare leurs pages wiki en anglais et en
français, et identifie celles qui ont besoin de mises à jour.
2. **post_outdated_page.py** : Sélectionne aléatoirement une page wiki française qui n'est pas à jour et publie un
message sur Mastodon pour suggérer sa mise à jour.
3. **suggest_translation.py** : Identifie les pages wiki anglaises qui n'ont pas de traduction française et publie une
suggestion de traduction sur Mastodon.
4. **detect_suspicious_deletions.py** : Analyse les changements récents du wiki OSM pour détecter les suppressions
suspectes (plus de 20 caractères) et les enregistre dans un fichier JSON pour affichage sur le site web.
5. **fetch_proposals.py** : Récupère les propositions de tags OSM en cours de vote et les propositions récemment modifiées,
et les enregistre dans un fichier JSON pour affichage sur le site web. Les données sont mises en cache pendant une heure
pour éviter des requêtes trop fréquentes au serveur wiki.
6. **find_untranslated_french_pages.py** : Identifie les pages wiki françaises qui n'ont pas de traduction en anglais
et les enregistre dans un fichier JSON pour affichage sur le site web. Les données sont mises en cache pendant une heure.
7. **find_pages_unavailable_in_french.py** : Scrape la catégorie des pages non disponibles en français, gère la pagination
pour récupérer toutes les pages, les groupe par préfixe de langue et priorise les pages commençant par "En:". Les données
sont mises en cache pendant une heure.
8. **fetch_osm_fr_groups.py** : Récupère les informations sur les groupes de travail et les groupes locaux d'OSM-FR
depuis la section #Pages_des_groupes_locaux et les enregistre dans un fichier JSON pour affichage sur le site web.
Les données sont mises en cache pendant une heure.
## Installation
@ -60,6 +77,7 @@ Pour analyser les pages wiki et générer les fichiers de données :
```
Cela produira :
- `top_keys.json` : Les 10 clés OSM les plus utilisées
- `wiki_pages.csv` : Informations sur chaque page wiki
- `outdated_pages.json` : Pages qui ont besoin de mises à jour
@ -93,17 +111,124 @@ Pour simuler la publication sans réellement poster sur Mastodon (mode test) :
./suggest_translation.py --dry-run
```
### Détecter les suppressions suspectes
Pour analyser les changements récents du wiki OSM et détecter les suppressions suspectes :
```bash
./detect_suspicious_deletions.py
```
Pour afficher les suppressions détectées sans les enregistrer dans un fichier (mode test) :
```bash
./detect_suspicious_deletions.py --dry-run
```
### Récupérer les propositions de tags
Pour récupérer les propositions de tags OSM en cours de vote et récemment modifiées :
```bash
./fetch_proposals.py
```
Pour forcer la mise à jour des données même si le cache est encore frais :
```bash
./fetch_proposals.py --force
```
Pour afficher les propositions sans les enregistrer dans un fichier (mode test) :
```bash
./fetch_proposals.py --dry-run
```
### Trouver les pages françaises sans traduction anglaise
Pour identifier les pages wiki françaises qui n'ont pas de traduction en anglais :
```bash
./find_untranslated_french_pages.py
```
Pour forcer la mise à jour des données même si le cache est encore frais :
```bash
./find_untranslated_french_pages.py --force
```
Pour afficher les pages sans les enregistrer dans un fichier (mode test) :
```bash
./find_untranslated_french_pages.py --dry-run
```
### Trouver les pages non disponibles en français
Pour identifier les pages wiki qui n'ont pas de traduction française, groupées par langue d'origine :
```bash
./find_pages_unavailable_in_french.py
```
Pour forcer la mise à jour des données même si le cache est encore frais :
```bash
./find_pages_unavailable_in_french.py --force
```
Pour afficher les pages sans les enregistrer dans un fichier (mode test) :
```bash
./find_pages_unavailable_in_french.py --dry-run
```
### Récupérer les groupes OSM-FR
Pour récupérer les informations sur les groupes de travail et les groupes locaux d'OSM-FR :
```bash
./fetch_osm_fr_groups.py
```
Pour forcer la mise à jour des données même si le cache est encore frais :
```bash
./fetch_osm_fr_groups.py --force
```
Pour afficher les groupes sans les enregistrer dans un fichier (mode test) :
```bash
./fetch_osm_fr_groups.py --dry-run
```
## Automatisation
Vous pouvez automatiser l'exécution de ces scripts à l'aide de cron pour publier régulièrement des suggestions de mises à jour et de traductions.
Vous pouvez automatiser l'exécution de ces scripts à l'aide de cron pour publier régulièrement des suggestions de mises
à jour et de traductions, ainsi que pour maintenir à jour les données affichées sur le site web.
Exemple de configuration cron pour publier une suggestion de mise à jour chaque lundi et une suggestion de traduction chaque jeudi :
Exemple de configuration cron pour publier des suggestions et mettre à jour les données :
```
# Publier des suggestions sur Mastodon
0 10 * * 1 cd /chemin/vers/wiki_compare && ./wiki_compare.py && ./post_outdated_page.py
0 10 * * 4 cd /chemin/vers/wiki_compare && ./wiki_compare.py && ./suggest_translation.py
# Mettre à jour les données pour le site web (toutes les 6 heures)
0 */6 * * * cd /chemin/vers/wiki_compare && ./detect_suspicious_deletions.py
0 */6 * * * cd /chemin/vers/wiki_compare && ./fetch_proposals.py
0 */6 * * * cd /chemin/vers/wiki_compare && ./find_untranslated_french_pages.py
0 */6 * * * cd /chemin/vers/wiki_compare && ./find_pages_unavailable_in_french.py
0 */6 * * * cd /chemin/vers/wiki_compare && ./fetch_osm_fr_groups.py
```
Note : Les scripts de mise à jour des données pour le site web intègrent déjà une vérification de fraîcheur du cache (1 heure),
mais la configuration cron ci-dessus permet de s'assurer que les données sont régulièrement mises à jour même en cas de problème
temporaire avec les scripts.
## Structure des données
### top_keys.json
@ -115,8 +240,7 @@ Contient les 10 clés OSM les plus utilisées avec leur nombre d'utilisations :
{
"key": "building",
"count": 459876543
},
...
}
]
```
@ -140,8 +264,8 @@ Contient des informations détaillées sur les pages qui ont besoin de mises à
{
"key": "building",
"reason": "French page outdated by 491 days",
"en_page": { ... },
"fr_page": { ... },
"en_page": {},
"fr_page": {},
"date_diff": 491,
"word_diff": 700,
"section_diff": 2,
@ -150,30 +274,209 @@ Contient des informations détaillées sur les pages qui ont besoin de mises à
{
"key": "amenity",
"reason": "French page missing",
"en_page": { ... },
"en_page": {},
"fr_page": null,
"date_diff": 0,
"word_diff": 4200,
"section_diff": 15,
"priority": 100
},
...
}
]
```
### suspicious_deletions.json
Contient des informations sur les suppressions suspectes détectées dans les changements récents du wiki OSM :
```json
{
"last_updated": "2025-08-22T15:03:03.616532",
"deletions": [
{
"page_title": "FR:Key:roof:shape",
"page_url": "https://wiki.openstreetmap.org/wiki/FR:Key:roof:shape",
"deletion_size": -286,
"timestamp": "22 août 2025 à 14:15",
"user": "RubenKelevra",
"comment": "Suppression de contenu obsolète"
},
{
"page_title": "FR:Key:sport",
"page_url": "https://wiki.openstreetmap.org/wiki/FR:Key:sport",
"deletion_size": -240,
"timestamp": "21 août 2025 à 09:30",
"user": "Computae",
"comment": "Mise à jour de la documentation"
}
]
}
```
### proposals.json
Contient des informations sur les propositions de tags OSM en cours de vote et récemment modifiées :
```json
{
"last_updated": "2025-08-22T15:09:49.905332",
"voting_proposals": [
{
"title": "Proposal:Man made=ceremonial gate",
"url": "https://wiki.openstreetmap.org/wiki/Proposal:Man_made%3Dceremonial_gate",
"status": "Voting",
"type": "voting"
},
{
"title": "Proposal:Developer",
"url": "https://wiki.openstreetmap.org/wiki/Proposal:Developer",
"status": "Voting",
"type": "voting"
}
],
"recent_proposals": [
{
"title": "Proposal:Landuse=brownfield",
"url": "https://wiki.openstreetmap.org/wiki/Proposal:Landuse=brownfield",
"last_modified": "22 août 2025 à 10:45",
"modified_by": "MapperUser",
"type": "recent"
}
]
}
```
### untranslated_french_pages.json
Contient des informations sur les pages wiki françaises qui n'ont pas de traduction en anglais :
```json
{
"last_updated": "2025-08-22T16:30:15.123456",
"untranslated_pages": [
{
"title": "FR:Key:building:colour",
"key": "Key:building:colour",
"url": "https://wiki.openstreetmap.org/wiki/FR:Key:building:colour",
"has_translation": false
},
{
"title": "FR:Tag:amenity=bicycle_repair_station",
"key": "Tag:amenity=bicycle_repair_station",
"url": "https://wiki.openstreetmap.org/wiki/FR:Tag:amenity=bicycle_repair_station",
"has_translation": false
}
]
}
```
### pages_unavailable_in_french.json
Contient des informations sur les pages wiki qui n'ont pas de traduction française, groupées par langue d'origine :
```json
{
"last_updated": "2025-08-22T17:15:45.123456",
"grouped_pages": {
"En": [
{
"title": "En:Key:building:colour",
"url": "https://wiki.openstreetmap.org/wiki/En:Key:building:colour",
"language_prefix": "En",
"is_english": true,
"priority": 1
}
],
"De": [
{
"title": "De:Tag:highway=residential",
"url": "https://wiki.openstreetmap.org/wiki/De:Tag:highway=residential",
"language_prefix": "De",
"is_english": false,
"priority": 0
}
],
"Other": [
{
"title": "Tag:amenity=bicycle_repair_station",
"url": "https://wiki.openstreetmap.org/wiki/Tag:amenity=bicycle_repair_station",
"language_prefix": "Other",
"is_english": false,
"priority": 0
}
]
},
"all_pages": [
{
"title": "En:Key:building:colour",
"url": "https://wiki.openstreetmap.org/wiki/En:Key:building:colour",
"language_prefix": "En",
"is_english": true,
"priority": 1
},
{
"title": "De:Tag:highway=residential",
"url": "https://wiki.openstreetmap.org/wiki/De:Tag:highway=residential",
"language_prefix": "De",
"is_english": false,
"priority": 0
},
{
"title": "Tag:amenity=bicycle_repair_station",
"url": "https://wiki.openstreetmap.org/wiki/Tag:amenity=bicycle_repair_station",
"language_prefix": "Other",
"is_english": false,
"priority": 0
}
]
}
```
### osm_fr_groups.json
Contient des informations sur les groupes de travail et les groupes locaux d'OSM-FR :
```json
{
"last_updated": "2025-08-22T16:45:30.789012",
"working_groups": [
{
"name": "Groupe Bâtiments",
"url": "https://wiki.openstreetmap.org/wiki/France/OSM-FR/Groupes_de_travail/B%C3%A2timents",
"description": "Groupe de travail sur la cartographie des bâtiments",
"category": "Cartographie",
"type": "working_group"
}
],
"local_groups": [
{
"name": "Groupe local de Paris",
"url": "https://wiki.openstreetmap.org/wiki/France/Paris",
"description": "Groupe local des contributeurs parisiens",
"type": "local_group"
}
],
"umap_url": "https://umap.openstreetmap.fr/fr/map/groupes-locaux-openstreetmap_152488"
}
```
## Dépannage
### Problèmes courants
1. **Erreur d'authentification Mastodon** : Vérifiez que la variable d'environnement `MASTODON_ACCESS_TOKEN` est correctement définie et que le jeton est valide.
1. **Erreur d'authentification Mastodon** : Vérifiez que la variable d'environnement `MASTODON_ACCESS_TOKEN` est
correctement définie et que le jeton est valide.
2. **Erreur de chargement des fichiers JSON** : Assurez-vous d'exécuter `wiki_compare.py` avant les autres scripts pour générer les fichiers de données nécessaires.
2. **Erreur de chargement des fichiers JSON** : Assurez-vous d'exécuter `wiki_compare.py` avant les autres scripts pour
générer les fichiers de données nécessaires.
3. **Aucune page à mettre à jour ou à traduire** : Il est possible que toutes les pages soient à jour ou traduites. Essayez d'augmenter le nombre de clés analysées en modifiant la valeur `limit` dans la fonction `fetch_top_keys` de `wiki_compare.py`.
3. **Aucune page à mettre à jour ou à traduire** : Il est possible que toutes les pages soient à jour ou traduites.
Essayez d'augmenter le nombre de clés analysées en modifiant la valeur `limit` dans la fonction `fetch_top_keys` de
`wiki_compare.py`.
### Journalisation
Tous les scripts utilisent le module `logging` pour enregistrer les informations d'exécution. Par défaut, les logs sont affichés dans la console. Pour les rediriger vers un fichier, modifiez la configuration de logging dans chaque script.
Tous les scripts utilisent le module `logging` pour enregistrer les informations d'exécution. Par défaut, les logs sont
affichés dans la console. Pour les rediriger vers un fichier, modifiez la configuration de logging dans chaque script.
## Contribution

View file

@ -0,0 +1,252 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import requests
from bs4 import BeautifulSoup
import json
import logging
import argparse
import os
import re
from datetime import datetime
from urllib.parse import urlparse, parse_qs, urlencode
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
# URL for recent changes in OSM Wiki (namespace 202 is for Tag pages)
RECENT_CHANGES_URL = "https://wiki.openstreetmap.org/w/index.php?hidebots=1&hidenewpages=1&hidecategorization=1&hideWikibase=1&hidelog=1&hidenewuserlog=1&namespace=202&limit=250&days=30&enhanced=1&title=Special:RecentChanges&urlversion=2"
# Threshold for suspicious deletions (percentage of total content)
DELETION_THRESHOLD_PERCENT = 5.0
# Base URL for OSM Wiki
WIKI_BASE_URL = "https://wiki.openstreetmap.org"
def fetch_recent_changes():
"""
Fetch the recent changes page from OSM Wiki
"""
logger.info(f"Fetching recent changes from {RECENT_CHANGES_URL}")
try:
response = requests.get(RECENT_CHANGES_URL)
response.raise_for_status()
return response.text
except requests.exceptions.RequestException as e:
logger.error(f"Error fetching recent changes: {e}")
return None
def fetch_page_content(page_title):
"""
Fetch the content of a wiki page to count characters
"""
url = f"{WIKI_BASE_URL}/wiki/{page_title}"
logger.info(f"Fetching page content from {url}")
try:
response = requests.get(url)
response.raise_for_status()
return response.text
except requests.exceptions.RequestException as e:
logger.error(f"Error fetching page content: {e}")
return None
def count_page_characters(html_content):
"""
Count the total number of characters in the wiki page content
"""
if not html_content:
return 0
soup = BeautifulSoup(html_content, 'html.parser')
# Find the main content div
content_div = soup.select_one('#mw-content-text')
if not content_div:
return 0
# Get all text content
text_content = content_div.get_text(strip=True)
# Count characters
char_count = len(text_content)
logger.info(f"Page has {char_count} characters")
return char_count
def generate_diff_url(page_title, oldid):
"""
Generate URL to view the diff of a specific revision
"""
return f"{WIKI_BASE_URL}/w/index.php?title={page_title}&diff=prev&oldid={oldid}"
def generate_history_url(page_title):
"""
Generate URL to view the history of a page
"""
return f"{WIKI_BASE_URL}/w/index.php?title={page_title}&action=history"
def load_existing_deletions():
"""
Load existing suspicious deletions from the JSON file
"""
output_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'suspicious_deletions.json')
existing_pages = set()
try:
if os.path.exists(output_file):
with open(output_file, 'r', encoding='utf-8') as f:
data = json.load(f)
if 'deletions' in data:
for deletion in data['deletions']:
if 'page_title' in deletion:
existing_pages.add(deletion['page_title'])
logger.info(f"Loaded {len(existing_pages)} existing pages from {output_file}")
else:
logger.info(f"No existing file found at {output_file}")
except Exception as e:
logger.error(f"Error loading existing deletions: {e}")
return existing_pages
def parse_suspicious_deletions(html_content):
"""
Parse the HTML content to find suspicious deletions
"""
if not html_content:
return []
# Load existing pages from the JSON file
existing_pages = load_existing_deletions()
soup = BeautifulSoup(html_content, 'html.parser')
suspicious_deletions = []
# Find all change list lines
change_lines = soup.select('.mw-changeslist .mw-changeslist-line')
logger.info(f"Found {len(change_lines)} change lines to analyze")
for line in change_lines:
# Look for deletion indicators
deletion_indicator = line.select_one('.mw-plusminus-neg')
if deletion_indicator:
# Extract the deletion size
deletion_text = deletion_indicator.text.strip()
try:
# Remove any non-numeric characters except minus sign
deletion_size = int(''.join(c for c in deletion_text if c.isdigit() or c == '-'))
# Skip if deletion size is not greater than 100 characters
if abs(deletion_size) <= 100:
logger.info(f"Skipping deletion with size {deletion_size} (not > 100 characters)")
continue
# Get the page title and URL
title_element = line.select_one('.mw-changeslist-title')
if title_element:
page_title = title_element.text.strip()
# Skip if page is already in the JSON file
if page_title in existing_pages:
logger.info(f"Skipping {page_title} (already in JSON file)")
continue
page_url = title_element.get('href', '')
if not page_url.startswith('http'):
page_url = f"{WIKI_BASE_URL}{page_url}"
# Extract oldid from the URL if available
oldid = None
if 'oldid=' in page_url:
parsed_url = urlparse(page_url)
query_params = parse_qs(parsed_url.query)
if 'oldid' in query_params:
oldid = query_params['oldid'][0]
# Fetch the page content to count characters
page_html = fetch_page_content(page_title)
total_chars = count_page_characters(page_html)
# Calculate deletion percentage
deletion_percentage = 0
if total_chars > 0:
deletion_percentage = (abs(deletion_size) / total_chars) * 100
# If deletion percentage is significant
if deletion_percentage > DELETION_THRESHOLD_PERCENT:
# Get the timestamp
timestamp_element = line.select_one('.mw-changeslist-date')
timestamp = timestamp_element.text.strip() if timestamp_element else ""
# Get the user who made the change
user_element = line.select_one('.mw-userlink')
user = user_element.text.strip() if user_element else "Unknown"
# Get the comment if available
comment_element = line.select_one('.comment')
comment = comment_element.text.strip() if comment_element else ""
# Generate diff and history URLs
diff_url = generate_diff_url(page_title, oldid) if oldid else ""
history_url = generate_history_url(page_title)
suspicious_deletions.append({
'page_title': page_title,
'page_url': page_url,
'diff_url': diff_url,
'history_url': history_url,
'deletion_size': deletion_size,
'total_chars': total_chars,
'deletion_percentage': round(deletion_percentage, 2),
'timestamp': timestamp,
'user': user,
'comment': comment
})
logger.info(f"Found suspicious deletion: {page_title} ({deletion_size} chars, {deletion_percentage:.2f}% of content)")
except ValueError:
logger.warning(f"Could not parse deletion size from: {deletion_text}")
return suspicious_deletions
def save_suspicious_deletions(suspicious_deletions):
"""
Save the suspicious deletions to a JSON file
"""
output_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'suspicious_deletions.json')
# Add timestamp to the data
data = {
'last_updated': datetime.now().isoformat(),
'deletions': suspicious_deletions
}
with open(output_file, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
logger.info(f"Saved {len(suspicious_deletions)} suspicious deletions to {output_file}")
return output_file
def main():
parser = argparse.ArgumentParser(description='Detect suspicious deletions in OSM Wiki recent changes')
parser.add_argument('--dry-run', action='store_true', help='Print results without saving to file')
args = parser.parse_args()
html_content = fetch_recent_changes()
if html_content:
suspicious_deletions = parse_suspicious_deletions(html_content)
if args.dry_run:
logger.info(f"Found {len(suspicious_deletions)} suspicious deletions:")
for deletion in suspicious_deletions:
logger.info(f"- {deletion['page_title']}: {deletion['deletion_size']} chars by {deletion['user']}")
else:
output_file = save_suspicious_deletions(suspicious_deletions)
logger.info(f"Results saved to {output_file}")
else:
logger.error("Failed to fetch recent changes. Exiting.")
if __name__ == "__main__":
main()

View file

@ -0,0 +1,316 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
fetch_osm_fr_groups.py
This script scrapes the OpenStreetMap wiki page for France/OSM-FR to extract
information about local working groups. It specifically targets links in the
#Pages_des_groupes_locaux section.
Usage:
python fetch_osm_fr_groups.py [--dry-run] [--force]
Options:
--dry-run Run the script without saving the results to a file
--force Force update even if the cache is still fresh (less than 1 hour old)
Output:
- osm_fr_groups.json: JSON file with information about OSM-FR local groups
- Log messages about the scraping process and results
"""
import json
import argparse
import logging
import os
from datetime import datetime, timedelta
import requests
from bs4 import BeautifulSoup
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
logger = logging.getLogger(__name__)
# Constants
OUTPUT_FILE = "osm_fr_groups.json"
BASE_URL = "https://wiki.openstreetmap.org/wiki/France/OSM-FR"
WIKI_BASE_URL = "https://wiki.openstreetmap.org"
CACHE_DURATION = timedelta(hours=1) # Cache duration of 1 hour
def is_cache_fresh():
"""
Check if the cache file exists and is less than CACHE_DURATION old
Returns:
bool: True if cache is fresh, False otherwise
"""
if not os.path.exists(OUTPUT_FILE):
return False
try:
with open(OUTPUT_FILE, 'r', encoding='utf-8') as f:
data = json.load(f)
last_updated = datetime.fromisoformat(data.get('last_updated', '2000-01-01T00:00:00'))
now = datetime.now()
return (now - last_updated) < CACHE_DURATION
except (IOError, json.JSONDecodeError, ValueError) as e:
logger.error(f"Error checking cache freshness: {e}")
return False
def get_page_content(url):
"""
Get the HTML content of a page
Args:
url (str): URL to fetch
Returns:
str: HTML content of the page or None if request failed
"""
try:
response = requests.get(url)
response.raise_for_status()
return response.text
except requests.exceptions.RequestException as e:
logger.error(f"Error fetching {url}: {e}")
return None
def extract_working_groups(html_content):
"""
Extract working groups from the wiki page HTML
Args:
html_content (str): HTML content of the wiki page
Returns:
list: List of working group dictionaries
"""
if not html_content:
return []
soup = BeautifulSoup(html_content, 'html.parser')
working_groups = []
# Find the working groups section
working_groups_section = None
for heading in soup.find_all(['h2', 'h3']):
if heading.get_text().strip() == 'Groupes de travail' or 'Groupes_de_travail' in heading.get_text():
working_groups_section = heading
break
if not working_groups_section:
logger.warning("Could not find working groups section")
# Return an empty list but with a default category
return []
# Get the content following the heading until the next heading
current = working_groups_section.next_sibling
while current and not current.name in ['h2', 'h3']:
if current.name == 'ul':
# Process list items
for li in current.find_all('li', recursive=False):
link = li.find('a')
if link:
name = link.get_text().strip()
url = WIKI_BASE_URL + link.get('href') if link.get('href').startswith('/') else link.get('href')
# Extract description (text after the link)
description = ""
next_node = link.next_sibling
while next_node:
if isinstance(next_node, str):
description += next_node.strip()
next_node = next_node.next_sibling if hasattr(next_node, 'next_sibling') else None
description = description.strip(' :-,')
working_groups.append({
"name": name,
"url": url,
"description": description,
"category": "Général",
"type": "working_group"
})
current = current.next_sibling
logger.info(f"Found {len(working_groups)} working groups")
return working_groups
def extract_local_groups(html_content):
"""
Extract local groups from the wiki page HTML
Args:
html_content (str): HTML content of the wiki page
Returns:
list: List of local group dictionaries
"""
if not html_content:
return []
soup = BeautifulSoup(html_content, 'html.parser')
local_groups = []
# Find the local groups section
local_groups_section = None
for heading in soup.find_all(['h2', 'h3']):
if heading.get_text().strip() == 'Groupes locaux' or 'Pages des groupes locaux' in heading.get_text():
local_groups_section = heading
break
if not local_groups_section:
logger.warning("Could not find local groups section")
return []
# Get the content following the heading until the next heading
current = local_groups_section.next_sibling
while current and not current.name in ['h2', 'h3']:
if current.name == 'ul':
# Process list items
for li in current.find_all('li', recursive=False):
link = li.find('a')
if link:
name = link.get_text().strip()
url = WIKI_BASE_URL + link.get('href') if link.get('href').startswith('/') else link.get('href')
# Extract description (text after the link)
description = ""
next_node = link.next_sibling
while next_node:
if isinstance(next_node, str):
description += next_node.strip()
next_node = next_node.next_sibling if hasattr(next_node, 'next_sibling') else None
description = description.strip(' :-,')
local_groups.append({
"name": name,
"url": url,
"description": description,
"type": "local_group"
})
current = current.next_sibling
logger.info(f"Found {len(local_groups)} local groups")
return local_groups
def extract_umap_url(html_content):
"""
Extract the uMap URL for OSM-FR local groups
Args:
html_content (str): HTML content of the wiki page
Returns:
str: uMap URL or None if not found
"""
if not html_content:
return None
soup = BeautifulSoup(html_content, 'html.parser')
# Look for links to umap.openstreetmap.fr
for link in soup.find_all('a'):
href = link.get('href', '')
if 'umap.openstreetmap.fr' in href and 'groupes-locaux' in href:
return href
return None
def save_results(local_groups, working_groups, umap_url, dry_run=False):
"""
Save the results to a JSON file
Args:
local_groups (list): List of local group dictionaries
working_groups (list): List of working group dictionaries
umap_url (str): URL to the uMap for local groups
dry_run (bool): If True, don't actually save to file
Returns:
bool: True if saving was successful or dry run, False otherwise
"""
if dry_run:
logger.info("DRY RUN: Would have saved results to file")
logger.info(f"Local groups: {len(local_groups)}")
for group in local_groups:
logger.info(f" - {group['name']}: {group['url']}")
logger.info(f"Working groups: {len(working_groups)}")
for group in working_groups:
logger.info(f" - {group['name']}: {group['url']}")
if umap_url:
logger.info(f"uMap URL: {umap_url}")
return True
# Prepare the data structure
data = {
"last_updated": datetime.now().isoformat(),
"local_groups": local_groups,
"working_groups": working_groups,
"umap_url": umap_url
}
try:
with open(OUTPUT_FILE, 'w', encoding='utf-8') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
logger.info(f"Successfully saved {len(local_groups)} local groups and {len(working_groups)} working groups to {OUTPUT_FILE}")
return True
except IOError as e:
logger.error(f"Error saving results to {OUTPUT_FILE}: {e}")
return False
def main():
"""Main function to execute the script"""
parser = argparse.ArgumentParser(description="Scrape OSM-FR local groups from the wiki")
parser.add_argument("--dry-run", action="store_true", help="Run without saving results to file")
parser.add_argument("--force", action="store_true", help="Force update even if cache is fresh")
args = parser.parse_args()
logger.info("Starting fetch_osm_fr_groups.py")
# Check if cache is fresh
if is_cache_fresh() and not args.force:
logger.info(f"Cache is still fresh (less than {CACHE_DURATION.total_seconds()/3600} hours old)")
logger.info(f"Use --force to update anyway")
return
# Get the wiki page content
html_content = get_page_content(BASE_URL)
if not html_content:
logger.error("Failed to get wiki page content")
return
# Extract local groups
local_groups = extract_local_groups(html_content)
if not local_groups:
logger.warning("No local groups found")
# Extract working groups
working_groups = extract_working_groups(html_content)
if not working_groups:
logger.warning("No working groups found")
# Initialize with an empty list to avoid errors in the controller
working_groups = []
# Extract uMap URL
umap_url = extract_umap_url(html_content)
# Save results
success = save_results(local_groups, working_groups, umap_url, args.dry_run)
if success:
logger.info("Script completed successfully")
else:
logger.error("Script completed with errors")
if __name__ == "__main__":
main()

183
wiki_compare/fetch_proposals.py Executable file
View file

@ -0,0 +1,183 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import requests
from bs4 import BeautifulSoup
import json
import logging
import argparse
import os
from datetime import datetime, timedelta
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
# URLs for OSM Wiki proposals
VOTING_PROPOSALS_URL = "https://wiki.openstreetmap.org/wiki/Category:Proposals_with_%22Voting%22_status"
RECENT_CHANGES_URL = "https://wiki.openstreetmap.org/w/index.php?title=Special:RecentChanges&namespace=102&limit=50" # Namespace 102 is for Proposal pages
# Output file
OUTPUT_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'proposals.json')
# Cache timeout (in hours)
CACHE_TIMEOUT = 1
def should_update_cache():
"""
Check if the cache file exists and if it's older than the cache timeout
"""
if not os.path.exists(OUTPUT_FILE):
logger.info("Cache file doesn't exist, creating it")
return True
# Check file modification time
file_mtime = datetime.fromtimestamp(os.path.getmtime(OUTPUT_FILE))
now = datetime.now()
# If file is older than cache timeout, update it
if now - file_mtime > timedelta(hours=CACHE_TIMEOUT):
logger.info(f"Cache is older than {CACHE_TIMEOUT} hour(s), updating")
return True
logger.info(f"Cache is still fresh (less than {CACHE_TIMEOUT} hour(s) old)")
return False
def fetch_voting_proposals():
"""
Fetch proposals with "Voting" status from the OSM Wiki
"""
logger.info(f"Fetching voting proposals from {VOTING_PROPOSALS_URL}")
try:
response = requests.get(VOTING_PROPOSALS_URL)
response.raise_for_status()
soup = BeautifulSoup(response.text, 'html.parser')
proposals = []
# Find all links in the mw-pages section
links = soup.select('#mw-pages a')
for link in links:
# Skip category links and other non-proposal links
if 'Category:' in link.get('href', '') or 'Special:' in link.get('href', ''):
continue
proposal_title = link.text.strip()
proposal_url = 'https://wiki.openstreetmap.org' + link.get('href', '')
proposals.append({
'title': proposal_title,
'url': proposal_url,
'status': 'Voting',
'type': 'voting'
})
logger.info(f"Found {len(proposals)} voting proposals")
return proposals
except requests.exceptions.RequestException as e:
logger.error(f"Error fetching voting proposals: {e}")
return []
def fetch_recent_proposals():
"""
Fetch recently modified proposals from the OSM Wiki
"""
logger.info(f"Fetching recent changes from {RECENT_CHANGES_URL}")
try:
response = requests.get(RECENT_CHANGES_URL)
response.raise_for_status()
soup = BeautifulSoup(response.text, 'html.parser')
proposals = []
# Find all change list lines
change_lines = soup.select('.mw-changeslist .mw-changeslist-line')
for line in change_lines:
# Get the page title
title_element = line.select_one('.mw-changeslist-title')
if not title_element:
continue
page_title = title_element.text.strip()
page_url = title_element.get('href', '')
if not page_url.startswith('http'):
page_url = f"https://wiki.openstreetmap.org{page_url}"
# Get the timestamp
timestamp_element = line.select_one('.mw-changeslist-date')
timestamp = timestamp_element.text.strip() if timestamp_element else ""
# Get the user who made the change
user_element = line.select_one('.mw-userlink')
user = user_element.text.strip() if user_element else "Unknown"
# Skip if it's not a proposal page
if not page_title.startswith('Proposal:'):
continue
proposals.append({
'title': page_title,
'url': page_url,
'last_modified': timestamp,
'modified_by': user,
'type': 'recent'
})
# Limit to the 10 most recent proposals
proposals = proposals[:10]
logger.info(f"Found {len(proposals)} recently modified proposals")
return proposals
except requests.exceptions.RequestException as e:
logger.error(f"Error fetching recent proposals: {e}")
return []
def save_proposals(voting_proposals, recent_proposals):
"""
Save the proposals to a JSON file
"""
data = {
'last_updated': datetime.now().isoformat(),
'voting_proposals': voting_proposals,
'recent_proposals': recent_proposals
}
with open(OUTPUT_FILE, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
logger.info(f"Saved {len(voting_proposals)} voting proposals and {len(recent_proposals)} recent proposals to {OUTPUT_FILE}")
return OUTPUT_FILE
def main():
parser = argparse.ArgumentParser(description='Fetch OSM Wiki proposals')
parser.add_argument('--force', action='store_true', help='Force update even if cache is fresh')
parser.add_argument('--dry-run', action='store_true', help='Print results without saving to file')
args = parser.parse_args()
# Check if we should update the cache
if args.force or should_update_cache() or args.dry_run:
voting_proposals = fetch_voting_proposals()
recent_proposals = fetch_recent_proposals()
if args.dry_run:
logger.info(f"Found {len(voting_proposals)} voting proposals:")
for proposal in voting_proposals:
logger.info(f"- {proposal['title']}")
logger.info(f"Found {len(recent_proposals)} recent proposals:")
for proposal in recent_proposals:
logger.info(f"- {proposal['title']} (modified by {proposal['modified_by']} on {proposal['last_modified']})")
else:
output_file = save_proposals(voting_proposals, recent_proposals)
logger.info(f"Results saved to {output_file}")
else:
logger.info("Using cached proposals data")
if __name__ == "__main__":
main()

View file

@ -0,0 +1,263 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
find_pages_unavailable_in_french.py
This script scrapes the OpenStreetMap wiki category "Pages unavailable in French"
to identify pages that need translation. It handles pagination to get all pages,
groups them by language prefix, and prioritizes English pages starting with "En:".
Usage:
python find_pages_unavailable_in_french.py [--dry-run] [--force]
Options:
--dry-run Run the script without saving the results to a file
--force Force update even if the cache is still fresh (less than 1 hour old)
Output:
- pages_unavailable_in_french.json: JSON file with pages that need translation
- Log messages about the scraping process and results
"""
import json
import argparse
import logging
import os
import re
from datetime import datetime, timedelta
import requests
from bs4 import BeautifulSoup
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
logger = logging.getLogger(__name__)
# Constants
OUTPUT_FILE = "pages_unavailable_in_french.json"
BASE_URL = "https://wiki.openstreetmap.org/wiki/Category:Pages_unavailable_in_French"
WIKI_BASE_URL = "https://wiki.openstreetmap.org"
CACHE_DURATION = timedelta(hours=1) # Cache duration of 1 hour
def is_cache_fresh():
"""
Check if the cache file exists and is less than CACHE_DURATION old
Returns:
bool: True if cache is fresh, False otherwise
"""
if not os.path.exists(OUTPUT_FILE):
return False
try:
with open(OUTPUT_FILE, 'r', encoding='utf-8') as f:
data = json.load(f)
last_updated = datetime.fromisoformat(data.get('last_updated', '2000-01-01T00:00:00'))
now = datetime.now()
return (now - last_updated) < CACHE_DURATION
except (IOError, json.JSONDecodeError, ValueError) as e:
logger.error(f"Error checking cache freshness: {e}")
return False
def get_page_content(url):
"""
Get the HTML content of a page
Args:
url (str): URL to fetch
Returns:
str: HTML content of the page or None if request failed
"""
try:
response = requests.get(url)
response.raise_for_status()
return response.text
except requests.exceptions.RequestException as e:
logger.error(f"Error fetching {url}: {e}")
return None
def extract_pages_from_category(html_content, current_url):
"""
Extract pages from the category page HTML
Args:
html_content (str): HTML content of the category page
current_url (str): URL of the current page for resolving relative links
Returns:
tuple: (list of page dictionaries, next page URL or None)
"""
if not html_content:
return [], None
soup = BeautifulSoup(html_content, 'html.parser')
pages = []
# Find the category content
category_content = soup.find('div', class_='mw-category-generated')
if not category_content:
logger.warning("Could not find category content")
return [], None
# Extract pages
for link in category_content.find_all('a'):
title = link.get_text()
url = WIKI_BASE_URL + link.get('href')
# Extract language prefix (e.g., "En:", "De:", etc.)
language_prefix = "Other"
match = re.match(r'^([A-Za-z]{2}):', title)
if match:
language_prefix = match.group(1)
# Check if it's an English page
is_english = language_prefix.lower() == "en"
# Set priority (English pages have higher priority)
priority = 1 if is_english else 0
pages.append({
"title": title,
"url": url,
"language_prefix": language_prefix,
"is_english": is_english,
"priority": priority
})
# Find next page link
next_page_url = None
pagination = soup.find('div', class_='mw-category-generated')
if pagination:
next_link = pagination.find('a', string='next page')
if next_link:
next_page_url = WIKI_BASE_URL + next_link.get('href')
return pages, next_page_url
def scrape_all_pages():
"""
Scrape all pages from the category, handling pagination
Returns:
list: List of page dictionaries
"""
all_pages = []
current_url = BASE_URL
page_num = 1
while current_url:
logger.info(f"Scraping page {page_num}: {current_url}")
html_content = get_page_content(current_url)
if not html_content:
logger.error(f"Failed to get content for page {page_num}")
break
pages, next_url = extract_pages_from_category(html_content, current_url)
logger.info(f"Found {len(pages)} pages on page {page_num}")
all_pages.extend(pages)
current_url = next_url
page_num += 1
if not next_url:
logger.info("No more pages to scrape")
logger.info(f"Total pages scraped: {len(all_pages)}")
return all_pages
def group_pages_by_language(pages):
"""
Group pages by language prefix
Args:
pages (list): List of page dictionaries
Returns:
dict: Dictionary with language prefixes as keys and lists of pages as values
"""
grouped = {}
for page in pages:
prefix = page["language_prefix"]
if prefix not in grouped:
grouped[prefix] = []
grouped[prefix].append(page)
# Sort each group by priority (English pages first)
for prefix in grouped:
grouped[prefix].sort(key=lambda x: (-x["priority"], x["title"]))
return grouped
def save_results(pages, dry_run=False):
"""
Save the results to a JSON file
Args:
pages (list): List of page dictionaries
dry_run (bool): If True, don't actually save to file
Returns:
bool: True if saving was successful or dry run, False otherwise
"""
if dry_run:
logger.info("DRY RUN: Would have saved results to file")
return True
# Group pages by language prefix
grouped_pages = group_pages_by_language(pages)
# Prepare the data structure
data = {
"last_updated": datetime.now().isoformat(),
"grouped_pages": grouped_pages,
"all_pages": pages
}
try:
with open(OUTPUT_FILE, 'w', encoding='utf-8') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
logger.info(f"Successfully saved {len(pages)} pages to {OUTPUT_FILE}")
return True
except IOError as e:
logger.error(f"Error saving results to {OUTPUT_FILE}: {e}")
return False
def main():
"""Main function to execute the script"""
parser = argparse.ArgumentParser(description="Scrape pages unavailable in French from OSM wiki")
parser.add_argument("--dry-run", action="store_true", help="Run without saving results to file")
parser.add_argument("--force", action="store_true", help="Force update even if cache is fresh")
args = parser.parse_args()
logger.info("Starting find_pages_unavailable_in_french.py")
# Check if cache is fresh
if is_cache_fresh() and not args.force:
logger.info(f"Cache is still fresh (less than {CACHE_DURATION.total_seconds()/3600} hours old)")
logger.info(f"Use --force to update anyway")
return
# Scrape pages
pages = scrape_all_pages()
if not pages:
logger.error("No pages found")
return
# Save results
success = save_results(pages, args.dry_run)
if success:
logger.info("Script completed successfully")
else:
logger.error("Script completed with errors")
if __name__ == "__main__":
main()

View file

@ -0,0 +1,212 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
find_untranslated_french_pages.py
This script scrapes the OSM wiki to find French pages that don't have translations
in other languages. It caches the results and only performs the scraping
at most once per hour.
Usage:
python find_untranslated_french_pages.py [--force] [--dry-run]
Options:
--force Force update even if cache is fresh
--dry-run Print results without saving to file
Output:
- untranslated_french_pages.json: JSON file containing information about French pages without translations
"""
import requests
from bs4 import BeautifulSoup
import json
import logging
import argparse
import os
from datetime import datetime, timedelta
import re
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
logger = logging.getLogger(__name__)
# Constants
OUTPUT_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'untranslated_french_pages.json')
CACHE_TIMEOUT = 1 # hours
WIKI_BASE_URL = "https://wiki.openstreetmap.org"
FRENCH_PAGES_URL = "https://wiki.openstreetmap.org/wiki/Special:AllPages?from=&to=&namespace=202&hideredirects=1&prefix=FR:"
def should_update_cache():
"""
Check if the cache file exists and if it's older than the cache timeout
Returns:
bool: True if cache should be updated, False otherwise
"""
if not os.path.exists(OUTPUT_FILE):
logger.info("Cache file doesn't exist, creating it")
return True
# Check file modification time
file_mtime = datetime.fromtimestamp(os.path.getmtime(OUTPUT_FILE))
now = datetime.now()
# If file is older than cache timeout, update it
if now - file_mtime > timedelta(hours=CACHE_TIMEOUT):
logger.info(f"Cache is older than {CACHE_TIMEOUT} hour(s), updating")
return True
logger.info(f"Cache is still fresh (less than {CACHE_TIMEOUT} hour(s) old)")
return False
def fetch_french_pages():
"""
Fetch all French pages from the OSM wiki
Returns:
list: List of dictionaries containing French page information
"""
logger.info(f"Fetching French pages from {FRENCH_PAGES_URL}")
french_pages = []
next_page_url = FRENCH_PAGES_URL
while next_page_url:
try:
response = requests.get(next_page_url)
response.raise_for_status()
soup = BeautifulSoup(response.text, 'html.parser')
# Find all links in the mw-allpages-body section
links_container = soup.select_one('.mw-allpages-body')
if links_container:
links = links_container.select('li a')
for link in links:
page_title = link.text.strip()
page_url = WIKI_BASE_URL + link.get('href', '')
# Extract the key name (remove the FR: prefix)
key_match = re.match(r'FR:(.*)', page_title)
if key_match:
key_name = key_match.group(1)
french_pages.append({
'title': page_title,
'key': key_name,
'url': page_url,
'has_translation': False # Will be updated later
})
# Check if there's a next page
next_link = soup.select_one('a.mw-nextlink')
next_page_url = WIKI_BASE_URL + next_link.get('href') if next_link else None
except requests.exceptions.RequestException as e:
logger.error(f"Error fetching French pages: {e}")
break
logger.info(f"Found {len(french_pages)} French pages")
return french_pages
def check_translations(french_pages):
"""
Check if each French page has translations in other languages
Args:
french_pages (list): List of dictionaries containing French page information
Returns:
list: Updated list with translation information
"""
logger.info("Checking for translations of French pages")
for i, page in enumerate(french_pages):
if i % 10 == 0: # Log progress every 10 pages
logger.info(f"Checking page {i+1}/{len(french_pages)}: {page['title']}")
try:
# Construct the English page URL by removing the FR: prefix
en_url = page['url'].replace('/wiki/FR:', '/wiki/')
# Check if the English page exists
response = requests.head(en_url)
# If the page returns a 200 status code, it exists
if response.status_code == 200:
page['has_translation'] = True
page['en_url'] = en_url
else:
page['has_translation'] = False
except requests.exceptions.RequestException as e:
logger.error(f"Error checking translation for {page['title']}: {e}")
# Assume no translation in case of error
page['has_translation'] = False
# Filter to only include pages without translations
untranslated_pages = [page for page in french_pages if not page['has_translation']]
logger.info(f"Found {len(untranslated_pages)} French pages without translations")
return untranslated_pages
def save_untranslated_pages(untranslated_pages):
"""
Save the untranslated pages to a JSON file
Args:
untranslated_pages (list): List of dictionaries containing untranslated page information
Returns:
str: Path to the output file
"""
data = {
'last_updated': datetime.now().isoformat(),
'untranslated_pages': untranslated_pages
}
with open(OUTPUT_FILE, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
logger.info(f"Saved {len(untranslated_pages)} untranslated pages to {OUTPUT_FILE}")
return OUTPUT_FILE
def main():
"""Main function to execute the script"""
parser = argparse.ArgumentParser(description="Find French OSM wiki pages without translations")
parser.add_argument("--force", action="store_true", help="Force update even if cache is fresh")
parser.add_argument("--dry-run", action="store_true", help="Print results without saving to file")
args = parser.parse_args()
logger.info("Starting find_untranslated_french_pages.py")
# Check if we should update the cache
if args.force or should_update_cache() or args.dry_run:
# Fetch all French pages
french_pages = fetch_french_pages()
# Check which ones don't have translations
untranslated_pages = check_translations(french_pages)
if args.dry_run:
logger.info(f"Found {len(untranslated_pages)} French pages without translations:")
for page in untranslated_pages[:10]: # Show only the first 10 in dry run
logger.info(f"- {page['title']} ({page['url']})")
if len(untranslated_pages) > 10:
logger.info(f"... and {len(untranslated_pages) - 10} more")
else:
# Save the results
output_file = save_untranslated_pages(untranslated_pages)
logger.info(f"Results saved to {output_file}")
else:
logger.info("Using cached untranslated pages data")
logger.info("Script completed successfully")
if __name__ == "__main__":
main()

View file

@ -0,0 +1,104 @@
{
"last_updated": "2025-08-22T16:44:04.309688",
"local_groups": [
{
"name": "Liste des groupes locaux se réunissant régulièrement",
"url": "https://framacalc.org/osm-groupes-locaux",
"description": "",
"type": "local_group"
},
{
"name": "Carte des groupes locaux se réunissant régulièrement",
"url": "https://umap.openstreetmap.fr/fr/map/groupes-locaux-openstreetmap_152488",
"description": "",
"type": "local_group"
}
],
"working_groups": [
{
"name": "Que venir faire au sein de l'association ?",
"url": "https://forum.openstreetmap.fr/t/que-venir-faire-au-sein-de-lassociation/15454",
"description": "",
"category": "Général",
"type": "working_group"
},
{
"name": "GT Inclusivité",
"url": "https://wiki.openstreetmap.org/wiki/France/OSM-FR/Groupes_de_travail#GT_Inclusivité",
"description": "",
"category": "Général",
"type": "working_group"
},
{
"name": "GT Technique",
"url": "https://wiki.openstreetmap.org/wiki/France/OSM-FR/Groupes_de_travail#GT_Technique",
"description": "",
"category": "Général",
"type": "working_group"
},
{
"name": "GT Communication externe",
"url": "https://wiki.openstreetmap.org/wiki/France/OSM-FR/Groupes_de_travail#GT_Communication",
"description": "",
"category": "Général",
"type": "working_group"
},
{
"name": "GT Animation de la communauté",
"url": "https://wiki.openstreetmap.org/wiki/France/OSM-FR/Groupes_de_travail#GT_Animation_de_la_communauté",
"description": "",
"category": "Général",
"type": "working_group"
},
{
"name": "GT Communautés locales",
"url": "https://wiki.openstreetmap.org/wiki/France/OSM-FR/Groupes_de_travail#GT_Communautés_locales",
"description": "",
"category": "Général",
"type": "working_group"
},
{
"name": "GT International",
"url": "https://wiki.openstreetmap.org/wiki/France/OSM-FR/Groupes_de_travail#GT_International",
"description": "",
"category": "Général",
"type": "working_group"
},
{
"name": "GT Gestion et comptabilité",
"url": "https://wiki.openstreetmap.org/wiki/France/OSM-FR/Groupes_de_travail#GT_Gestion_et_comptabilité",
"description": "",
"category": "Général",
"type": "working_group"
},
{
"name": "GT Soutiens",
"url": "https://wiki.openstreetmap.org/wiki/France/OSM-FR/Groupes_de_travail#GT_Soutiens",
"description": "",
"category": "Général",
"type": "working_group"
},
{
"name": "GT Conférence SotM-FR",
"url": "https://wiki.openstreetmap.org/wiki/France/OSM-FR/Groupes_de_travail#GT_Conférence_SotM-FR",
"description": "",
"category": "Général",
"type": "working_group"
},
{
"name": "Groupes spéciaux",
"url": "https://wiki.openstreetmap.org/wiki/France/OSM-FR/Groupes_de_travail#Groupes_spéciaux",
"description": "",
"category": "Général",
"type": "working_group"
},
{
"name": "Groupes projets et thématiques",
"url": "https://wiki.openstreetmap.org/wiki/France/OSM-FR/Groupes_de_travail#Groupes_projets_et_thématiques",
"description": "",
"category": "Général",
"type": "working_group"
}
],
"umap_url": "https://umap.openstreetmap.fr/fr/map/groupes-locaux-openstreetmap_152488"
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,18 @@
{
"last_updated": "2025-08-22T17:17:53.415750",
"voting_proposals": [
{
"title": "Proposal:Man made=ceremonial gate",
"url": "https://wiki.openstreetmap.org/wiki/Proposal:Man_made%3Dceremonial_gate",
"status": "Voting",
"type": "voting"
},
{
"title": "Proposal:Developer",
"url": "https://wiki.openstreetmap.org/wiki/Proposal:Developer",
"status": "Voting",
"type": "voting"
}
],
"recent_proposals": []
}

View file

@ -0,0 +1,17 @@
{
"last_updated": "2025-08-22T16:37:41.133091",
"deletions": [
{
"page_title": "FR:Mapa en català",
"page_url": "https://wiki.openstreetmap.org/wiki/FR:Mapa_en_catal%C3%A0",
"diff_url": "",
"history_url": "https://wiki.openstreetmap.org/w/index.php?title=FR:Mapa en català&action=history",
"deletion_size": 616,
"total_chars": 6106,
"deletion_percentage": 10.09,
"timestamp": "",
"user": "LySioS",
"comment": "(màj méthode et BAL pour mairie)"
}
]
}

View file

@ -1,82 +1,202 @@
[
{
"key": "building",
"count": 656287377
"count": 656385865
},
{
"key": "source",
"count": 299623433
"count": 299647859
},
{
"key": "highway",
"count": 280087725
"count": 280148158
},
{
"key": "addr:housenumber",
"count": 171973287
"count": 171945679
},
{
"key": "addr:street",
"count": 160834345
"count": 160796997
},
{
"key": "addr:city",
"count": 123283625
"count": 123238768
},
{
"key": "name",
"count": 109176151
"count": 109198278
},
{
"key": "addr:postcode",
"count": 106943837
"count": 106896062
},
{
"key": "natural",
"count": 84435807
"count": 84462003
},
{
"key": "surface",
"count": 72048796
"count": 72076206
},
{
"key": "addr:country",
"count": 50511041
"count": 50514250
},
{
"key": "landuse",
"count": 48098130
"count": 48109623
},
{
"key": "power",
"count": 44639130
"count": 44663063
},
{
"key": "waterway",
"count": 37153506
"count": 37159863
},
{
"key": "building:levels",
"count": 36426521
"count": 36434874
},
{
"key": "amenity",
"count": 30874207
"count": 30885582
},
{
"key": "barrier",
"count": 30063102
"count": 30072729
},
{
"key": "source:date",
"count": 29107386
"count": 29105774
},
{
"key": "service",
"count": 28326346
"count": 28333572
},
{
"key": "addr:state",
"count": 25331031
"count": 25334152
},
{
"key": "access",
"count": 24181609
},
{
"key": "oneway",
"count": 24104463
},
{
"key": "height",
"count": 22722628
},
{
"key": "ref",
"count": 21319224
},
{
"key": "maxspeed",
"count": 20590670
},
{
"key": "lanes",
"count": 18429768
},
{
"key": "start_date",
"count": 17794337
},
{
"key": "addr:district",
"count": 16216409
},
{
"key": "layer",
"count": 14666751
},
{
"key": "type",
"count": 13753788
},
{
"key": "operator",
"count": 13510261
},
{
"key": "lit",
"count": 13412110
},
{
"key": "wall",
"count": 12771580
},
{
"key": "tiger:cfcc",
"count": 12592955
},
{
"key": "crossing",
"count": 12512388
},
{
"key": "tiger:county",
"count": 12488330
},
{
"key": "source:addr",
"count": 12377162
},
{
"key": "footway",
"count": 11461964
},
{
"key": "ref:bag",
"count": 11341389
},
{
"key": "addr:place",
"count": 11132132
},
{
"key": "tiger:reviewed",
"count": 10788557
},
{
"key": "leisure",
"count": 10656018
},
{
"key": "addr:suburb",
"count": 10308389
},
{
"key": "ele",
"count": 10261636
},
{
"key": "tracktype",
"count": 10147836
},
{
"key": "addr:neighbourhood",
"count": 10130674
},
{
"key": "addr:hamlet",
"count": 9972893
},
{
"key": "addr:province",
"count": 9653154
},
{
"key": "leaf_type",
"count": 9511262
},
{
"key": "addr:full",
"count": 9434493
}
]

View file

@ -0,0 +1,947 @@
{
"last_updated": "2025-08-22T15:22:37.234265",
"untranslated_pages": [
{
"title": "FR:2017 Ouragans Irma et Maria",
"key": "2017 Ouragans Irma et Maria",
"url": "https://wiki.openstreetmap.org/wiki/FR:2017_Ouragans_Irma_et_Maria",
"has_translation": false
},
{
"title": "FR:ARTM - Autorité régionale de transport métropolitain",
"key": "ARTM - Autorité régionale de transport métropolitain",
"url": "https://wiki.openstreetmap.org/wiki/FR:ARTM_-_Autorit%C3%A9_r%C3%A9gionale_de_transport_m%C3%A9tropolitain",
"has_translation": false
},
{
"title": "FR:Accessibilité",
"key": "Accessibilité",
"url": "https://wiki.openstreetmap.org/wiki/FR:Accessibilit%C3%A9",
"has_translation": false
},
{
"title": "FR:Accompagner les débutants",
"key": "Accompagner les débutants",
"url": "https://wiki.openstreetmap.org/wiki/FR:Accompagner_les_d%C3%A9butants",
"has_translation": false
},
{
"title": "FR:Adresses",
"key": "Adresses",
"url": "https://wiki.openstreetmap.org/wiki/FR:Adresses",
"has_translation": false
},
{
"title": "FR:Adresses/Brouillon",
"key": "Adresses/Brouillon",
"url": "https://wiki.openstreetmap.org/wiki/FR:Adresses/Brouillon",
"has_translation": false
},
{
"title": "FR:Aide",
"key": "Aide",
"url": "https://wiki.openstreetmap.org/wiki/FR:Aide",
"has_translation": false
},
{
"title": "FR:Aide du wiki",
"key": "Aide du wiki",
"url": "https://wiki.openstreetmap.org/wiki/FR:Aide_du_wiki",
"has_translation": false
},
{
"title": "FR:Aires d'accueil des gens du voyage",
"key": "Aires d'accueil des gens du voyage",
"url": "https://wiki.openstreetmap.org/wiki/FR:Aires_d%27accueil_des_gens_du_voyage",
"has_translation": false
},
{
"title": "FR:Algérie",
"key": "Algérie",
"url": "https://wiki.openstreetmap.org/wiki/FR:Alg%C3%A9rie",
"has_translation": false
},
{
"title": "FR:Animaux",
"key": "Animaux",
"url": "https://wiki.openstreetmap.org/wiki/FR:Animaux",
"has_translation": false
},
{
"title": "FR:Annulation des modifications",
"key": "Annulation des modifications",
"url": "https://wiki.openstreetmap.org/wiki/FR:Annulation_des_modifications",
"has_translation": false
},
{
"title": "FR:Annulation des suppressions de données",
"key": "Annulation des suppressions de données",
"url": "https://wiki.openstreetmap.org/wiki/FR:Annulation_des_suppressions_de_donn%C3%A9es",
"has_translation": false
},
{
"title": "FR:Anomalies",
"key": "Anomalies",
"url": "https://wiki.openstreetmap.org/wiki/FR:Anomalies",
"has_translation": false
},
{
"title": "FR:Antananarivo",
"key": "Antananarivo",
"url": "https://wiki.openstreetmap.org/wiki/FR:Antananarivo",
"has_translation": false
},
{
"title": "FR:Antsiranana",
"key": "Antsiranana",
"url": "https://wiki.openstreetmap.org/wiki/FR:Antsiranana",
"has_translation": false
},
{
"title": "FR:Aperçu des composants",
"key": "Aperçu des composants",
"url": "https://wiki.openstreetmap.org/wiki/FR:Aper%C3%A7u_des_composants",
"has_translation": false
},
{
"title": "FR:Argumentaires",
"key": "Argumentaires",
"url": "https://wiki.openstreetmap.org/wiki/FR:Argumentaires",
"has_translation": false
},
{
"title": "FR:Assurance qualité",
"key": "Assurance qualité",
"url": "https://wiki.openstreetmap.org/wiki/FR:Assurance_qualit%C3%A9",
"has_translation": false
},
{
"title": "FR:Attributs",
"key": "Attributs",
"url": "https://wiki.openstreetmap.org/wiki/FR:Attributs",
"has_translation": false
},
{
"title": "FR:Attributs OSM Humanitaire",
"key": "Attributs OSM Humanitaire",
"url": "https://wiki.openstreetmap.org/wiki/FR:Attributs_OSM_Humanitaire",
"has_translation": false
},
{
"title": "FR:Attributs suppressibles",
"key": "Attributs suppressibles",
"url": "https://wiki.openstreetmap.org/wiki/FR:Attributs_suppressibles",
"has_translation": false
},
{
"title": "FR:Augustind/testpage",
"key": "Augustind/testpage",
"url": "https://wiki.openstreetmap.org/wiki/FR:Augustind/testpage",
"has_translation": false
},
{
"title": "FR:Autres cartes en ligne",
"key": "Autres cartes en ligne",
"url": "https://wiki.openstreetmap.org/wiki/FR:Autres_cartes_en_ligne",
"has_translation": false
},
{
"title": "FR:Avant et arrière, gauche et droite",
"key": "Avant et arrière, gauche et droite",
"url": "https://wiki.openstreetmap.org/wiki/FR:Avant_et_arri%C3%A8re,_gauche_et_droite",
"has_translation": false
},
{
"title": "FR:Baignade",
"key": "Baignade",
"url": "https://wiki.openstreetmap.org/wiki/FR:Baignade",
"has_translation": false
},
{
"title": "FR:Balisage maritime/Catégories pour les objets",
"key": "Balisage maritime/Catégories pour les objets",
"url": "https://wiki.openstreetmap.org/wiki/FR:Balisage_maritime/Cat%C3%A9gories_pour_les_objets",
"has_translation": false
},
{
"title": "FR:Balisage maritime/Etiquettes et valeurs",
"key": "Balisage maritime/Etiquettes et valeurs",
"url": "https://wiki.openstreetmap.org/wiki/FR:Balisage_maritime/Etiquettes_et_valeurs",
"has_translation": false
},
{
"title": "FR:Balisage maritime/Mouillages",
"key": "Balisage maritime/Mouillages",
"url": "https://wiki.openstreetmap.org/wiki/FR:Balisage_maritime/Mouillages",
"has_translation": false
},
{
"title": "FR:Balisage maritime/Objets de balisage",
"key": "Balisage maritime/Objets de balisage",
"url": "https://wiki.openstreetmap.org/wiki/FR:Balisage_maritime/Objets_de_balisage",
"has_translation": false
},
{
"title": "FR:Balisage maritime/Schéma de balisage",
"key": "Balisage maritime/Schéma de balisage",
"url": "https://wiki.openstreetmap.org/wiki/FR:Balisage_maritime/Sch%C3%A9ma_de_balisage",
"has_translation": false
},
{
"title": "FR:Balisage maritime/Utilisation des objets",
"key": "Balisage maritime/Utilisation des objets",
"url": "https://wiki.openstreetmap.org/wiki/FR:Balisage_maritime/Utilisation_des_objets",
"has_translation": false
},
{
"title": "FR:Barrières",
"key": "Barrières",
"url": "https://wiki.openstreetmap.org/wiki/FR:Barri%C3%A8res",
"has_translation": false
},
{
"title": "FR:BeCikloXmlFond",
"key": "BeCikloXmlFond",
"url": "https://wiki.openstreetmap.org/wiki/FR:BeCikloXmlFond",
"has_translation": false
},
{
"title": "FR:BeCikloXmlInfos",
"key": "BeCikloXmlInfos",
"url": "https://wiki.openstreetmap.org/wiki/FR:BeCikloXmlInfos",
"has_translation": false
},
{
"title": "FR:BeCikloXmlPistes",
"key": "BeCikloXmlPistes",
"url": "https://wiki.openstreetmap.org/wiki/FR:BeCikloXmlPistes",
"has_translation": false
},
{
"title": "FR:Beginners Guide 1.3.3",
"key": "Beginners Guide 1.3.3",
"url": "https://wiki.openstreetmap.org/wiki/FR:Beginners_Guide_1.3.3",
"has_translation": false
},
{
"title": "FR:BelvederesLez",
"key": "BelvederesLez",
"url": "https://wiki.openstreetmap.org/wiki/FR:BelvederesLez",
"has_translation": false
},
{
"title": "FR:Bibliographie",
"key": "Bibliographie",
"url": "https://wiki.openstreetmap.org/wiki/FR:Bibliographie",
"has_translation": false
},
{
"title": "FR:Bienvenue aux wikipediens",
"key": "Bienvenue aux wikipediens",
"url": "https://wiki.openstreetmap.org/wiki/FR:Bienvenue_aux_wikipediens",
"has_translation": false
},
{
"title": "FR:Bing Cartes",
"key": "Bing Cartes",
"url": "https://wiki.openstreetmap.org/wiki/FR:Bing_Cartes",
"has_translation": false
},
{
"title": "FR:Blogues d'OSM",
"key": "Blogues d'OSM",
"url": "https://wiki.openstreetmap.org/wiki/FR:Blogues_d%27OSM",
"has_translation": false
},
{
"title": "FR:Bonnes pratiques",
"key": "Bonnes pratiques",
"url": "https://wiki.openstreetmap.org/wiki/FR:Bonnes_pratiques",
"has_translation": false
},
{
"title": "FR:Bons commentaires de groupe de modifications",
"key": "Bons commentaires de groupe de modifications",
"url": "https://wiki.openstreetmap.org/wiki/FR:Bons_commentaires_de_groupe_de_modifications",
"has_translation": false
},
{
"title": "FR:Bookmarklet OSM-Mapillary",
"key": "Bookmarklet OSM-Mapillary",
"url": "https://wiki.openstreetmap.org/wiki/FR:Bookmarklet_OSM-Mapillary",
"has_translation": false
},
{
"title": "FR:Breton, noms geographiques et toponymes",
"key": "Breton, noms geographiques et toponymes",
"url": "https://wiki.openstreetmap.org/wiki/FR:Breton,_noms_geographiques_et_toponymes",
"has_translation": false
},
{
"title": "FR:Breton, rendu br",
"key": "Breton, rendu br",
"url": "https://wiki.openstreetmap.org/wiki/FR:Breton,_rendu_br",
"has_translation": false
},
{
"title": "FR:Bâtiments",
"key": "Bâtiments",
"url": "https://wiki.openstreetmap.org/wiki/FR:B%C3%A2timents",
"has_translation": false
},
{
"title": "FR:Bâtiments 3D simples",
"key": "Bâtiments 3D simples",
"url": "https://wiki.openstreetmap.org/wiki/FR:B%C3%A2timents_3D_simples",
"has_translation": false
},
{
"title": "FR:Cadastre espagnol",
"key": "Cadastre espagnol",
"url": "https://wiki.openstreetmap.org/wiki/FR:Cadastre_espagnol",
"has_translation": false
},
{
"title": "FR:Cadastre espagnol/2011-2016",
"key": "Cadastre espagnol/2011-2016",
"url": "https://wiki.openstreetmap.org/wiki/FR:Cadastre_espagnol/2011-2016",
"has_translation": false
},
{
"title": "FR:Cadastre français/archives",
"key": "Cadastre français/archives",
"url": "https://wiki.openstreetmap.org/wiki/FR:Cadastre_fran%C3%A7ais/archives",
"has_translation": false
},
{
"title": "FR:Calcul d'itinéraires",
"key": "Calcul d'itinéraires",
"url": "https://wiki.openstreetmap.org/wiki/FR:Calcul_d%27itin%C3%A9raires",
"has_translation": false
},
{
"title": "FR:Calque Données de carte",
"key": "Calque Données de carte",
"url": "https://wiki.openstreetmap.org/wiki/FR:Calque_Donn%C3%A9es_de_carte",
"has_translation": false
},
{
"title": "FR:Canada/Signalisation routière/Québec",
"key": "Canada/Signalisation routière/Québec",
"url": "https://wiki.openstreetmap.org/wiki/FR:Canada/Signalisation_routi%C3%A8re/Qu%C3%A9bec",
"has_translation": false
},
{
"title": "FR:Canada/Signalisation routière/Québec/Danger",
"key": "Canada/Signalisation routière/Québec/Danger",
"url": "https://wiki.openstreetmap.org/wiki/FR:Canada/Signalisation_routi%C3%A8re/Qu%C3%A9bec/Danger",
"has_translation": false
},
{
"title": "FR:Canada/Signalisation routière/Québec/Prescription",
"key": "Canada/Signalisation routière/Québec/Prescription",
"url": "https://wiki.openstreetmap.org/wiki/FR:Canada/Signalisation_routi%C3%A8re/Qu%C3%A9bec/Prescription",
"has_translation": false
},
{
"title": "FR:Canaux de contact",
"key": "Canaux de contact",
"url": "https://wiki.openstreetmap.org/wiki/FR:Canaux_de_contact",
"has_translation": false
},
{
"title": "FR:CarteInnov",
"key": "CarteInnov",
"url": "https://wiki.openstreetmap.org/wiki/FR:CarteInnov",
"has_translation": false
},
{
"title": "FR:Cartes",
"key": "Cartes",
"url": "https://wiki.openstreetmap.org/wiki/FR:Cartes",
"has_translation": false
},
{
"title": "FR:CartoSatCamp",
"key": "CartoSatCamp",
"url": "https://wiki.openstreetmap.org/wiki/FR:CartoSatCamp",
"has_translation": false
},
{
"title": "FR:Cartographie",
"key": "Cartographie",
"url": "https://wiki.openstreetmap.org/wiki/FR:Cartographie",
"has_translation": false
},
{
"title": "FR:Cartographie d'après des photos",
"key": "Cartographie d'après des photos",
"url": "https://wiki.openstreetmap.org/wiki/FR:Cartographie_d%27apr%C3%A8s_des_photos",
"has_translation": false
},
{
"title": "FR:Cartographie des camps de réfugiés",
"key": "Cartographie des camps de réfugiés",
"url": "https://wiki.openstreetmap.org/wiki/FR:Cartographie_des_camps_de_r%C3%A9fugi%C3%A9s",
"has_translation": false
},
{
"title": "FR:Cartographie des routes en France",
"key": "Cartographie des routes en France",
"url": "https://wiki.openstreetmap.org/wiki/FR:Cartographie_des_routes_en_France",
"has_translation": false
},
{
"title": "FR:Cartographier depuis son fauteuil",
"key": "Cartographier depuis son fauteuil",
"url": "https://wiki.openstreetmap.org/wiki/FR:Cartographier_depuis_son_fauteuil",
"has_translation": false
},
{
"title": "FR:Cartoparties",
"key": "Cartoparties",
"url": "https://wiki.openstreetmap.org/wiki/FR:Cartoparties",
"has_translation": false
},
{
"title": "FR:Cartothèque",
"key": "Cartothèque",
"url": "https://wiki.openstreetmap.org/wiki/FR:Cartoth%C3%A8que",
"has_translation": false
},
{
"title": "FR:Catalogue des erreurs",
"key": "Catalogue des erreurs",
"url": "https://wiki.openstreetmap.org/wiki/FR:Catalogue_des_erreurs",
"has_translation": false
},
{
"title": "FR:Chemin",
"key": "Chemin",
"url": "https://wiki.openstreetmap.org/wiki/FR:Chemin",
"has_translation": false
},
{
"title": "FR:Cheminements piétons",
"key": "Cheminements piétons",
"url": "https://wiki.openstreetmap.org/wiki/FR:Cheminements_pi%C3%A9tons",
"has_translation": false
},
{
"title": "FR:Chemins de fer",
"key": "Chemins de fer",
"url": "https://wiki.openstreetmap.org/wiki/FR:Chemins_de_fer",
"has_translation": false
},
{
"title": "FR:Chemins non connectés",
"key": "Chemins non connectés",
"url": "https://wiki.openstreetmap.org/wiki/FR:Chemins_non_connect%C3%A9s",
"has_translation": false
},
{
"title": "FR:Choisir votre méthode de collecte de données",
"key": "Choisir votre méthode de collecte de données",
"url": "https://wiki.openstreetmap.org/wiki/FR:Choisir_votre_m%C3%A9thode_de_collecte_de_donn%C3%A9es",
"has_translation": false
},
{
"title": "FR:Chute d'eau",
"key": "Chute d'eau",
"url": "https://wiki.openstreetmap.org/wiki/FR:Chute_d%27eau",
"has_translation": false
},
{
"title": "FR:Circonscriptions législatives en France",
"key": "Circonscriptions législatives en France",
"url": "https://wiki.openstreetmap.org/wiki/FR:Circonscriptions_l%C3%A9gislatives_en_France",
"has_translation": false
},
{
"title": "FR:Code de conduite des modifications automatisées",
"key": "Code de conduite des modifications automatisées",
"url": "https://wiki.openstreetmap.org/wiki/FR:Code_de_conduite_des_modifications_automatis%C3%A9es",
"has_translation": false
},
{
"title": "FR:ComcomMaker",
"key": "ComcomMaker",
"url": "https://wiki.openstreetmap.org/wiki/FR:ComcomMaker",
"has_translation": false
},
{
"title": "FR:Comment cartographier les besoins des personnes handicapées",
"key": "Comment cartographier les besoins des personnes handicapées",
"url": "https://wiki.openstreetmap.org/wiki/FR:Comment_cartographier_les_besoins_des_personnes_handicap%C3%A9es",
"has_translation": false
},
{
"title": "FR:Comment cartographier un...",
"key": "Comment cartographier un...",
"url": "https://wiki.openstreetmap.org/wiki/FR:Comment_cartographier_un...",
"has_translation": false
},
{
"title": "FR:Comment cartographier un (santé)",
"key": "Comment cartographier un (santé)",
"url": "https://wiki.openstreetmap.org/wiki/FR:Comment_cartographier_un_(sant%C3%A9)",
"has_translation": false
},
{
"title": "FR:Comment contribuer",
"key": "Comment contribuer",
"url": "https://wiki.openstreetmap.org/wiki/FR:Comment_contribuer",
"has_translation": false
},
{
"title": "FR:Comores",
"key": "Comores",
"url": "https://wiki.openstreetmap.org/wiki/FR:Comores",
"has_translation": false
},
{
"title": "FR:Comparaison des concepts de cycle de vie",
"key": "Comparaison des concepts de cycle de vie",
"url": "https://wiki.openstreetmap.org/wiki/FR:Comparaison_des_concepts_de_cycle_de_vie",
"has_translation": false
},
{
"title": "FR:Comparaison des éditeurs",
"key": "Comparaison des éditeurs",
"url": "https://wiki.openstreetmap.org/wiki/FR:Comparaison_des_%C3%A9diteurs",
"has_translation": false
},
{
"title": "FR:Complète Tes Commerces/Avancé",
"key": "Complète Tes Commerces/Avancé",
"url": "https://wiki.openstreetmap.org/wiki/FR:Compl%C3%A8te_Tes_Commerces/Avanc%C3%A9",
"has_translation": false
},
{
"title": "FR:Complète Tes Commerces/Debutant",
"key": "Complète Tes Commerces/Debutant",
"url": "https://wiki.openstreetmap.org/wiki/FR:Compl%C3%A8te_Tes_Commerces/Debutant",
"has_translation": false
},
{
"title": "FR:Complète Tes Commerces/Débutant",
"key": "Complète Tes Commerces/Débutant",
"url": "https://wiki.openstreetmap.org/wiki/FR:Compl%C3%A8te_Tes_Commerces/D%C3%A9butant",
"has_translation": false
},
{
"title": "FR:Comptes services OpenStreetMap France",
"key": "Comptes services OpenStreetMap France",
"url": "https://wiki.openstreetmap.org/wiki/FR:Comptes_services_OpenStreetMap_France",
"has_translation": false
},
{
"title": "FR:Congo-Kinshasa/Réponse OSM 2020 à l'épidémie Ebola",
"key": "Congo-Kinshasa/Réponse OSM 2020 à l'épidémie Ebola",
"url": "https://wiki.openstreetmap.org/wiki/FR:Congo-Kinshasa/R%C3%A9ponse_OSM_2020_%C3%A0_l%27%C3%A9pid%C3%A9mie_Ebola",
"has_translation": false
},
{
"title": "FR:Conserver l'historique",
"key": "Conserver l'historique",
"url": "https://wiki.openstreetmap.org/wiki/FR:Conserver_l%27historique",
"has_translation": false
},
{
"title": "FR:Contacts pour la presse",
"key": "Contacts pour la presse",
"url": "https://wiki.openstreetmap.org/wiki/FR:Contacts_pour_la_presse",
"has_translation": false
},
{
"title": "FR:Contribuer aux données cartographiques",
"key": "Contribuer aux données cartographiques",
"url": "https://wiki.openstreetmap.org/wiki/FR:Contribuer_aux_donn%C3%A9es_cartographiques",
"has_translation": false
},
{
"title": "FR:Conversion des traces GPS",
"key": "Conversion des traces GPS",
"url": "https://wiki.openstreetmap.org/wiki/FR:Conversion_des_traces_GPS",
"has_translation": false
},
{
"title": "FR:Corine Land Cover/Nomenclature",
"key": "Corine Land Cover/Nomenclature",
"url": "https://wiki.openstreetmap.org/wiki/FR:Corine_Land_Cover/Nomenclature",
"has_translation": false
},
{
"title": "FR:Corine Land Cover/Opérations post-import",
"key": "Corine Land Cover/Opérations post-import",
"url": "https://wiki.openstreetmap.org/wiki/FR:Corine_Land_Cover/Op%C3%A9rations_post-import",
"has_translation": false
},
{
"title": "FR:Cours d'eau",
"key": "Cours d'eau",
"url": "https://wiki.openstreetmap.org/wiki/FR:Cours_d%27eau",
"has_translation": false
},
{
"title": "FR:Créer un attribut qui manque",
"key": "Créer un attribut qui manque",
"url": "https://wiki.openstreetmap.org/wiki/FR:Cr%C3%A9er_un_attribut_qui_manque",
"has_translation": false
},
{
"title": "FR:Cyclisme tout terrain",
"key": "Cyclisme tout terrain",
"url": "https://wiki.openstreetmap.org/wiki/FR:Cyclisme_tout_terrain",
"has_translation": false
},
{
"title": "FR:Câble aérien",
"key": "Câble aérien",
"url": "https://wiki.openstreetmap.org/wiki/FR:C%C3%A2ble_a%C3%A9rien",
"has_translation": false
},
{
"title": "FR:DRC Tagging Guidelines",
"key": "DRC Tagging Guidelines",
"url": "https://wiki.openstreetmap.org/wiki/FR:DRC_Tagging_Guidelines",
"has_translation": false
},
{
"title": "FR:Datex",
"key": "Datex",
"url": "https://wiki.openstreetmap.org/wiki/FR:Datex",
"has_translation": false
},
{
"title": "FR:Debian/Bullseye/Installation",
"key": "Debian/Bullseye/Installation",
"url": "https://wiki.openstreetmap.org/wiki/FR:Debian/Bullseye/Installation",
"has_translation": false
},
{
"title": "FR:Demander aux contributeurs d'accepter l'ODbL",
"key": "Demander aux contributeurs d'accepter l'ODbL",
"url": "https://wiki.openstreetmap.org/wiki/FR:Demander_aux_contributeurs_d%27accepter_l%27ODbL",
"has_translation": false
},
{
"title": "FR:Directives du wiki",
"key": "Directives du wiki",
"url": "https://wiki.openstreetmap.org/wiki/FR:Directives_du_wiki",
"has_translation": false
},
{
"title": "FR:Débat Traduction",
"key": "Débat Traduction",
"url": "https://wiki.openstreetmap.org/wiki/FR:D%C3%A9bat_Traduction",
"has_translation": false
},
{
"title": "FR:Découpage administratif de la Tunisie",
"key": "Découpage administratif de la Tunisie",
"url": "https://wiki.openstreetmap.org/wiki/FR:D%C3%A9coupage_administratif_de_la_Tunisie",
"has_translation": false
},
{
"title": "FR:Déployer sa propre Slippy Map",
"key": "Déployer sa propre Slippy Map",
"url": "https://wiki.openstreetmap.org/wiki/FR:D%C3%A9ployer_sa_propre_Slippy_Map",
"has_translation": false
},
{
"title": "FR:Développement 3D",
"key": "Développement 3D",
"url": "https://wiki.openstreetmap.org/wiki/FR:D%C3%A9veloppement_3D",
"has_translation": false
},
{
"title": "FR:Développer",
"key": "Développer",
"url": "https://wiki.openstreetmap.org/wiki/FR:D%C3%A9velopper",
"has_translation": false
},
{
"title": "FR:EXO - Autorisation import GTFS",
"key": "EXO - Autorisation import GTFS",
"url": "https://wiki.openstreetmap.org/wiki/FR:EXO_-_Autorisation_import_GTFS",
"has_translation": false
},
{
"title": "FR:EXO - Réseau de transport métropolitain (autobus)",
"key": "EXO - Réseau de transport métropolitain (autobus)",
"url": "https://wiki.openstreetmap.org/wiki/FR:EXO_-_R%C3%A9seau_de_transport_m%C3%A9tropolitain_(autobus)",
"has_translation": false
},
{
"title": "FR:EXO - Réseau de transport métropolitain (train)",
"key": "EXO - Réseau de transport métropolitain (train)",
"url": "https://wiki.openstreetmap.org/wiki/FR:EXO_-_R%C3%A9seau_de_transport_m%C3%A9tropolitain_(train)",
"has_translation": false
},
{
"title": "FR:English CarteInnov",
"key": "English CarteInnov",
"url": "https://wiki.openstreetmap.org/wiki/FR:English_CarteInnov",
"has_translation": false
},
{
"title": "FR:Enregistrement de traces GPS",
"key": "Enregistrement de traces GPS",
"url": "https://wiki.openstreetmap.org/wiki/FR:Enregistrement_de_traces_GPS",
"has_translation": false
},
{
"title": "FR:Environnement marin",
"key": "Environnement marin",
"url": "https://wiki.openstreetmap.org/wiki/FR:Environnement_marin",
"has_translation": false
},
{
"title": "FR:Escalade",
"key": "Escalade",
"url": "https://wiki.openstreetmap.org/wiki/FR:Escalade",
"has_translation": false
},
{
"title": "FR:Espaces de noms",
"key": "Espaces de noms",
"url": "https://wiki.openstreetmap.org/wiki/FR:Espaces_de_noms",
"has_translation": false
},
{
"title": "FR:Espagne",
"key": "Espagne",
"url": "https://wiki.openstreetmap.org/wiki/FR:Espagne",
"has_translation": false
},
{
"title": "FR:Exactitude",
"key": "Exactitude",
"url": "https://wiki.openstreetmap.org/wiki/FR:Exactitude",
"has_translation": false
},
{
"title": "FR:Exemples de chemins",
"key": "Exemples de chemins",
"url": "https://wiki.openstreetmap.org/wiki/FR:Exemples_de_chemins",
"has_translation": false
},
{
"title": "FR:Flash Map Mob",
"key": "Flash Map Mob",
"url": "https://wiki.openstreetmap.org/wiki/FR:Flash_Map_Mob",
"has_translation": false
},
{
"title": "FR:Fondation",
"key": "Fondation",
"url": "https://wiki.openstreetmap.org/wiki/FR:Fondation",
"has_translation": false
},
{
"title": "FR:Fondation/Chapitres locaux",
"key": "Fondation/Chapitres locaux",
"url": "https://wiki.openstreetmap.org/wiki/FR:Fondation/Chapitres_locaux",
"has_translation": false
},
{
"title": "FR:Format PBF",
"key": "Format PBF",
"url": "https://wiki.openstreetmap.org/wiki/FR:Format_PBF",
"has_translation": false
},
{
"title": "FR:Format de fichier JOSM",
"key": "Format de fichier JOSM",
"url": "https://wiki.openstreetmap.org/wiki/FR:Format_de_fichier_JOSM",
"has_translation": false
},
{
"title": "FR:Formations",
"key": "Formations",
"url": "https://wiki.openstreetmap.org/wiki/FR:Formations",
"has_translation": false
},
{
"title": "FR:Fortunes",
"key": "Fortunes",
"url": "https://wiki.openstreetmap.org/wiki/FR:Fortunes",
"has_translation": false
},
{
"title": "FR:Forêt",
"key": "Forêt",
"url": "https://wiki.openstreetmap.org/wiki/FR:For%C3%AAt",
"has_translation": false
},
{
"title": "FR:France/Actualisation en temps réel",
"key": "France/Actualisation en temps réel",
"url": "https://wiki.openstreetmap.org/wiki/FR:France/Actualisation_en_temps_r%C3%A9el",
"has_translation": false
},
{
"title": "FR:France/Base Adresses Nationale Ouverte (BANO)",
"key": "France/Base Adresses Nationale Ouverte (BANO)",
"url": "https://wiki.openstreetmap.org/wiki/FR:France/Base_Adresses_Nationale_Ouverte_(BANO)",
"has_translation": false
},
{
"title": "FR:France/Base Adresses Nationale Ouverte (BANO)/Liste noire",
"key": "France/Base Adresses Nationale Ouverte (BANO)/Liste noire",
"url": "https://wiki.openstreetmap.org/wiki/FR:France/Base_Adresses_Nationale_Ouverte_(BANO)/Liste_noire",
"has_translation": false
},
{
"title": "FR:France/Base Adresses Nationale Ouverte (BANO)/MapCraft: communes sans aucune rue nommée",
"key": "France/Base Adresses Nationale Ouverte (BANO)/MapCraft: communes sans aucune rue nommée",
"url": "https://wiki.openstreetmap.org/wiki/FR:France/Base_Adresses_Nationale_Ouverte_(BANO)/MapCraft:_communes_sans_aucune_rue_nomm%C3%A9e",
"has_translation": false
},
{
"title": "FR:France/Base Adresses Nationale Ouverte (BANO)/OpenData",
"key": "France/Base Adresses Nationale Ouverte (BANO)/OpenData",
"url": "https://wiki.openstreetmap.org/wiki/FR:France/Base_Adresses_Nationale_Ouverte_(BANO)/OpenData",
"has_translation": false
},
{
"title": "FR:France/Base Adresses Nationale Ouverte (BANO)/Technique",
"key": "France/Base Adresses Nationale Ouverte (BANO)/Technique",
"url": "https://wiki.openstreetmap.org/wiki/FR:France/Base_Adresses_Nationale_Ouverte_(BANO)/Technique",
"has_translation": false
},
{
"title": "FR:France/Cadastre",
"key": "France/Cadastre",
"url": "https://wiki.openstreetmap.org/wiki/FR:France/Cadastre",
"has_translation": false
},
{
"title": "FR:France/DFCI et DECI",
"key": "France/DFCI et DECI",
"url": "https://wiki.openstreetmap.org/wiki/FR:France/DFCI_et_DECI",
"has_translation": false
},
{
"title": "FR:France/Intégration des adresses avec les outils BANO",
"key": "France/Intégration des adresses avec les outils BANO",
"url": "https://wiki.openstreetmap.org/wiki/FR:France/Int%C3%A9gration_des_adresses_avec_les_outils_BANO",
"has_translation": false
},
{
"title": "FR:France/Intégration des adresses depuis la BAN",
"key": "France/Intégration des adresses depuis la BAN",
"url": "https://wiki.openstreetmap.org/wiki/FR:France/Int%C3%A9gration_des_adresses_depuis_la_BAN",
"has_translation": false
},
{
"title": "FR:France/Intégration des adresses depuis la BAN/BAN.json",
"key": "France/Intégration des adresses depuis la BAN/BAN.json",
"url": "https://wiki.openstreetmap.org/wiki/FR:France/Int%C3%A9gration_des_adresses_depuis_la_BAN/BAN.json",
"has_translation": false
},
{
"title": "FR:France/Map",
"key": "France/Map",
"url": "https://wiki.openstreetmap.org/wiki/FR:France/Map",
"has_translation": false
},
{
"title": "FR:France/Map/COM",
"key": "France/Map/COM",
"url": "https://wiki.openstreetmap.org/wiki/FR:France/Map/COM",
"has_translation": false
},
{
"title": "FR:France/Map/DOM",
"key": "France/Map/DOM",
"url": "https://wiki.openstreetmap.org/wiki/FR:France/Map/DOM",
"has_translation": false
},
{
"title": "FR:France/Map/France",
"key": "France/Map/France",
"url": "https://wiki.openstreetmap.org/wiki/FR:France/Map/France",
"has_translation": false
},
{
"title": "FR:France/Map/France métropolitaine",
"key": "France/Map/France métropolitaine",
"url": "https://wiki.openstreetmap.org/wiki/FR:France/Map/France_m%C3%A9tropolitaine",
"has_translation": false
},
{
"title": "FR:France/Map/Guadeloupe",
"key": "France/Map/Guadeloupe",
"url": "https://wiki.openstreetmap.org/wiki/FR:France/Map/Guadeloupe",
"has_translation": false
},
{
"title": "FR:France/Map/Guyane",
"key": "France/Map/Guyane",
"url": "https://wiki.openstreetmap.org/wiki/FR:France/Map/Guyane",
"has_translation": false
},
{
"title": "FR:France/Map/La Réunion",
"key": "France/Map/La Réunion",
"url": "https://wiki.openstreetmap.org/wiki/FR:France/Map/La_R%C3%A9union",
"has_translation": false
},
{
"title": "FR:France/Map/Martinique",
"key": "France/Map/Martinique",
"url": "https://wiki.openstreetmap.org/wiki/FR:France/Map/Martinique",
"has_translation": false
},
{
"title": "FR:France/Map/Mayotte",
"key": "France/Map/Mayotte",
"url": "https://wiki.openstreetmap.org/wiki/FR:France/Map/Mayotte",
"has_translation": false
},
{
"title": "FR:France/Map/Nouvelle-Calédonie",
"key": "France/Map/Nouvelle-Calédonie",
"url": "https://wiki.openstreetmap.org/wiki/FR:France/Map/Nouvelle-Cal%C3%A9donie",
"has_translation": false
},
{
"title": "FR:France/Map/Outre-Mer",
"key": "France/Map/Outre-Mer",
"url": "https://wiki.openstreetmap.org/wiki/FR:France/Map/Outre-Mer",
"has_translation": false
},
{
"title": "FR:France/Map/Polynésie française",
"key": "France/Map/Polynésie française",
"url": "https://wiki.openstreetmap.org/wiki/FR:France/Map/Polyn%C3%A9sie_fran%C3%A7aise",
"has_translation": false
},
{
"title": "FR:France/Map/Saint-Barthélemy",
"key": "France/Map/Saint-Barthélemy",
"url": "https://wiki.openstreetmap.org/wiki/FR:France/Map/Saint-Barth%C3%A9lemy",
"has_translation": false
},
{
"title": "FR:France/Map/Saint-Martin",
"key": "France/Map/Saint-Martin",
"url": "https://wiki.openstreetmap.org/wiki/FR:France/Map/Saint-Martin",
"has_translation": false
},
{
"title": "FR:France/Map/Saint-Pierre-et-Miquelon",
"key": "France/Map/Saint-Pierre-et-Miquelon",
"url": "https://wiki.openstreetmap.org/wiki/FR:France/Map/Saint-Pierre-et-Miquelon",
"has_translation": false
},
{
"title": "FR:France/Map/Terres australes et antarctiques françaises",
"key": "France/Map/Terres australes et antarctiques françaises",
"url": "https://wiki.openstreetmap.org/wiki/FR:France/Map/Terres_australes_et_antarctiques_fran%C3%A7aises",
"has_translation": false
}
]
}

View file

@ -43,7 +43,7 @@ TOP_KEYS_FILE = "top_keys.json"
WIKI_PAGES_CSV = "wiki_pages.csv"
OUTDATED_PAGES_FILE = "outdated_pages.json"
# Number of wiki pages to examine
NUM_WIKI_PAGES = 20
NUM_WIKI_PAGES = 50
def fetch_top_keys(limit=NUM_WIKI_PAGES):
"""
@ -144,10 +144,14 @@ def fetch_wiki_page(key, language='en'):
# Extract section titles
section_titles = []
for section_elem in section_elements:
# Skip sections that are part of the table of contents or navigation
# Skip sections that are part of the table of contents, navigation, or DescriptionBox
if section_elem.parent and section_elem.parent.get('id') in ['toc', 'mw-navigation']:
continue
# Skip sections that are inside a table with class DescriptionBox
if section_elem.find_parent('table', class_='DescriptionBox'):
continue
# Get the text of the section title, removing any edit links
for edit_link in section_elem.select('.mw-editsection'):
edit_link.extract()
@ -167,6 +171,10 @@ def fetch_wiki_page(key, language='en'):
for script in content.select('script, style'):
script.extract()
# Remove .languages elements
for languages_elem in content.select('.languages'):
languages_elem.extract()
# Get text and count words
text = content.get_text(separator=' ', strip=True)
word_count = len(text.split())
@ -214,12 +222,19 @@ def fetch_wiki_page(key, language='en'):
'src': src,
'alt': alt_text
})
# Extract categories
categories = []
category_links = soup.select('#mw-normal-catlinks li a')
for cat_link in category_links:
categories.append(cat_link.get_text(strip=True))
else:
word_count = 0
link_count = 0
link_details = []
media_count = 0
media_details = []
categories = []
return {
'key': key,
@ -232,7 +247,8 @@ def fetch_wiki_page(key, language='en'):
'link_count': link_count,
'link_details': link_details,
'media_count': media_count,
'media_details': media_details
'media_details': media_details,
'categories': categories
}
except requests.exceptions.RequestException as e:
@ -300,7 +316,8 @@ def analyze_wiki_pages(pages):
'priority': missing_staleness_score, # Use staleness score as priority
'section_comparison': None, # No comparison possible
'link_comparison': None, # No comparison possible
'media_comparison': None # No comparison possible
'media_comparison': None, # No comparison possible
'category_comparison': None # No comparison possible
})
continue
@ -430,6 +447,32 @@ def analyze_wiki_pages(pages):
if not media['alt'] or media['alt'].lower() not in fr_media:
media_comparison['fr_only'].append(media)
# Compare categories between English and French pages
category_comparison = {
'en_only': [],
'fr_only': [],
'common': []
}
# Extract categories for comparison (case insensitive)
en_categories = [cat.lower() for cat in en_page.get('categories', [])]
fr_categories = [cat.lower() for cat in fr_page.get('categories', [])]
# Find categories only in English
for cat in en_page.get('categories', []):
if cat.lower() not in fr_categories:
category_comparison['en_only'].append(cat)
# Find categories only in French
for cat in fr_page.get('categories', []):
if cat.lower() not in en_categories:
category_comparison['fr_only'].append(cat)
# Find common categories
for cat in en_page.get('categories', []):
if cat.lower() in fr_categories:
category_comparison['common'].append(cat)
if date_diff > 30 or word_diff > 200 or section_diff > 2 or link_diff > 20 or fr_page['word_count'] < en_page['word_count'] * 0.7:
reason = []
if date_diff > 30:
@ -459,7 +502,8 @@ def analyze_wiki_pages(pages):
'priority': staleness_score, # Use staleness score as priority
'section_comparison': section_comparison,
'link_comparison': link_comparison,
'media_comparison': media_comparison
'media_comparison': media_comparison,
'category_comparison': category_comparison
})
# Sort by priority (descending)

View file

@ -1,40 +1,90 @@
key,language,url,last_modified,sections,word_count,link_count,media_count,staleness_score
building,en,https://wiki.openstreetmap.org/wiki/Key:building,2025-06-10,31,3873,712,158,8.91
building,fr,https://wiki.openstreetmap.org/wiki/FR:Key:building,2025-05-22,25,3280,629,155,8.91
source,en,https://wiki.openstreetmap.org/wiki/Key:source,2025-08-12,27,2851,399,42,113.06
source,fr,https://wiki.openstreetmap.org/wiki/FR:Key:source,2024-02-07,23,2692,315,35,113.06
highway,en,https://wiki.openstreetmap.org/wiki/Key:highway,2025-04-10,30,4225,865,314,20.35
highway,fr,https://wiki.openstreetmap.org/wiki/FR:Key:highway,2025-01-05,30,4240,780,313,20.35
addr:housenumber,en,https://wiki.openstreetmap.org/wiki/Key:addr:housenumber,2025-07-24,11,429,182,20,32.04
addr:housenumber,fr,https://wiki.openstreetmap.org/wiki/FR:Key:addr:housenumber,2025-03-26,15,1754,236,78,32.04
addr:street,en,https://wiki.openstreetmap.org/wiki/Key:addr:street,2024-10-29,12,701,186,16,36.07
addr:street,fr,https://wiki.openstreetmap.org/wiki/FR:Key:addr:street,2025-03-26,15,1754,236,78,36.07
addr:city,en,https://wiki.openstreetmap.org/wiki/Key:addr:city,2025-07-29,15,901,190,17,29.96
addr:city,fr,https://wiki.openstreetmap.org/wiki/FR:Key:addr:city,2025-03-26,15,1754,236,78,29.96
name,en,https://wiki.openstreetmap.org/wiki/Key:name,2025-07-25,17,2295,366,82,42.39
name,fr,https://wiki.openstreetmap.org/wiki/FR:Key:name,2025-01-16,21,1819,272,60,42.39
addr:postcode,en,https://wiki.openstreetmap.org/wiki/Key:addr:postcode,2024-10-29,14,481,168,11,37.14
addr:postcode,fr,https://wiki.openstreetmap.org/wiki/FR:Key:addr:postcode,2025-03-26,15,1754,236,78,37.14
natural,en,https://wiki.openstreetmap.org/wiki/Key:natural,2025-07-17,17,2169,620,189,22.06
natural,fr,https://wiki.openstreetmap.org/wiki/FR:Key:natural,2025-04-21,13,1598,540,174,22.06
surface,en,https://wiki.openstreetmap.org/wiki/Key:surface,2025-06-29,24,3574,676,238,252.64
surface,fr,https://wiki.openstreetmap.org/wiki/FR:Key:surface,2022-02-22,13,2686,546,232,252.64
addr:country,en,https://wiki.openstreetmap.org/wiki/Key:addr:country,2024-12-01,9,283,150,11,22.96
addr:country,fr,https://wiki.openstreetmap.org/wiki/FR:Key:addr:country,2025-03-25,8,286,150,11,22.96
landuse,en,https://wiki.openstreetmap.org/wiki/Key:landuse,2025-03-01,17,2170,531,168,39.41
landuse,fr,https://wiki.openstreetmap.org/wiki/FR:Key:landuse,2024-08-20,19,2152,503,182,39.41
power,en,https://wiki.openstreetmap.org/wiki/Key:power,2025-02-28,20,740,212,21,124.89
power,fr,https://wiki.openstreetmap.org/wiki/FR:Key:power,2023-06-27,14,489,190,25,124.89
waterway,en,https://wiki.openstreetmap.org/wiki/Key:waterway,2025-03-10,21,1929,450,118,77.94
waterway,fr,https://wiki.openstreetmap.org/wiki/FR:Key:waterway,2024-03-08,18,1390,357,113,77.94
building:levels,en,https://wiki.openstreetmap.org/wiki/Key:building:levels,2025-08-13,16,1450,289,25,76.11
building:levels,fr,https://wiki.openstreetmap.org/wiki/FR:Key:building:levels,2024-08-01,15,1556,287,26,76.11
amenity,en,https://wiki.openstreetmap.org/wiki/Key:amenity,2025-03-16,29,3139,999,504,128.43
amenity,fr,https://wiki.openstreetmap.org/wiki/FR:Key:amenity,2023-07-19,22,2245,885,487,128.43
barrier,en,https://wiki.openstreetmap.org/wiki/Key:barrier,2025-04-15,17,2236,528,173,207.98
barrier,fr,https://wiki.openstreetmap.org/wiki/FR:Key:barrier,2022-08-16,15,641,188,18,207.98
source:date,en,https://wiki.openstreetmap.org/wiki/Key:source:date,2023-04-01,11,494,160,10,22.47
source:date,fr,https://wiki.openstreetmap.org/wiki/FR:Key:source:date,2023-07-21,10,518,160,11,22.47
service,en,https://wiki.openstreetmap.org/wiki/Key:service,2025-03-16,22,1535,303,17,83.79
service,fr,https://wiki.openstreetmap.org/wiki/FR:Key:service,2024-03-04,11,542,185,10,83.79
addr:state,en,https://wiki.openstreetmap.org/wiki/Key:addr:state,2023-06-23,12,388,159,11,100
building,en,https://wiki.openstreetmap.org/wiki/Key:building,2025-06-10,31,3774,627,158,8.91
building,fr,https://wiki.openstreetmap.org/wiki/FR:Key:building,2025-05-22,25,3181,544,155,8.91
source,en,https://wiki.openstreetmap.org/wiki/Key:source,2025-08-12,27,2752,314,42,113.06
source,fr,https://wiki.openstreetmap.org/wiki/FR:Key:source,2024-02-07,23,2593,230,35,113.06
highway,en,https://wiki.openstreetmap.org/wiki/Key:highway,2025-04-10,30,4126,780,314,20.35
highway,fr,https://wiki.openstreetmap.org/wiki/FR:Key:highway,2025-01-05,30,4141,695,313,20.35
addr:housenumber,en,https://wiki.openstreetmap.org/wiki/Key:addr:housenumber,2025-07-24,11,330,97,20,32.04
addr:housenumber,fr,https://wiki.openstreetmap.org/wiki/FR:Key:addr:housenumber,2025-03-26,15,1655,151,78,32.04
addr:street,en,https://wiki.openstreetmap.org/wiki/Key:addr:street,2024-10-29,12,602,101,16,36.07
addr:street,fr,https://wiki.openstreetmap.org/wiki/FR:Key:addr:street,2025-03-26,15,1655,151,78,36.07
addr:city,en,https://wiki.openstreetmap.org/wiki/Key:addr:city,2025-07-29,15,802,105,17,29.96
addr:city,fr,https://wiki.openstreetmap.org/wiki/FR:Key:addr:city,2025-03-26,15,1655,151,78,29.96
name,en,https://wiki.openstreetmap.org/wiki/Key:name,2025-07-25,17,2196,281,82,42.39
name,fr,https://wiki.openstreetmap.org/wiki/FR:Key:name,2025-01-16,21,1720,187,60,42.39
addr:postcode,en,https://wiki.openstreetmap.org/wiki/Key:addr:postcode,2024-10-29,14,382,83,11,37.14
addr:postcode,fr,https://wiki.openstreetmap.org/wiki/FR:Key:addr:postcode,2025-03-26,15,1655,151,78,37.14
natural,en,https://wiki.openstreetmap.org/wiki/Key:natural,2025-07-17,17,2070,535,189,22.06
natural,fr,https://wiki.openstreetmap.org/wiki/FR:Key:natural,2025-04-21,13,1499,455,174,22.06
surface,en,https://wiki.openstreetmap.org/wiki/Key:surface,2025-06-29,24,3475,591,238,252.64
surface,fr,https://wiki.openstreetmap.org/wiki/FR:Key:surface,2022-02-22,13,2587,461,232,252.64
addr:country,en,https://wiki.openstreetmap.org/wiki/Key:addr:country,2024-12-01,9,184,65,11,22.96
addr:country,fr,https://wiki.openstreetmap.org/wiki/FR:Key:addr:country,2025-03-25,8,187,65,11,22.96
landuse,en,https://wiki.openstreetmap.org/wiki/Key:landuse,2025-03-01,17,2071,446,168,39.41
landuse,fr,https://wiki.openstreetmap.org/wiki/FR:Key:landuse,2024-08-20,19,2053,418,182,39.41
power,en,https://wiki.openstreetmap.org/wiki/Key:power,2025-02-28,20,641,127,21,124.89
power,fr,https://wiki.openstreetmap.org/wiki/FR:Key:power,2023-06-27,14,390,105,25,124.89
waterway,en,https://wiki.openstreetmap.org/wiki/Key:waterway,2025-03-10,21,1830,365,118,77.94
waterway,fr,https://wiki.openstreetmap.org/wiki/FR:Key:waterway,2024-03-08,18,1291,272,113,77.94
building:levels,en,https://wiki.openstreetmap.org/wiki/Key:building:levels,2025-08-13,16,1351,204,25,76.11
building:levels,fr,https://wiki.openstreetmap.org/wiki/FR:Key:building:levels,2024-08-01,15,1457,202,26,76.11
amenity,en,https://wiki.openstreetmap.org/wiki/Key:amenity,2025-03-16,29,3040,914,504,128.43
amenity,fr,https://wiki.openstreetmap.org/wiki/FR:Key:amenity,2023-07-19,22,2146,800,487,128.43
barrier,en,https://wiki.openstreetmap.org/wiki/Key:barrier,2025-04-15,17,2137,443,173,207.98
barrier,fr,https://wiki.openstreetmap.org/wiki/FR:Key:barrier,2022-08-16,15,542,103,18,207.98
source:date,en,https://wiki.openstreetmap.org/wiki/Key:source:date,2023-04-01,11,395,75,10,22.47
source:date,fr,https://wiki.openstreetmap.org/wiki/FR:Key:source:date,2023-07-21,10,419,75,11,22.47
service,en,https://wiki.openstreetmap.org/wiki/Key:service,2025-03-16,22,1436,218,17,83.79
service,fr,https://wiki.openstreetmap.org/wiki/FR:Key:service,2024-03-04,11,443,100,10,83.79
addr:state,en,https://wiki.openstreetmap.org/wiki/Key:addr:state,2023-06-23,12,289,74,11,100
access,en,https://wiki.openstreetmap.org/wiki/Key:access,2025-08-06,31,5803,708,98,66.73
access,fr,https://wiki.openstreetmap.org/wiki/FR:Key:access,2024-11-27,33,3200,507,84,66.73
oneway,en,https://wiki.openstreetmap.org/wiki/Key:oneway,2025-07-17,28,2318,290,30,19.4
oneway,fr,https://wiki.openstreetmap.org/wiki/FR:Key:oneway,2025-06-16,14,645,108,14,19.4
height,en,https://wiki.openstreetmap.org/wiki/Key:height,2025-07-21,24,1184,184,20,8.45
height,fr,https://wiki.openstreetmap.org/wiki/FR:Key:height,2025-06-14,21,1285,190,21,8.45
ref,en,https://wiki.openstreetmap.org/wiki/Key:ref,2025-07-25,26,4404,782,115,11.79
ref,fr,https://wiki.openstreetmap.org/wiki/FR:Key:ref,2025-07-30,20,3393,460,12,11.79
maxspeed,en,https://wiki.openstreetmap.org/wiki/Key:maxspeed,2025-08-20,30,4275,404,38,39.24
maxspeed,fr,https://wiki.openstreetmap.org/wiki/FR:Key:maxspeed,2025-05-10,25,1401,156,23,39.24
lanes,en,https://wiki.openstreetmap.org/wiki/Key:lanes,2025-08-21,26,2869,355,48,117.16
lanes,fr,https://wiki.openstreetmap.org/wiki/FR:Key:lanes,2024-03-07,19,1492,167,19,117.16
start_date,en,https://wiki.openstreetmap.org/wiki/Key:start_date,2025-08-01,22,1098,168,29,214.58
start_date,fr,https://wiki.openstreetmap.org/wiki/FR:Key:start_date,2022-08-29,19,1097,133,22,214.58
addr:district,en,https://wiki.openstreetmap.org/wiki/Key:addr:district,2023-11-06,11,244,76,11,109.98
addr:district,fr,https://wiki.openstreetmap.org/wiki/FR:Key:addr:district,2025-03-26,15,1655,151,78,109.98
layer,en,https://wiki.openstreetmap.org/wiki/Key:layer,2025-01-02,16,1967,181,17,65.95
layer,fr,https://wiki.openstreetmap.org/wiki/FR:Key:layer,2024-02-16,15,2231,162,17,65.95
type,en,https://wiki.openstreetmap.org/wiki/Key:type,2025-05-13,20,911,200,72,334.06
type,fr,https://wiki.openstreetmap.org/wiki/FR:Key:type,2020-11-13,10,444,78,10,334.06
operator,en,https://wiki.openstreetmap.org/wiki/Key:operator,2025-03-12,24,1891,241,37,189.8
operator,fr,https://wiki.openstreetmap.org/wiki/FR:Key:operator,2022-09-30,15,418,89,11,189.8
lit,en,https://wiki.openstreetmap.org/wiki/Key:lit,2024-07-20,17,931,174,52,38.88
lit,fr,https://wiki.openstreetmap.org/wiki/FR:Key:lit,2025-01-19,17,628,123,14,38.88
wall,en,https://wiki.openstreetmap.org/wiki/Key:wall,2024-05-02,14,682,206,61,100
tiger:cfcc,en,https://wiki.openstreetmap.org/wiki/Key:tiger:cfcc,2022-12-09,10,127,24,7,100
crossing,en,https://wiki.openstreetmap.org/wiki/Key:crossing,2024-02-18,25,2678,363,34,76.98
crossing,fr,https://wiki.openstreetmap.org/wiki/FR:Key:crossing,2025-01-20,15,1390,254,28,76.98
tiger:county,en,https://wiki.openstreetmap.org/wiki/Key:tiger:county,2022-12-09,10,127,24,7,100
source:addr,en,https://wiki.openstreetmap.org/wiki/Key:source:addr,2023-07-05,9,200,70,10,100
footway,en,https://wiki.openstreetmap.org/wiki/Key:footway,2025-08-20,23,2002,369,39,99.66
footway,fr,https://wiki.openstreetmap.org/wiki/FR:Key:footway,2024-06-04,14,685,147,28,99.66
ref:bag,en,https://wiki.openstreetmap.org/wiki/Key:ref:bag,2024-10-09,10,254,69,11,100
addr:place,en,https://wiki.openstreetmap.org/wiki/Key:addr:place,2025-03-28,16,1204,154,13,136.57
addr:place,fr,https://wiki.openstreetmap.org/wiki/FR:Key:addr:place,2023-06-17,11,276,75,12,136.57
tiger:reviewed,en,https://wiki.openstreetmap.org/wiki/Key:tiger:reviewed,2025-08-01,16,734,105,11,100
leisure,en,https://wiki.openstreetmap.org/wiki/Key:leisure,2025-02-28,12,1084,374,180,232.43
leisure,fr,https://wiki.openstreetmap.org/wiki/FR:Key:leisure,2021-12-29,11,951,360,186,232.43
addr:suburb,en,https://wiki.openstreetmap.org/wiki/Key:addr:suburb,2024-02-24,14,439,89,11,1.49
addr:suburb,fr,https://wiki.openstreetmap.org/wiki/FR:Key:addr:suburb,2024-02-18,13,418,87,11,1.49
ele,en,https://wiki.openstreetmap.org/wiki/Key:ele,2025-07-18,18,1846,165,24,104.45
ele,fr,https://wiki.openstreetmap.org/wiki/FR:Key:ele,2024-03-02,15,1277,128,13,104.45
tracktype,en,https://wiki.openstreetmap.org/wiki/Key:tracktype,2024-12-02,16,652,146,35,32.71
tracktype,fr,https://wiki.openstreetmap.org/wiki/FR:Key:tracktype,2025-05-03,11,463,105,29,32.71
addr:neighbourhood,en,https://wiki.openstreetmap.org/wiki/Key:addr:neighbourhood,2025-04-29,24,2020,235,83,100
addr:hamlet,en,https://wiki.openstreetmap.org/wiki/Key:addr:hamlet,2024-12-05,9,142,64,11,100
addr:province,en,https://wiki.openstreetmap.org/wiki/Key:addr:province,2022-05-04,9,156,64,11,100
leaf_type,en,https://wiki.openstreetmap.org/wiki/Key:leaf_type,2025-01-22,15,739,201,57,114.46
leaf_type,fr,https://wiki.openstreetmap.org/wiki/FR:Key:leaf_type,2023-07-02,14,734,220,64,114.46
addr:full,en,https://wiki.openstreetmap.org/wiki/Key:addr:full,2025-04-29,24,2020,235,83,100

1 key language url last_modified sections word_count link_count media_count staleness_score
2 building en https://wiki.openstreetmap.org/wiki/Key:building 2025-06-10 31 3873 3774 712 627 158 8.91
3 building fr https://wiki.openstreetmap.org/wiki/FR:Key:building 2025-05-22 25 3280 3181 629 544 155 8.91
4 source en https://wiki.openstreetmap.org/wiki/Key:source 2025-08-12 27 2851 2752 399 314 42 113.06
5 source fr https://wiki.openstreetmap.org/wiki/FR:Key:source 2024-02-07 23 2692 2593 315 230 35 113.06
6 highway en https://wiki.openstreetmap.org/wiki/Key:highway 2025-04-10 30 4225 4126 865 780 314 20.35
7 highway fr https://wiki.openstreetmap.org/wiki/FR:Key:highway 2025-01-05 30 4240 4141 780 695 313 20.35
8 addr:housenumber en https://wiki.openstreetmap.org/wiki/Key:addr:housenumber 2025-07-24 11 429 330 182 97 20 32.04
9 addr:housenumber fr https://wiki.openstreetmap.org/wiki/FR:Key:addr:housenumber 2025-03-26 15 1754 1655 236 151 78 32.04
10 addr:street en https://wiki.openstreetmap.org/wiki/Key:addr:street 2024-10-29 12 701 602 186 101 16 36.07
11 addr:street fr https://wiki.openstreetmap.org/wiki/FR:Key:addr:street 2025-03-26 15 1754 1655 236 151 78 36.07
12 addr:city en https://wiki.openstreetmap.org/wiki/Key:addr:city 2025-07-29 15 901 802 190 105 17 29.96
13 addr:city fr https://wiki.openstreetmap.org/wiki/FR:Key:addr:city 2025-03-26 15 1754 1655 236 151 78 29.96
14 name en https://wiki.openstreetmap.org/wiki/Key:name 2025-07-25 17 2295 2196 366 281 82 42.39
15 name fr https://wiki.openstreetmap.org/wiki/FR:Key:name 2025-01-16 21 1819 1720 272 187 60 42.39
16 addr:postcode en https://wiki.openstreetmap.org/wiki/Key:addr:postcode 2024-10-29 14 481 382 168 83 11 37.14
17 addr:postcode fr https://wiki.openstreetmap.org/wiki/FR:Key:addr:postcode 2025-03-26 15 1754 1655 236 151 78 37.14
18 natural en https://wiki.openstreetmap.org/wiki/Key:natural 2025-07-17 17 2169 2070 620 535 189 22.06
19 natural fr https://wiki.openstreetmap.org/wiki/FR:Key:natural 2025-04-21 13 1598 1499 540 455 174 22.06
20 surface en https://wiki.openstreetmap.org/wiki/Key:surface 2025-06-29 24 3574 3475 676 591 238 252.64
21 surface fr https://wiki.openstreetmap.org/wiki/FR:Key:surface 2022-02-22 13 2686 2587 546 461 232 252.64
22 addr:country en https://wiki.openstreetmap.org/wiki/Key:addr:country 2024-12-01 9 283 184 150 65 11 22.96
23 addr:country fr https://wiki.openstreetmap.org/wiki/FR:Key:addr:country 2025-03-25 8 286 187 150 65 11 22.96
24 landuse en https://wiki.openstreetmap.org/wiki/Key:landuse 2025-03-01 17 2170 2071 531 446 168 39.41
25 landuse fr https://wiki.openstreetmap.org/wiki/FR:Key:landuse 2024-08-20 19 2152 2053 503 418 182 39.41
26 power en https://wiki.openstreetmap.org/wiki/Key:power 2025-02-28 20 740 641 212 127 21 124.89
27 power fr https://wiki.openstreetmap.org/wiki/FR:Key:power 2023-06-27 14 489 390 190 105 25 124.89
28 waterway en https://wiki.openstreetmap.org/wiki/Key:waterway 2025-03-10 21 1929 1830 450 365 118 77.94
29 waterway fr https://wiki.openstreetmap.org/wiki/FR:Key:waterway 2024-03-08 18 1390 1291 357 272 113 77.94
30 building:levels en https://wiki.openstreetmap.org/wiki/Key:building:levels 2025-08-13 16 1450 1351 289 204 25 76.11
31 building:levels fr https://wiki.openstreetmap.org/wiki/FR:Key:building:levels 2024-08-01 15 1556 1457 287 202 26 76.11
32 amenity en https://wiki.openstreetmap.org/wiki/Key:amenity 2025-03-16 29 3139 3040 999 914 504 128.43
33 amenity fr https://wiki.openstreetmap.org/wiki/FR:Key:amenity 2023-07-19 22 2245 2146 885 800 487 128.43
34 barrier en https://wiki.openstreetmap.org/wiki/Key:barrier 2025-04-15 17 2236 2137 528 443 173 207.98
35 barrier fr https://wiki.openstreetmap.org/wiki/FR:Key:barrier 2022-08-16 15 641 542 188 103 18 207.98
36 source:date en https://wiki.openstreetmap.org/wiki/Key:source:date 2023-04-01 11 494 395 160 75 10 22.47
37 source:date fr https://wiki.openstreetmap.org/wiki/FR:Key:source:date 2023-07-21 10 518 419 160 75 11 22.47
38 service en https://wiki.openstreetmap.org/wiki/Key:service 2025-03-16 22 1535 1436 303 218 17 83.79
39 service fr https://wiki.openstreetmap.org/wiki/FR:Key:service 2024-03-04 11 542 443 185 100 10 83.79
40 addr:state en https://wiki.openstreetmap.org/wiki/Key:addr:state 2023-06-23 12 388 289 159 74 11 100
41 access en https://wiki.openstreetmap.org/wiki/Key:access 2025-08-06 31 5803 708 98 66.73
42 access fr https://wiki.openstreetmap.org/wiki/FR:Key:access 2024-11-27 33 3200 507 84 66.73
43 oneway en https://wiki.openstreetmap.org/wiki/Key:oneway 2025-07-17 28 2318 290 30 19.4
44 oneway fr https://wiki.openstreetmap.org/wiki/FR:Key:oneway 2025-06-16 14 645 108 14 19.4
45 height en https://wiki.openstreetmap.org/wiki/Key:height 2025-07-21 24 1184 184 20 8.45
46 height fr https://wiki.openstreetmap.org/wiki/FR:Key:height 2025-06-14 21 1285 190 21 8.45
47 ref en https://wiki.openstreetmap.org/wiki/Key:ref 2025-07-25 26 4404 782 115 11.79
48 ref fr https://wiki.openstreetmap.org/wiki/FR:Key:ref 2025-07-30 20 3393 460 12 11.79
49 maxspeed en https://wiki.openstreetmap.org/wiki/Key:maxspeed 2025-08-20 30 4275 404 38 39.24
50 maxspeed fr https://wiki.openstreetmap.org/wiki/FR:Key:maxspeed 2025-05-10 25 1401 156 23 39.24
51 lanes en https://wiki.openstreetmap.org/wiki/Key:lanes 2025-08-21 26 2869 355 48 117.16
52 lanes fr https://wiki.openstreetmap.org/wiki/FR:Key:lanes 2024-03-07 19 1492 167 19 117.16
53 start_date en https://wiki.openstreetmap.org/wiki/Key:start_date 2025-08-01 22 1098 168 29 214.58
54 start_date fr https://wiki.openstreetmap.org/wiki/FR:Key:start_date 2022-08-29 19 1097 133 22 214.58
55 addr:district en https://wiki.openstreetmap.org/wiki/Key:addr:district 2023-11-06 11 244 76 11 109.98
56 addr:district fr https://wiki.openstreetmap.org/wiki/FR:Key:addr:district 2025-03-26 15 1655 151 78 109.98
57 layer en https://wiki.openstreetmap.org/wiki/Key:layer 2025-01-02 16 1967 181 17 65.95
58 layer fr https://wiki.openstreetmap.org/wiki/FR:Key:layer 2024-02-16 15 2231 162 17 65.95
59 type en https://wiki.openstreetmap.org/wiki/Key:type 2025-05-13 20 911 200 72 334.06
60 type fr https://wiki.openstreetmap.org/wiki/FR:Key:type 2020-11-13 10 444 78 10 334.06
61 operator en https://wiki.openstreetmap.org/wiki/Key:operator 2025-03-12 24 1891 241 37 189.8
62 operator fr https://wiki.openstreetmap.org/wiki/FR:Key:operator 2022-09-30 15 418 89 11 189.8
63 lit en https://wiki.openstreetmap.org/wiki/Key:lit 2024-07-20 17 931 174 52 38.88
64 lit fr https://wiki.openstreetmap.org/wiki/FR:Key:lit 2025-01-19 17 628 123 14 38.88
65 wall en https://wiki.openstreetmap.org/wiki/Key:wall 2024-05-02 14 682 206 61 100
66 tiger:cfcc en https://wiki.openstreetmap.org/wiki/Key:tiger:cfcc 2022-12-09 10 127 24 7 100
67 crossing en https://wiki.openstreetmap.org/wiki/Key:crossing 2024-02-18 25 2678 363 34 76.98
68 crossing fr https://wiki.openstreetmap.org/wiki/FR:Key:crossing 2025-01-20 15 1390 254 28 76.98
69 tiger:county en https://wiki.openstreetmap.org/wiki/Key:tiger:county 2022-12-09 10 127 24 7 100
70 source:addr en https://wiki.openstreetmap.org/wiki/Key:source:addr 2023-07-05 9 200 70 10 100
71 footway en https://wiki.openstreetmap.org/wiki/Key:footway 2025-08-20 23 2002 369 39 99.66
72 footway fr https://wiki.openstreetmap.org/wiki/FR:Key:footway 2024-06-04 14 685 147 28 99.66
73 ref:bag en https://wiki.openstreetmap.org/wiki/Key:ref:bag 2024-10-09 10 254 69 11 100
74 addr:place en https://wiki.openstreetmap.org/wiki/Key:addr:place 2025-03-28 16 1204 154 13 136.57
75 addr:place fr https://wiki.openstreetmap.org/wiki/FR:Key:addr:place 2023-06-17 11 276 75 12 136.57
76 tiger:reviewed en https://wiki.openstreetmap.org/wiki/Key:tiger:reviewed 2025-08-01 16 734 105 11 100
77 leisure en https://wiki.openstreetmap.org/wiki/Key:leisure 2025-02-28 12 1084 374 180 232.43
78 leisure fr https://wiki.openstreetmap.org/wiki/FR:Key:leisure 2021-12-29 11 951 360 186 232.43
79 addr:suburb en https://wiki.openstreetmap.org/wiki/Key:addr:suburb 2024-02-24 14 439 89 11 1.49
80 addr:suburb fr https://wiki.openstreetmap.org/wiki/FR:Key:addr:suburb 2024-02-18 13 418 87 11 1.49
81 ele en https://wiki.openstreetmap.org/wiki/Key:ele 2025-07-18 18 1846 165 24 104.45
82 ele fr https://wiki.openstreetmap.org/wiki/FR:Key:ele 2024-03-02 15 1277 128 13 104.45
83 tracktype en https://wiki.openstreetmap.org/wiki/Key:tracktype 2024-12-02 16 652 146 35 32.71
84 tracktype fr https://wiki.openstreetmap.org/wiki/FR:Key:tracktype 2025-05-03 11 463 105 29 32.71
85 addr:neighbourhood en https://wiki.openstreetmap.org/wiki/Key:addr:neighbourhood 2025-04-29 24 2020 235 83 100
86 addr:hamlet en https://wiki.openstreetmap.org/wiki/Key:addr:hamlet 2024-12-05 9 142 64 11 100
87 addr:province en https://wiki.openstreetmap.org/wiki/Key:addr:province 2022-05-04 9 156 64 11 100
88 leaf_type en https://wiki.openstreetmap.org/wiki/Key:leaf_type 2025-01-22 15 739 201 57 114.46
89 leaf_type fr https://wiki.openstreetmap.org/wiki/FR:Key:leaf_type 2023-07-02 14 734 220 64 114.46
90 addr:full en https://wiki.openstreetmap.org/wiki/Key:addr:full 2025-04-29 24 2020 235 83 100