{"id":6294,"date":"2025-01-24T11:29:56","date_gmt":"2025-01-24T10:29:56","guid":{"rendered":"https:\/\/www.lrob.fr\/?p=6294"},"modified":"2025-01-24T11:29:56","modified_gmt":"2025-01-24T10:29:56","slug":"traduire-un-site-wordpress-entier-en-une-fois-avec-translatepress","status":"publish","type":"post","link":"https:\/\/portail.lrob.fr\/en\/news\/traduire-un-site-wordpress-entier-en-une-fois-avec-translatepress\/","title":{"rendered":"Traduire un site WordPress &#8211; En une fois avec TranslatePress"},"content":{"rendered":"<p class=\"wp-block-paragraph\">Traduire un site WordPress peut \u00eatre un challenge, en particulier lorsque la traduction automatique d&rsquo;une page n\u00e9cessite sa visite au pr\u00e9alable. En tant qu&rsquo;<a href=\"https:\/\/portail.lrob.fr\/en\/hebergement-web\/\">h\u00e9bergeur sp\u00e9cialiste WordPress<\/a> et <a href=\"https:\/\/portail.lrob.fr\/en\/services\/webmastering-wordpress\/\">webmaster sp\u00e9cialiste WordPress<\/a>, j&rsquo;interviens r\u00e9guli\u00e8rement sur des sites multilingues avec traduction automatique. Pour cela, j&rsquo;utilise g\u00e9n\u00e9ralement TranslatePress Developer edition, avec l&rsquo;API DeepL pour op\u00e9rer cette traduction. Le probl\u00e8me ? Tout traduire d&rsquo;un coup n&rsquo;est pas possible nativement. Alors il a fallu trouver une solution. D\u00e9couvrez cette solution et gagnez des heures !<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Probl\u00e8me : La traduction du site complet en une fois n&rsquo;est pas possible.<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Avec TranslatePress, la traduction du contenu de vos pages et articles et surtout de leurs URLs (disponible uniquement en version payante) n&rsquo;intervient qu&rsquo;une fois que quelqu&rsquo;un a visit\u00e9 la page.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Or on voudrait que toutes les URLs soient \u00e0 jour, pour \u00e9viter qu&rsquo;elles ne changent pour Google et g\u00e9n\u00e8rent des redirections 301, voire pire, des erreurs 404.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Sur les petits sites, on peut visiter chaque page et article dans chaque langue.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Pour un site qui a des centaines de pages et articles, tout visiter \u00e0 la main prendrait des heures.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Alors comment faire ?<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Solution : Visiter tout le sitemap automatiquement !<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">La solution est la suivante : Cr\u00e9er un script qui visite toutes les pages de votre site, en s&rsquo;appuyant sur son SiteMap.<\/p>\n\n\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>Votre site n&rsquo;a pas de SiteMap ? Cliquez ici pour plus de d\u00e9tails.<\/summary>\n<p class=\"wp-block-paragraph\">Un SiteMap est une page, g\u00e9n\u00e9ralement au format XML, que vous pouvez transmettre aux moteurs de recherche (typiquement la Google Search Console) pour lui faciliter le r\u00e9f\u00e9rencement de toutes les pages de votre site. Cela est plut\u00f4t indispensable avec les standards actuels.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Si vous n&rsquo;avez pas encore de SiteMap, cela peut s&rsquo;ajouter facilement gr\u00e2ce par exemple au plugin WordPress <a href=\"https:\/\/wordpress.org\/plugins\/seo-by-rank-math\/\" target=\"_blank\" rel=\"noopener\">RankMath SEO<\/a>.<\/p>\n<\/details>\n\n\n\n<p class=\"wp-block-paragraph\">Ensuite vous devez avoir un terminal supportant BASH. Sous Linux et Mac, c&rsquo;est natif. Sous Windows, il est possible que le powershell supporte BASH, mais alternativement, je vous conseillerais plut\u00f4t d&rsquo;installer <a href=\"https:\/\/learn.microsoft.com\/fr-fr\/windows\/wsl\/install\" target=\"_blank\" rel=\"noopener\">WSL<\/a>. Si vous avez acc\u00e8s SSH \u00e0 un serveur Linux, cela fonctionne \u00e9videmment parfaitement.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Le script<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Pour gagner du temps, je me suis aid\u00e9 de ChatGPT pour faire le script suivant. Celui-ci va r\u00e9cursivement visiter toutes les URLs de votre sitemap.xml via curl.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>Vous pouvez appeler ce script par exemple \u00ab\u00a0sitemap_visitor.sh\u00a0\u00bb, le rendre ex\u00e9cutable (chmod +x sitemap_visitor.sh), puis l&rsquo;ex\u00e9cuter avec votre sitemap.<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Les deux arguments \u00e0 indiquer sont :<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>L&rsquo;URL de votre site<\/li>\n\n\n\n<li>La dur\u00e9e d&rsquo;attente entre chaque requ\u00eate (vous pouvez mettre 0 si vous avez confiance en votre serveur, et en votre consommation d&rsquo;API de traduction)<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Par exemple :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.\/sitemap_visitor.sh https:\/\/wwww.votresite.fr\/sitemap_index.xml 1<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Le script :<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#!\/bin\/bash\n\nsitemap_url=\"$1\"\ndelay=\"$2\"\ndeclare -A visited_sitemaps  # Declare an associative array to track visited sitemaps\n\n# Function to visit all URLs in a sitemap\nvisit_sitemap_urls() {\n  local current_sitemap=\"$1\"\n\n  # Check if the sitemap has already been visited\n  if &#91;&#91; ${visited_sitemaps&#91;\"$current_sitemap\"]} ]]; then\n    echo \"Skipping already visited sitemap: $current_sitemap\"\n    return\n  fi\n\n  # Mark the current sitemap as visited\n  visited_sitemaps&#91;\"$current_sitemap\"]=1\n\n  # Fetch the sitemap\n  echo \"Fetching sitemap from: $current_sitemap\"\n  sitemap_content=$(curl -s -L \"$current_sitemap\")  # Added -L to follow redirects\n\n  if &#91;&#91; -z \"$sitemap_content\" ]]; then\n    echo \"Failed to fetch sitemap. Skipping.\"\n    return\n  fi\n\n  # Extract URLs from the sitemap using grep and sed\n  urls=$(echo \"$sitemap_content\" | grep -oP '(?&lt;=&lt;loc&gt;).*?(?=&lt;\/loc&gt;)')\n\n  if &#91;&#91; -z \"$urls\" ]]; then\n    echo \"No URLs found in the sitemap. Skipping.\"\n    return\n  fi\n\n  echo \"Found $(echo \"$urls\" | wc -l) URLs in the sitemap.\"\n\n  # Visit each URL\n  while read -r url; do\n    echo \"Visiting: $url\"\n    response_code=$(curl -o \/dev\/null -s -w \"%{http_code}\" -L \"$url\")  # Added -L here too\n\n    if &#91;&#91; \"$response_code\" == \"200\" ]]; then\n      echo \"Successfully visited: $url\"\n    else\n      echo \"Failed to visit $url: HTTP $response_code\"\n    fi\n\n    # Respectful crawling: wait between requests\n    sleep \"$delay\"\n\n    # Check if the URL is another sitemap\n    if &#91;&#91; \"$url\" == *.xml ]]; then\n      echo \"Found nested sitemap: $url\"\n      visit_sitemap_urls \"$url\"\n    fi\n  done &lt;&lt;&lt; \"$urls\"\n}\n\nvisit_sitemap_urls \"$sitemap_url\"<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Vous avez maintenant traduit votre site WordPress en entier !<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">J&rsquo;esp\u00e8re que vous aurez gagn\u00e9 des heures gr\u00e2ce \u00e0 cette astuce !<\/p>\n\n\n\n<div class=\"wp-block-group is-nowrap is-layout-flex wp-container-core-group-is-layout-3a88641f wp-block-group-is-layout-flex\">\n<p class=\"wp-block-paragraph\">Pour un site d&rsquo;une centaine de pages, et 5 langues additionnelles, cela m&rsquo;a co\u00fbt\u00e9 un peu moins de 20\u20ac d&rsquo;API DeepL (+4.99\u20ac d&rsquo;abonnement). Votre exp\u00e9rience peut varier, alors pensez bien \u00e0 d\u00e9finir des plafonds, que ce soit dans TranslatePress ou DeepL.<\/p>\n\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;6a1c8fe70f0ad&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"6a1c8fe70f0ad\" class=\"wp-block-image size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"829\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on--pointerdown=\"actions.preloadImage\" data-wp-on--pointerenter=\"actions.preloadImageWithDelay\" data-wp-on--pointerleave=\"actions.cancelPreload\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/portail.lrob.fr\/wp-content\/uploads\/2025\/01\/translate-deepl-api-cost-1024x829.png\" alt=\"Co\u00fbt API DeepL\" class=\"wp-image-6295\" srcset=\"https:\/\/portail.lrob.fr\/wp-content\/uploads\/2025\/01\/translate-deepl-api-cost-1024x829.png 1024w, https:\/\/portail.lrob.fr\/wp-content\/uploads\/2025\/01\/translate-deepl-api-cost-300x243.png 300w, https:\/\/portail.lrob.fr\/wp-content\/uploads\/2025\/01\/translate-deepl-api-cost-768x622.png 768w, https:\/\/portail.lrob.fr\/wp-content\/uploads\/2025\/01\/translate-deepl-api-cost-600x486.png 600w, https:\/\/portail.lrob.fr\/wp-content\/uploads\/2025\/01\/translate-deepl-api-cost.png 1468w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\tdata-wp-bind--aria-label=\"state.thisImage.triggerButtonAriaLabel\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.thisImage.buttonRight\"\n\t\t\tdata-wp-style--top=\"state.thisImage.buttonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewbox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><em>PS : Cette solution permet \u00e9galement de mettre en cache l&rsquo;int\u00e9gralit\u00e9 de votre site apr\u00e8s un vidage de celui-ci. \ud83d\ude1c<\/em><\/p>\n\n\n\n<div class=\"wp-block-group is-layout-flex wp-block-group-is-layout-flex\">\n<p class=\"wp-block-paragraph\"><strong>D\u00e9j\u00e0 client LRob et vous souhaitez traduire votre site ?<\/strong><\/p>\n\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/portail.lrob.fr\/en\/product\/gestion-annuelle-translatepress\/\">Obtenir TranslatePress<\/a><\/div>\n<\/div>\n<\/div>\n\n\n\n<hr class=\"wp-block-separator has-text-color has-custom-darker-blue-color has-alpha-channel-opacity has-custom-darker-blue-background-color has-background is-style-default\" style=\"margin-top:var(--wp--preset--spacing--30);margin-bottom:var(--wp--preset--spacing--30)\"\/>\n\n\n\n<p class=\"is-style-text-subtitle is-style-text-subtitle--1 wp-block-paragraph\"><strong>Vous cherchez un <a href=\"https:\/\/portail.lrob.fr\/en\/hebergement-web\/\">h\u00e9bergeur comp\u00e9tent et impliqu\u00e9 dans WordPress<\/a> ?<\/strong><br><strong>Ou un <a href=\"https:\/\/portail.lrob.fr\/en\/services\/webmastering-wordpress\/\">Webmaster<\/a> ?<\/strong><\/p>\n\n\n\n<div class=\"wp-block-group is-layout-flex wp-block-group-is-layout-flex\">\n<p class=\"is-style-text-subtitle is-style-text-subtitle--2 wp-block-paragraph\">Choisissez LRob !<\/p>\n\n\n\n<div class=\"wp-block-buttons is-content-justification-center is-layout-flex wp-container-core-buttons-is-layout-c48d8f91 wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/portail.lrob.fr\/en\/hebergement-web\/\">H\u00e9bergement web WordPress<\/a><\/div>\n\n\n\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/portail.lrob.fr\/en\/services\/webmastering-wordpress\/\">Webmaster sp\u00e9cialiste WordPress<\/a><\/div>\n<\/div>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>","protected":false},"excerpt":{"rendered":"<p>Traduire un site WordPress peut \u00eatre un challenge, en particulier lorsque la traduction automatique d&rsquo;une page n\u00e9cessite sa visite au pr\u00e9alable. En tant qu&rsquo;h\u00e9bergeur sp\u00e9cialiste WordPress et webmaster sp\u00e9cialiste WordPress, j&rsquo;interviens r\u00e9guli\u00e8rement sur des sites multilingues avec traduction automatique. Pour cela, j&rsquo;utilise g\u00e9n\u00e9ralement TranslatePress Developer edition, avec l&rsquo;API DeepL pour op\u00e9rer cette traduction. Le probl\u00e8me [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":6295,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[39],"tags":[],"class_list":["post-6294","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-news"],"_links":{"self":[{"href":"https:\/\/portail.lrob.fr\/en\/wp-json\/wp\/v2\/posts\/6294","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/portail.lrob.fr\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/portail.lrob.fr\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/portail.lrob.fr\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/portail.lrob.fr\/en\/wp-json\/wp\/v2\/comments?post=6294"}],"version-history":[{"count":0,"href":"https:\/\/portail.lrob.fr\/en\/wp-json\/wp\/v2\/posts\/6294\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/portail.lrob.fr\/en\/wp-json\/wp\/v2\/media\/6295"}],"wp:attachment":[{"href":"https:\/\/portail.lrob.fr\/en\/wp-json\/wp\/v2\/media?parent=6294"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/portail.lrob.fr\/en\/wp-json\/wp\/v2\/categories?post=6294"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/portail.lrob.fr\/en\/wp-json\/wp\/v2\/tags?post=6294"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}