<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Anna Aimeri - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Descubre miles de cursos de programación escritos por expertos. Aprende Desarrollo Web, Ciencia de Datos, DevOps, Seguridad y obtén asesoramiento profesional para desarrolladores. ]]>
        </description>
        <link>https://www.freecodecamp.org/espanol/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Anna Aimeri - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/espanol/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Mon, 25 May 2026 15:26:59 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/espanol/news/author/anna/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Variables globales en Python ]]>
                </title>
                <description>
                    <![CDATA[ En Python y en la mayoría de los lenguajes de programación, las variables declaradas fuera de una función se conocen como variables globales. Se puede acceder a estas variables tanto dentro como fuera de una función, ya que tienen un alcance global. Un ejemplo de una variable global: x = ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/variables-globales-en-python/</link>
                <guid isPermaLink="false">653b088ce76d6303de0db36d</guid>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Anna Aimeri ]]>
                </dc:creator>
                <pubDate>Mon, 30 Oct 2023 19:00:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2023/10/kevin-ku-w7ZyuGYNpRQ-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artículo original:</strong> <a href="https://www.freecodecamp.org/news/global-variable-in-python-non-local-python-variables/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">Global Variable in Python – Non-Local Python Variables</a>
      </p><p>En Python y en la mayoría de los lenguajes de programación, las variables declaradas fuera de una función se conocen como variables globales. Se puede acceder a estas variables tanto dentro como fuera de una función, ya que tienen un alcance global.</p><p>Un ejemplo de una variable global:</p><pre><code class="language-python">x = 10 

def mostrarX():
    print("El valor de x es", x)
    
mostrarX()
# El valor de x es 10</code></pre><p>La variable <code>x</code> en el código anterior se declaró fuera de una función: <code>x = 10</code>. Utilizando la función <code>mostrarX()</code>, aún pudimos acceder a <code>x</code> porque se declaró en un alcance global.</p><p>Veamos otro ejemplo que muestra lo que pasa cuando declaramos una variable dentro de una función y tratamos de acceder a ella en otro lugar.</p><pre><code class="language-python">def X():
    x = 10 

X()

def mostrarX():
    print("El valor de x es", x)
    
mostrarX()
NameError: name 'x' is not defined</code></pre><p>En el ejemplo anterior, declaramos <code>x</code> dentro de una función e intentamos acceder a ella en otra función. Esto resultó en un <code>NameError</code> porque <code>x</code> no se definió globalmente.</p><p>Las variables definidas dentro de las funciones se llaman variables locales. Su valor sólo se puede utilizar dentro de la función en la que se declaran.</p><p>Se puede cambiar el alcance de una variable local utilizando la palabra clave 	<code>global</code>, lo cual discutiremos en la próxima sección.</p><h2 id="-para-qu-se-usa-la-palabra-clave-global-en-python"><strong>¿Para qué se usa la palabra clave <code>global</code> en Python?</strong></h2><p>La palabra clave <code>global</code> se utiliza principalmente por dos razones:</p><ol><li>Para modificar el valor de una variable global.</li><li>Para hacer que una variable local sea accesible fuera del alcance local.</li></ol><p>Echemos un vistazo a algunos ejemplos de cada uno de estos escenarios para que puedas comprenderlo mejor.</p><h3 id="ejemplo-1-modificando-una-variable-global-usando-la-palabra-clave-global"><strong>Ejemplo #1 - Modificando una variable global usando la palabra clave <code>global</code> </strong></h3><p>En la última sección en la que declaramos una variable global, no intentamos cambiar el valor de la variable. Todo lo que hicimos fue acceder y mostrar su valor en una función.</p><p>Intentemos cambiar el valor de una variable global y veamos qué pasa:</p><pre><code class="language-python">x = 10 

def mostrarX():
    x = x + 2
    print("El valor de x es", x)
    
mostrarX()
# local variable 'x' referenced before assignment</code></pre><p>Como se puede ver arriba, cuando intentamos sumar 2 al valor de <code>x</code>, obtuvimos un error. Esto se debe a que solo podemos acceder pero no modificar <code>x</code>.</p><p>Para solucionar eso, utilizamos la variable global de esta forma:</p><pre><code class="language-python">x = 10 

def mostrarX():
    global x
    x = x + 2
    print("El valor de x es", x)
    
showX()
# El valor de x es 12</code></pre><p>Al usar la palabra clave <code>global</code>, pudimos modificar el valor de <code>x</code> y sumarle 2.</p><h3 id="ejemplo-2-c-mo-hacer-que-una-variable-local-sea-accesible-fuera-de-su-alcance-local-usando-la-palabra-clave-global"><strong>Ejemplo #2 - Cómo hacer que una variable local sea accesible fuera de su alcance local usando la palabra clave <code>global</code></strong></h3><p>Cuando creamos una variable dentro de una función, no fue posible utilizar su valor en otra función porque el compilador no reconoció la variable.</p><p>Así es cómo podemos solucionarlo utilizando la palabra clave <code>global</code>:</p><pre><code class="language-python">def X():
    global x
    x = 10 
    
X()
    
def mostrarX():
    print("El valor de x es ", x)
    
mostrarX()
# El valor de x es 10</code></pre><p>Para hacer posible que <code>x</code> sea accesible fuera de su alcance local, lo declaramos utilizando la palabra clave <code>global</code>: <code>global x</code>. Después, le asignamos un valor a <code>x</code>. Luego, llamamos a la función que utilizamos para declararla: <code>X()</code>.</p><p>Cuando llamamos a la función <code>mostrarX()</code>, que imprime el valor de <code>x</code> declarado en la función <code>X()</code>, no obtuvimos un error porque <code>x</code> tiene un alcance global.</p><h2 id="resumen"><strong>Resumen</strong></h2><p>En este artículo, hablamos de las variables globales y locales en Python. </p><p>Los ejemplos mostraron cómo declarar tanto variables globales como locales.</p><p> También discutimos la palabra clave <code>global</code>, que te permite modificar el valor de una variable global o hacer que una variable local sea accesible fuera de su alcance.</p><p> ¡Feliz programación!</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Getline en C++ - Ejemplo con función getline() ]]>
                </title>
                <description>
                    <![CDATA[ En este artículo, hablaremos sobre la función getline() en C++. Esta es una función incorporada que acepta entradas de un solo carácter o múltiples caracteres. Cuando trabajamos con la entrada del usuario en C++, el objeto cin nos permite obtener información de entrada del usuario. Pero cuando intentamos registrar la ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/getline-en-c-ejemplo-con-funcion-getline/</link>
                <guid isPermaLink="false">65286dc6be1eb103de68386a</guid>
                
                    <category>
                        <![CDATA[ c++ ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Anna Aimeri ]]>
                </dc:creator>
                <pubDate>Mon, 16 Oct 2023 16:27:59 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2023/10/getline.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artículo original:</strong> <a href="https://www.freecodecamp.org/news/getline-in-cpp-cin-getline-function-example/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">Getline in C++ – cin getline() Function Example</a>
      </p><p>En este artículo, hablaremos sobre la función <code>getline()</code> en C++. Esta es una función incorporada que acepta entradas de un solo carácter o múltiples caracteres.</p><p>Cuando trabajamos con la entrada del usuario en C++, el objeto <code>cin</code> nos permite obtener información de entrada del usuario. Pero cuando intentamos registrar la entrada del usuario que tiene múltiples valores, solo devuelve el primer carácter.</p><p>Esto sucede porque el compilador de C++ asume que cualquier espacio en blanco termina el programa al obtener la entrada. Es decir, "Mi nombre es Ihechikara" solo devolvería "Mi" al registrarse.</p><p>Aquí tienes un mejor ejemplo:</p><pre><code class="language-none">#include &lt;iostream&gt;
using namespace std;

int main() {

    string bio;
    
    // Mensaje impreso en la consola
    cout &lt;&lt; "Contanos sobre vos: ";
    
    /* Esto le pide al usuario que escriba un mensaje y yo escribí esto: 				"JavaScript es mi lenguaje preferido"
    */
    cin &gt;&gt; bio;
    
    /* Cuando quiero imprimir la bio de arriba, sólo se imprime "Javascript"
    */
    cout &lt;&lt; "Tu bio dice: " &lt;&lt; bio;
    // Tu bio dice: Javascript

    
}</code></pre><p>En el código anterior, se le pide al usuario que ingrese su bio. Luego ingresaron "JavaScript es mi lenguaje preferido". Pero cuando la bio se mostró en la consola, solo se registró "JavaScript".</p><p>A continuación, veremos cómo usar la función <code>getline()</code> para obtener el resto de los caracteres en la cadena.</p><h2 id="ejemplo-con-getline-en-c-"><strong>Ejemplo con getline() en C++</strong></h2><p>En esta sección, veremos un ejemplo práctico de cómo usar la función <code>getline()</code>.</p><pre><code class="language-none">#include &lt;iostream&gt;
using namespace std;

int main() {

    string bio;
    
    cout &lt;&lt; "Contanos sobre vos: ";
    
    getline(cin, bio);
    
    cout &lt;&lt; "Tu bio dice: " &lt;&lt; bio;
}</code></pre><p>En el ejemplo anterior, pasamos dos parámetros a la función <code>getline()</code>: <code>getline(cin, bio)</code>;. El primer parámetro es el objeto <code>cin</code> y el segundo es la variable de cadena <code>bio</code>.</p><p>Cuando ejecutas el código, se te pedirá que ingreses algún texto. Después de hacerlo, presiona "Enter" y verás la salida que contiene todo el texto de tu entrada en lugar de solo el primer carácter.</p><p>En mi caso, ingresé una cadena con múltiples caracteres y la obtuve registrada en la consola. Inténtalo para ver cómo funciona.</p><p>Con esto, puedes trabajar de manera efectiva con las entradas de usuario en tus programas.</p><h2 id="conclusi-n"><strong>Conclusión</strong></h2><p>En este artículo, hablamos sobre la función <code>getline()</code>, que nos permite obtener múltiples caracteres de la entrada del usuario.</p><p>Primero vimos lo que sucede cuando obtenemos una cadena con múltiples caracteres de un usuario: solo se devuelve el primer carácter.</p><p>Luego vimos cómo obtener todos los caracteres de la cadena utilizando la función <code>getline()</code>, que toma dos parámetros: el objeto <code>cin</code> y la variable de cadena.</p><p>¡Feliz codificación!</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Double vs Float en C++ – La diferencia entre Floats y Doubles ]]>
                </title>
                <description>
                    <![CDATA[ En C++, existen varios tipos de datos como string, int, char, bool, float y  double. Cada uno de estos tipos de datos tiene valores específicos que se pueden almacenar en ellos. Cuando trabajamos con números enteros, generalmente los almacenamos en un tipo de dato int. Sin embargo, esto solo ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/double-vs-float-en-c-la-diferencia-entre-floats-y-doubles/</link>
                <guid isPermaLink="false">6527e1dfbe1eb103de682ee6</guid>
                
                    <category>
                        <![CDATA[ c++ ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Anna Aimeri ]]>
                </dc:creator>
                <pubDate>Mon, 16 Oct 2023 16:25:59 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2023/10/nick-hillier-yD5rv8_WzxA-unsplash-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artículo original:</strong> <a href="https://www.freecodecamp.org/news/double-vs-float-in-cpp-the-difference-between-floats-and-doubles/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">Double VS Float in C++ – The Difference Between Floats and Doubles</a>
      </p><p>En C++, existen varios tipos de datos como <code>string</code>, <code>int</code>, <code>char</code>, <code>bool</code>, <code>float</code> y <code>double</code>. Cada uno de estos tipos de datos tiene valores específicos que se pueden almacenar en ellos.</p><p>Cuando trabajamos con números enteros, generalmente los almacenamos en un tipo de dato <code>int</code>. Sin embargo, esto solo es útil para números enteros.</p><p>Cuando queremos almacenar números con decimales, podemos usar <code>float</code> o <code>double</code>. Aunque estos dos tipos de datos se utilizan para un propósito similar, tienen algunas diferencias.</p><p>En este artículo, hablaremos sobre las diferencias entre float y double en C++ junto con algunos ejemplos.</p><h2 id="diferencia-entre-floats-y-doubles"><strong>Diferencia entre Floats y Doubles</strong></h2><p>Esta sección se dividirá en secciones más pequeñas, cada una enfocada en una diferencia entre float y double.</p><h3 id="diferencia-en-el-tama-o-en-bytes"><strong>Diferencia en el tamaño en bytes </strong></h3><p>El tamaño en bytes para <code>float</code> es 4, mientras que el tamaño en bytes para <code>double</code> es 8. Esto implica que <code>double</code> puede almacenar valores que son el doble de la cantidad que <code>float</code> puede contener. Podemos comprobar esto usando el operador <code>sizeof()</code>. Aquí tienes un ejemplo:</p><pre><code class="language-none">#include &lt;iostream&gt;
using namespace std;
int main() {
    
    cout &lt;&lt; "float: " &lt;&lt; sizeof(float) &lt;&lt; endl; // float: 4
    cout &lt;&lt; "double: " &lt;&lt; sizeof(double) &lt;&lt; endl;// double: 8

}</code></pre><h3 id="diferencia-en-la-precisi-n-exactitud-"><strong>Diferencia en la precisión (exactitud)</strong></h3><p>Cuando trabajamos con números que tienen muchas cifras decimales, generalmente esperamos que el valor resultante sea preciso. Sin embargo, la precisión de nuestro resultado depende de la cantidad de cifras decimales con las que estamos tratando. No te preocupes, seguimos hablando de C++, no de matemáticas.</p><p><code>float</code> y <code>double</code> tienen capacidades variables cuando se trata de la cantidad de cifras decimales que pueden contener. <code>float</code> puede mantener hasta 7 cifras decimales de manera precisa, mientras que <code>double</code> puede mantener hasta 15.</p><p>Veamos algunos ejemplos para demostrar esto:</p><pre><code class="language-none">#include &lt;iomanip&gt;
#include &lt;iostream&gt;
using namespace std;

int main() {
    double MY_DOUBLE_VALUE = 5.12345678987;

    float MY_FLOAT_VALUE = 5.12345678987;
    
    cout &lt;&lt; setprecision(7);
    cout &lt;&lt; MY_DOUBLE_VALUE &lt;&lt; endl; // 5.123457
    cout &lt;&lt; MY_FLOAT_VALUE &lt;&lt; endl; // 5.123457
}</code></pre><p>En el ejemplo anterior, creamos variables <code>float</code> y <code>double</code>, ambas con el mismo valor: <code>5.12345678987</code>. La función <code>setprecision()</code> se utiliza para indicar al compilador la cantidad de decimales que deseamos que se impriman. En nuestro caso, el valor es 7.</p><p>Podemos observar en los resultados del código anterior que ambas variables imprimieron valores precisos hasta el séptimo lugar decimal: <code>5.123457</code>.</p><p>Ahora aumentemos el parámetro en la función <code>setprecision()</code> a 12 y veamos qué pasa:</p><pre><code class="language-none">#include &lt;iomanip&gt;
#include &lt;iostream&gt;
using namespace std;

int main() {
    double MY_DOUBLE_VALUE = 5.12345678987;

    float MY_FLOAT_VALUE = 5.12345678987;
    
    cout &lt;&lt; setprecision(12);
    cout &lt;&lt; MY_DOUBLE_VALUE &lt;&lt; endl; // 5.12345678987
    cout &lt;&lt; MY_FLOAT_VALUE &lt;&lt; endl; // 5.12345695496
}</code></pre><p>De los resultados anteriores, podemos ver que la variable <code>MY_DOUBLE_VALUE</code> imprimió valores precisos. Sin embargo, la variable <code>MY_FLOAT_VALUE</code>, a partir del séptimo lugar decimal, imprimió valores completamente diferentes al valor original que se le dio. Esto nos muestra la diferencia en la precisión de ambos tipos de datos. Al igual que <code>float</code>, si intentamos devolver un valor que excede el rango de precisión del tipo de dato <code>double</code>, obtendremos un valor inexacto.</p><h3 id="diferencia-en-el-uso"><strong>Diferencia en el uso</strong></h3><p><br><code>float</code> se utiliza principalmente en bibliotecas gráficas para aplicaciones que requieren un alto poder de procesamiento debido a su rango limitado. <br><code>double</code> se utiliza principalmente en cálculos de programación para eliminar errores cuando se redondean valores decimales. Aunque <code>float</code> todavía se puede utilizar, solo debe hacerse en casos en los que se estén manejando valores decimales pequeños. Para estar seguro, siempre se debe utilizar <code>double</code>.</p><p>Esta información destaca la importancia de elegir el tipo de dato adecuado según las necesidades de precisión y rango de tus cálculos en C++.</p><h3 id="conclusi-n"><strong>Conclusión</strong></h3><p>En este artículo, hemos hablado de las diferencias entre <code>float</code> y <code>double</code> en C++. Hemos destacado tres diferencias clave: tamaño en bytes, precisión y casos de uso.</p><p>Hemos aprendido que los <code>doubles</code> tienen el doble del tamaño en bytes de los <code>floats</code> y son más precisos al trabajar con valores decimales grandes. Además, hemos explorado los casos de uso que nos ayudan a comprender cuándo utilizar cada tipo de dato.</p><p>¡Feliz codificación!</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Cómo descargar y recortar archivos MP3s de YouTube con Python ]]>
                </title>
                <description>
                    <![CDATA[ Todos somos diferentes, pero creo que casi todos disfrutamos de escuchar música.  Si deseas mantener una versión local de los archivos de audio que escuchas con frecuencia, vas a necesitar descargarlos. A veces, también querrás recortar una parte de este archivo de audio en lugar de tener solo la ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/descargar-y-recortar-mp3s-con-python/</link>
                <guid isPermaLink="false">65275105be1eb103de682d32</guid>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Anna Aimeri ]]>
                </dc:creator>
                <pubDate>Mon, 16 Oct 2023 16:19:38 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2023/10/pexels-pixabay-164821.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artículo original:</strong> <a href="https://www.freecodecamp.org/news/download-trim-mp3-from-youtube-with-python/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to Download and Trim MP3s from YouTube with Python</a>
      </p><p>Todos somos diferentes, pero creo que casi todos disfrutamos de escuchar música.</p><p> Si deseas mantener una versión local de los archivos de audio que escuchas con frecuencia, vas a necesitar descargarlos. A veces, también querrás recortar una parte de este archivo de audio en lugar de tener solo la versión completa disponible. </p><p>Puedes desarrollar un script en Python para hacer exactamente estas cosas. También puedes ampliarlo con funcionalidades adicionales si lo deseas. Y te mostraré cómo hacerlo en este tutorial.</p><h2 id="una-nota-sobre-los-derechos-de-autor"><strong>Una nota sobre los derechos de autor</strong></h2><p>Si has utilizado Internet antes, es probable que seas consciente de que los problemas de derechos de autor pueden provocar mucha controversia, tanto en aquellos que defienden la gratuidad del contenido como en los que no. </p><p><a href="https://www.xataka.com/servicios/github-cierra-repositorio-youtube-dl-software-utilizado-multitud-apps-paginas-descarga-videos">La propia biblioteca que utilizaremos ha tenido sus propios problemas de derechos de autor. </a></p><p>Afortunadamente, tenemos material libre de derechos de autor disponible para que lo disfrutemos y utilicemos en nuestros programas. En este tutorial, usaremos el <a href="https://www.youtube.com/watch?v=8OAPLk20epo">cuarto movimiento de la Novena Sinfonía de Beethoven</a>, que es libre de <em>copyright</em>. Esta guía asume que usarás los siguientes métodos para descargar material libre de derechos de autor. ¡No uses esta información para infringir ningún derecho de autor!</p><h2 id="lo-que-vamos-a-hacer-en-este-tutorial"><strong>Lo que vamos a hacer en este tutorial</strong></h2><p>Primero, vamos a instalar la dependencia básica, FFMPEG. Luego, instalaremos la biblioteca <code>youtube-dl</code> (que también funciona con Vimeo y muchas otras plataformas) para descargar audio desde una URL de YouTube y utilizarlo en el código de Python. </p><p>A continuación, vamos a descargar la librería <code>pydub</code> para recortar archivos de audio e implementaremos esta funcionalidad en nuestro código. </p><p>Por último, vamos a crear una interfaz de usuario amigable para que podamos reutilizar este script más adelante sin necesidad de editar el código. </p><p>Todo esto se va a ejecutar dentro de una función principal <code>main()</code> para que podamos separar la funcionalidad, la implementación y el uso.</p><h2 id="c-mo-instalar-el-paquete-ffmpeg"><strong>Cómo instalar el paquete FFMPEG</strong></h2><p>Este paquete es fundamental en muchos programas multimedia (y en todos los de código abierto que he usado hasta ahora). Lo necesitaremos para ambas bibliotecas de Python que instalaremos muy pronto.</p><h3 id="c-mo-instalar-en-linux"><strong>Cómo instalar en Linux</strong></h3><p>Si te encuentras en una máquina que usa Debian de base (como Ubuntu o Kali), este es el comando para instalar FFMPEG:</p><pre><code>sudo apt-get install ffmpeg</code></pre><p>Si estás usando otra distribución, las instrucciones están <a href="https://ffmpeg.org/download.html">acá</a>.</p><h3 id="c-mo-instalar-en-windows"><strong>Cómo instalar en Windows</strong></h3><p>Primero, hay que instalar el gestor de paquetes <a href="https://chocolatey.org/how-chocolatey-works">Chocolatey</a>. Las instrucciones están <a href="https://chocolatey.org/install">acá</a>, te espero. </p><p>Después de instalarlo correctamente, descarga el paquete desde una <strong>instancia de Powershell con permisos de administrador</strong>.</p><pre><code class="language-powershell">choco install ffmpeg
</code></pre><h3 id="c-mo-instalar-en-mac"><strong>Cómo instalar en Mac</strong></h3><p>Si todavía no lo tienes, <a href="https://brew.sh/">instala homebrew</a>. Luego, en la terminal:</p><pre><code>brew install ffmpeg</code></pre><h2 id="c-mo-descargar-audio-de-urls-de-youtube"><strong>Cómo descargar audio de URLs de YouTube</strong></h2><p>Primero, descarga el paquete <code>youtube-dl</code> de <code>pip</code>. Es <a href="https://github.com/ytdl-org/youtube-dl">uno de los más guardados en GitHub</a>.</p><p><code>pip install youtube-dl</code></p><p>Vamos a importar este módulo y luego declarar una función que va a descargar el audio en formato mp3 con una calidad razonable desde una URL de YouTube.</p><pre><code class="language-python">import youtube_dl # cliente para muchos portales de multimedia

# descarga yt_url al mismo directorio desde donde corre el script
def download_audio(yt_url):
    ydl_opts = {
        'format': 'bestaudio/best',
        'postprocessors': [{
            'key': 'FFmpegExtractAudio',
            'preferredcodec': 'mp3',
            'preferredquality': '192',
        }],
    }
    with youtube_dl.YoutubeDL(ydl_opts) as ydl:
        ydl.download([yt_url])

def main():
    yt_url = "https://www.youtube.com/watch?v=8OAPLk20epo"
    download_audio(yt_url)

main()
</code></pre><p>El método <code>.download()</code> va a descargar gradualmente el flujo de audio como un archivo .webm. Una vez que detecta que el archivo completo está disponible, utilizará <code>ffmpeg</code> para convertirlo en un archivo de audio MP3. Esto significa que si ocurre algo, como que la conexión a Internet se interrumpa cuando el archivo esté al 90% descargado, la descarga se reanudará en el 90% en lugar de comenzar desde el principio, lo cual es bastante útil. Ten en cuenta que si ya tienes el archivo mp3 descargado, la descarga se reiniciará y sobrescribirá el archivo.</p><p>Ejecuta tu script de Python. La descarga de audio de esta interpretación del Cuarto Movimiento de la Novena Sinfonía de Beethoven debería generar un archivo MP3 de aproximadamente 33 MB con el título del video disponible localmente. Es posible que la descarga sea un poco lenta, así que aprovecha para hacerte una taza de té.</p><p>Como puedes ver, es posible pasar parámetros opcionales a <code>youtube-dl</code> (que también estarán disponibles como un programa independiente de línea de comandos fuera del script). Una de sus capacidades es <a href="https://github.com/ytdl-org/youtube-dl#video-selection">descargar una serie de videos desde una URL de lista de reproducción</a>. Si estás más interesado, puedes consultar su documentación. Mantendré el uso más sencillo a lo largo de este tutorial.</p><h2 id="c-mo-recortar-el-archivo-descargado"><strong>Cómo recortar el archivo descargado</strong></h2><p>Con el archivo descargado, ahora vamos a dividirlo localmente de forma arbitraria (puede que hayas considerado si es posible simplemente descargar un fragmento de YouTube. Todos los métodos fiables que encontré básicamente se reducirán a descargarlo completo y luego editarlo localmente). Para esto, utilizaremos la biblioteca <a href="https://github.com/jiaaro/pydub">pydub</a>. Puedes instalarla de la siguiente manera:</p><pre><code class="language-python">pip install pydub</code></pre><p>Esta es una biblioteca bastante útil que te permite manipular por completo el audio, reducir o aumentar el volumen en ciertos intervalos, repetir clips, y más. Por ahora, solo estamos interesados en recortar.</p><p>Para recortar nuestro archivo descargado, tendremos que obtener el nombre de archivo de nuestro MP3 recién descargado, convertir los puntos de inicio y final de nuestro intervalo de audio deseado de 'horas:minutos:segundos' a milisegundos, y finalmente utilizar <code>pydub</code> para dividir nuestro archivo de audio.</p><h3 id="c-mo-obtener-el-nombre-del-archivo"><strong>Cómo obtener el nombre del archivo</strong></h3><p>Lamentablemente, el método <code>.download()</code> no nos va a devolver el nombre de archivo generado, al cual tampoco tendremos acceso, ya que solo estamos pasando la URL como parámetro. Pero tenemos Python, y es una herramienta fantástica.</p><p>Sabemos que estamos buscando un archivo .mp3 que se generó justo antes de nuestra operación de búsqueda de nombre de archivo (Python es monohilo y va a ejecutar el código de forma síncrona por defecto). Obtendremos el nombre de nuestro archivo más reciente en el directorio del script, y eso será nuestro archivo.</p><p>Podemos realizar esta operación listando todos los archivos .mp3 en el directorio local, recopilando sus marcas de tiempo como números enteros (lo que significa el tiempo en milisegundos contados desde una fecha en el pasado determinada; esto significa que cuanto mayor sea el valor, más en el tiempo se creó el archivo) y obteniendo el archivo con el valor más alto.</p><p>Para esto, necesitaremos los módulos <code>glob</code> para navegar por el directorio y <code>os</code> para obtener información de la marca de tiempo, ambos disponibles de forma nativa.</p><pre><code class="language-python">import glob
import os

def newest_mp3_filename():
	# lista todos los mp3s en el directorio local
    list_of_mp3s = glob.glob('./*.mp3')
    # devuelve aquel con mayor valor de timestamp (último creado)
    return max(list_of_mp3s, key = os.path.getctime)
</code></pre><h3 id="c-mo-obtener-hh-mm-ss-en-milisegundos"><strong>Cómo obtener HH:MM:SS en milisegundos</strong></h3><p>Una vez que cortemos nuestro archivo, <code>pydub</code> esperará intervalos de tiempo expresados en milisegundos. Pero para nosotros, los humanos, calcular el momento exacto en milisegundos cada vez que queramos recortar un video sería bastante molesto, así que le pediremos respetuosamente a la computadora que lo haga por nosotros.</p><p>Nuestra entrada será una cadena en el formato <strong>HH:MM:SS</strong>. Esto funciona bien si queremos recortar un video de más de una hora, pero la mayor parte del tiempo solo querremos obtener el intervalo de un minuto:segundo a otro. Así que también vamos a tener esto en cuenta.</p><p>Un milisegundo es 1/1000 de segundo, un minuto tiene 60 segundos y una hora tiene 60 minutos. Entonces, debemos obtener el valor para las horas, luego para los minutos, luego para los segundos, realizar la conversión a milisegundos en cada uno y luego sumar las partes para obtener el resultado.</p><pre><code class="language-python">def get_video_time_in_ms(video_timestamp):
    vt_split = video_timestamp.split(":")
    if (len(vt_split) == 3): # condicional en formato HH:MM:SS
        hours = int(vt_split[0]) * 60 * 60 * 1000
        minutes = int(vt_split[1]) * 60 * 1000
        seconds = int(vt_split[2]) * 1000
    else: # formato MM:SS
        hours = 0
        minutes = int(vt_split[0]) * 60 * 1000
        seconds = int(vt_split[1]) * 1000
    # marca de tiempo en milisegundos
    return hours + minutes + seconds
</code></pre><h3 id="c-mo-obtener-el-audio-recortado"><strong>Cómo obtener el audio recortado</strong></h3><p>Ahora leeremos nuestro archivo MP3 como un objeto de <code>pydub</code> y cortaremos el intervalo deseado. La sintaxis es exactamente la misma que las operaciones de corte en cadenas y arreglos, pero en lugar de un índice para un elemento, usaremos milisegundos para momentos específicos dentro del audio.</p><pre><code class="language-python">def get_trimmed(mp3_filename, initial, final = ""):
    if (not mp3_filename):
    	# levanta una excepción para detener el programa
        raise Exception("No se encontró ningún MP3 en el directorio local.")
    # lee el mp3 como un objeto de Pydub
    sound = AudioSegment.from_mp3(mp3_filename)
    t0 = get_video_time_in_ms(initial)
    print("Comenzando proceso de recorte para el archivo ", mp3_filename, ".\n")
    print("Iniciando en ", initial, "...")
    if (len(final) &gt; 0):
        print("...hasta ", final, ".\n")
        t1 = get_video_time_in_ms(final)
        return sound[t0:t1] # t0 hasta t1
    return sound[t0:] # t0 hasta el final
</code></pre><h2 id="c-mo-unirlo-todo"><strong>Cómo unirlo todo</strong></h2><blockquote>Alle Menschen werden Brüder,<br>Wo dein sanfter Flügel weilt.<br>-- Friedrich Schiller</blockquote><p>En caso de que te lo estuvieras preguntando, el fragmento anterior se traduce como "Todos los hombres se convertirán en hermanos, dondequiera que tus suaves alas revuelen". Es un fragmento de "<em>Oda a la alegría</em>", un poema de Friedrich Schiller que forma la mayor parte de la letra de las partes corales del Cuarto Movimiento.</p><p>Este es el fragmento más famoso del movimiento más famoso de la sinfonía más famosa de Beethoven. Sea quien seas, cuando y cómo hayas crecido, es muy probable que reconozcas esta pieza.</p><p>Ahora vamos a poner todo lo que hemos hecho juntos. Descargaremos el audio de YouTube, cortaremos el coro de la "<em>Oda a la Alegría</em>" (desde el minuto 9:51 hasta el minuto 14:04) y lo guardaremos como <code>&lt;nombre&gt; - TRIM.mp3</code>.</p><p>Si has seguido el tutorial correctamente, actualiza tu función <code>main()</code> para ejecutar cada paso de manera que al final tengas el MP3 completo y su versión recortada como archivos disponibles en el directorio desde el que ejecutes el script. No olvides ejecutar la función <code>main()</code> al final del script.</p><pre><code class="language-python">def main():
    yt_url = "https://www.youtube.com/watch?v=8OAPLk20epo"
    download_audio(yt_url)
    initial = "9:51"
    final = "14:04"
    filename = newest_mp3_filename()
    trimmed_file = get_trimmed(filename, initial, final)
    trimmed_filename = "".join([filename.split(".mp3")[0], "- TRIM.mp3"])
    print("El proceso finalizó con éxito. Guardando archivo recortado como ", trimmed_filename)
    # guarda archivo con nuevo nombre
    trimmed_file.export(trimmed_filename, format="mp3")
</code></pre><h2 id="c-mo-agregar-interacci-n-desde-la-l-nea-de-comandos"><strong>Cómo agregar interacción desde la línea de comandos</strong></h2><p>Para esta parte, necesitaremos el módulo <code>sys</code> de Python, que lee la entrada pasada desde la línea de comandos, entre otras cosas. Simplemente actualizaremos las variables en la función <code>main()</code> para leer la entrada desde la línea de comandos en lugar de los datos actualmente codificados en el script.</p><p><code>ARGV</code> lee la entrada secuencialmente como un array, comenzando desde el índice 1 (el 0 representa el nombre del script de Python en ejecución). Lo configuraremos para que lea una URL como el primer argumento y, opcionalmente, instantes de inicio y finalización para el recorte.</p><pre><code class="language-python">import sys

def main():
    if (not len(sys.argv) &gt; 1):
        print("Por favor inserta una URL soportada por youtube-dl como tu primer argumento.")
        return
    yt_url = sys.argv[1]
    download_audio(yt_url)
    if (not len(sys.argv &gt; 2)): # terminar si no hay argumentos
        return
    initial = sys.argv[2]
    final = ""
    if (sys.argv[3]):
        final = sys.argv[3]
    filename = newest_mp3_filename()
    trimmed_file = get_trimmed(filename, initial, final)
    trimmed_filename = "".join([filename.split(".mp3")[0], "- TRIM.mp3"])
    print("El proceso finalizó con éxito. Guardando archivo como ", trimmed_filename)
    # guarda archivo con nuevo nombre
    trimmed_file.export(trimmed_filename, format="mp3")
</code></pre><p>Ejecuta el archivo para probarlo. Recuerda actualizar el nombre del script con el mismo nombre que tienes en tu máquina.</p><pre><code class="language-bash">python ytauddown.py https://www.youtube.com/watch?v=8OAPLk20epo 9:51 14:04
</code></pre><h2 id="script-final"><strong>Script final</strong></h2><p>Esta es la versión final con todo integrado. Ten en cuenta que los comentarios sobre los módulos están relacionados solo con para qué los estamos utilizando y que la función <code>main()</code> se está invocando en la última línea.</p><pre><code class="language-python">import youtube_dl # cliente para muchos portales de multimedia
import glob # operaciones de directorio
import os # interfaz para información provista por el sistema operativo
import sys # interfaz para línea de comandos
from pydub import AudioSegment # sólo operaciones de audio

def newest_mp3_filename():
    # lista todos los mp3 en el directorio local
    list_of_mp3s = glob.glob('./*.mp3')
    # devuelve último mp3 creado
    return max(list_of_mp3s, key = os.path.getctime)

def get_video_time_in_ms(video_timestamp):
    vt_split = video_timestamp.split(":")
    if (len(vt_split) == 3): # condicional en formato HH:MM:SS 
        hours = int(vt_split[0]) * 60 * 60 * 1000
        minutes = int(vt_split[1]) * 60 * 1000
        seconds = int(vt_split[2]) * 1000
    else: # formato MM:SS 
        hours = 0
        minutes = int(vt_split[0]) * 60 * 1000
        seconds = int(vt_split[1]) * 1000
    # marca de tiempo en milisegundos
    return hours + minutes + seconds

def get_trimmed(mp3_filename, initial, final = ""):
    if (not mp3_filename):
        # levanta una excepción para interrumpir programa
        raise Exception("No MP3 found in local directory.")
    # lee mp3 como objeto de Pydub
    sound = AudioSegment.from_mp3(mp3_filename)
    t0 = get_video_time_in_ms(initial)
    print("Comenzando proceso de recorte para ", mp3_filename, ".\n")
    print("Comenzando desde ", initial, "...")
    if (len(final) &gt; 0):
        print("...hasta ", final, ".\n")
        t1 = get_video_time_in_ms(final)
        return sound[t0:t1] # t0 hasta t1
    return sound[t0:] # t0 hasta el final



# descarga yt_url al mismo directorio donde corre el script
def download_audio(yt_url):
    ydl_opts = {
        'format': 'bestaudio/best',
        'postprocessors': [{
            'key': 'FFmpegExtractAudio',
            'preferredcodec': 'mp3',
            'preferredquality': '192',
        }],
    }
    with youtube_dl.YoutubeDL(ydl_opts) as ydl:
        ydl.download([yt_url])

def main():
    if (not len(sys.argv) &gt; 1):
        print("Por favor inserta una URL soportada por youtube-dl como tu primer argumento.")
        return
    yt_url = sys.argv[1]
    download_audio(yt_url)
    if (not len(sys.argv &gt; 2)): # terminar si no hay argumentos
        return
    initial = sys.argv[2]
    final = ""
    if (sys.argv[3]):
        final = sys.argv[3]
    filename = newest_mp3_filename()
    trimmed_file = get_trimmed(filename, initial, final)
    trimmed_filename = "".join([filename.split(".mp3")[0], "- TRIM.mp3"])
    print("El proceso finalizó con éxito. Descargando archivo como ", trimmed_filename)
    # descarga archivo con nuevo nombre
    trimmed_file.export(trimmed_filename, format="mp3")

# ejemplo
# python ytauddown.py https://www.youtube.com/watch?v=8OAPLk20epo 9:51 14:04
main()
</code></pre><h2 id="ejercicios-sugeridos">Ejercicios sugeridos</h2><ol><li>Detectar si la primera entrada es una URL válida o no. Consulta las expresiones regulares en Python si no sabes por dónde empezar.</li><li>Detectar si las segundas y terceras entradas tienen un formato válido (horas:minutos:segundos O minutos:segundos).</li><li>Agregar una opción para cambiar el nombre del archivo MP3 directamente desde la línea de comandos. Recuerda que los argumentos de ARGV se ejecutan en orden.</li><li>Refactorizar este script para interactuar con su funcionalidad utilizando una interfaz gráfica de usuario (GUI). Puede ser una aplicación web o local, tu elección.</li></ol><h2 id="consideraciones-finales"><strong>Consideraciones finales</strong></h2><p>Espero que disfrutes de este proyecto y le des un buen uso. </p><p>Recuerda que ganarse la vida como artista puede ser bastante difícil, especialmente para la mayoría que no cuenta con el respaldo de una empresa. No olvides apoyar a los artistas cuyo trabajo disfrutas siempre que puedas y también recuerda apoyar el software de código abierto.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Harvard CS50 – Curso gratis de Ciencias de la Computación ]]>
                </title>
                <description>
                    <![CDATA[ El curso CS50 de la Universidad de Harvard es uno de los cursos de Ciencias de la Computación para principiantes más populares en el mundo. Acabamos de lanzar el curso completo de cs50 -las 25 horas- en el canal de YouTube de freeCodeCamp.org. David J. Malan, quien enseña este curso, ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/harvard-cs50-curso-gratis/</link>
                <guid isPermaLink="false">65274e32be1eb103de682d17</guid>
                
                    <category>
                        <![CDATA[ informatica ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Anna Aimeri ]]>
                </dc:creator>
                <pubDate>Mon, 16 Oct 2023 16:14:04 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2023/10/cs502.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artículo original:</strong> <a href="https://www.freecodecamp.org/news/harvard-cs50/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">Harvard CS50 – Free Computer Science University Course</a>
      </p><p>El curso CS50 de la Universidad de Harvard es uno de los cursos de Ciencias de la Computación para principiantes más populares en el mundo.</p><p>Acabamos de lanzar el curso completo de cs50 -las 25 horas- en el canal de YouTube de freeCodeCamp.org.</p><p>David J. Malan, quien enseña este curso, es considerado uno de los mejores instructores de ciencias de la computación.</p><p>Este curso ofrece una introducción a las disciplinas intelectuales de la informática y el arte de la programación. En este curso, se enseña a los estudiantes a pensar de manera algorítmica y a resolver problemas de manera eficiente.</p><p>El programa incluye temas como abstracción, algoritmos, estructuras de datos, encapsulación, gestión de recursos, seguridad, ingeniería del software y programación web. Los lenguajes incluyen C, Python y SQL, además de HTML, CSS y JavaScript.</p><p>Entre los objetivos generales de este curso se encuentran inspirar a los estudiantes a explorar territorios desconocidos sin temor al fracaso, crear una experiencia intensiva y compartida, accesible para todos los estudiantes, y fomentar una comunidad entre los estudiantes.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2022/10/image-122.png" class="kg-image" alt="image-122" width="600" height="400" loading="lazy"><figcaption>David J. Malan enseñando CS50.</figcaption></figure><p>Estas son las clases incluidas en el curso:</p><ul><li>Clase 0 - Scratch</li><li>Clase 1 - C</li><li>Clase 2 - Arreglos</li><li>Clase 3 - Algoritmos</li><li>Clase 4 - Memoria</li><li>Clase 5 - Estructuras de datos</li><li>Clase 6 - Python</li><li>Clase 7 - SQL</li><li>Clase 8 - HTML, CSS, JavaScript</li><li>Clase 9 - Flask</li><li>Clase 10 - Emoji</li><li>Ciberseguridad</li></ul><p>Mira el curso completo en <a href="https://www.youtube.com/watch?v=8mAITcNt710">el canal de YouTube de freeCodeCamp.org</a> &nbsp;(25 horas de duración).</p><figure class="kg-card kg-embed-card" data-test-label="fitted">
        <div class="fluid-width-video-container">
          <div style="padding-top: 56.17977528089888%;" class="fluid-width-video-wrapper">
            <iframe width="356" height="200" src="https://www.youtube.com/embed/8mAITcNt710?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" title="Harvard CS50 – Full Computer Science University Course" name="fitvid0" style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-optical-sizing: inherit; font-kerning: inherit; font-feature-settings: inherit; font-variation-settings: inherit; font-size: 22px; vertical-align: middle; position: absolute; top: 0px; left: 0px; width: 720px; height: 404.492px;"></iframe>
          </div>
        </div>
      </figure> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Operador Ternario en C ]]>
                </title>
                <description>
                    <![CDATA[ Los programadores usan el operador ternario para tomar decisiones en lugar de sentencias condicionales if y else más largas. El operador ternario toma tres argumentos:  1. Un argumento de comparación  2. El resultado si esa comparación devuelve true  3. El resultado si esa comparación devuelve false Es ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/operador-ternario-en-c/</link>
                <guid isPermaLink="false">6302763849da500911a0ee62</guid>
                
                    <category>
                        <![CDATA[ Programación ]]>
                    </category>
                
                    <category>
                        <![CDATA[ c ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Anna Aimeri ]]>
                </dc:creator>
                <pubDate>Thu, 22 Sep 2022 17:33:19 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2022/08/5f9c9db2740569d1a4ca3922.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artículo original:</strong> <a href="https://www.freecodecamp.org/news/c-ternary-operator/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">Ternary Operator in C Explained</a>
      </p><p>Los programadores usan el <strong>operador ternario</strong> para tomar decisiones en lugar de sentencias condicionales <strong>if </strong>y <strong>else </strong>más largas.</p><p>El operador ternario toma tres argumentos:</p><ol><li>Un argumento de comparación</li><li>El resultado si esa comparación devuelve true</li><li>El resultado si esa comparación devuelve false</li></ol><p>Es de ayuda pensar en el operador ternario como una forma corta de escribir una sentencia if-else. A continuación un ejemplo simple de toma de decisiones usando <strong>if </strong>y <strong>else</strong>:</p><pre><code class="language-c">int a = 10, b = 20, c;

if (a &lt; b) {
    c = a;
}
else {
    c = b;
}

printf("%d", c);</code></pre><p>Este ejemplo tiene más de 10 líneas, pero eso no es necesario. El programa puede escribirse en 3 líneas de código usando un operador ternario.</p><h3 id="sintaxis"><strong><strong><strong>S</strong>intaxis</strong></strong></h3><p><code>condición ? valor_true : valor_false</code></p><p>Esta sentencia se evalúa a <code>valor_true</code> si se cumple la <code>condición</code>, y a <code>valor_false</code> en caso contrario.</p><p>Este es el ejemplo de arriba usando el operador ternario:</p><pre><code class="language-c">int a = 10, b = 20, c;

c = (a &lt; b) ? a : b;

printf("%d", c);</code></pre><p>El output del ejemplo de arriba es:</p><pre><code class="language-c">10</code></pre><p><code>c</code> toma el valor de <code>a</code>, porque se cumplió la condición <code>a &lt; b</code>.</p><p>Recordemos que los argumentos de <code>valor_true</code> y <code>valor_false</code> deben tener el mismo tipo, y deben ser expresiones simples en lugar de sentencias completas.</p><p>Los operadores ternarios pueden anidarse al igual que las sentencias if-else. Consideremos el siguiente código:</p><pre><code class="language-c">int a = 1, b = 2, ans;
if (a == 1) {
    if (b == 2) {
        ans = 3;
    } else {
        ans = 5;
    }
} else {
    ans = 0;
}
printf ("%d\n", ans);</code></pre><p>Este es el código de arriba escrito con operadores ternarios anidados:</p><pre><code class="language-c">int a = 1, b = 2, ans;
ans = (a == 1 ? (b == 2 ? 3 : 5) : 0);
printf ("%d\n", ans);</code></pre><p>El output de ambos programas debería ser:</p><pre><code class="language-c">3</code></pre> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Cómo escribir letras con tildes en Mac ]]>
                </title>
                <description>
                    <![CDATA[ Si estás escribiendo en un idioma distinto del inglés, seguramente necesites saber cómo incluir tildes. Como voilà, olé, o über. Afortunadamente, hay varias maneras simples de hacer esto en una Mac. En este artículo, vamos a ver los métodos principales para que puedas añadir tildes a tus textos con facilidad. ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/como-escribir-letras-con-tildes-en-mac/</link>
                <guid isPermaLink="false">62efe56bb4def50851977701</guid>
                
                    <category>
                        <![CDATA[ escritura ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Anna Aimeri ]]>
                </dc:creator>
                <pubDate>Sat, 20 Aug 2022 01:21:06 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2022/08/5fac64b849c47664ed81e086.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artículo original:</strong> <a href="https://www.freecodecamp.org/news/how-to-type-letters-with-accents-on-mac/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to Type Letters with Accents on Mac</a>
      </p><p>Si estás escribiendo en un idioma distinto del inglés, seguramente necesites saber cómo incluir tildes. Como voilà, olé, o über.</p><p>Afortunadamente, hay varias maneras simples de hacer esto en una Mac. En este artículo, vamos a ver los métodos principales para que puedas añadir tildes a tus textos con facilidad.</p><h2 id="m-todo-de-mantener-presionado-en-mac"><strong>Método de mantener presionado en Mac</strong></h2><p>Si no estás apurado y quieres ver todas las opciones de tildes a la vez, hay una manera fácil de hacer eso.</p><p>Simplemente, mantiene presionada la tecla sobre la que quieres la tilde, y las opciones aparecerán arriba de la letra, así:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2020/11/Press-and-hold-accent-method.png" class="kg-image" alt="Press-and-hold-accent-method" width="600" height="400" loading="lazy"><figcaption>Método de mantener presionado</figcaption></figure><p>Cuando veas la tilde que quieras agregar, simplemente teclea el número y la tilde se añadirá a la letra. También puedes usar las teclas de flechas a izquierda o derecha (y enter) para seleccionar el que quieras.</p><p>Entonces, por ejemplo, si quisieras la segunda opción, mantienes presionada e, y luego presionas 2 (o presionas la tecla de flecha a derecha una vez y luego enter).</p><p>Este método funciona bien si no te importa el tiempo que demora ese menú de tildes en aparecer. Pero no siempre incluye todas las tildes de cada idioma. Y demora tu escritura, especialmente si estás escribiendo un artículo completo en un idioma diferente. ¡Eso es mucho tiempo!</p><p>Afortunadamente, hay más métodos que involucran atajos de teclado. Y te dan todas las opciones, también.</p><h2 id="m-todo-de-tilde-con-tecla-option-en-mac"><strong>Método de tilde con tecla <code>Option</code> en Mac</strong></h2><p>La tecla <code>option</code> te ayuda a agregar todos los acentos y signos diacríticos a tu texto. Simplemente, mantén presionada la tecla <code>option</code> (la misma que la tecla <code>Alt</code>), y luego la tecla "e", después suéltalas y presiona la tecla de la letra a la que le quieres añadir el acento.</p><p>Por ejemplo, si quisieras agregar un acento agudo (´) a las letras a, e, i, o, u, presionarías <code>option</code> + e, y luego la letra a la que le quieres añadir el acento. Entonces, <code>option</code>+e+a te devuelve á.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2020/11/quincy-accent-tweet.png" class="kg-image" alt="quincy-accent-tweet" width="600" height="400" loading="lazy"><figcaption>Conocimientos de acentos del fundador de freeCodeCamp</figcaption></figure><p>¿Y si quieres otro tipo de acento, como uno grave o una diéresis? No te preocupes, – hay combinaciones con la tecla <code>option</code> para esos, también (y más).</p><ul><li><code>Option</code> + ` + letra = acento grave à, è, ì, ò, o ù (así: Voilà)</li><li><code>Option</code> + i + letra = acento circunflejo â, ê, î, ô, o û (así: Crêpe)</li><li><code>Option</code> + n + letra = letra eñe ñ, ã, o õ (así: El Niño)</li><li><code>Option</code> + u + letra = diéresis ä, ë, ï, ö, o ü (así: Über)</li><li><code>Option</code> + a o <code>Shift</code> + <code>Option</code> + A (para A mayúscula) = å o Å</li><li><code>Optio</code>n + ' o <code>Shift</code> + <code>Option</code> + ' = æ o Æ (ae ligada)</li><li><code>Option</code> + q o <code>Shift</code> + <code>Option</code> + Q (para letras mayúsculas) = œ o Œ</li><li><code>Option</code> + c o <code>Shift</code> + <code>Option</code> + C (para mayúscula) = ç o Ç</li><li><code>Option</code> + o o <code>Shift</code> + <code>Option</code> + O (para mayúscula) = ø o Ø</li><li><code>Shift</code> + <code>Option</code> + ? = ¿</li><li><code>Option</code> + 1 = ¡</li><li><code>Option</code> + 5 = ∞</li></ul><p>Una vez que memorices estas combinaciones, puedes incorporarlas en tu día a día. Y siempre puedes guardar este artículo en marcadores por si se te olvidan :).</p><h2 id="bonus-otras-combinaciones-con-tecla-option-en-mac"><strong>Bonus: otras combinaciones con tecla <code>Option</code> en Mac</strong></h2><p>¿Y si quieres escribir símbolos matemáticos? ¿O el símbolo del Euro? Necesitarás más opciones.</p><p>Bueno, ¿Sabías que tu teclado esconde todos estos caracteres especiales (casi) a plena vista?</p><p>Presionando la tecla <code>Option</code> y cualquiera de las letras/números/símbolos de puntuación, puedes crear un carácter totalmente diferente del que está impreso en tu teclado.</p><p>¿Cómo saber lo que cada combinación de teclas te devuelve? No te preocupes – tu Mac puede decírtelo. Necesitas solo un par de pasos para encontrar esa información.</p><h3 id="paso-1-ir-a-preferencias-del-sistema"><strong>Paso 1: ir a Preferencias del Sistema</strong></h3><p>Encuentra el ícono de Apple en la esquina superior izquierda y haz clic en él. Luego selecciona "Preferencias del sistema" del menú de opciones.</p><p>Selecciona el ícono del teclado, y verás esta pestaña:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2020/11/keyboard-customization.png" class="kg-image" alt="keyboard-customization" width="600" height="400" loading="lazy"><figcaption>Cómo customizar tu teclado.</figcaption></figure><p>Asegúrate de que la casilla "Mostrar los visores de teclado y caracteres en la barra de menús" esté seleccionada (como lo está en la imagen de arriba). </p><h3 id="paso-2-presiona-el-cono-de-teclado-en-tu-barra-de-men-de-arriba"><strong>Paso 2: Presiona el ícono de teclado en tu barra de menú de arriba</strong></h3><p>Ahora verás un pequeño ícono de teclado en tu barra de menú superior, al lado de tus íconos de bluetooth y wifi. Presiónala, y selecciona "Mostrar visor de teclado".</p><p>Eso te mostrará una imagen de tu teclado como está configurado en tu Mac:</p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2020/11/keyboard-viewer.png" class="kg-image" alt="keyboard-viewer" width="600" height="400" loading="lazy"><figcaption>La configuración básica de tu teclado.</figcaption></figure><h3 id="paso-3-presiona-la-tecla-option"><strong>Paso 3: Presiona la tecla <code>Option</code></strong></h3><p>Ahora, si mantienes presionada la tecla <code>Option</code>, te mostrará todo lo que esas teclas pueden hacer, así:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2020/11/Options-keyboard.png" class="kg-image" alt="Options-keyboard" width="600" height="400" loading="lazy"><figcaption>Tantas opciones...</figcaption></figure><p>Puedes ver los símbolos más usados resaltados en naranja arriba. Esas son las teclas que, combinadas con la tecla <code>Option</code>, te devuelven esos acentos (como aprendimos arriba).</p><p>También verás todo tipo de símbolos útiles, como símbolos de divisas, símbolos matemáticos, y muchos más. Entonces, si alguna vez necesitas un recordatorio rápido de qué teclas presionar cuando necesites escribir la letra griega µ (miu), por ejemplo, usa esta imagen como referencia.</p><h2 id="c-mo-a-adir-tildes-en-windows-con-el-teclado-internacional"><strong>Cómo añadir tildes en Windows con el teclado internacional</strong></h2><p>Si quieres usar atajos de teclado para incluir acentos y caracteres especiales sin cambiar totalmente de teclado, puedes habilitar el teclado internacional.</p><p>Primero, presiona la tecla Windows, en la pestaña "Idiomas" y luego "Preferencias de Idioma" para abrir el menú de idiomas:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2020/11/image-152.png" class="kg-image" alt="image-152" width="600" height="400" loading="lazy"><figcaption>El menú de idiomas de Windows 10.</figcaption></figure><p>Luego, debajo de "Idiomas de preferencia", selecciona "English" y "Opciones" para abrir el menú de opciones de idioma:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2020/11/image-150.png" class="kg-image" alt="The Windows 10 English Language Options menu." width="600" height="400" loading="lazy"><figcaption>El menú de opciones de Idioma de Windows 10.</figcaption></figure><p>Debajo de "Teclados", selecciona "Añadir un teclado" y presiona "United States-International" para añadir el teclado internacional a tu sistema.</p><p>Para habilitar el teclado internacional, mueve tu ratón hasta la barra de tareas y selecciona "ENG US", luego "ENG INTL":</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2020/11/image-153.png" class="kg-image" alt="Use the keyboard select menu in the taskbar to enable the international keyboard." width="600" height="400" loading="lazy"><figcaption>Usa el menú de selección de teclado en la barra de tareas para habilitar el teclado internacional.</figcaption></figure><p>Alternativamente, presiona la tecla Windows y la barra espaciadora para revisar tus teclados instalados.</p><p>La principal diferencia entre el teclado normal de Estados Unidos y el internacional es que algunas teclas funcionan como un "lock de caracteres acentuados".</p><p>Por ejemplo, para escribir un apóstrofe (') con el teclado internacional habilitado, simplemente escribe ' + barra espaciadora. Para comillas dobles, simplemente " + barra espaciadora. Y comillas simples de igual manera con ` + barra espaciadora.</p><p>Habiendo dicho eso, aquí tienes cómo escribir tildes comunes con el teclado internacional de Windows 10:</p><ul><li>` + letra = acento grave à, è, ì, ò, o ù (así: Voilà)</li><li>^ + letra = acento circunflejo â, ê, î, ô, o û (así: Crêpe)</li><li>~ + letra = letra eñe ñ, ã, o õ (así: El Niño)</li><li>" + letra = diéresis ä, ë, ï, ö, o ü (así: Über)</li><li>Alt derecho + w o Shift + Alt derecho + W (para A mayúscula) = å o Å</li><li>Alt derecho + z o Shift + Alt derecho + Z = æ o Æ (ae ligada)</li><li>Alt derecho + &lt; o Shift + Alt derecho + &lt; (para mayúscula) = ç o Ç</li><li>Alt derecho + l o Shift + Alt derecho + L (para mayúscula) = ø o Ø</li><li>Alt derecho + ? = ¿</li><li>Alt derecho + 1 = ¡</li></ul><p>Pero puede que hayas notado que no hay atajo para œ, Œ, o ∞ con el teclado internacional.</p><p>Para eso, veamos otra manera de escribir acentos, caracteres especiales y símbolos en Windows 10.</p><h2 id="c-mo-a-adir-acentos-en-windows-con-el-panel-de-emojis"><strong>Cómo añadir acentos en Windows con el panel de Emojis</strong></h2><p>El panel de emojis hace que sea fácil navegar por todos los emojis disponibles y agregar uno a un mensaje. Pero también puedes usarlo para añadir rápidamente un acento o caracter especial, también.</p><p>Usa la tecla Windows + . para abrir el panel de emojis:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2020/11/image-154.png" class="kg-image" alt="The Windows 10 emoji panel." width="600" height="400" loading="lazy"><figcaption>Panel de emojis de Windows 10.</figcaption></figure><p>Para agregar acentos o caracteres especiales, presiona el botón de símbolos arriba:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2020/11/image-156.png" class="kg-image" alt="The Windows 10 emoji panel's Symbol options." width="600" height="400" loading="lazy"><figcaption>Opciones de símbolos del panel de emojis de Windows 10.</figcaption></figure><p>Luego navega por el menú y selecciona el acento/carácter que quieres:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2020/11/image-157.png" class="kg-image" alt="Selecting the œ character in the Windows 10 emoji picker." width="600" height="400" loading="lazy"><figcaption>Seleccionando el caracter œ en el menú de Windows 10.</figcaption></figure><p>Y puedes también seleccionar los distintos menús debajo para diferentes tipos de símbolos. Por ejemplo, ∞ está en la sección de símbolos matemáticos:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2020/11/image-158.png" class="kg-image" alt="Selecting the ∞ character in the Windows 10 emoji picker." width="600" height="400" loading="lazy"><figcaption>Seleccionando el caracter ∞ en el menú de Windows 10.</figcaption></figure><p>Y eso debería ser todo lo que necesitas para escribir acentos y caracteres especiales en Mac y Windows. ¡Adiós!</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Cómo deshacer cambios en Git ]]>
                </title>
                <description>
                    <![CDATA[ Puede que ya sepas que Git es un sistema de control de versiones. Lo que generalmente aprendes con Git es a guardar los cambios y confirmarlos a un repositorio remoto. Pero, ¿Cómo deshaces un cambio y vuelves a un estado anterior? Eso es lo que vamos a cubrir en este ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/como-deshacer-cambios-en-git/</link>
                <guid isPermaLink="false">62ebdb0cb4def5085197727e</guid>
                
                <dc:creator>
                    <![CDATA[ Anna Aimeri ]]>
                </dc:creator>
                <pubDate>Sun, 07 Aug 2022 02:11:04 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2022/08/0_6JjR02sGP4FgM6zj.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artículo original:</strong> <a href="https://www.freecodecamp.org/news/how-to-undo-changes-in-git-e1da7930afdb/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to undo changes in Git</a>
      </p><p>Puede que ya sepas que Git es un sistema de control de versiones. Lo que generalmente aprendes con Git es a guardar los cambios y confirmarlos a un repositorio remoto. Pero, ¿Cómo deshaces un cambio y vuelves a un estado anterior?</p><p>Eso es lo que vamos a cubrir en este artículo.</p><h3 id="local-vs-remoto"><strong>Local vs. remoto</strong></h3><p>Es más complicado deshacer algo que ya está en el repositorio remoto. Es por esto que quieres mantener las cosas en tu local hasta que estén dentro de todo confirmadas.</p><h3 id="cuatro-situaciones-comunes"><strong>Cuatro situaciones comunes</strong></h3><p>Vamos a cubrir las siguientes situaciones comunes:</p><ol><li>Descartar cambios locales</li><li>Corregir las confirmaciones anteriores</li><li>Regresar a la confirmación anterior</li><li>Revertir una confirmación que se ha enviado al repositorio remoto.</li></ol><p>Nota: En las capturas de pantalla de abajo, usé el cliente de Git <a href="https://git-fork.com/" rel="noopener">Fork para Mac OS</a>. Puedes hacer lo mismo en otros clientes de Git similares.</p><h2 id="situaci-n-1-descartando-cambios-locales">Situación 1: Descartando cambios locales</h2><p>La primera situación es cuando generaste algunos cambios. Aún no fueron confirmados, y quieres eliminarlos.</p><p>Digamos que queremos crear una nueva función. Vamos a agregar un poco de HTML y CSS al proyecto:</p><pre><code class="language-html">&lt;!--In index.html--&gt;
&lt;div class="feature"&gt;&lt;/div&gt;
```

```css
/* In CSS file */
.feature {
  font-size: 2em; 
  /* Other styles */
}</code></pre><p>Para descartar estos cambios:</p><ol><li>Ve a staging area</li><li>Seleccionar los archivos donde quieres descartar cambios</li><li>Has clic derecho en los archivos</li><li>Selecciona descartar cambios</li></ol><figure class="kg-card kg-image-card"><img src="https://cdn-media-1.freecodecamp.org/images/0*6JjR02sGP4FgM6zj.png" class="kg-image" alt="0*6JjR02sGP4FgM6zj" width="800" height="779" loading="lazy"></figure><h4 id="situaci-n-2-corrigiendo-la-confirmaci-n-anterior"><strong>Situación 2: Corrigiendo la confirmación anterior</strong></h4><p>Cuando has creado una confirmación y te olvidaste algunos cambios, y quieres agregarlos en el mensaje de la confirmación anterior.</p><ol><li>Ve a staging area</li><li>Agrega los archivos para confirmar</li><li>Has clic en casilla para corregir</li><li>Edita tu mensaje de confirmación</li><li>Confirma</li></ol><figure class="kg-card kg-image-card"><img src="https://cdn-media-1.freecodecamp.org/images/0*1wkCc2i9X8JWsBz4.png" class="kg-image" alt="0*1wkCc2i9X8JWsBz4" width="800" height="252" loading="lazy"></figure><h4 id="situaci-n-3-regresando-a-una-confirmaci-n-anterior"><strong>Situación 3: Regresando a una confirmación anterior</strong></h4><p>Ya tienes algunas confirmaciones en tu repositorio local. Decides entonces que ya no quieres estas conformaciones y que quieres "cargar" tus archivos desde un estado previo.</p><ol><li>Ve a historial de Git</li><li>Has clic derecho a la confirmación al que quieres regresar</li><li>Selecciona reset <code>branch</code> aquí</li></ol><figure class="kg-card kg-image-card"><img src="https://cdn-media-1.freecodecamp.org/images/0*IwWQ9XZNRmCaVvb8.png" class="kg-image" alt="0*IwWQ9XZNRmCaVvb8" width="800" height="326" loading="lazy"></figure><blockquote>Nota: Sólo puedes volver a una confirmación que no haya sido cargada al repositorio remoto.</blockquote><h4 id="situaci-n-4-revirtiendo-una-confirmaci-n-que-ya-fue-cargada-a-un-repositorio-remoto"><strong>Situación 4: Revirtiendo una confirmación que ya fue cargada a un repositorio remoto</strong></h4><p>Si tienes una confirmación que ya cargaste al repositorio remoto, necesitas revertirlo.</p><blockquote>Revertir significa deshacer los cambios creando una nueva confirmación. Si agregaste una línea, esta confirmación va a eliminarla. Si eliminaste una línea, esta confirmación va a añadirla de nuevo.</blockquote><p>Para revertir:</p><ol><li>Ve a historial de Git</li><li>Has clic derecho en la confirmación que quieres revertir</li><li>Selecciona revertir confirmación</li><li>Asegurarte de que la casilla <code>commit the changes</code> esté seleccionada</li><li>Has clic revertir</li></ol><figure class="kg-card kg-image-card"><img src="https://cdn-media-1.freecodecamp.org/images/0*29rgArX4rXn3aH6x.png" class="kg-image" alt="0*29rgArX4rXn3aH6x" width="800" height="364" loading="lazy"></figure><figure class="kg-card kg-image-card"><img src="https://cdn-media-1.freecodecamp.org/images/0*fUD5rUESrzaMnbXu.png" class="kg-image" alt="0*fUD5rUESrzaMnbXu" width="800" height="235" loading="lazy"></figure><h2 id="gracias-por-leer">Gracias por leer</h2><p>¿Este artículo te sirvió? Si lo hizo, espero que consideres compartirlo. Puede que le sirva a alguien más. ¡Gracias!</p><p>Este artículo fue publicado originalmente en <a href="https://zellwk.com/blog/git-undo">mi blog</a>.</p><p>Regístrate a mi<a href="https://zellwk.com/" rel="noopener"> newsletter</a> si quieres más artículos para convertirte en un mejor desarrollador front-end.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Convenciones de nomenclatura de CSS que te ahorrarán horas de depuración ]]>
                </title>
                <description>
                    <![CDATA[ He escuchado a muchos desarrolladores decir que odian CSS. En mi experiencia, esto es un resultado de no tomarse el tiempo de aprenderlo. CSS no es el lenguaje más lindo, pero ha impulsado el estilo de la web desde hace más de 20 años. No le fue tan mal, ¿no? ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/convenciones-de-nomenclatura-de-css-que-te-ahorraran-horas-de-depuracion/</link>
                <guid isPermaLink="false">62bb1473c5b22c08edf8c6df</guid>
                
                    <category>
                        <![CDATA[ CSS ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Anna Aimeri ]]>
                </dc:creator>
                <pubDate>Wed, 06 Jul 2022 18:16:56 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2022/06/1_YunI3ChUVMlpmFzo75FczQ.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artículo original:</strong> <a href="https://www.freecodecamp.org/news/css-naming-conventions-that-will-save-you-hours-of-debugging-35cea737d849/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">CSS Naming Conventions that Will Save You Hours of Debugging</a>
      </p><p>He escuchado a muchos desarrolladores decir que odian CSS. En mi experiencia, esto es un resultado de no tomarse el tiempo de aprenderlo.</p><p>CSS no es el lenguaje más lindo, pero ha impulsado el <em>estilo</em> de la web desde hace más de 20 años. No le fue tan mal, ¿no?</p><p>Sin embargo, a medida que escribes más código en CSS, rápidamente notas una gran desventaja.</p><p>Es realmente difícil de mantener.</p><p>Código en CSS mal escrito se convierte rápidamente en una pesadilla.</p><p>Aquí hay algunas convenciones de nomenclatura que te ahorrarán un poco de estrés y un sinfín de horas a la larga.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/0Nm4l3DA3bWTbPc6C4ViWDqewokYYootpoqb" class="kg-image" alt="0Nm4l3DA3bWTbPc6C4ViWDqewokYYootpoqb" width="650" height="605" loading="lazy"><figcaption>Has estado allí antes, ¿verdad?</figcaption></figure><h3 id="usa-cadenas-delimitadas-con-guiones"><strong>Usa cadenas delimitadas con guiones</strong></h3><p>Si escribes mucho en JavaScript, sabes que escribir variables en <em>camel case </em>es algo usual.</p><pre><code>var cajaRoja = document.getElementById('...')</code></pre><p>Genial, ¿no?</p><p>El problema es que esta forma de nomenclatura no le sienta bien a CSS.</p><p>No hagas esto:</p><pre><code>.cajaRoja {  contorno: 1px rojo;}</code></pre><p>Haz esto:</p><pre><code>.caja-roja {   contorno: 1px rojo;}</code></pre><p>Esta es una convención de nomenclatura de CSS bastante estándar. Es posiblemente más legible. </p><p>Además, es consistente con los nombres de propiedades de CSS.</p><pre><code>// Correcto</code></pre><pre><code>.alguna-clase {   font-weight: 10em}</code></pre><pre><code>// Incorrecto</code></pre><pre><code>.alguna-clase {   fontWeight: 10em}</code></pre><h3 id="la-convenci-n-de-nomenclatura-bem"><strong>La convención de nomenclatura BEM</strong></h3><p>Los equipos de desarrollo tienen diferentes estrategias para escribir selectores de CSS. Algunos equipos usan delimitadores de guiones, mientras que otros prefieren usar una convención de nomenclatura más estructurada llamada BEM.</p><p>Generalmente, hay 3 problemas que las convenciones de nomenclatura de CSS intentan resolver:</p><ol><li>Para saber lo que hace un selector, basta con mirar su nombre</li><li>Para saber dónde puede usarse un selector, basta con mirarlo</li><li>Para conocer las relaciones entre nombres de clases, basta con mirarlos</li></ol><p>¿Alguna vez viste nombres de clases escritos así?:</p><pre><code>.nav--secundario {  ...}</code></pre><pre><code>.nav__encabezado {  ...}</code></pre><p>Esa es la convención de nomenclatura BEM.</p><h3 id="explicando-bem-a-un-ni-o-de-5-a-os"><strong>Explicando BEM a un niño de 5 años</strong></h3><p>BEM intenta dividir la interfaz del usuario en pequeñas componentes reutilizables.</p><p>Considera esta imagen:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/pIFVbUmRtKN8x6DvLHEvJeUSM9Oda8ClkY5f" class="kg-image" alt="pIFVbUmRtKN8x6DvLHEvJeUSM9Oda8ClkY5f" width="800" height="400" loading="lazy"><figcaption>Es una imagen galardonada de un hombre palo :)</figcaption></figure><p>No ganaría ningún premio :(</p><p>Esta persona representa un componente, como un bloque de diseño.</p><p>Debes haber adivinado a esta altura que la B de BEM es de Bloque.</p><p>En el mundo real, este 'bloque' podría representar un sitio, encabezado, pie de página, o cualquier otro bloque de diseño.</p><p>Luego, un nombre de clase ideal para esta componente sería <code>persona-de-palitos</code>.</p><p>La componente debería escribirse así:</p><pre><code>.persona-de-palitos {   }</code></pre><p>Usamos cadenas delimitadas aquí. ¡Bien!</p><figure class="kg-card kg-image-card"><img src="https://cdn-media-1.freecodecamp.org/images/ThMVqj-sv26pjpzLJU3MIF2TCdn-S4CjlEZk" class="kg-image" alt="ThMVqj-sv26pjpzLJU3MIF2TCdn-S4CjlEZk" width="800" height="400" loading="lazy"></figure><h3 id="e-de-elemento"><strong>E de Elemento</strong></h3><p>La E de ‘BEM’ viene de Elemento.</p><p>Por lo general, los bloques de diseño casi nunca viven aislados.</p><p>Por ejemplo, esta persona tiene una <code>cabeza</code>, dos hermosos <code>brazos</code>, y <code>pies</code>.</p><figure class="kg-card kg-image-card"><img src="https://cdn-media-1.freecodecamp.org/images/bf2jyOzcZ8wgd95I3qR9IS3Cf6pRlQ2hHuGM" class="kg-image" alt="bf2jyOzcZ8wgd95I3qR9IS3Cf6pRlQ2hHuGM" width="800" height="400" loading="lazy"></figure><p>La <code>cabeza</code>, <code>pies</code> y <code>brazos</code> son todos elementos dentro del componente. Pueden ser vistos como componentes hijos, es decir, hijos del componente padre.</p><p>Usando la convención de nomenclatura BEM, los nombres de clases de los elementos se derivan agregando <strong>dos guiones bajos</strong>, seguidos del nombre del elemento.</p><p>Por ejemplo:</p><pre><code>.persona-de-palitos__cabeza {</code></pre><pre><code>}</code></pre><pre><code>.persona-de-palitos__brazos {</code></pre><pre><code>}</code></pre><pre><code>.persona-de-palitos__pies {</code></pre><pre><code>}</code></pre><h3 id="m-de-modificador"><strong>M de Modificador</strong></h3><p>La M de ‘BEM’ es de Modificador.</p><p>¿Qué pasaría si la persona fuera modificada y pudiéramos tener una persona <code>azul</code> o <code>roja</code>?</p><figure class="kg-card kg-image-card"><img src="https://cdn-media-1.freecodecamp.org/images/Q-aWWnpw1UuoXxp5NGHxsjP5689VQBT0oGdQ" class="kg-image" alt="Q-aWWnpw1UuoXxp5NGHxsjP5689VQBT0oGdQ" width="800" height="400" loading="lazy"></figure><p>En el mundo real, esto podría ser un botón <code>rojo</code> o <code>azul</code>. Estas son modificaciones del componente en cuestión.</p><p>Usando BEM, los nombres de las clases de los modificadores se derivan agregando dos <strong>guiones medios</strong> seguidos del nombre del elemento.</p><p>Por ejemplo:</p><pre><code>.persona-de-palitos--azul {</code></pre><pre><code>}</code></pre><pre><code>.persona-de-palitos--roja {</code></pre><pre><code>}</code></pre><p>El último ejemplo muestra el componente padre siendo modificado. Esto no es siempre así.</p><p>¿Qué pasaría si tuviéramos personas con distintos tamaños de <code>cabeza</code>?</p><figure class="kg-card kg-image-card"><img src="https://cdn-media-1.freecodecamp.org/images/ZK-riYJhmFfBVEof6xO8yGGR3O10g2dW7Xqn" class="kg-image" alt="ZK-riYJhmFfBVEof6xO8yGGR3O10g2dW7Xqn" width="800" height="400" loading="lazy"></figure><p>Esta vez el elemento ha sido modificado. Recordemos que el elemento es un componente hijo del bloque que lo contiene.</p><p>La <code>.persona-de-palitos</code> representa el <code>Block</code>, <code>.persona-de-palitos__cabeza</code> el elemento.</p><p>Como vimos en el ejemplo de arriba, también podemos usar guiones dobles de la siguiente manera:</p><pre><code>.persona-de-palitos__cabeza--pequeña {</code></pre><pre><code>}</code></pre><pre><code>.persona-de-palitos__cabeza--grande {</code></pre><pre><code>}</code></pre><p>De nuevo, notar el uso de los <strong>guiones</strong> dobles en el ejemplo de arriba. Esto se usa para denotar un modificador.</p><p>Ahora ya lo tienes.</p><p>Esta es la idea básica de cómo funciona la convención de nomenlatura de BEM.</p><p>Personalmente, tiendo a usar los nombres de clases delimitados con guion para proyectos simples, y BEM para interfaces que involucran más al usuario.</p><p><strong><strong>BEM - Blo</strong>que<strong> Element</strong>o<strong> Modifi</strong>cador</strong></p><h3 id="-por-qu-usar-convenciones-de-nomenclatura"><strong>¿Por qué usar convenciones de nomenclatura?</strong></h3><blockquote>There are only two hard problems in Computer Science: cache invalidation and naming things — <em><em>Phil Karlton</em></em></blockquote><p>Nombrar cosas es difícil. Intentamos facilitarlo, y ahorrarnos tiempo en el futuro con código más fácil de mantener.</p><p>Nombrar cosas correctamente en CSS va a generar que tu código sea más fácil de leer y mantener.</p><p>Si eliges usar la convención de nomenclatura de BEM, se volverá más fácil ver la relación entre tus componentes de diseño/bloques con solo mirarlos en el markup.</p><p>¿Te sientes confiado?</p><h3 id="nombres-de-css-con-hooks-de-javascript"><strong>Nombres de CSS con hooks de JavaScript</strong></h3><p>Hoy es el primer día de Juan en su trabajo.</p><p>Le dieron un código <code>HTML</code> que se ve así:</p><pre><code>&lt;div class="siteNavigation"&gt;</code></pre><pre><code>&lt;/div&gt;</code></pre><p>John leyó este artículo y se dio cuenta de que esta puede no ser la mejor manera de nombrar cosas en <code>CSS</code>. Entonces, refactoriza la base de códigos así:</p><pre><code>&lt;div class="site-navigation"&gt;</code></pre><pre><code>&lt;/div&gt;</code></pre><p>Se ve bien, ¿no?</p><p>Para la desgracia de Juan, rompió la base de código.</p><p>¿Cómo?</p><p>En algún lugar del código de JavaScript, había una relación con el nombre de clase anterior, <code>siteNavigation</code>:</p><pre><code>// el código de JavaScript</code></pre><pre><code>const nav = document.querySelector('.siteNavigation')</code></pre><p>Luego, con el cambio en el nombre de la clase, la variable <code>nav</code> se volvió <code>null</code>.</p><p>Qué triste.</p><p>Para prevenir casos como este, los desarrolladores pensaron una serie de estrategias.</p><h4 id="1-usa-nombres-de-clases-js-"><strong>1. Usa nombres de clases js-</strong></h4><p>Una forma de mitigar estos bugs es usando un nombre de clase <code>js-*</code> denotando una relación con el elemento DOM en cuestión.</p><p>Por ejemplo:</p><pre><code>&lt;div class="site-navigation js-site-navigation"&gt;</code></pre><pre><code>&lt;/div&gt;</code></pre><p>Y en el código en JavaScript:</p><pre><code>// el código en JavaScript</code></pre><pre><code>const nav = document.querySelector('.js-site-navigation')</code></pre><p>Como convención, cualquier que vea el <code><strong>js-</strong>site-navigation</code> como nombre de clase va a entender que hay una relación con ese elemento DOM en el código de JavaScript.</p><h4 id="2-usa-el-atributo-rel"><strong>2. Usa el atributo rel</strong></h4><p>Personalmente, no uso esta técnica, pero he visto a algunos hacerlo.</p><p>¿Reconoces esto?</p><pre><code>&lt;link rel="stylesheet" type="text/css" href="main.css"&gt;</code></pre><p>Básicamente, el <strong>atributo rel</strong> define la relación que tiene el recurso linkeado con el documento desde el que se referencia.</p><p>En el ejemplo anterior con Juan, partidarios de esta técnica harían esto:</p><pre><code>&lt;div class="site-navigation" rel="js-site-navigation"&gt;</code></pre><pre><code>&lt;/div&gt;</code></pre><p>Y en el de JavaScript:</p><pre><code>const nav = document.querySelector("[rel='js-site-navigation']")</code></pre><p>Tengo mis dudas sobre esta técnica, pero es probable que la encuentres en algunas bases de código. Lo que se suele argumentar es, <em><em>“</em>bueno, hay una relación con JavaScript, entonces uso el atributo rel para denotar esto<em>”</em></em>.</p><p>La web es un gran lugar con muchos métodos diferentes para resolver el mismo problema.</p><h4 id="3-no-uses-atributos-de-datos"><strong>3. No uses atributos de datos</strong></h4><p>Algunos desarrolladores usan atributos de datos como hooks de JavaScript. Esto no está bien. Por definición, los atributos de datos se usan para <strong>almacenar data personalizada.</strong></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://cdn-media-1.freecodecamp.org/images/08r5ESO6cpzZvcZz-KczJEGXtPBtCLorryI6" class="kg-image" alt="08r5ESO6cpzZvcZz-KczJEGXtPBtCLorryI6" width="800" height="400" loading="lazy"><figcaption>Buen uso de los atributos de datos. Como se ve en Twitter</figcaption></figure><p><strong><strong>Edit</strong>ar<strong> #1: </strong>Como algunas personas mencionaron en los comentarios, si la gente usa el atributo 'rel', entonces quizás está bien usar atributos de datos en ciertos casos. Es tu decisión, después de todo.</strong></p><h3 id="consejo-extra-a-ade-m-s-comentarios-en-css">Consejo extra<strong>: Añade más comentarios en CSS</strong></h3><p>Esto no tiene nada que ver con convenciones de nomenclatura, pero te ahorrará algo de tiempo.</p><p>Mientras que muchos desarrolladores web intentan NO comentar en JavaScript o comentar muy poco, yo creo que deberías comentar más en CSS.</p><p>Debido a que CSS no es el lenguaje más elegante, los comentarios bien estructurados pueden ahorrar tiempo cuando estás intentando entender tu código.</p><p>No hace daño.</p><p>Mira lo bien comentado que está este <a href="https://github.com/twbs/bootstrap/blob/v4-dev/scss/_carousel.scss" rel="noopener">código fuente</a> de Bootstrap.</p><p>No necesitas comentar cosas como <code>color:rojo</code> para decir que algo va a dar el color rojo. Pero si estás usando un truco de CSS menos obvio, siéntete libre de comentar.</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Cómo restaurar pestañas en Chrome: Restaura tu última sesión y páginas web ]]>
                </title>
                <description>
                    <![CDATA[ Chrome se ha convertido en el navegador web más popular del mundo, ofreciendo un desempeño y funciones que superan a sus competidores. Pero este aumento en su popularidad provocó que muchos tengan problemas como perder páginas web importantes, investigación, y sesiones con pestañas cerradas o perdidas. JavaScript line chart created ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/como-restaurar-pestanas-en-chrome-restaura-tu-ultima-sesion-y-paginas-web/</link>
                <guid isPermaLink="false">62b73a2ac5b22c08edf8c1b5</guid>
                
                    <category>
                        <![CDATA[ Chrome ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Anna Aimeri ]]>
                </dc:creator>
                <pubDate>Sun, 03 Jul 2022 04:11:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2022/06/chromeTabs.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p data-test-label="translation-intro">
        <strong>Artículo original:</strong> <a href="https://www.freecodecamp.org/news/how-to-restore-tabs-in-google-chrome-restore-your-last-session-and-pages/" target="_blank" rel="noopener noreferrer" data-test-label="original-article-link">How to Restore Tabs on Chrome: Restore Your Last Session and Pages</a>
      </p><p>Chrome se ha convertido en el navegador web más popular del mundo, ofreciendo un desempeño y funciones que superan a sus competidores. Pero este aumento en su popularidad provocó que muchos tengan problemas como perder páginas web importantes, investigación, y sesiones con pestañas cerradas o perdidas.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.freecodecamp.org/news/content/images/2020/03/image-49.png" class="kg-image" alt="Un gráfico de líneas de JavaScript con varias series que ilustran el dominio de los navegadores Chrome a lo largo del tiempo. Creado usando gráficos JS con datos de statcounter.com" width="600" height="400" loading="lazy"><figcaption>JavaScript line chart created using <a href="https://jscharting.com/" style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 17.6px; vertical-align: baseline; background-color: transparent; color: var(--gray90); text-decoration: underline; cursor: pointer; word-break: break-word;">JSCharting</a> with data from statcounter.comExplore the <a href="https://jscharting.com/examples/chart-types/line/multi-series-trendline/" style="box-sizing: inherit; margin: 0px; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 17.6px; vertical-align: baseline; background-color: transparent; color: var(--gray90); text-decoration: underline; cursor: pointer; word-break: break-word;">interactive chart</a> illustrating Chrome browsers rise to dominance over time.</figcaption></figure><p>Imagina que estás investigando para un proyecto, y luego de cliquear un montón de links, llegas a la fuente de información perfecta. No tienes idea de cómo llegaste ahí, pero estás ahí ahora y eso es lo único que importa.</p><p>Estás trabajando en notas, mails, cambias de pestaña, todo está saliendo bien... hasta que el desastre ataca: accidentalmente cliqueas el píxel equivocado y la pestaña que necesitabas desaparece sin advertencia.</p><p>O de repente Chrome decide fallarte y cerrarse sin razón aparente.</p><p>No tienes que preocuparte. No eres la primera persona a la que le ha ocurrido esto, ni serás la última. Afortunadamente, Google Chrome recuerda tu historial de páginas web, y sin importar lo que haya salido mal, deberías poder recuperarlas por completo.</p><p>Aquí hay algunas maneras de restaurar pestañas cerradas en Chrome si esto te ocurre.</p><h2 id="pesta-a-cerrada-por-accidente"><strong>Pestaña cerrada por accidente</strong></h2><p>Si simplemente cliqueaste el píxel equivocado y cerraste una pestaña que no debías, es fácil restaurarla. Simplemente, haz clic derecho en un área vacía de la barra de pestañas y elige volver a abrir pestañas cerradas.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2020/03/image-20.png" class="kg-image" alt="image-20" width="600" height="400" loading="lazy"></figure><p>También puedes usar un atajo de teclado — presiona Ctrl+Shift+T (o Command+Shift+T en Mac) y la última pestaña que cerraste se abrirá en una nueva pestaña.</p><h2 id="cierre-inesperado-de-chrome-o-de-tu-computadora">Cierre inesperado de Chrome o de tu computadora</h2><p>Una falla inesperada en tu computadora nunca es una experiencia placentera, pero no tienes que preocuparte por perder tu sesión actual de Chrome.</p><p>Google Chrome puede manejar un fallo sin problemas cuando pierdes todas tus pestañas abiertas. Normalmente, cuando reinicias Chrome, este muestra un botón de "restaurar pestañas". Esta opción va a restaurar tu última sesión de navegación por completo. Cliqueala, y estarás de vuelta donde lo dejaste.</p><p>Si no obtienes esta opción, está bien. Cliquea el menú de Chrome y sitúa el cursor sobre el botón del historial. Allí deberías hallar una opción que lea "# pestañas" por ejemplo "12 pestañas". Puedes presionar esta opción para restaurar tu sesión previa.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2020/03/image-19.png" class="kg-image" alt="image-19" width="600" height="400" loading="lazy"></figure><p>El comando Ctrl+Shift+T también puede reabrir ventanas de Chrome cerradas inesperada o deliberadamente. Puedes usar este atajo múltiples veces hasta agotar las pestañas y ventanas para restaurar.</p><h2 id="restaurar-pesta-as-recientemente-cerradas"><strong>Restaurar pestañas recientemente cerradas</strong></h2><p>Similarmente, puedes restaurar pestañas cerradas recientemente cliqueando el menú de Chrome y colocando el cursor sobre el botón del historial. Se listará allí un pequeño resumen de páginas que visitaste recientemente.</p><p>Si la página que quieres restaurar está listada allí, puedes cliquearla para restaurarla. Si no, puedes intentar el siguiente método.</p><h2 id="pesta-a-que-cerraste-el-otro-d-a"><strong>Pestaña que cerraste el otro día</strong></h2><p>Si no ves la página web que quieres recuperar aún, presiona el sub-menú del historial (menú de Chrome &gt; historial &gt; historial). O puedes usar el atajo Ctrl+H (Mac: Command+Y).</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2020/03/image-21.png" class="kg-image" alt="image-21" width="600" height="400" loading="lazy"></figure><p>Esto va a mostrarte un historial completo de las páginas que visitaste. Deberías poder encontrar la página que querías allí. Incluso puedes buscar tu historial de páginas web para facilitar el trabajo si ha pasado mucho tiempo desde que cerraste o perdiste tu pestaña.</p><p><strong>Cuidado </strong>- Si estabas navegando en incógnito (modo privado) y perdiste tus pestañas, Chrome no va a recordarlas.</p><h2 id="consejo"><strong>Consejo</strong></h2><p>Guarda en marcadores las páginas web que visitas regularmente presionando el ícono ⭐ en el lado derecho de la barra de direcciones. Esto añadirá un botón al navegador Chrome — cliqueando este botón se redirigirá la pestaña actual a esta página web.</p> ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
