summaryrefslogtreecommitdiffhomepage
path: root/es-es
diff options
context:
space:
mode:
Diffstat (limited to 'es-es')
-rw-r--r--es-es/amd-es.html.markdown214
-rw-r--r--es-es/brainfuck-es.html.markdown18
-rw-r--r--es-es/git-es.html.markdown14
-rw-r--r--es-es/javascript-es.html.markdown20
-rw-r--r--es-es/json-es.html.markdown16
-rw-r--r--es-es/markdown-es.html.markdown6
-rw-r--r--es-es/python3-es.html.markdown2
-rw-r--r--es-es/ruby-es.html.markdown247
-rw-r--r--es-es/swift-es.html.markdown596
-rw-r--r--es-es/tmux-es.html.markdown253
10 files changed, 1324 insertions, 62 deletions
diff --git a/es-es/amd-es.html.markdown b/es-es/amd-es.html.markdown
new file mode 100644
index 00000000..7a59ddd6
--- /dev/null
+++ b/es-es/amd-es.html.markdown
@@ -0,0 +1,214 @@
+---
+
+category: tool
+tool: amd
+contributors:
+ - ["Frederik Ring", "https://github.com/m90"]
+
+translators:
+ - ["Damaso Sanoja", "https://github.com/damasosanoja"]
+filename: learnamd-es.js
+lang: es-es
+---
+
+## Iniciando con AMD
+
+El API del **Módulo de Definición Asíncrono** especifica un mecanismo para definir módulos JavaScript de manera tal que tanto el módulo como sus dependencias puedan ser cargadas de manera asíncrona. Esto es particularmente adecuado para el entorno del navegador donde la carga sincronizada de los módulos genera problemas de rendimiento, usabilidad, depuración y acceso de multi-dominios.
+
+### Conceptos básicos
+```javascript
+// El API básico de AMD consiste en tan solo dos métodos: `define` y `require`
+// y se basa en la definición y consumo de los módulos:
+// `define(id?, dependencias?, fábrica)` define un módulo
+// `require(dependencias, callback)` importa un conjunto de dependencias y
+// las consume al invocar el callback
+
+// Comencemos usando define para definir un nuevo módulo
+// que no posee dependencias. Lo haremos enviando un nombre
+// y una función fábrica para definirla:
+define('awesomeAMD', function(){
+ var isAMDAwesome = function(){
+ return true;
+ };
+ // El valor que regresa la función fábrica del módulo será
+ // lo que los otros módulos o llamados require recibirán cuando
+ // soliciten nuestro módulo `awesomeAMD`.
+ // El valor exportado puede ser cualquier cosa, funciones (constructores),
+ // objetos, primitivos, incluso indefinidos (aunque eso no ayuda mucho).
+ return isAMDAwesome;
+});
+
+// Ahora definamos otro módulo que dependa de nuestro módulo `awesomeAMD`.
+// Observe que ahora hay un argumento adicional que define
+// las dependencias de nuestro módulo:
+define('loudmouth', ['awesomeAMD'], function(awesomeAMD){
+ // las dependencias serán enviadas a los argumentos de la fábrica
+ // en el orden que sean especificadas
+ var tellEveryone = function(){
+ if (awesomeAMD()){
+ alert('This is sOoOo rad!');
+ } else {
+ alert('Pretty dull, isn\'t it?');
+ }
+ };
+ return tellEveryone;
+});
+
+// Como ya sabemos utilizar define usemos ahora `require` para poner en marcha
+// nuestro programa. La firma de `require` es `(arrayOfDependencies, callback)`.
+require(['loudmouth'], function(loudmouth){
+ loudmouth();
+});
+
+// Para hacer que este tutorial corra código, vamos a implementar una
+// versión muy básica (no-asíncrona) de AMD justo aquí:
+function define(name, deps, factory){
+ // observa como son manejados los módulos sin dependencias
+ define[name] = require(factory ? deps : [], factory || deps);
+}
+
+function require(deps, callback){
+ var args = [];
+ // primero recuperemos todas las dependencias que necesita
+ // el llamado require
+ for (var i = 0; i < deps.length; i++){
+ args[i] = define[deps[i]];
+ }
+ // satisfacer todas las dependencias del callback
+ return callback.apply(null, args);
+}
+// puedes ver este código en acción aquí: http://jsfiddle.net/qap949pd/
+```
+
+### Uso en el mundo real con require.js
+
+En contraste con el ejemplo introductorio, `require.js` (la librería AMD más popular) implementa la **A** de **AMD**, permitiéndote cargar los módulos y sus dependencias asincrónicamente via XHR:
+
+```javascript
+/* file: app/main.js */
+require(['modules/someClass'], function(SomeClass){
+ // el callback es diferido hasta que la dependencia sea cargada
+ var thing = new SomeClass();
+});
+console.log('So here we are, waiting!'); // esto correrá primero
+```
+
+Por convención, usualmente guardas un módulo en un fichero. `require.js` puede resolver los nombres de los módulos basados en rutas de archivo, de forma que no tienes que nombrar tus módulos, simplemente referenciarlos usando su ubicación. En el ejemplo `someClass` asumimos que se ubica en la carpeta `modules`, relativa a tu `baseUrl` configurada:
+
+* app/
+ * main.js
+ * modules/
+ * someClass.js
+ * someHelpers.js
+ * ...
+ * daos/
+ * things.js
+ * ...
+
+Esto significa que podemos definir `someClass` sin especificar su id de módulo:
+
+```javascript
+/* file: app/modules/someClass.js */
+define(['daos/things', 'modules/someHelpers'], function(thingsDao, helpers){
+ // definición de módulo, por supuesto, ocurrirá también asincrónicamente
+ function SomeClass(){
+ this.method = function(){/**/};
+ // ...
+ }
+ return SomeClass;
+});
+```
+
+Para alterar el comportamiento del mapeo de ruta usa `requirejs.config(configObj)` en tu `main.js`:
+
+```javascript
+/* file: main.js */
+requirejs.config({
+ baseUrl : 'app',
+ paths : {
+ // también puedes cargar módulos desde otras ubicaciones
+ jquery : '//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min',
+ coolLibFromBower : '../bower_components/cool-lib/coollib'
+ }
+});
+require(['jquery', 'coolLibFromBower', 'modules/someHelpers'], function($, coolLib, helpers){
+ // un fichero `main` necesita llamar a require al menos una vez,
+ // de otra forma jamás correrá el código
+ coolLib.doFancyStuffWith(helpers.transform($('#foo')));
+});
+```
+Las aplicaciones basadas en `require.js` usualmente tendrán un solo punto de entrada (`main.js`) que se pasa a la etiqueta del script `require.js` como un atributo de datos. Será cargado y ejecutado automáticamente al cargar la página:
+
+```html
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Cien etiquetas de script? Nunca más!</title>
+</head>
+<body>
+ <script src="require.js" data-main="app/main"></script>
+</body>
+</html>
+```
+
+### Optimizar todo un proyecto usando r.js
+
+Muchas personas prefieren usar AMD para la organización del código durante el desarrollo, pero quieren enviar para producción un solo fichero en vez de ejecutar cientos de XHRs en las cargas de página.
+
+`require.js` incluye un script llamado `r.js` (el que probablemente correrás en node.js, aunque Rhino también es soportado) que puede analizar el gráfico de dependencias de tu proyecto, y armar un solo fichero que contenga todos tus módulos (adecuadamente nombrados), minificado y listo para consumo.
+
+Instálalo usando `npm`:
+```shell
+$ npm install requirejs -g
+```
+
+Ahora puedes alimentarlo con un fichero de configuración:
+```shell
+$ r.js -o app.build.js
+```
+
+Para nuestro ejemplo anterior el archivo de configuración luciría así:
+```javascript
+/* file : app.build.js */
+({
+ name : 'main', // nombre del punto de entrada
+ out : 'main-built.js', // nombre del fichero donde se escribirá la salida
+ baseUrl : 'app',
+ paths : {
+ // `empty:` le dice a r.js que esto aún debe ser cargado desde el CDN, usando
+ // la ubicación especificada en `main.js`
+ jquery : 'empty:',
+ coolLibFromBower : '../bower_components/cool-lib/coollib'
+ }
+})
+```
+
+Para usar el fichero creado en producción, simplemente intercambia `data-main`:
+```html
+<script src="require.js" data-main="app/main-built"></script>
+```
+
+Un increíblemente detallado [resumen de opciones de generación](https://github.com/jrburke/r.js/blob/master/build/example.build.js) está disponible en el repositorio de GitHub.
+
+### Tópicos no cubiertos en este tutorial
+* [Cargador de plugins / transformaciones](http://requirejs.org/docs/plugins.html)
+* [Cargando y exportando estilos CommonJS](http://requirejs.org/docs/commonjs.html)
+* [Configuración avanzada](http://requirejs.org/docs/api.html#config)
+* [Configuración de Shim (cargando módulos no-AMD)](http://requirejs.org/docs/api.html#config-shim)
+* [Cargando y optimizando CSS con require.js](http://requirejs.org/docs/optimization.html#onecss)
+* [Usando almond.js para construcciones](https://github.com/jrburke/almond)
+
+### Otras lecturas:
+
+* [Especificaciones oficiales](https://github.com/amdjs/amdjs-api/wiki/AMD)
+* [¿Por qué AMD?](http://requirejs.org/docs/whyamd.html)
+* [Definición Universal de Módulos](https://github.com/umdjs/umd)
+
+### Implementaciones:
+
+* [require.js](http://requirejs.org)
+* [dojo toolkit](http://dojotoolkit.org/documentation/tutorials/1.9/modules/)
+* [cujo.js](http://cujojs.com/)
+* [curl.js](https://github.com/cujojs/curl)
+* [lsjs](https://github.com/zazl/lsjs)
+* [mmd](https://github.com/alexlawrence/mmd)
diff --git a/es-es/brainfuck-es.html.markdown b/es-es/brainfuck-es.html.markdown
index e33d672d..550511da 100644
--- a/es-es/brainfuck-es.html.markdown
+++ b/es-es/brainfuck-es.html.markdown
@@ -9,8 +9,10 @@ lang: es-es
---
Brainfuck (con mayúscula sólo al inicio de una oración) es un
-lenguaje de programación mínimo, computacionalmente universal
-en tamaño con sólo 8 comandos.
+lenguaje de programación extremadamente pequeño, Turing completo con sólo 8 comandos.
+
+Puedes probar brainfuck en tu navegador con [brainfuck-visualizer](http://fatiherikli.github.io/brainfuck-visualizer/).
+
```
@@ -18,7 +20,7 @@ Cualquier caracter que no sea "><+-.,[]" (sin incluir las comillas)
será ignorado.
Brainfuck es representado por un arreglo de 30,000 celdas inicializadas
-en cero y un apuntador en la celda actual.
+en cero y un puntero apuntando la celda actual.
Existen ocho comandos:
@@ -26,7 +28,7 @@ Existen ocho comandos:
- : Decrementa 1 al valor de la celda actual.
> : Mueve el apuntador a la siguiente celda. (a la derecha)
< : Mueve el apuntador a la celda anterior. (a la izquierda)
-. : Imprime el valor en ASCII de la celda actual (i.e. 65 = 'A')
+. : Imprime el valor en ASCII de la celda actual (p.e. 65 = 'A')
, : Lee un caracter como input y lo escribe en la celda actual.
[ : Si el valor en la celda actual es cero mueve el apuntador
hasta el primer ']' que encuentre. Si no es cero sigue a la
@@ -37,7 +39,7 @@ Existen ocho comandos:
[ y ] forman un while. Obviamente, deben estar balanceados.
-Ahora unos ejemplos de programas escritos con brainfuck.
+Estos son algunos ejemplos de programas escritos con brainfuck.
++++++ [ > ++++++++++ < - ] > +++++ .
@@ -63,7 +65,7 @@ Esto continúa hasta que la celda #1 contenga un cero. Cuando #1 contenga un
cero la celda #2 tendrá el valor inicial de #1. Como este ciclo siempre
terminara en la celda #1 nos movemos a la celda #2 e imprimimos (.).
-Ten en mente que los espacios son sólo para fines de legibilidad.
+Ten en cuenta que los espacios son sólo para fines de legibilidad.
Es lo mismo escribir el ejemplo de arriba que esto:
,[>+<-]>.
@@ -81,7 +83,7 @@ hasta la próxima vez. Para resolver este problema también incrementamos la
celda #4 y luego copiamos la celda #4 a la celda #2. La celda #3 contiene
el resultado.
```
-Y eso es brainfuck. ¿No tan difícil o sí? Como diversión, puedes escribir
+Y eso es brainfuck. No es tan difícil, ¿verdad? Como diversión, puedes escribir
tu propio intérprete de brainfuck o tu propio programa en brainfuck. El
intérprete es relativamente sencillo de hacer, pero si eres masoquista,
-intenta construir tu proprio intérprete de brainfuck... en brainfuck.
+puedes intentar construir tu propio intérprete de brainfuck... en brainfuck.
diff --git a/es-es/git-es.html.markdown b/es-es/git-es.html.markdown
index 18b544b4..4e1e68ba 100644
--- a/es-es/git-es.html.markdown
+++ b/es-es/git-es.html.markdown
@@ -18,11 +18,11 @@ versionar y administrar nuestro código fuente.
## Versionamiento, conceptos.
-### Qué es el control de versiones?
+### ¿Qué es el control de versiones?
El control de versiones es un sistema que guarda todos los cambios realizados en
uno o varios archivos, a lo largo del tiempo.
-### Versionamiento centralizado vs Versionamiento Distribuido.
+### Versionamiento centralizado vs versionamiento distribuido.
+ El versionamiento centralizado se enfoca en sincronizar, rastrear, y respaldar
archivos.
@@ -33,9 +33,9 @@ uno o varios archivos, a lo largo del tiempo.
[Información adicional](http://git-scm.com/book/es/Empezando-Acerca-del-control-de-versiones)
-### Por qué usar Git?
+### ¿Por qué usar Git?
-* Se puede trabajar sin conexion.
+* Se puede trabajar sin conexión.
* ¡Colaborar con otros es sencillo!.
* Derivar, crear ramas del proyecto (aka: Branching) es fácil.
* Combinar (aka: Merging)
@@ -47,7 +47,7 @@ uno o varios archivos, a lo largo del tiempo.
### Repositorio
Un repositorio es un conjunto de archivos, directorios, registros, cambios (aka:
-comits), y encabezados (aka: heads). Imagina que un repositorio es una clase,
+commits), y encabezados (aka: heads). Imagina que un repositorio es una clase,
y que sus atributos otorgan acceso al historial del elemento, además de otras
cosas.
@@ -62,12 +62,12 @@ y mas.
### Directorio de trabajo (componentes del repositorio)
-Es basicamente los directorios y archivos dentro del repositorio. La mayoría de
+Es básicamente los directorios y archivos dentro del repositorio. La mayoría de
las veces se le llama "directorio de trabajo".
### Índice (componentes del directorio .git)
-El índice es el área de inicio en git. Es basicamente la capa que separa el
+El índice es el área de inicio en git. Es básicamente la capa que separa el
directorio de trabajo del repositorio en git. Esto otorga a los desarrolladores
más poder sobre lo que se envía y se recibe del repositorio.
diff --git a/es-es/javascript-es.html.markdown b/es-es/javascript-es.html.markdown
index d475cf42..9ef0c63e 100644
--- a/es-es/javascript-es.html.markdown
+++ b/es-es/javascript-es.html.markdown
@@ -30,7 +30,7 @@ Aunque JavaScript no sólo se limita a los navegadores web: Node.js, Un proyecto
// Cada sentencia puede ser terminada con punto y coma ;
hazAlgo();
-// ... aunque no es necesario, ya que el punto y coma se agrega automaticamente
+// ... aunque no es necesario, ya que el punto y coma se agrega automáticamente
// cada que se detecta una nueva línea, a excepción de algunos casos.
hazAlgo()
@@ -109,7 +109,7 @@ null == undefined; // = true
null === undefined; // false
// Los Strings funcionan como arreglos de caracteres
-// Puedes accesar a cada caracter con la función charAt()
+// Puedes acceder a cada caracter con la función charAt()
"Este es un String".charAt(0); // = 'E'
// ...o puedes usar la función substring() para acceder a pedazos más grandes
@@ -186,7 +186,7 @@ miObjeto.miLlave; // = "miValor"
// agregar nuevas llaves.
miObjeto.miTerceraLlave = true;
-// Si intentas accesar con una llave que aún no está asignada tendrás undefined.
+// Si intentas acceder con una llave que aún no está asignada tendrás undefined.
miObjeto.miCuartaLlave; // = undefined
///////////////////////////////////
@@ -301,7 +301,7 @@ i; // = 5 - en un lenguaje que da ámbitos por bloque esto sería undefined, per
//inmediatamente", que preveé variables temporales de fugarse al ámbito global
(function(){
var temporal = 5;
- // Podemos accesar al ámbito global asignando al 'objeto global', el cual
+ // Podemos acceder al ámbito global asignando al 'objeto global', el cual
// en un navegador siempre es 'window'. El objeto global puede tener
// un nombre diferente en ambientes distintos, por ejemplo Node.js .
window.permanente = 10;
@@ -321,7 +321,7 @@ function decirHolaCadaCincoSegundos(nombre){
alert(texto);
}
setTimeout(interna, 5000);
- // setTimeout es asíncrono, así que la funcion decirHolaCadaCincoSegundos
+ // setTimeout es asíncrono, así que la función decirHolaCadaCincoSegundos
// terminará inmediatamente, y setTimeout llamará a interna() a los cinco segundos
// Como interna está "cerrada dentro de" decirHolaCadaCindoSegundos, interna todavía tiene
// acceso a la variable 'texto' cuando es llamada.
@@ -339,7 +339,7 @@ var miObjeto = {
};
miObjeto.miFuncion(); // = "¡Hola Mundo!"
-// Cuando las funciones de un objeto son llamadas, pueden accesar a las variables
+// Cuando las funciones de un objeto son llamadas, pueden acceder a las variables
// del objeto con la palabra clave 'this'.
miObjeto = {
miString: "¡Hola Mundo!",
@@ -401,11 +401,11 @@ var MiConstructor = function(){
miNuevoObjeto = new MiConstructor(); // = {miNumero: 5}
miNuevoObjeto.miNumero; // = 5
-// Todos los objetos JavaScript tienen un 'prototipo'. Cuando vas a accesar a una
+// Todos los objetos JavaScript tienen un 'prototipo'. Cuando vas a acceder a una
// propiedad en un objeto que no existe en el objeto el intérprete buscará en
// el prototipo.
-// Algunas implementaciones de JavaScript te permiten accesar al prototipo de
+// Algunas implementaciones de JavaScript te permiten acceder al prototipo de
// un objeto con la propiedad __proto__. Mientras que esto es útil para explicar
// prototipos, no es parte del estándar; veremos formas estándar de usar prototipos
// más adelante.
@@ -440,7 +440,7 @@ miPrototipo.sentidoDeLaVida = 43;
miObjeto.sentidoDeLaVida; // = 43
// Mencionabamos anteriormente que __proto__ no está estandarizado, y que no
-// existe una forma estándar de accesar al prototipo de un objeto. De todas formas.
+// existe una forma estándar de acceder al prototipo de un objeto. De todas formas.
// hay dos formas de crear un nuevo objeto con un prototipo dado.
// El primer método es Object.create, el cual es una adición reciente a JavaScript,
@@ -476,7 +476,7 @@ typeof miNumero; // = 'number'
typeof miNumeroObjeto; // = 'object'
miNumero === miNumeroObjeyo; // = false
if (0){
- // Este código no se ejecutara porque 0 es false.
+ // Este código no se ejecutará porque 0 es false.
}
// Aún así, los objetos que envuelven y los prototipos por defecto comparten
diff --git a/es-es/json-es.html.markdown b/es-es/json-es.html.markdown
index fff678eb..c98049f9 100644
--- a/es-es/json-es.html.markdown
+++ b/es-es/json-es.html.markdown
@@ -21,22 +21,22 @@ JSON en su forma más pura no tiene comentarios, pero la mayoría de los parsead
"llaves": "siempre debe estar entre comillas (ya sean dobles o simples)",
"numeros": 0,
"strings": "Høla, múndo. Todo el unicode está permitido, así como \"escapar\".",
- "soporta booleanos?": true,
- "vacios": null,
+ "¿soporta booleanos?": true,
+ "vacíos": null,
"numero grande": 1.2e+100,
"objetos": {
- "comentario": "La mayoria de tu estructura vendra de objetos.",
+ "comentario": "La mayoría de tu estructura vendrá de objetos.",
"arreglo": [0, 1, 2, 3, "Los arreglos pueden contener cualquier cosa.", 5],
"otro objeto": {
- "comentario": "Estas cosas pueden estar anidadas, muy util."
+ "comentario": "Estas cosas pueden estar anidadas, muy útil."
}
},
- "tonteria": [
+ "tontería": [
{
"fuentes de potasio": ["bananas"]
},
@@ -50,10 +50,10 @@ JSON en su forma más pura no tiene comentarios, pero la mayoría de los parsead
"estilo alternativo": {
"comentario": "Mira esto!"
- , "posicion de la coma": "no importa - mientras este antes del valor, entonces sera valido"
- , "otro comentario": "que lindo"
+ , "posición de la coma": "no importa - mientras este antes del valor, entonces sera válido"
+ , "otro comentario": "qué lindo"
},
- "eso fue rapido": "Y, estas listo. Ahora sabes todo lo que JSON tiene para ofrecer."
+ "eso fue rapido": "Y, estás listo. Ahora sabes todo lo que JSON tiene para ofrecer."
}
```
diff --git a/es-es/markdown-es.html.markdown b/es-es/markdown-es.html.markdown
index d90e3eb5..bc481df7 100644
--- a/es-es/markdown-es.html.markdown
+++ b/es-es/markdown-es.html.markdown
@@ -11,7 +11,7 @@ lang: es-es
Markdown fue creado por John Gruber en 2004. Su propósito es ser una sintaxis fácil de leer y escribir que se convierta
fácilmente a HTML (y, actualmente, otros formatos también).
-¡Denme todo la retroalimentación que quieran! / ¡Sientanse en la libertad de hacer forks o pull requests!
+¡Denme toda la retroalimentación que quieran! / ¡Sientanse en la libertad de hacer forks o pull requests!
```markdown
@@ -44,7 +44,7 @@ Esto es un h2
-------------
<!-- Estilos para texto plano -->
-<!-- El texto puede ser fácilmente estilizaedo con italicas, negritas o tachado
+<!-- El texto puede ser fácilmente estilizado con italicas, negritas o tachado
usando markdown -->
*Este texto está en itálicas.*
@@ -62,7 +62,7 @@ Markdown en Github, también tenemos: -->
~~Este texto está tachado.~~
-<!-- Los párrafos son una o múltuples líneas de texto adyacentes separadas por
+<!-- Los párrafos son una o múltiples líneas de texto adyacentes separadas por
una o múltiples líneas en blanco-->
Este es un párrafo. Estoy escribiendo un párrafo, ¿No es divertido?
diff --git a/es-es/python3-es.html.markdown b/es-es/python3-es.html.markdown
index 1c69481a..d30af1c8 100644
--- a/es-es/python3-es.html.markdown
+++ b/es-es/python3-es.html.markdown
@@ -478,7 +478,7 @@ Humano.roncar() #=> "*roncar*"
# Puedes importar módulos
import math
-print(math.sqrt(16)) #=> 4
+print(math.sqrt(16)) #=> 4.0
# Puedes obtener funciones específicas desde un módulo
from math import ceil, floor
diff --git a/es-es/ruby-es.html.markdown b/es-es/ruby-es.html.markdown
index 66a5d0fe..d8b67fe7 100644
--- a/es-es/ruby-es.html.markdown
+++ b/es-es/ruby-es.html.markdown
@@ -5,8 +5,18 @@ contributors:
- ["David Underwood", "http://theflyingdeveloper.com"]
- ["Joel Walden", "http://joelwalden.net"]
- ["Luke Holder", "http://twitter.com/lukeholder"]
+ - ["Tristan Hume", "http://thume.ca/"]
+ - ["Nick LaMuro", "https://github.com/NickLaMuro"]
+ - ["Marcos Brizeno", "http://www.about.me/marcosbrizeno"]
+ - ["Ariel Krakowski", "http://www.learneroo.com"]
+ - ["Dzianis Dashkevich", "https://github.com/dskecse"]
+ - ["Levi Bostian", "https://github.com/levibostian"]
+ - ["Rahil Momin", "https://github.com/iamrahil"]
+ - ["Gabriel Halley", "https://github.com/ghalley"]
+ - ["Persa Zula", "http://persazula.com"]
translators:
- ["Camilo Garrido", "http://www.twitter.com/hirohope"]
+ - ["Erick Bernal", "http://www.twitter.com/billowkib"]
lang: es-es
---
@@ -33,6 +43,8 @@ Tu tampoco deberías
8 - 1 #=> 7
10 * 2 #=> 20
35 / 5 #=> 7
+2**5 #=> 32
+5 % 3 #=> 2
# La aritmética es sólo azúcar sintáctico
# para llamar un método de un objeto
@@ -55,8 +67,6 @@ false.class #=> FalseClass
# Desigualdad
1 != 1 #=> false
2 != 1 #=> true
-!true #=> false
-!false #=> true
# Además de 'false', 'nil' es otro valor falso
@@ -70,14 +80,29 @@ false.class #=> FalseClass
2 <= 2 #=> true
2 >= 2 #=> true
+# Operadores lógicos
+true && false #=> false
+true || false #=> true
+!true #=> false
+
+# Existen versiones alternativas de los operadores lógicos con menor prioridad
+# Estos son usados como constructores controladores de flujo que encadenan
+# sentencias hasta que una de ellas retorne verdadero o falso
+
+# `has_otra_cosa` solo se llama si `has_algo` retorna verdadero.
+has_algo() and has_otra_cosa()
+# `registra_error` solo se llama si `has_algo` falla
+has_algo() or registra_error()
+
+
# Los strings son objetos
'Soy un string'.class #=> String
"Soy un string también".class #=> String
-referente = "usar interpolacion de strings"
+referente = "usar interpolación de strings"
"Yo puedo #{referente} usando strings de comillas dobles"
-#=> "Yo puedo usar interpolacion de strings usando strings de comillas dobles"
+#=> "Yo puedo usar interpolación de strings usando strings de comillas dobles"
# Imprime a la salida estándar
@@ -119,15 +144,16 @@ status == :aprovado #=> false
# Arreglos
# Esto es un arreglo
-[1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5]
+arreglo = [1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5]
# Arreglos pueden contener elementos de distintos tipos
-arreglo = [1, "hola", false] #=> => [1, "hola", false]
+[1, "hola", false] #=> => [1, "hola", false]
# Arreglos pueden ser indexados
# Desde el frente
arreglo[0] #=> 1
+arreglo.first #=> 1
arreglo[12] #=> nil
# Tal como la aritmética, el acceso como variable[índice]
@@ -138,15 +164,25 @@ arreglo.[] 12 #=> nil
# Desde el final
arreglo[-1] #=> 5
+arreglo.last #=> 5
+
+# Con un índice de inicio y longitud
+arreglo[2, 3] #=> [3, 4, 5]
-# Con un índice de inicio y final
-arreglo[2, 4] #=> [3, 4, 5]
+# Invertir un arreglo
+a = [1, 2, 3]
+a.reverse! #=> [3, 2, 1]
# O con rango
arreglo[1..3] #=> [2, 3, 4]
# Añade elementos a un arreglo así
arreglo << 6 #=> [1, 2, 3, 4, 5, 6]
+# O así
+arreglo.push(6) #=> [1, 2, 3, 4, 5, 6]
+
+#Verifica si un elemento ya existe en ese arreglo
+arreglo.include?(1) #=> true
# Hashes son los diccionarios principales de Ruby con pares llave/valor.
# Hashes se denotan con llaves:
@@ -161,17 +197,16 @@ hash['numero'] #=> 5
# Preguntarle a un hash por una llave que no existe retorna 'nil':
hash['nada aqui'] #=> nil
-# Itera sobre un hash con el método 'each':
-hash.each do |k, v|
- puts "#{k} is #{v}"
-end
-
# Desde Ruby 1.9, hay una sintaxis especial cuando se usa un símbolo como llave:
nuevo_hash = { defcon: 3, accion: true}
nuevo_hash.keys #=> [:defcon, :accion]
+# Verifica la existencia de llaves y valores en el hash
+new_hash.has_key?(:defcon) #=> true
+new_hash.has_value?(3) #=> true
+
# Tip: Tanto los arreglos como los hashes son Enumerable (enumerables)
# Comparten muchos métodos útiles tales como 'each', 'map', 'count', y más
@@ -194,9 +229,15 @@ end
#=> iteracion 4
#=> iteracion 5
-# Aunque
-# Nadie usa los ciclos `for`
-# Usa `each`, así:
+# SIN EMBARGO, nadie usa ciclos `for`
+# En su lugar debes usar el método "each" y pasarle un block (bloque).
+# Un bloque es un fragmento código que puedes pasar a métodos como `each`.
+# Es símilar a las funciones lambda, funciones anónimas o `closures` en otros
+# lenguajes de programación.
+#
+# El método `each` de un Range (rango) ejecuta el bloque una vez por cada elemento.
+# Al bloque se le pasa un contador como parametro.
+# Usar el método `each` con un bloque se ve así:
(1..5).each do |contador|
puts "iteracion #{contador}"
@@ -207,10 +248,27 @@ end
#=> iteracion 4
#=> iteracion 5
-counter = 1
-while counter <= 5 do
- puts "iteracion #{counter}"
- counter += 1
+# También puedes envolver el bloque entre llaves:
+(1..5).each { |counter| puts "iteración #{contador}" }
+
+#El contenido de las estructuras de datos en ruby puede ser iterado usando `each`.
+arreglo.each do |elemento|
+ puts "#{elemento} es parte del arreglo"
+end
+hash.each do |llave, valor|
+ puts "#{llave} es #{valor}"
+end
+
+# Si aún necesitas un índice puedes usar "each_with_index" y definir una variable
+# índice.
+arreglo.each_with_index do |element, index|
+ puts "#{element} tiene la posición #{index} en el arreglo"
+end
+
+contador = 1
+while contador <= 5 do
+ puts "iteracion #{contador}"
+ contador += 1
end
#=> iteracion 1
#=> iteracion 2
@@ -218,6 +276,19 @@ end
#=> iteracion 4
#=> iteracion 5
+# Hay una gran variedad de otras funciones iterativas útiles en Ruby,
+# por ejemplo `map`, `reduce`, `inject`, entre otras. Map, por ejemplo,
+# toma el arreglo sobre el cuál está iterando, le hace cambios
+# definidos en el bloque, y retorna un arreglo completamente nuevo.
+arreglo = [1,2,3,4,5]
+duplicado = array.map do |elemento|
+ elemento * 2
+end
+puts duplicado
+#=> [2,4,6,8,10]
+puts array
+#=> [1,2,3,4,5]
+
nota = 'B'
case nota
@@ -234,6 +305,34 @@ when 'F'
else
puts "Sistema alternativo de notas, ¿eh?"
end
+#=> "Mejor suerte para la proxima"
+
+# Los casos también pueden usar rangos
+nota = 82
+
+case nota
+when 90..100
+ puts 'Excelente!'
+when 80..100
+ puts 'Buen trabajo'
+else
+ puts '¡Reprobaste!'
+end
+#=> "Buen trabajo"
+
+# Manejo de excepciones
+begin
+ # código que podría causar excepción
+ raise NoMemoryError, 'Se te acabó la memoria'
+rescue NoMemoryError => variable_de_excepcion
+ puts 'El error NoMemoryError ocurrió', variable_de_excepcion
+rescue RuntimeError => otra_variable_de_excepcion
+ puts 'El error RuntimeError ocurrió'
+else
+ puts 'Esto se ejecuta si ningun error ocurrió'
+ensure
+ puts 'Este código siempre se ejecuta, sin importar que'
+end
# Funciones
@@ -244,7 +343,7 @@ end
# Funciones (y todos los bloques) implícitamente retornan el valor de la última instrucción
doble(2) #=> 4
-# Paréntesis son opcionales cuando el resultado es ambiguo
+# Paréntesis son opcionales cuando el resultado no es ambiguo
doble 3 #=> 6
doble doble 3 #=> 12
@@ -259,7 +358,7 @@ suma 3, 4 #=> 7
suma suma(3,4), 5 #=> 12
# yield
-# Todos los métodos tienen un parámetro de bloqueo opcional e implícitp
+# Todos los métodos tienen un parámetro bloque opcional e implícito
# puede llamarse con la palabra clave 'yield'
def alrededor
@@ -274,6 +373,17 @@ alrededor { puts 'hola mundo' }
# hola mundo
# }
+# Puedes pasar un bloque a una función
+# '&' representa una referencia a un bloque
+def visitantes(&bloque)
+ bloque.call
+end
+
+# Puedes pasar una lista de argumentos, que serán convertidos en un arreglo
+# Para eso sirve el operador ('*')
+def visitantes(*arreglo)
+ arreglo.each { |visitante| puts visitante }
+end
# Define una clase con la palabra clave 'class'
class Humano
@@ -299,16 +409,26 @@ class Humano
@nombre
end
+ # La funcionalidad anterior puede ser encapsulada usando el método attr_accessor
+ # de la siguiente manera
+
+ attr_accessor :name
+
+ # Los métodos de tipo getter y setter también se pueden crear de manera individual
+ # de la siguiente manera
+
+ attr_reader :name
+ attr_writer :name
+
# Un método de clase usa 'self' (sí mismo) para distinguirse de métodos de instancia.
# Sólo puede ser llamado en la clase, no por una instancia.
def self.decir(mensaje)
- puts "#{mensaje}"
+ puts mensaje
end
def especie
@@especie
end
-
end
@@ -328,6 +448,23 @@ dwight.nombre #=> "Dwight K. Schrute"
# Llama el método de clase
Humano.decir("Hi") #=> "Hi"
+# El alcance de las variables es definido por la manera en que las nombramos.
+# Las variables que inician con $ tienen un alcance global
+$var = "Soy una variable global"
+defined? $var #=> "global-variable"
+
+# Las variables que empiezan con @ tienen un alcance de instancia
+@var = "Soy una variable de instancia"
+defined? @var #=> "instance-variable"
+
+# Variables que empiezan con @@ tienen un alcance de clase
+@@var = "Soy una variable de clase"
+defined? @@var #=> "class variable"
+
+# Las variables que empiezan con letra mayuscula son constantes
+Var = "Soy una constante"
+defined? Var #=> "constant"
+
# Las clases también son un objeto en ruby. Por lo cual, las clases también pueden tener variables de instancia.
# Variables de clase son compartidas a través de la clase y todos sus descendientes.
@@ -371,7 +508,67 @@ end
class Doctor < Humano
end
-Human.bar # 0
+Humano.bar # 0
Doctor.bar # nil
+module ModuloEjemplo
+ def foo
+ 'foo'
+ end
+end
+
+# Al incluir un módulo sus métodos se comparten con las instancias de la clase
+# Al extender un módulo sus métodos se comparten con la clase misma
+
+class Persona
+ include ModuloEjemplo
+end
+
+class Libro
+ extend ModuloEjemplo
+end
+
+Persona.foo # => NoMethodError: undefined method `foo' for Persona:Class
+Persona.new.foo # => 'foo'
+Libro.foo # => 'foo'
+Libro.new.foo # => NoMethodError: undefined method `foo'
+
+# Las llamadas de retorno (callbacks) son ejecutadas cuando se incluye o
+# extiende un módulo
+module EjemploConcern
+ def self.incluido(base)
+ base.extend(MetodosClase)
+ base.send(:include, MetodosInstancia)
+ end
+
+ module MetodosClase
+ def bar
+ 'bar'
+ end
+ end
+
+ module MetodosInstancia
+ def qux
+ 'qux'
+ end
+ end
+end
+
+class Algo
+ include EjemploConcern
+end
+
+Algo.bar #=> 'bar'
+Algo.qux #=> NoMethodError: undefined method `qux'
+Algo.new.bar # => NoMethodError: undefined method `bar'
+Algo.new.qux # => 'qux'
```
+
+## Recursos adicionales
+- [Aprende Ruby Mediante Ejemplo con Ejercicios](http://www.learneroo.com/modules/61/nodes/338) - Una variante de
+esta referencia con ejercicios en navegador.
+- [Documentación Oficial](http://www.ruby-doc.org/core-2.1.1/)
+- [Ruby desde otros lenguajes](https://www.ruby-lang.org/en/documentation/ruby-from-other-languages/)
+- [Programando Ruby](http://www.amazon.com/Programming-Ruby-1-9-2-0-Programmers/dp/1937785491/) - Una
+[edición antigua](http://ruby-doc.com/docs/ProgrammingRuby/) gratuita disponible en línea.
+- [Guía de estilo de Ruby](https://github.com/bbatsov/ruby-style-guide) - Guía de estilo creada por la comunidad.
diff --git a/es-es/swift-es.html.markdown b/es-es/swift-es.html.markdown
new file mode 100644
index 00000000..c04ab02b
--- /dev/null
+++ b/es-es/swift-es.html.markdown
@@ -0,0 +1,596 @@
+---
+language: swift
+contributors:
+ - ["Grant Timmerman", "http://github.com/grant"]
+ - ["Christopher Bess", "http://github.com/cbess"]
+ - ["Joey Huang", "http://github.com/kamidox"]
+ - ["Anthony Nguyen", "http://github.com/anthonyn60"]
+translators:
+ - ["David Hsieh", "http://github.com/deivuh"]
+lang: es-es
+filename: learnswift-es.swift
+---
+
+Swift es un lenguaje de programación para el desarrollo en iOS y OS X creado
+por Apple. Diseñado para coexistir con Objective-C y ser más resistente contra
+el código erroneo, Swift fue introducido en el 2014 en el WWDC, la conferencia
+de desarrolladores de Apple.
+
+Véase también la guía oficial de Apple, [getting started guide](https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/DevelopiOSAppsSwift/), el cual tiene un completo tutorial de Swift.
+
+
+```swift
+// Importar un módulo
+import UIKit
+
+//
+// MARK: Básicos
+//
+
+// XCode soporta referencias para anotar tu código y agregarlos a lista de la
+// barra de saltos.
+// MARK: Marca de sección
+// TODO: Hacer algo pronto
+// FIXME: Arreglar este código
+
+// En Swift 2, println y print fueron combinados en un solo método print.
+// Print añade una nueva línea automáticamente.
+print("Hola, mundo") // println ahora es print
+print("Hola, mundo", appendNewLine: false) // print sin agregar nueva línea
+
+// Valores de variables (var) pueden cambiar después de ser asignados
+// Valores de constrantes (let) no pueden cambiarse después de ser asignados
+
+var myVariable = 42
+let øπΩ = "value" // nombres de variable unicode
+let π = 3.1415926
+let convenience = "keyword" // nombre de variable contextual
+// Las declaraciones pueden ser separadas por punto y coma (;)
+let weak = "keyword"; let override = "another keyword"
+// Los acentos abiertos (``) permiten utilizar palabras clave como nombres de
+// variable
+let `class` = "keyword"
+let explicitDouble: Double = 70
+let intValue = 0007 // 7
+let largeIntValue = 77_000 // 77000
+let label = "some text " + String(myVariable) // Conversión (casting)
+let piText = "Pi = \(π), Pi 2 = \(π * 2)" // Interpolación de string
+
+// Valores específicos de la compilación (build)
+// utiliza la configuración -D
+#if false
+ print("No impreso")
+ let buildValue = 3
+#else
+ let buildValue = 7
+#endif
+print("Build value: \(buildValue)") // Build value: 7
+
+/*
+ Las opcionales son un aspecto del lenguaje Swift que permite el
+ almacenamiento de un valor `Some` (algo) o `None` (nada).
+
+ Debido a que Swift requiere que cada propiedad tenga un valor,
+ hasta un valor 'nil' debe de ser explicitamente almacenado como un
+ valor opcional.
+
+ Optional<T> es un enum.
+*/
+var someOptionalString: String? = "opcional" // Puede ser nil
+// Al igual que lo anterior, pero ? es un operador postfix (sufijo)
+var someOptionalString2: Optional<String> = "opcional"
+
+if someOptionalString != nil {
+ // No soy nil
+ if someOptionalString!.hasPrefix("opt") {
+ print("Tiene el prefijo")
+ }
+
+ let empty = someOptionalString?.isEmpty
+}
+someOptionalString = nil
+
+// Opcional implícitamente desenvuelto
+var unwrappedString: String! = "Un valor esperado."
+// Al igual que lo anterior, pero ! es un operador postfix (sufijo)
+var unwrappedString2: ImplicitlyUnwrappedOptional<String> = "Un valor esperado."
+
+if let someOptionalStringConstant = someOptionalString {
+ // tiene valor `Some` (algo), no nil
+ if !someOptionalStringConstant.hasPrefix("ok") {
+ // No tiene el prefijo
+ }
+}
+
+// Swift tiene soporte de almacenamiento para cualquier tipo de valor.
+// AnyObject == id
+// A diferencia de Objective-C `id`, AnyObject funciona con cualquier
+// valor (Class, Int, struct, etc)
+var anyObjectVar: AnyObject = 7
+anyObjectVar = "Cambiado a un valor string, no es buena práctica, pero posible."
+
+/*
+ Comentar aquí
+
+ /*
+ Comentarios anidados también son soportados
+ */
+*/
+
+//
+// MARK: Colecciones
+//
+
+/*
+ Tipos Array (arreglo) y Dictionary (diccionario) son structs (estructuras).
+ Así que `let` y `var` también indican si son mudables (var) o
+ inmutables (let) durante la declaración de sus tipos.
+*/
+
+// Array (arreglo)
+var shoppingList = ["catfish", "water", "lemons"]
+shoppingList[1] = "bottle of water"
+let emptyArray = [String]() // let == inmutable
+let emptyArray2 = Array<String>() // igual que lo anterior
+var emptyMutableArray = [String]() // var == mudable
+
+
+// Dictionary (diccionario)
+var occupations = [
+ "Malcolm": "Captain",
+ "kaylee": "Mechanic"
+]
+occupations["Jayne"] = "Public Relations"
+let emptyDictionary = [String: Float]() // let == inmutable
+let emptyDictionary2 = Dictionary<String, Float>() // igual que lo anterior
+var emptyMutableDictionary = [String: Float]() // var == mudable
+
+
+//
+// MARK: Flujo de control
+//
+
+// Ciclo for (array)
+let myArray = [1, 1, 2, 3, 5]
+for value in myArray {
+ if value == 1 {
+ print("Uno!")
+ } else {
+ print("No es uno!")
+ }
+}
+
+// Ciclo for (dictionary)
+var dict = ["uno": 1, "dos": 2]
+for (key, value) in dict {
+ print("\(key): \(value)")
+}
+
+// Ciclo for (range)
+for i in -1...shoppingList.count {
+ print(i)
+}
+shoppingList[1...2] = ["steak", "peacons"]
+// Utilizar ..< para excluir el último valor
+
+// Ciclo while
+var i = 1
+while i < 1000 {
+ i *= 2
+}
+
+// Ciclo do-while
+do {
+ print("Hola")
+} while 1 == 2
+
+// Switch
+// Muy potente, se puede pensar como declaraciones `if` con _azúcar sintáctico_
+// Soportan String, instancias de objetos, y primitivos (Int, Double, etc)
+let vegetable = "red pepper"
+switch vegetable {
+case "celery":
+ let vegetableComment = "Add some raisins and make ants on a log."
+case "cucumber", "watercress":
+ let vegetableComment = "That would make a good tea sandwich."
+case let localScopeValue where localScopeValue.hasSuffix("pepper"):
+ let vegetableComment = "Is it a spicy \(localScopeValue)?"
+default: // obligatorio (se debe cumplir con todos los posibles valores de entrada)
+ let vegetableComment = "Everything tastes good in soup."
+}
+
+
+//
+// MARK: Funciones
+//
+
+// Funciones son un tipo de primera-clase, quiere decir que pueden ser anidados
+// en funciones y pueden ser pasados como parámetros
+
+// Función en documentación de cabeceras Swift (formato reStructedText)
+
+/**
+ Una operación de saludo
+
+ - Una viñeta en la documentación
+ - Otra viñeta en la documentación
+
+ :param: name Un nombre
+ :param: day Un día
+ :returns: Un string que contiene el valor de name y day
+*/
+func greet(name: String, day: String) -> String {
+ return "Hola \(name), hoy es \(day)."
+}
+greet("Bob", "Martes")
+
+// Similar a lo anterior, a excepción del compartamiento de los parámetros
+// de la función
+func greet2(requiredName: String, externalParamName localParamName: String) -> String {
+ return "Hola \(requiredName), hoy es el día \(localParamName)"
+}
+greet2(requiredName:"John", externalParamName: "Domingo")
+
+// Función que devuelve múltiples valores en una tupla
+func getGasPrices() -> (Double, Double, Double) {
+ return (3.59, 3.69, 3.79)
+}
+let pricesTuple = getGasPrices()
+let price = pricesTuple.2 // 3.79
+// Ignorar tupla (u otros) valores utilizando _ (guión bajo)
+let (_, price1, _) = pricesTuple // price1 == 3.69
+print(price1 == pricesTuple.1) // true
+print("Gas price: \(price)")
+
+// Cantidad variable de argumentos
+func setup(numbers: Int...) {
+ // Es un arreglo
+ let number = numbers[0]
+ let argCount = numbers.count
+}
+
+// Pasando y devolviendo funciones
+func makeIncrementer() -> (Int -> Int) {
+ func addOne(number: Int) -> Int {
+ return 1 + number
+ }
+ return addOne
+}
+var increment = makeIncrementer()
+increment(7)
+
+// Pasando como referencia
+func swapTwoInts(inout a: Int, inout b: Int) {
+ let tempA = a
+ a = b
+ b = tempA
+}
+var someIntA = 7
+var someIntB = 3
+swapTwoInts(&someIntA, &someIntB)
+print(someIntB) // 7
+
+
+//
+// MARK: Closures (Clausuras)
+//
+var numbers = [1, 2, 6]
+
+// Las funciones son un caso especial de closure ({})
+
+// Ejemplo de closure.
+// `->` Separa los argumentos del tipo de retorno
+// `in` Separa la cabecera del cuerpo del closure
+numbers.map({
+ (number: Int) -> Int in
+ let result = 3 * number
+ return result
+})
+
+// Cuando se conoce el tipo, como en lo anterior, se puede hacer esto
+numbers = numbers.map({ number in 3 * number })
+// o esto
+//numbers = numbers.map({ $0 * 3 })
+
+print(numbers) // [3, 6, 18]
+
+// Closure restante
+numbers = sorted(numbers) { $0 > $1 }
+
+print(numbers) // [18, 6, 3]
+
+// Bastante corto, debido a que el operador < infiere los tipos
+
+numbers = sorted(numbers, < )
+
+print(numbers) // [3, 6, 18]
+
+//
+// MARK: Estructuras
+//
+
+// Las estructuras y las clases tienen capacidades similares
+struct NamesTable {
+ let names = [String]()
+
+ // Subscript personalizado
+ subscript(index: Int) -> String {
+ return names[index]
+ }
+}
+
+// Las estructuras tienen un inicializador designado autogenerado (implícitamente)
+let namesTable = NamesTable(names: ["Me", "Them"])
+let name = namesTable[1]
+print("Name is \(name)") // Name is Them
+
+//
+// MARK: Clases
+//
+
+// Las clases, las estructuras y sus miembros tienen tres niveles de control de acceso
+// Éstos son: internal (predeterminado), public, private
+
+public class Shape {
+ public func getArea() -> Int {
+ return 0;
+ }
+}
+
+// Todos los métodos y las propiedades de una clase son public (públicas)
+// Si solo necesitas almacenar datos en un objecto estructurado,
+// debes de utilizar `struct`
+
+internal class Rect: Shape {
+ var sideLength: Int = 1
+
+ // Getter y setter personalizado
+ private var perimeter: Int {
+ get {
+ return 4 * sideLength
+ }
+ set {
+ // `newValue` es una variable implícita disponible para los setters
+ sideLength = newValue / 4
+ }
+ }
+
+ // Lazily loading (inicialización bajo demanda) a una propiedad
+ // subShape queda como nil (sin inicializar) hasta que getter es llamado
+ lazy var subShape = Rect(sideLength: 4)
+
+ // Si no necesitas un getter y setter personalizado
+ // pero aún quieres ejecutar código antes y después de hacer get o set
+ // a una propiedad, puedes utilizar `willSet` y `didSet`
+ var identifier: String = "defaultID" {
+ // El argumento `willSet` será el nombre de variable para el nuevo valor
+ willSet(someIdentifier) {
+ print(someIdentifier)
+ }
+ }
+
+ init(sideLength: Int) {
+ self.sideLength = sideLength
+ // Siempre poner super.init de último al momento de inicializar propiedades
+ // personalizadas
+ super.init()
+ }
+
+ func shrink() {
+ if sideLength > 0 {
+ --sideLength
+ }
+ }
+
+ override func getArea() -> Int {
+ return sideLength * sideLength
+ }
+}
+
+// Una clase simple `Square` que extiende de `Rect`
+class Square: Rect {
+ convenience init() {
+ self.init(sideLength: 5)
+ }
+}
+
+var mySquare = Square()
+print(mySquare.getArea()) // 25
+mySquare.shrink()
+print(mySquare.sideLength) // 4
+
+// Conversión de tipo de instancia
+let aShape = mySquare as Shape
+
+// Comparar instancias, no es igual a == que compara objetos (equal to)
+if mySquare === mySquare {
+ print("Yep, it's mySquare")
+}
+
+// Inicialización (init) opcional
+class Circle: Shape {
+ var radius: Int
+ override func getArea() -> Int {
+ return 3 * radius * radius
+ }
+
+ // Un signo de interrogación como sufijo después de `init` es un init opcional
+ // que puede devolver nil
+ init?(radius: Int) {
+ self.radius = radius
+ super.init()
+
+ if radius <= 0 {
+ return nil
+ }
+ }
+}
+
+var myCircle = Circle(radius: 1)
+print(myCircle?.getArea()) // Optional(3)
+print(myCircle!.getArea()) // 3
+var myEmptyCircle = Circle(radius: -1)
+print(myEmptyCircle?.getArea()) // "nil"
+if let circle = myEmptyCircle {
+ // no será ejecutado debido a que myEmptyCircle es nil
+ print("circle is not nil")
+}
+
+
+//
+// MARK: Enums
+//
+
+
+// Los enums pueden ser opcionalmente de un tipo específico o de su propio tipo
+// Al igual que las clases, pueden contener métodos
+
+enum Suit {
+ case Spades, Hearts, Diamonds, Clubs
+ func getIcon() -> String {
+ switch self {
+ case .Spades: return "♤"
+ case .Hearts: return "♡"
+ case .Diamonds: return "♢"
+ case .Clubs: return "♧"
+ }
+ }
+}
+
+// Los valores de enum permite la sintaxis corta, sin necesidad de poner
+// el tipo del enum cuando la variable es declarada de manera explícita
+var suitValue: Suit = .Hearts
+
+// Enums de tipo no-entero requiere asignaciones de valores crudas directas
+enum BookName: String {
+ case John = "John"
+ case Luke = "Luke"
+}
+print("Name: \(BookName.John.rawValue)")
+
+// Enum con valores asociados
+enum Furniture {
+ // Asociación con Int
+ case Desk(height: Int)
+ // Asociación con String e Int
+ case Chair(String, Int)
+
+ func description() -> String {
+ switch self {
+ case .Desk(let height):
+ return "Desk with \(height) cm"
+ case .Chair(let brand, let height):
+ return "Chair of \(brand) with \(height) cm"
+ }
+ }
+}
+
+var desk: Furniture = .Desk(height: 80)
+print(desk.description()) // "Desk with 80 cm"
+var chair = Furniture.Chair("Foo", 40)
+print(chair.description()) // "Chair of Foo with 40 cm"
+
+
+//
+// MARK: Protocolos
+//
+
+// `protocol` puede requerir que los tipos tengan propiedades
+// de instancia específicas, métodos de instancia, métodos de tipo,
+// operadores, y subscripts
+
+
+protocol ShapeGenerator {
+ var enabled: Bool { get set }
+ func buildShape() -> Shape
+}
+
+// Protocolos declarados con @objc permiten funciones opcionales,
+// que te permite evaluar conformidad
+@objc protocol TransformShape {
+ optional func reshaped()
+ optional func canReshape() -> Bool
+}
+
+class MyShape: Rect {
+ var delegate: TransformShape?
+
+ func grow() {
+ sideLength += 2
+
+ // Pon un signo de interrogación después de la propiedad opcional,
+ // método, o subscript para ignorar un valor nil y devolver nil
+ // en lugar de tirar un error de tiempo de ejecución
+ // ("optional chaining")
+ if let allow = self.delegate?.canReshape?() {
+ // test for delegate then for method
+ self.delegate?.reshaped?()
+ }
+ }
+}
+
+
+//
+// MARK: Otros
+//
+
+// `extension`: Agrega funcionalidades a tipos existentes
+
+// Square ahora se "conforma" al protocolo `Printable`
+extension Square: Printable {
+ var description: String {
+ return "Area: \(self.getArea()) - ID: \(self.identifier)"
+ }
+}
+
+print("Square: \(mySquare)")
+
+// También puedes hacer extend a tipos prefabricados (built-in)
+extension Int {
+ var customProperty: String {
+ return "This is \(self)"
+ }
+
+ func multiplyBy(num: Int) -> Int {
+ return num * self
+ }
+}
+
+print(7.customProperty) // "This is 7"
+print(14.multiplyBy(3)) // 42
+
+// Generics: Similar Java y C#. Utiliza la palabra clave `where` para
+// especificar los requerimientos de los genéricos.
+
+func findIndex<T: Equatable>(array: [T], valueToFind: T) -> Int? {
+ for (index, value) in enumerate(array) {
+ if value == valueToFind {
+ return index
+ }
+ }
+ return nil
+}
+let foundAtIndex = findIndex([1, 2, 3, 4], 3)
+print(foundAtIndex == 2) // true
+
+// Operadores:
+// Operadores personalizados puede empezar con los siguientes caracteres:
+// / = - + * % < > ! & | ^ . ~
+// o
+// Caracteres unicode: math, symbol, arrow, dingbat, y line/box.
+prefix operator !!! {}
+
+// Un operador prefix que triplica la longitud del lado cuando es utilizado
+prefix func !!! (inout shape: Square) -> Square {
+ shape.sideLength *= 3
+ return shape
+}
+
+// Valor actual
+print(mySquare.sideLength) // 4
+
+// Cambiar la longitud del lado utilizando el operador !!!,
+// incrementa el tamaño por 3
+!!!mySquare
+print(mySquare.sideLength) // 12
+```
diff --git a/es-es/tmux-es.html.markdown b/es-es/tmux-es.html.markdown
new file mode 100644
index 00000000..a7354be1
--- /dev/null
+++ b/es-es/tmux-es.html.markdown
@@ -0,0 +1,253 @@
+---
+category: tool
+tool: tmux
+contributors:
+ - ["mdln", "https://github.com/mdln"]
+filename: LearnTmux-es.txt
+translators:
+ - ["Damaso Sanoja", "https://github.com/damasosanoja"]
+lang: es-es
+---
+
+
+[tmux](http://tmux.sourceforge.net)
+es un terminal multiplexor: habilita la creación, acceso y control
+de múltiples terminales controlados desde una sola pantalla. tmux
+puede ser separado de una pantalla y continuar corriendo en el fondo
+y luego ser insertado nuevamente.
+
+
+```
+
+ tmux [command] # Corre un comando
+ # 'tmux' sin comandos creará una nueva sesión
+
+ new # Crea una nueva sesión
+ -s "Session" # Crea sesión con nombre
+ -n "Window" # Crea ventana con nombre
+ -c "/dir" # Comienza en el directorio destino
+
+ attach # Adjunta sesión última/disponible
+ -t "#" # Adjunta sesión destino
+ -d # Separa la sesión de otras instancias
+
+ ls # Lista las sesiones abiertas
+ -a # Lista todas las sesiones abiertas
+
+ lsw # Lista las ventanas
+ -a # Lista todas las ventanas
+ -s # Lista todas las ventanas en la sesión
+
+ lsp # Lista los páneles
+ -a # Lista todos los páneles
+ -s # Lista todos los páneles de la sesión
+ -t # Lista los páneles de aplicación en el destino
+
+ kill-window # Cierra la ventana actual
+ -t "#" # Cierra la ventana destino
+ -a # Cierra todas las ventanas
+ -a -t "#" # Cierra todas las ventanas menos el destino
+
+ kill-session # Cierra la sesión actual
+ -t "#" # Cierra la sesión destino
+ -a # Cierra todas las sesiones
+ -a -t "#" # Cierra todas las sesiones menos el destino
+
+```
+
+
+### Atajos de Teclado
+
+El método para controlar una sesión adjunta tmux es mediante
+combinaciones de teclas llamadas teclas 'Prefijo'.
+
+```
+----------------------------------------------------------------------
+ (C-b) = Ctrl + b # combinación 'Prefijo' necesaria para usar atajos
+
+ (M-1) = Meta + 1 -o- Alt + 1
+----------------------------------------------------------------------
+
+ ? # Lista todos los atajos de teclado
+ : # Entra en la línea de comandos tmux
+ r # Fuerza el redibujado del cliente adjuntado
+ c # Crea una nueva ventana
+
+ ! # Separa el panel actual fuera de la ventana.
+ % # Separa el panel actual en dos, izquierdo y derecho
+ " # Separa el panel actual en dos, superior e inferior
+
+ n # Cambia a la siguiente ventana
+ p # Cambia a la ventana previa
+ { # Intercambia el panel actual con el anterior
+ } # Intercambia el panel actual con el próximo
+
+ s # Selecciona una nueva sesión para el cliente adjuntado
+ interactivamente
+ w # Elegir la ventana actual interactivamente
+ 0 al 9 # Seleccionar ventanas 0 al 9
+
+ d # Separa el cliente actual
+ D # Elige un cliente para separar
+
+ & # Cierra la ventana actual
+ x # Cierra el panel actual
+
+ Up, Down # Cambia al panel superior, inferior, izquierdo, o derecho
+ Left, Right
+
+ M-1 to M-5 # Organizar páneles:
+ # 1) uniformes horizontales
+ # 2) uniformes verticales
+ # 3) principal horizontal
+ # 4) principal vertical
+ # 5) mozaico
+
+ C-Up, C-Down # Redimensiona el panel actual en pasos de una celda
+ C-Left, C-Right
+
+ M-Up, M-Down # Redimensiona el panel actual en pasos de cinco celdas
+ M-Left, M-Right
+
+```
+
+
+### Configurando ~/.tmux.conf
+
+tmux.conf puede usarse para establecer opciones automáticas al arrancar, parecido a como .vimrc o init.el hacen.
+
+```
+# Ejemplo de tmux.conf
+# 2014.10
+
+
+### General
+###########################################################################
+
+# Habilita UTF-8
+setw -g utf8 on
+set-option -g status-utf8 on
+
+# Fuera de pantalla/Historia límite
+set -g history-limit 2048
+
+# Comienzo de índice
+set -g base-index 1
+
+# Ratón
+set-option -g mouse-select-pane on
+
+# Forza recarga de fichero de configuración
+unbind r
+bind r source-file ~/.tmux.conf
+
+
+### Atajos de teclado
+###########################################################################
+
+# Desvincula C-b como el prefijo por defecto
+unbind C-b
+
+# Establece el nuevo prefijo
+set-option -g prefix `
+
+# Regresa a la ventana previa cuando el prefijo es accionado dos veces
+bind C-a last-window
+bind ` last-window
+
+# Permite intercambiar C-a y ` usando F11/F12
+bind F11 set-option -g prefix C-a
+bind F12 set-option -g prefix `
+
+# Preferencias de atajos
+setw -g mode-keys vi
+set-option -g status-keys vi
+
+# Moviéndose entre paneles con movimientos de teclas vim
+bind h select-pane -L
+bind j select-pane -D
+bind k select-pane -U
+bind l select-pane -R
+
+# Ciclo/Intercambio de Ventana
+bind e previous-window
+bind f next-window
+bind E swap-window -t -1
+bind F swap-window -t +1
+
+# División rápida de paneles
+bind = split-window -h
+bind - split-window -v
+unbind '"'
+unbind %
+
+# Activar sesión mas interna (cuando se anida tmux) para enviar comandos
+bind a send-prefix
+
+
+### Temas
+###########################################################################
+
+# Paleta de Colores de la Barra de estado
+set-option -g status-justify left
+set-option -g status-bg black
+set-option -g status-fg white
+set-option -g status-left-length 40
+set-option -g status-right-length 80
+
+# Paleta de Colores del Borde del Panel
+set-option -g pane-active-border-fg green
+set-option -g pane-active-border-bg black
+set-option -g pane-border-fg white
+set-option -g pane-border-bg black
+
+# Paleta de Colores de Mensajes
+set-option -g message-fg black
+set-option -g message-bg green
+
+# Paleta de Colores de la Ventana
+setw -g window-status-bg black
+setw -g window-status-current-fg green
+setw -g window-status-bell-attr default
+setw -g window-status-bell-fg red
+setw -g window-status-content-attr default
+setw -g window-status-content-fg yellow
+setw -g window-status-activity-attr default
+setw -g window-status-activity-fg yellow
+
+
+### UI
+###########################################################################
+
+# Notificación
+setw -g monitor-activity on
+set -g visual-activity on
+set-option -g bell-action any
+set-option -g visual-bell off
+
+# Establece automáticamente títulos de ventanas
+set-option -g set-titles on
+set-option -g set-titles-string '#H:#S.#I.#P #W #T' # window number,program name,active (or not)
+
+# Ajustes de barra de estado
+set -g status-left "#[fg=red] #H#[fg=green]:#[fg=white]#S#[fg=green] |#[default]"
+
+# Muestra indicadores de rendimiento en barra de estado
+# Requiere https://github.com/thewtex/tmux-mem-cpu-load/
+set -g status-interval 4
+set -g status-right "#[fg=green] | #[fg=white]#(tmux-mem-cpu-load)#[fg=green] | #[fg=cyan]%H:%M #[default]"
+
+```
+
+
+### Referencias
+
+[Tmux | Inicio](http://tmux.sourceforge.net)
+
+[Tmux Manual](http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man1/tmux.1?query=tmux)
+
+[Gentoo Wiki](http://wiki.gentoo.org/wiki/Tmux)
+
+[Archlinux Wiki](https://wiki.archlinux.org/index.php/Tmux)
+
+[Mostrar CPU/MEM % en barra de estado](https://stackoverflow.com/questions/11558907/is-there-a-better-way-to-display-cpu-usage-in-tmux)