<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Pokémon Following Renegade Platinum on Christian Martínez De La Rosa</title><link>https://christt105.github.io/es/categories/pok%C3%A9mon-following-renegade-platinum/</link><description>Recent content in Pokémon Following Renegade Platinum on Christian Martínez De La Rosa</description><generator>Hugo -- gohugo.io</generator><language>es</language><lastBuildDate>Sun, 30 Aug 2026 00:00:00 +0200</lastBuildDate><atom:link href="https://christt105.github.io/es/categories/pok%C3%A9mon-following-renegade-platinum/index.xml" rel="self" type="application/rss+xml"/><item><title>Cómo traduje Pokémon Following Renegade Platinum</title><link>https://christt105.github.io/es/blog/translating-pokemon-following-renegade-platinum/</link><pubDate>Sun, 30 Aug 2026 00:00:00 +0200</pubDate><guid>https://christt105.github.io/es/blog/translating-pokemon-following-renegade-platinum/</guid><enclosure url="https://christt105.github.io/blog/translating-pokemon-following-renegade-platinum/cover.webp" length="61886" type="image/webp"/><description>&lt;p&gt;Vamos a recuperar un proyecto de hace varios años del que estoy bastante orgulloso.&lt;/p&gt;&#10;&lt;h2 id="cómo-empezó-todo"&gt;Cómo empezó todo&#10;&lt;/h2&gt;&lt;p&gt;Me apetecía jugar a la cuarta generación de Pokémon pero quería que fuera algo diferente y con mecánicas de calidad de vida. Investigando me encontré con Pokémon Renegade Platinum, una modificación de Pokémon Platino con más dificultad y muchas más mejoras, hecha por Drayano. También encontré un proyecto de dos españoles, Mikelan98 y AdAstra, llamado Pokémon Following Platinum, una modificación de Pokémon Platino que añadía la mecánica tan característica de Pokémon HeartGold y SoulSilver de que te siguen los Pokémon en el mundo. También añadía alguna mejora como el tipo hada y un poco más. Finalmente, había una persona que había juntado ambos parches y había hecho un parche que incluía los Pokémon que te siguen en el Renegade Platinum. Yo quería eso. Había un problema, estaba en inglés y me daba mucha pereza jugarlo con los ataques en inglés.&lt;/p&gt;&#10;&lt;p&gt;El Pokémon Renegade Platinum lo tradujo Drakyem, hizo un trabajo excelente. Por otro lado, aunque los que hicieron el Pokémon Following Platinum son españoles, lo sacaron únicamente en inglés. Así que me propuse traducir el Following Platinum y luego combinar ambas traducciones en el Pokémon Following Renegade Platinum, sin tener ni idea por dónde empezar.&lt;/p&gt;&#10;&lt;p&gt;Encontré un programa bastante antiguo y escondido que exportaba todos los diálogos de una ROM. Luego los podías editar y volver a introducir en el juego. Flujo completado, podía empezar. Mi idea era simple: extraer los diálogos de una ROM del Pokémon Platino en español e inglés, hacer el match de todos los diálogos, extraer los ficheros del Following Platinum y sobrescribirlos con los del juego original en español, traducir los pocos diálogos que tenía el Following Platinum y finalmente, coger los del Renegade Platinum en castellano, sobrescribirlos en el Following Renegade Platinum y añadir los del Following Platinum. Esto me daría una ROM con las traducciones de Drakyem y la mía. Manos a la obra.&lt;/p&gt;&#10;&lt;h2 id="el-proceso-de-traducción"&gt;El proceso de traducción&#10;&lt;/h2&gt;&lt;p&gt;Esto es a lo que quería llegar, con los diálogos ya en español y el Pokémon siguiéndome por el mapa:&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="Diálogo en español con un Pokémon en el overworld en una cinemática en el laboratorio" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="192" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://christt105.github.io/blog/translating-pokemon-following-renegade-platinum/following-veamos.png" width="256"&gt;&lt;/p&gt;&#10;&lt;p&gt;Antes de nada tocaba montar todas las ROMs que iba a necesitar: Pokémon Platino en inglés y en español, Pokémon Renegade Platinum en inglés y en español (parcheadas con el hack de Drayano) y Pokémon Following Platinum, que solo existía en inglés, así que hice una copia para trabajar sobre ella en español. Todo esto con thenewpoketext, la herramienta que exporta e importa los textos de las ROMs de Pokémon de DS. Fui escribiendo un script de Python para cada paso del proceso, así que voy a explicar qué hacía cada uno.&lt;/p&gt;&#10;&lt;p&gt;Con tantas ROMs y scripts moviéndose a la vez, así es como encajaba todo el proceso:&lt;/p&gt;&#10;&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart TD&#10; A["Platino EN + ES&lt;br/&gt;Renegade EN + ES&lt;br/&gt;Following EN"] --&gt;|export.py| B["XML por&lt;br/&gt;cada ROM"]&#10; B --&gt;|comparer.py| C["Diffs EN↔ES&lt;br/&gt;por parejas"]&#10; C --&gt;|replace.py| D["Following ES&lt;br/&gt;(texto reciclado&lt;br/&gt;de Platino)"]&#10; D --&gt;|"translate_following.py&lt;br/&gt;+ revisión manual"| E["Following ES&lt;br/&gt;(traducido)"]&#10; E --&gt;|"import_following_into_&lt;br/&gt;followingrenegade.py"| F["Following&lt;br/&gt;Renegade ES"]&#10; C --&gt;|"Renegade ES&lt;br/&gt;(Drakyem)"| F&#10; F --&gt;|"thenewpoketext:&lt;br/&gt;patch + mkrom"| G["ROMs jugables&lt;br/&gt;en español"]&lt;/pre&gt;&lt;h3 id="exportar-y-comparar-los-diálogos"&gt;Exportar y comparar los diálogos&#10;&lt;/h3&gt;&lt;p&gt;Lo primero era sacar el texto de dentro de las ROMs. &lt;code&gt;export.py&lt;/code&gt; llamaba a thenewpoketext para volcar los diálogos de cada ROM a un XML, y de paso usaba &lt;code&gt;msg_name_changer.py&lt;/code&gt; para renombrar un par de archivos &lt;code&gt;.narc&lt;/code&gt; de mensajes que en Platino salen mal ordenados si no se tocan a mano. Me costó bastante encontrar esta información en su momento.&lt;/p&gt;&#10;&lt;p&gt;Con todo en XML, entraba &lt;code&gt;comparer.py&lt;/code&gt;. Este script cogía parejas de ROMs (Platino inglés contra Platino español, Renegade inglés contra Renegade español, Following inglés contra Following Renegade inglés, etc.) y, apoyándose en &lt;code&gt;xml_parser.py&lt;/code&gt; para leer cada XML a un diccionario, comparaba diálogo a diálogo por su id. El resultado lo guardaba en dos formatos de JSON: uno con todos los cambios juntos y otro separado en tres bloques, los textos que cambian entre las dos ROMs, los que faltan en la primera y los que faltan en la segunda. Esta comparación es la base de todo el proyecto: me permitía saber exactamente qué diálogo en inglés correspondía a qué diálogo en español, y qué diálogos eran nuevos y no existían en el juego original.&lt;/p&gt;&#10;&lt;p&gt;Así es, más o menos, la parte que hace el reparto en esos tres bloques:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;span class="lnt"&gt;12&#10;&lt;/span&gt;&lt;span class="lnt"&gt;13&#10;&lt;/span&gt;&lt;span class="lnt"&gt;14&#10;&lt;/span&gt;&lt;span class="lnt"&gt;15&#10;&lt;/span&gt;&lt;span class="lnt"&gt;16&#10;&lt;/span&gt;&lt;span class="lnt"&gt;17&#10;&lt;/span&gt;&lt;span class="lnt"&gt;18&#10;&lt;/span&gt;&lt;span class="lnt"&gt;19&#10;&lt;/span&gt;&lt;span class="lnt"&gt;20&#10;&lt;/span&gt;&lt;span class="lnt"&gt;21&#10;&lt;/span&gt;&lt;span class="lnt"&gt;22&#10;&lt;/span&gt;&lt;span class="lnt"&gt;23&#10;&lt;/span&gt;&lt;span class="lnt"&gt;24&#10;&lt;/span&gt;&lt;span class="lnt"&gt;25&#10;&lt;/span&gt;&lt;span class="lnt"&gt;26&#10;&lt;/span&gt;&lt;span class="lnt"&gt;27&#10;&lt;/span&gt;&lt;span class="lnt"&gt;28&#10;&lt;/span&gt;&lt;span class="lnt"&gt;29&#10;&lt;/span&gt;&lt;span class="lnt"&gt;30&#10;&lt;/span&gt;&lt;span class="lnt"&gt;31&#10;&lt;/span&gt;&lt;span class="lnt"&gt;32&#10;&lt;/span&gt;&lt;span class="lnt"&gt;33&#10;&lt;/span&gt;&lt;span class="lnt"&gt;34&#10;&lt;/span&gt;&lt;span class="lnt"&gt;35&#10;&lt;/span&gt;&lt;span class="lnt"&gt;36&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compare_files_split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;files_dict1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;files_dict2&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;changed&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;missing_in_1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;missing_in_2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;file_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;texts_dict1&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;files_dict1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;file_id&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;files_dict2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;text_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text1&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;texts_dict1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;missing_in_2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setdefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{})[&lt;/span&gt;&lt;span class="n"&gt;text_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;text1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;text1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;text2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;texts_dict2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;files_dict2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;file_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;text_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text1&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;texts_dict1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;text_id&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;texts_dict2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;missing_in_2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setdefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{})[&lt;/span&gt;&lt;span class="n"&gt;text_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;text1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;text1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;text2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;text2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;texts_dict2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;text_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;text1&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;text2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;changed&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setdefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{})[&lt;/span&gt;&lt;span class="n"&gt;text_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;text1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;text1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;text2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;text2&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# ... y el mismo bucle a la inversa para rellenar &amp;#34;missing_in_1&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;También hice un par de scripts de apoyo para revisar todo esto a ojo: &lt;code&gt;export_csv.py&lt;/code&gt;, que vuelca todos los XML a una única tabla en csv con una columna por ROM para poder comparar rápido, y &lt;code&gt;check_max_newline.py&lt;/code&gt;, que recorre los diálogos originales para calcular cuántos caracteres caben en una línea del cuadro de texto antes de que el juego meta un salto de línea automático.&lt;/p&gt;&#10;&lt;h3 id="reaprovechar-la-traducción-de-pokémon-platino"&gt;Reaprovechar la traducción de Pokémon Platino&#10;&lt;/h3&gt;&lt;p&gt;Con la comparación hecha, &lt;code&gt;replace.py&lt;/code&gt; cogía los textos en inglés de Following Platinum y Following Renegade Platinum y, allá donde coincidían con un diálogo del Platino o Renegade Platinum original, los sustituía por su equivalente en español. El resultado era una ROM casi completamente en español, salvo los diálogos nuevos que Mikelan98 y AdAstra habían escrito para Following Platinum, que no existían en el juego original y por tanto no tenían ninguna traducción con la que hacer match.&lt;/p&gt;&#10;&lt;h3 id="traducir-lo-nuevo-de-following-platinum"&gt;Traducir lo nuevo de Following Platinum&#10;&lt;/h3&gt;&lt;p&gt;Esos diálogos nuevos estaban prácticamente todos concentrados en un único archivo, el 724. No recuerdo si para entonces ya existía alguna IA como ChatGPT, imagino que sí pero ni de lejos al nivel de ahora, así que todo esto fue bastante artesano. Mi idea desde el principio era escribir los scripts necesarios para traducir las dos ROMs sin tener que hacerlo todo a mano, así que tiré de traducción automática de toda la vida: &lt;code&gt;translate_following.py&lt;/code&gt; recorría ese archivo con la librería &lt;code&gt;deep_translator&lt;/code&gt;, que no es más que un envoltorio en Python de traductores como Google Translate o MyMemory, y generaba un csv con el texto original y su traducción. Antes de mandar cada texto a traducir tenía que sustituir variables como el nombre del jugador o de un Pokémon por texto de relleno, si no el traductor se comía o deformaba esas marcas.&lt;/p&gt;&#10;&lt;p&gt;Así de simple era el csv que salía de ahí, con el id del diálogo dentro del archivo 724, el texto original y la traducción automática (la línea 5 es, de hecho, la misma frase que sale en una de las capturas de más abajo):&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csv" data-lang="csv"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;id;original;translated&lt;/span&gt;&lt;span class="p"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;2;......\nYour Pokémon won’t look you in the eye.;...... Tu Pokémon no te mira a los ojos.&lt;/span&gt;&lt;span class="p"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;5;...Your Pokémon is so very angry!;... ¡Tu Pokémon está muy enfadado!&lt;/span&gt;&lt;span class="p"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;20;Your Pokémon is dancing with you!;¡Tu Pokémon está bailando contigo!&lt;/span&gt;&lt;span class="p"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;Ese csv lo repasé entrada por entrada a mano para pulir la traducción automática, que para diálogos cortos de videojuego se equivocaba bastante. Con &lt;code&gt;import_translation_following.py&lt;/code&gt; volvía a meter ese csv ya revisado dentro del XML, deshaciendo el relleno de las variables, cortando las líneas demasiado largas para que no se salieran del cuadro de texto y traduciendo a mano un puñado de textos que quedaban fuera del archivo 724 y que no merecía la pena automatizar.&lt;/p&gt;&#10;&lt;h3 id="combinar-following-platinum-con-renegade-platinum"&gt;Combinar Following Platinum con Renegade Platinum&#10;&lt;/h3&gt;&lt;p&gt;Con Following Platinum ya traducido, pasé a por Following Renegade Platinum. Aquí no hacía falta traducir nada nuevo: los diálogos de Renegade Platinum ya estaban traducidos por Drakyem, y los de Following Platinum los acababa de traducir yo, solo tenía que combinarlos. &lt;code&gt;import_following_into_followingrenegade.py&lt;/code&gt; cogía la comparación entre Renegade Platinum inglés y Following Platinum inglés para saber exactamente qué diálogos añadía este último, y por cada uno de ellos copiaba su traducción ya hecha desde el XML de Following Platinum español al de Following Renegade Platinum español. El resultado era el XML completo de Following Renegade Platinum en español.&lt;/p&gt;&#10;&lt;h3 id="volver-a-meter-todo-en-la-rom"&gt;Volver a meter todo en la ROM&#10;&lt;/h3&gt;&lt;p&gt;El último paso, para las tres ROMs, era volver a meter el XML traducido dentro del juego con thenewpoketext, parcheando la ROM y reordenando otra vez esos archivos &lt;code&gt;.narc&lt;/code&gt; de mensajes. Con eso ya tenía las ROMs jugables en español. Por el camino fui encontrando algún bug curioso, como el diálogo de Regigigas roto, que también arreglé y dejé documentado en el propio repositorio.&lt;/p&gt;&#10;&lt;p&gt;Quedó alguna cosa sin traducir, como los textos que van metidos dentro de imágenes en vez de en los diálogos, por ejemplo el nombre de los tipos de Pokémon en alguna pantalla, pero son detalles menores que no afectan a jugar el juego en español.&lt;/p&gt;&#10;&lt;p&gt;Mirando los commits, tampoco tardé tanto. El primero es del 19 de febrero de 2023, el parche de Following Platinum lo publiqué el 13 de marzo y el de Following Renegade Platinum llegó apenas tres días después, el 16 de marzo, porque ya tenía toda la traducción hecha y solo hacía falta combinarla. No fueron tres semanas seguidas dándole todos los días, hubo parones de varios días entre commits, pero para lo artesano que era el proceso, se hizo bastante rápido.&lt;/p&gt;&#10;&lt;a class="github-repo-card" href="https://github.com/christt105/PokemonFollowingRenegadePlatinumTranslation" target="_blank" rel="noopener"&gt;&#10; &lt;img src="https://avatars.githubusercontent.com/u/36189169?v=4" alt="christt105 avatar" class="repo-avatar"&gt;&#10; &lt;h3&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brand-github" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"&gt;&#10; &lt;path stroke="none" d="M0 0h24v24H0z" fill="none"/&gt;&#10; &lt;path d="M9 19c-4.3 1.4 -4.3 -2.5 -6 -3m12 5v-3.5c0 -1 .1 -1.4 -.5 -2c2.8 -.3 5.5 -1.4 5.5 -6a4.6 4.6 0 0 0 -1.3 -3.2a4.2 4.2 0 0 0 -.1 -3.2s-1.1 -.3 -3.5 1.3a12.3 12.3 0 0 0 -6.2 0c-2.4 -1.6 -3.5 -1.3 -3.5 -1.3a4.2 4.2 0 0 0 -.1 3.2a4.6 4.6 0 0 0 -1.3 3.2c0 4.6 2.7 5.7 5.5 6c-.6 .6 -.6 1.2 -.5 2v3.5" /&gt;&#10;&lt;/svg&gt;&#10;&#10;&#10; christt105/PokemonFollowingRenegadePlatinumTranslation&lt;/h3&gt;&#10; &lt;p&gt;&lt;/p&gt;&#10; &lt;div class="repo-stats"&gt;&#10; &lt;span&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor" class="icon icon-tabler icons-tabler-filled icon-tabler-star"&gt;&lt;path stroke="none" d="M0 0h24v24H0z" fill="none"/&gt;&lt;path d="M8.243 7.34l-6.38 .925l-.113 .023a1 1 0 0 0 -.44 1.684l4.622 4.499l-1.09 6.355l-.013 .11a1 1 0 0 0 1.464 .944l5.706 -3l5.693 3l.1 .046a1 1 0 0 0 1.352 -1.1l-1.091 -6.355l4.624 -4.5l.078 -.085a1 1 0 0 0 -.633 -1.62l-6.38 -.926l-2.852 -5.78a1 1 0 0 0 -1.794 0l-2.853 5.78z" /&gt;&lt;/svg&gt; 3&lt;/span&gt;&#10; &lt;span&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-git-fork"&gt;&lt;path stroke="none" d="M0 0h24v24H0z" fill="none"/&gt;&lt;path d="M10 18a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" /&gt;&lt;path d="M5 6a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" /&gt;&lt;path d="M15 6a2 2 0 1 0 4 0a2 2 0 1 0 -4 0" /&gt;&lt;path d="M7 8v2a2 2 0 0 0 2 2h6a2 2 0 0 0 2 -2v-2" /&gt;&lt;path d="M12 12l0 4" /&gt;&lt;/svg&gt; 0&lt;/span&gt;&#10; &lt;span&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-calendar-event"&gt;&lt;path stroke="none" d="M0 0h24v24H0z" fill="none"/&gt;&lt;path d="M4 7a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2l0 -12" /&gt;&lt;path d="M16 3l0 4" /&gt;&lt;path d="M8 3l0 4" /&gt;&lt;path d="M4 11l16 0" /&gt;&lt;path d="M8 15h2v2h-2l0 -2" /&gt;&lt;/svg&gt; 2026-05-12&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;h2 id="classic-mode-y-ratio-de-shiny"&gt;Classic Mode y ratio de shiny&#10;&lt;/h2&gt;&lt;p&gt;El repositorio no se quedó parado en 2023. Más adelante añadí variantes del parche de Following Renegade Platinum sin tocar nada del proceso de traducción: unas &amp;ldquo;Classic&amp;rdquo;, que revierten el cambio de tipos que introduce Drayano en Renegade Platinum para quien prefiera los tipos originales de cada Pokémon, y otras que cambian el ratio de aparición de shiny a 1/4096 o 1/512 en vez del 1/8192 de base, combinables entre sí. Sinceramente, el de la modificación del ratio de shiny no lo he sabido testear bien, no tengo una forma fiable de comprobar la probabilidad real sin jugar miles de horas o hacer fuerza bruta con un emulador, así que lo publiqué confiando en el cambio de los valores y sin poder confirmarlo del todo.&lt;/p&gt;&#10;&lt;h2 id="cómo-le-ha-ido"&gt;Cómo le ha ido&#10;&lt;/h2&gt;&lt;p&gt;Más ejemplos del resultado final:&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="Diálogo en español con otro Pokémon siguiendo al protagonista frente a una casa" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="192" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://christt105.github.io/blog/translating-pokemon-following-renegade-platinum/following-enfadado.png" width="256"&gt;&#10;&lt;img alt="Diálogo en español dentro de la casa del protagonista" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="192" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://christt105.github.io/blog/translating-pokemon-following-renegade-platinum/following-laboratorio.png" width="256"&gt;&lt;/p&gt;&#10;&lt;p&gt;Contando solo las descargas de GitHub, sin contar el formulario de Google ni las páginas de terceros donde ha acabado subido, el parche de Following Platinum tiene más de 3700 descargas entre el patch y la ROM ya parcheada, y el de Following Renegade Platinum casi 2900 contando todas sus variantes (normal, Classic Mode y shiny). Más de 6500 descargas entre los dos, para un proyecto que hice pensando únicamente en mí mismo.&lt;/p&gt;&#10;&lt;p&gt;Estoy contento porque lo ha disfrutado mucha gente, incluido yo, mis amigos y mi hermana. Realmente lo ha descargado más gente de lo que reflejan esas cifras, porque ha acabado subido en páginas de terceros, donde en algunos casos no han dado créditos. Lo llegaron a jugar Xamork y Folagor, aunque no dieron créditos ninguno de los dos y publicaron la descarga directa ellos mismos. Yo lo jugué y me lo pasé con un equipo monotype psíquico.&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="Hall of Fame de Pokémon Following Renegade Platinum completado con un equipo monotype psíquico" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="800" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://christt105.github.io/blog/translating-pokemon-following-renegade-platinum/PokemonFollowingRenegadePlatinumMonotypeHallOfFame.png" srcset="https://christt105.github.io/blog/translating-pokemon-following-renegade-platinum/PokemonFollowingRenegadePlatinumMonotypeHallOfFame_hu_164864e17107a9b8.png 800w, https://christt105.github.io/blog/translating-pokemon-following-renegade-platinum/PokemonFollowingRenegadePlatinumMonotypeHallOfFame.png 1067w" width="1067"&gt;&lt;/p&gt;&#10;&lt;p&gt;No puse la descarga directa de la ROM porque me daba algo de miedo y le tengo mucho aprecio a mi cuenta de GitHub. Igualmente se puede descargar el parche desde el repositorio o directamente en &lt;a class="link" href="https://forms.gle/YwseURAufk9wccrJ9" target="_blank" rel="noopener"&#10; &gt;este formulario&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;He disfrutado mucho de hacerlo y de que más gente lo haya disfrutado. Es un grano de arena que he aportado a la comunidad de esta franquicia que tanto me ha marcado de pequeño.&lt;/p&gt;&#10;&lt;p&gt;Mi hermana se lo pasó al 100%, completando una Living dex.&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="Living dex completa de mi hermana, con todos los Pokémon organizados por número de Pokédex" class="gallery-image" data-flex-basis="633px" data-flex-grow="263" height="1524" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://christt105.github.io/blog/translating-pokemon-following-renegade-platinum/livingdex_collage.png" srcset="https://christt105.github.io/blog/translating-pokemon-following-renegade-platinum/livingdex_collage_hu_279ab6461f32449c.png 800w, https://christt105.github.io/blog/translating-pokemon-following-renegade-platinum/livingdex_collage_hu_52c3bef070ebf40c.png 1600w, https://christt105.github.io/blog/translating-pokemon-following-renegade-platinum/livingdex_collage_hu_752860622831a4f9.png 2400w, https://christt105.github.io/blog/translating-pokemon-following-renegade-platinum/livingdex_collage.png 4020w" width="4020"&gt;&#10;&lt;img alt="Tarjeta de entrenador de mi hermana" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="492" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://christt105.github.io/blog/translating-pokemon-following-renegade-platinum/sister-trainer-card.png" width="656"&gt;&#10;&lt;img alt="Diploma por completar la Pokédex Nacional" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="492" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://christt105.github.io/blog/translating-pokemon-following-renegade-platinum/sister-diploma.png" width="656"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;em&gt;En la tarjeta de entrenador pone que empezó la aventura en 2011, pero eso es porque no cambió la fecha de la consola, los que habéis jugado a Animal Crossing lo entenderéis.&lt;/em&gt;&lt;/p&gt;&#10;&lt;p&gt;Y hasta aquí el post de hoy. Estoy muy contento de que haya gente, además de mí, que disfrute de lo que hago. ¡Hasta la próxima!&lt;/p&gt;&#10;</description></item><item><title>Pokémon Following Renegade Platinum Traducción</title><link>https://christt105.github.io/es/projects/pokemonfollowingrenegadeplatinum/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://christt105.github.io/es/projects/pokemonfollowingrenegadeplatinum/</guid><enclosure url="https://christt105.github.io/projects/pokemonfollowingrenegadeplatinum/PokemonFollowingPlatinum.webp" length="45500" type="image/webp"/><description>&lt;p&gt;Este proyecto proporciona parches de traducción para los ROM hacks Pokémon Following Platinum y Pokémon Following Renegade Platinum, haciéndolos totalmente jugables en español.&#10;Se desarrolló usando Python junto con la herramienta thenewpoketext, que permite extraer, editar y reinsertar texto del juego en las ROMs.&lt;/p&gt;&#10;&lt;p&gt;Para Following Platinum, la traducción combina el texto original en español de Pokémon Platinum con contenido nuevo traducido introducido por el hack.&#10;Para Following Renegade Platinum, se basa en la traducción al español de Drakyem de Renegade Platinum, añadiendo todo el contenido adicional de Following Platinum también.&lt;/p&gt;&#10;</description></item></channel></rss>